Merge "ASoC: wcd9xxx: fix build warning"
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
index 04310ec..b489f7a 100644
--- a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -13,21 +13,17 @@
 Required properties:
 - compatible:			Must be "qcom,cpr-regulator"
 - reg:				Register addresses for RBCPR, RBCPR clock
-				select, PVS eFuse and CPR eFuse
+				select, PVS and CPR eFuse address
 - reg-names:			Register names. Must be "rbcpr", "rbcpr_clk",
-				"pvs_efuse" and "cpr_efuse"
+				"efuse_addr"
 - regulator-name:		A string used to describe the regulator
 - interrupts:			Interrupt line from RBCPR to interrupt controller.
 - regulator-min-microvolt:	Minimum corner value as min constraint, which
 				should be 1 for SVS corner
 - regulator-max-microvolt:	Maximum corner value as max constraint, which
 				should be 4 for SUPER_TURBO or 3 for TURBO
-- qcom,num-efuse-bits:		The number of bits used in efuse memory to
-				represent total number of PVS bins. It should
-				not exceed a maximum of 5 for total number of
-				32 bins.
 - qcom,pvs-bin-process:		A list of integers whose length is equal to 2 to
-				the power of qcom,num-efuse-bits. The location or
+				the power of qcom,pvs-fuse[num-of-bits]. The location or
 				0-based index of an element in the list corresponds
 				to the bin number. The value of each integer
 				corresponds to the PVS process speed of the APC
@@ -54,7 +50,7 @@
 - qcom,cpr-timer-cons-down:	Consecutive number of timer interval (qcom,cpr-timer-delay)
 				occurred before issuing DOWN interrupt.
 - qcom,cpr-irq-line:		Internal interrupt route signal of RBCPR, one of 0, 1 or 2.
-- qcom,cpr-step-quotient:	Number of CPR quotient (RO count) per vdd-apc-supply step
+- qcom,cpr-step-quotient:	Number of CPR quotient (Ring Oscillator(RO) count) per vdd-apc-supply step
 				to issue error_steps.
 - qcom,cpr-up-threshold:	The threshold for CPR to issue interrupt when
 				error_steps is greater than it when stepping up.
@@ -64,6 +60,62 @@
 - qcom,cpr-gcnt-time:		The time for gate count in microseconds.
 - qcom,cpr-apc-volt-step:	The voltage in microvolt per CPR step, such as 5000uV.
 
+- qcom,pvs-fuse-redun-sel:	Array of 4 elements to indicate where to read the bits and what value to
+				compare with in order to decide if the redundant PVS fuse bits would be
+				used instead of the original bits. The 4 elements with index [0..3] are:
+				  [0] => the fuse row number of the selector
+				  [1] => LSB bit position of the bits
+				  [2] => number of bits
+				  [3] => the value to indicate redundant selection
+				When the value of the fuse bits specified by first 3 elements equals to
+				the value in 4th element, redundant PVS fuse bits should be selected.
+				Otherwise, the original PVS bits should be selected.
+- qcom,pvs-fuse:		Array of three elements to indicate the bits for PVS fuse. The array
+				should have index and value like this:
+				  [0] => the PVS fuse row number
+				  [1] => LSB bit position of the bits
+				  [2] => number of bits
+- qcom,pvs-fuse-redun:		Array of three elements to indicate the bits for redundant PVS fuse.
+				The array should have index and value like this:
+				  [0] => the redundant PVS fuse row number
+				  [1] => LSB bit position of the bits
+				  [2] => number of bits
+
+- qcom,cpr-fuse-redun-sel:	Array of 4 elements to indicate where to read the bits and what value to
+				compare with in order to decide if the redundant CPR fuse bits would be
+				used instead of the original bits. The 4 elements with index [0..3] are:
+				  [0] => the fuse row number of the selector
+				  [1] => LSB bit position of the bits
+				  [2] => number of bits
+				  [3] => the value to indicate redundant selection
+				When the value of the fuse bits specified by first 3 elements equals to
+				the value in 4th element, redundant CPR fuse bits should be selected.
+				Otherwise, the original CPR bits should be selected.
+- qcom,cpr-fuse-row:		Row number of CPR fuse
+- qcom,cpr-fuse-bp-cpr-disable:	Bit position of the bit to indicate if CPR should be disable
+- qcom,cpr-fuse-bp-scheme:	Bit position of the bit to indicate if it's a global/local scheme
+- qcom,cpr-fuse-target-quot:	Array of bit positions in fuse for Target Quotient of all corners.
+				It should have index and value like this:
+				  [0] => bit position of the LSB bit for SVS target quotient
+				  [1] => bit position of the LSB bit for NOMINAL target quotient
+				  [2] => bit position of the LSB bit for TURBO target quotient
+- qcom,cpr-fuse-ro-sel:		Array of bit positions in fuse for RO select of all corners.
+				It should have index and value like this:
+				  [0] => bit position of the LSB bit for SVS RO select bits
+				  [1] => bit position of the LSB bit for NOMINAL RO select bits
+				  [2] => bit position of the LSB bit for TURBO RO select bits
+- qcom,cpr-fuse-redun-row:	Row number of the redundant CPR fuse
+- qcom,cpr-fuse-redun-target-quot:	Array of bit positions in fuse for redundant Target Quotient of all corners.
+				It should have index and value like this:
+				  [0] => bit position of the LSB bit for redundant SVS target quotient
+				  [1] => bit position of the LSB bit for redundant NOMINAL target quotient
+				  [2] => bit position of the LSB bit for redundant TURBO target quotient
+- qcom,cpr-fuse-redun-ro-sel:	Array of bit positions in eFuse for redundant RO select.
+				It should have index and value like this:
+				  [0] => bit position of the LSB bit for redundant SVS RO select bits
+				  [1] => bit position of the LSB bit for redundant NOMINAL RO select bits
+				  [2] => bit position of the LSB bit for redundant TURBO RO select bits
+
 
 Optional properties:
 - vdd-mx-supply:		Regulator to supply memory power as dependency
@@ -78,6 +130,10 @@
 				  2 => equal to slow speed corner ceiling
 				  3 => equal to qcom,vdd-mx-vmax
 				This is required when vdd-mx-supply is present.
+- qcom,cpr-fuse-redun-bp-cpr-disable:	Redundant bit position of the bit to indicate if CPR should be disable
+- qcom,cpr-fuse-redun-bp-scheme:	Redundant bit position of the bit to indicate if it's a global/local scheme
+					This property is required if cpr-fuse-redun-bp-cpr-disable
+					is present, and vise versa.
 - qcom,cpr-enable:		Present: CPR enabled by default.
 				Not Present: CPR disable by default.
 
@@ -86,13 +142,17 @@
 	apc_vreg_corner: regulator@f9018000 {
 		status = "okay";
 		compatible = "qcom,cpr-regulator";
-		reg = <0xf9018000 0x1000>, <0xfc4b80b0 8>, <0xfc4bc450 16>;
-		reg-names = "rbcpr", "pvs_efuse", "cpr_efuse";
+		reg = <0xf9018000 0x1000>, <0xfc4b8000 0x1000>;
+		reg-names = "rbcpr", "efuse_addr";
 		interrupts = <0 15 0>;
 		regulator-name = "apc_corner";
 		regulator-min-microvolt = <1>;
 		regulator-max-microvolt = <3>;
-		qcom,num-efuse-bits = <5>;
+
+		qcom,pvs-fuse = <22 6 5>;
+		qcom,pvs-fuse-redun-sel = <22 24 3 2>;
+		qcom,pvs-fuse-redun = <22 27 5>;
+
 		qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
 					2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
 		qcom,pvs-corner-ceiling-slow = <1050000 1160000 1275000>;
@@ -115,5 +175,15 @@
 		qcom,cpr-idle-clocks = <5>;
 		qcom,cpr-gcnt-time = <1>;
 		qcom,cpr-apc-volt-step = <5000>;
+
+		qcom,cpr-fuse-row = <138>;
+		qcom,cpr-fuse-bp-cpr-disable = <36>;
+		qcom,cpr-fuse-bp-scheme = <37>;
+		qcom,cpr-fuse-target-quot = <24 12 0>;
+		qcom,cpr-fuse-ro-sel = <54 38 41>;
+		qcom,cpr-fuse-redun-sel = <138 57 1 1>;
+		qcom,cpr-fuse-redun-row = <139>;
+		qcom,cpr-fuse-redun-target-quot = <24 12 0>;
+		qcom,cpr-fuse-redun-ro-sel = <46 36 39>;
 	};
 
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
index 195a98d..f57d928 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
@@ -3,10 +3,8 @@
 The application processor in MSM can do a variety of C-States for low power
 management. These C-States are invoked by the CPUIdle framework when the core
 becomes idle. But based on the time available until the next scheduled wakeup,
-the system can do a combination of low power modes of different resources -
-L2, XO, Vdd Dig and Vdd Mem. The combination is captured in the device tree as
-lpm-level. The units for voltage are dependent on the PMIC used on the target
-and are in uV.
+the system can do several low power modes. The combination is captured in the
+device tree as lpm-level.
 
 The required nodes for lpm-levels are:
 
@@ -20,20 +18,11 @@
 		"retention" - Retention
 		"pc_suspend" - Suspended Power Collapse
 		"pc_no_xo_shutdown" - Power Collapse with no XO shutdown
-- qcom,xo: The state of XO clock. Values are "xo_on" and "xo_off"
 - qcom,l2: The state of L2 cache. Values are:
 		"l2_cache_pc" - L2 cache in power collapse
 		"l2_cache_retenetion" - L2 cache in retention
 		"l2_cache_gdhs" - L2 cache in GDHS
 		"l2_cache_active" - L2 cache in active mode
-- qcom,vdd-mem-upper-bound: The upper bound value of mem voltage in uV
-- qcom,vdd-mem-lower-bound: The lower bound value of mem voltage in uV
-- qcom,vdd-dig-upper-bound: The upper bound value of dig voltage in uV
-                            or an RBCPR (Rapid Bridge Core Power Reduction)
-                            corner voltage.
-- qcom,vdd-dig-lower-bound: The lower bound value of dig voltage in uV
-                            or an RBCPR (Rapid Bridge Core Power Reduction)
-                            corner voltage.
 - qcom,latency-us: The latency in handling the interrupt if this level was
 	chosen, in uSec
 - qcom,ss-power: The steady state power expelled when the processor is in this
@@ -42,29 +31,18 @@
 	in mWatts.uSec
 - qcom,time-overhead: The time spent in entering and exiting this level in uS
 
-Optional properties
-- qcom,irqs-detectable: The field indicates whether the IRQs are detectable by
-			the GIC controller when entering a low power mode.
-- qcom,gpio-detectable: The field indicates whether the GPIOs can be detected
-			by the GPIO interrupt controller during a given low
-			power mode.
-- qcom,use-qtimer: Indicates whether the target uses the synchronized QTimer.
+The optional nodes for lpm-levels are :
+-  qcom,no-l2-saw: Indicates if this target has an L2 SAW (SPM and AVS wrapper).
+-  qcom,default-l2-state: Indicates what the default low power state of the L2 SAW should be. This property is used only when there is an L2 SAW.
 
 Example:
 
 qcom,lpm-levels {
-	qcom,use-qtimer;
+	qcom,no-l2-saw;
 	qcom,lpm-level@0 {
 		reg = <0>;
 		qcom,mode = "wfi";
-		qcom,xo = "xo_on";
 		qcom,l2 = "l2_cache_active";
-		qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-		qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-		qcom,vdd-dig-upper-bound = <5>; /* MAX */
-		qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-		qcom,irqs-detectable;
-		qcom,gpio-detectable;
 		qcom,latency-us = <100>;
 		qcom,ss-power = <650>;
 		qcom,energy-overhead = <801>;
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
deleted file mode 100644
index 7b5fda3..0000000
--- a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-* Low Power Management Resources
-
-The application processor in the MSM can enter several different low power
-states depending on the sleep time and on the required system resources. The
-MSM cannot enter a given low power state if that state involves turning off
-some shared resources which are required by some components of the
-system.The lpm-resources device tree node represents the shared resources
-that need to be monitored for usage requirement to check if a given low power
-state can be entered.Each resource is identified by a combination of the name,
-id,type and key which is also used by the RPM to identify a shared resource.
-The name and resource-type are required nodes; the type, id and key are
-optional nodes which are needed if the resource type is RPM shared resource
-(MSM_LPM_RPM_RS_TYPE).
-
-The nodes for lpm-resources are:
-
-Required Nodes:
-
-- compatible: "qcom,lpm-resources"
-- reg: The numeric level id
-- qcom,name: The name of the low power resource represented
-             as a string.
-- qcom,init-value: Initialization value of the LPM resource represented as
-			decimal value for vdd-dig and vdd-mem resources and
-			as string for pxo and l2 resources.
-
-
-Optional Nodes:
-
-- qcom,type: The type of resource used like smps or pxo
-             represented as a hex value.
-- qcom,id: The id representing a device within a resource type.
-- qcom,key: The key is the specific attribute of the resource being
-            monitored represented as a hex value.
-- qcom,local-resource-type: The property exists only for locally managed
-				resource and is represented as a bool.
-
-Example:
-            qcom,lpm-resources@0 {
-                        reg = <0x0>;
-                        qcom,name = "vdd-dig";
-                        qcom,type = <0x62706d73>;   /* "smpb" */
-                        qcom,id = <0x02>;
-                        qcom,key = <0x6e726f63>;   /* "corn" */
-			qcom,init-value= <5>;   /* Active Corner*/
-                };
-
diff --git a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
index 6dac1b7..bf5e544 100644
--- a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
+++ b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
@@ -26,12 +26,13 @@
 add the appropriate binding:
 
 Required parameters:
-- qcom,memblock-remove: base and size of block to be removed
+- qcom,memblock-remove: array of the base and size of blocks to be removed
 
 	qcom,a-driver {
 		compatible = "qcom,a-driver";
-		/* Remove 4MB at 0x200000*/
-		qcom,memblock-remove = <0x200000 0x400000>;
+		/* Remove 4MB at 0x200000 and 2MB at 0x800000*/
+		qcom,memblock-remove = <0x200000 0x400000
+					0x800000 0x200000>;
 	};
 
 In order to ensure memory is only reserved when a driver is actually enabled,
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
index 6ef2b77..d07eba6 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
@@ -85,19 +85,19 @@
 		qcom,core-control-mask = <7>;
 		qcom,pmic-sw-mode-temp = <90>;
 		qcom,pmic-sw-mode-temp-hysteresis = <80>;
-		qcom,pmic-sw-mode-regs = "vdd_dig";
+		qcom,pmic-sw-mode-regs = "vdd-dig";
 		qcom,vdd-restriction-temp = <5>;
 		qcom,vdd-restriction-temp-hysteresis = <10>;
-		vdd_dig-supply=<&pm8841_s2_floor_corner>
+		vdd-dig-supply=<&pm8841_s2_floor_corner>
 
 		qcom,vdd-dig-rstr{
-			qcom,vdd-rstr-reg = "vdd_dig";
+			qcom,vdd-rstr-reg = "vdd-dig";
 			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
 			qcom,min-level = <1>; /* No Request */
 		};
 
 		qcom,vdd-apps-rstr{
-			qcom,vdd-rstr-reg = "vdd_apps";
+			qcom,vdd-rstr-reg = "vdd-apps";
 			qcom,levels = <1881600 1958400 2265600>;
 			qcom,freq-req;
 		};
diff --git a/Documentation/devicetree/bindings/batterydata/batterydata.txt b/Documentation/devicetree/bindings/batterydata/batterydata.txt
new file mode 100644
index 0000000..985fb4c
--- /dev/null
+++ b/Documentation/devicetree/bindings/batterydata/batterydata.txt
@@ -0,0 +1,163 @@
+Battery Profile Data
+
+Battery Data is a collection of battery profile data made available to
+the QPNP Charger and BMS drivers via device tree.
+
+qcom,battery-data node required properties:
+- qcom,rpull-up-kohm : The vadc pullup resistor's resistance value in kOhms.
+- qcom,vref-batt-therm-uv : The vadc voltage used to make readings.
+			For Qualcomm VADCs this should be 1800000uV.
+
+qcom,battery-data can also include any number of children nodes. These children
+nodes will be treated as battery profile data nodes.
+
+Profile data node required properties:
+- qcom,fcc-mah : Full charge count of the battery in milliamp-hours
+- qcom,default-rbatt-mohm : The nominal battery resistance value
+- qcom,rbatt-capacitive-mohm : The capacitive resistance of the battery.
+- qcom,flat-ocv-threshold-uv : The threshold under which the battery can be
+			considered to be in the flat portion of the discharge
+			curve.
+- qcom,max-voltage-uv : The maximum rated voltage of the battery
+- qcom,v-cutoff-uv : The cutoff voltage of the battery at which the device
+			should shutdown gracefully.
+- qcom,chg-term-ua : The termination charging current of the battery.
+- qcom,batt-id-kohm : The battery id resistance of the battery.
+
+Profile data node required subnodes:
+- qcom,fcc-temp-lut : An 1-dimensional lookup table node that encodes
+			temperature to fcc lookup. The units for this lookup
+			table should be degrees celsius to milliamp-hours.
+- qcom,pc-temp-ocv-lut : A 2-dimensional lookup table node that encodes
+			temperature and percent charge to open circuit voltage
+			lookup. The units for this lookup table should be
+			degrees celsius and percent to millivolts.
+- qcom,rbatt-sf-lut : A 2-dimentional lookup table node that encodes
+			temperature and percent charge to battery internal
+			resistance lookup. The units for this lookup table
+			should be degrees celsius and percent to milliohms.
+
+Lookup table required properties:
+- qcom,lut-col-legend : An array that encodes the legend of the lookup table's
+			columns. The length of this array will determine the
+			lookup table's width.
+- qcom,lut-data : An array that encodes the lookup table's data. The size of this
+			array should be equal to the size of qcom,lut-col-legend
+			multiplied by 1 if it's a 1-dimensional table, or
+			the size of qcom,lut-row-legend if it's a 2-dimensional
+			table. The data should be in a flattened row-major
+			representation.
+
+Lookup table optional properties:
+- qcom,lut-row-legend : An array that encodes the legend of the lookup table's rows.
+			If this property exists, then it is assumed that the
+			lookup table is a 2-dimensional table.
+
+Example:
+
+In msm8974-mtp.dtsi:
+
+mtp_batterydata: qcom,battery-data {
+	qcom,rpull-up-kohm = <100>;
+	qcom,vref-batt-therm-uv = <1800000>;
+
+	/include/ "batterydata-palladium.dtsi"
+	/include/ "batterydata-mtp-3000mah.dtsi"
+};
+
+&pm8941_bms {
+	qcom,battery-data = <&mtp_batterydata>;
+};
+
+In batterydata-palladium.dtsi:
+
+qcom,palladium-batterydata {
+	qcom,fcc-mah = <1500>;
+	qcom,default-rbatt-mohm = <236>;
+	qcom,rbatt-capacitive-mohm = <50>;
+	qcom,flat-ocv-threshold-uv = <3800000>;
+	qcom,max-voltage-uv = <4200000>;
+	qcom,v-cutoff-uv = <3400000>;
+	qcom,chg-term-ua = <100000>;
+	qcom,batt-id-kohm = <75>;
+
+	qcom,fcc-temp-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 65>;
+		qcom,lut-data = <1492 1492 1493 1483 1502>;
+	};
+
+	qcom,pc-temp-ocv-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 65>;
+		qcom,lut-row-legend = <100 95 90 85 80 75 70>,
+				<65 60 55 50 45 40 35>,
+				<30 25 20 15 10 9 8>,
+				<7 6 5 4 3 2 1 0>;
+		qcom,lut-data = <4173 4167 4163 4156 4154>,
+			<4104 4107 4108 4102 4104>,
+			<4057 4072 4069 4061 4060>,
+			<3973 4009 4019 4016 4020>,
+			<3932 3959 3981 3982 3983>,
+			<3899 3928 3954 3950 3950>,
+			<3868 3895 3925 3921 3920>,
+			<3837 3866 3898 3894 3892>,
+			<3812 3841 3853 3856 3862>,
+			<3794 3818 3825 3823 3822>,
+			<3780 3799 3804 3804 3803>,
+			<3768 3787 3790 3788 3788>,
+			<3757 3779 3778 3775 3776>,
+			<3747 3772 3771 3766 3765>,
+			<3736 3763 3766 3760 3746>,
+			<3725 3749 3756 3747 3729>,
+			<3714 3718 3734 3724 3706>,
+			<3701 3703 3696 3689 3668>,
+			<3675 3695 3682 3675 3662>,
+			<3670 3691 3680 3673 3661>,
+			<3661 3686 3679 3672 3656>,
+			<3649 3680 3676 3669 3641>,
+			<3633 3669 3667 3655 3606>,
+			<3610 3647 3640 3620 3560>,
+			<3580 3607 3596 3572 3501>,
+			<3533 3548 3537 3512 3425>,
+			<3457 3468 3459 3429 3324>,
+			<3328 3348 3340 3297 3172>,
+			<3000 3000 3000 3000 3000>;
+	};
+
+	qcom,rbatt-sf-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 65>;
+		qcom,lut-row-legend = <100 95 90 85 80 75 70>,
+				<65 60 55 50 45 40 35>,
+				<30 25 20 15 10 9 8>,
+				<7 6 5 4 3 2 1 0>;
+		qcom,lut-data = <357 187 100 91 91>,
+			<400 208 105 94 94>,
+			<390 204 106 95 96>,
+			<391 201 108 98 98>,
+			<391 202 110 98 100>,
+			<390 200 110 99 102>,
+			<389 200 110 99 102>,
+			<393 202 101 93 100>,
+			<407 205 99 89 94>,
+			<428 208 100 91 96>,
+			<455 212 102 92 98>,
+			<495 220 104 93 101>,
+			<561 232 107 95 102>,
+			<634 245 112 98 98>,
+			<714 258 114 98 98>,
+			<791 266 114 97 100>,
+			<871 289 108 95 97>,
+			<973 340 124 108 105>,
+			<489 241 109 96 99>,
+			<511 246 110 96 99>,
+			<534 252 111 95 98>,
+			<579 263 112 96 96>,
+			<636 276 111 95 97>,
+			<730 294 109 96 99>,
+			<868 328 112 98 104>,
+			<1089 374 119 101 115>,
+			<1559 457 128 105 213>,
+			<12886 1026 637 422 3269>,
+			<170899 127211 98968 88907 77102>;
+	};
+};
+
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
index d24e671..7f7ee25 100644
--- a/Documentation/devicetree/bindings/coresight/coresight.txt
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -118,6 +118,12 @@
 - qcom,setb-gpios-pull : active pull configuration for set B gpios
 - qcom,setb-gpios-dir : active direction for set B gpios
 - qcom,hwevent-clks : list of clocks required by hardware event driver
+- qcom,byte-cntr-absent : specifies if the byte counter feature is absent on
+			  the device. Only relevant in case of tmc-etr device.
+- interrupts : <a b c> where a is 0 or 1 depending on if the interrupt is
+		spi/ppi, b is the interrupt number and c is the mask,
+- interrupt-names : a list of strings that map in order to the list of
+		    interrupts specified in the 'interrupts' property.
 
 Examples:
 
@@ -128,6 +134,11 @@
 		      <0xfc37c000 0x3000>;
 		reg-names = "tmc-base", "bam-base";
 
+		interrupts = <0 166 0>;
+		interrupt-names = "byte-cntr-irq";
+
+		qcom,byte-cntr-absent;
+
 		coresight-id = <0>;
 		coresight-name = "coresight-tmc-etr";
 		coresight-nr-inports = <1>;
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
index ce4972a..4cec0cd 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
@@ -12,21 +12,41 @@
 - vdda-supply:				Phandle for vreg regulator device node.
 - qcom,mdss-fb-map:			pHandle that specifies the framebuffer to which the
 					interface is mapped.
+- qcom,platform-regulator-settings:	An array of length 7 that specifies the PHY
+					regulator settings.
+- qcom,platform-strength-ctrl:		An array of length 2 that specifies the PHY
+					strengthCtrl settings.
+- qcom,platform-bist-ctrl:		An array of length 6 that specifies the PHY
+					BIST ctrl settings.
+- qcom,platform-lane-config:		An array of length 45 that specifies the PHY
+					lane configuration settings.
 
 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-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.
 
+- qcom,platform-supply-entry<1..n>:	A node that lists the elements of the supply. There
+					can be more than one instance of this binding,
+					in which case the entry would be appended with
+					the supply entry index.
+					e.g. qcom,platform-supply-entry1
+					-- qcom,supply-name: name of the supply (vdd/vdda/vddio)
+					-- qcom,supply-min-voltage: minimum voltage level (uV)
+					-- qcom,supply-max-voltage: maximum voltage level (uV)
+					-- qcom,supply-enable-load: load drawn (uA) from enabled supply
+					-- qcom,supply-disable-load: load drawn (uA) from disabled supply
+					-- qcom,supply-pre-on-sleep: time to sleep (ms) before turning on
+					-- qcom,supply-post-on-sleep: time to sleep (ms) after turning on
+					-- qcom,supply-pre-off-sleep: time to sleep (ms) before turning off
+					-- qcom,supply-post-off-sleep: time to sleep (ms) after turning off
+- qcom,platform-enable-gpio:		Specifies the panel lcd/display enable gpio.
+- qcom,platform-reset-gpio:		Specifies the panel reset gpio.
+- qcom,platform-te-gpio:		Specifies the gpio used for TE.
+- qcom,platform-reset-sequence:		An array that lists the
+					sequence of reset gpio values and sleeps
+					Each command will have the format defined
+					as below:
+					--> Reset GPIO value
+					--> Sleep value (in ms)
 
 Example:
         mdss_dsi0: qcom,mdss_dsi@fd922800 {
@@ -37,9 +57,50 @@
 		vdd-supply = <&pm8226_l15>;
 		vddio-supply = <&pm8226_l8>;
 		vdda-supply = <&pm8226_l4>;
-		qcom,supply-names = "vdd", "vddio", "vdda";
-		qcom,supply-min-voltage-level = <2800000 1800000 1200000>;
-		qcom,supply-max-voltage-level = <2800000 1800000 1200000>;
-		qcom,supply-peak-current = <150000 100000 100000>;
+		qcom,platform-strength-ctrl = [ff 06];
+		qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];
+		qcom,platform-regulator-settings = [07 09 03 00 20 00 01];
+		qcom,platform-lane-config = [00 00 00 00 00 00 00 01 97
+			00 00 00 00 05 00 00 01 97
+			00 00 00 00 0a 00 00 01 97
+			00 00 00 00 0f 00 00 01 97
+			00 c0 00 00 00 00 00 01 bb];
 		qcom,mdss-fb-map = <&mdss_fb0>;
+		qcom,platform-reset-gpio = <&msmgpio 25 1>;
+		qcom,platform-te-gpio = <&msmgpio 24 0>;
+		qcom,platform-enable-gpio = <&msmgpio 58 1>;
+		qcom,platform-reset-sequence = <1 25 0 20 1 10>;
+		qcom,platform-supply-entry1 {
+			qcom,supply-name = "vdd";
+			qcom,supply-min-voltage = <2800000>;
+			qcom,supply-max-voltage = <2800000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-pre-on-sleep = <0>;
+			qcom,supply-post-on-sleep = <20>;
+			qcom,supply-pre-off-sleep = <0>;
+			qcom,supply-post-off-sleep = <20>;
+		};
+		qcom,platform-supply-entry2 {
+			qcom,supply-name = "vddio";
+			qcom,supply-min-voltage = <1800000>;
+			qcom,supply-max-voltage = <1800000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-pre-on-sleep = <0>;
+			qcom,supply-post-on-sleep = <30>;
+			qcom,supply-pre-off-sleep = <0>;
+			qcom,supply-post-off-sleep = <30>;
+		};
+		qcom,platform-supply-entry3 {
+			qcom,supply-name = "vdda";
+			qcom,supply-min-voltage = <1200000>;
+			qcom,supply-max-voltage = <1200000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-pre-on-sleep = <0>;
+			qcom,supply-post-on-sleep = <20>;
+			qcom,supply-pre-off-sleep = <0>;
+			qcom,supply-post-off-sleep = <30>;
+		};
         };
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 8c87eac..44134f8 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -12,140 +12,173 @@
 					the panel driver. By default this property will be
 					set to "disable". Will be set to "ok/okay" status
 					for specific platforms.
-- qcom,dsi-ctrl-phandle:		Specifies the phandle for the DSI controller that
+- qcom,mdss-dsi-panel-controller:	Specifies the phandle for the DSI controller that
 					this panel will be mapped to.
-- qcom,mdss-pan-res:			A two dimensional array that specifies the panel
-					resolution.
-- qcom,mdss-pan-bpp:			Specifies the panel bits per pixel. Default value is 24(rgb888).
-					18 = for rgb666
+- qcom,mdss-dsi-panel-width:		Specifies panel width in pixels.
+- qcom,mdss-dsi-panel-height:		Specifies panel height in pixels.
+- qcom,mdss-dsi-bpp:			Specifies the panel bits per pixel.
+					3  = for rgb111
+					8  = for rgb332
+					12 = for rgb444
 					16 = for rgb565
-- qcom,mdss-pan-dest:			A string that specifies the destination display for the panel.
-					Default is "display_1".
+					18 = for rgb666
+					24 = for rgb888
+- qcom,mdss-dsi-panel-destination:	A string that specifies the destination display for the panel.
 					"display_1" = DISPLAY_1
 					"display_2" = DISPLAY_2
-- qcom,panel-phy-regulatorSettings:	An array of length 7 that specifies the PHY
-					regulator settings for the panel.
-- qcom,panel-phy-timingSettings:	An array of length 12 that specifies the PHY
+- qcom,mdss-dsi-panel-timings:		An array of length 12 that specifies the PHY
 					timing settings for the panel.
-- qcom,panel-phy-strengthCtrl:		An array of length 2 that specifies the PHY
-					strengthCtrl settings for the panel.
-- qcom,panel-phy-bistCtrl:		An array of length 6 that specifies the PHY
-					BIST ctrl settings for the panel.
-- qcom,panel-phy-laneConfig:		An array of length 45 that specifies the PHY
-					lane configuration settings for the panel.
-- qcom,mdss-panel-on-cmds:		An array of variable length that lists the init commands
-					of the panel. Each command will have the format specified
-					as below:
-					--> data type of the command
-					--> specifies whether this command packet is last.
-					--> virtual channel
-					--> Needs acknowledge from the panel or not.
-					--> wait time after the command is transmitter.
-					--> size of payload
-					--> payload.
-- qcom,mdss-panel-off-cmds:		An array of variable length that lists the panel off
-					commands. Each command will have the format specified
-					as below:
-					--> data type of the command
-					--> specifies whether this command packet is last.
-					--> virtual channel
-					--> Needs acknowledge from the panel or not.
-					--> wait time after the command is transmitter.
-					--> size of payload
-					--> payload.
+- qcom,mdss-dsi-on-command:		A byte stream formed by multiple dcs packets base on
+					qcom dsi controller protocol.
+					byte 0: dcs data type
+					byte 1: set to indicate this is an individual packet
+						 (no chain)
+					byte 2: virtual channel number
+					byte 3: expect ack from client (dcs read command)
+					byte 4: wait number of specified ms after dcs command
+						 transmitted
+					byte 5, 6: 16 bits length in network byte order
+					byte 7 and beyond: number byte of payload
+- qcom,mdss-dsi-off-command:		A byte stream formed by multiple dcs packets base on
+					qcom dsi controller protocol.
+					byte 0: dcs data type
+					byte 1: set to indicate this is an individual packet
+						 (no chain)
+					byte 2: virtual channel number
+					byte 3: expect ack from client (dcs read command)
+					byte 4: wait number of specified ms after dcs command
+						 transmitted
+					byte 5, 6: 16 bits length in network byte order
+					byte 7 and beyond: number byte of payload
 
 Optional properties:
-- label:		        	A string used as a descriptive name of the panel
-- qcom,enable-gpio:			Specifies the panel lcd/display enable gpio.
-- qcom,rst-gpio:			Specifies the panel reset gpio.
-- qcom,te-gpio:				Specifies the gpio used for TE.
-- qcom,pwm-lpg-channel:			LPG channel for backlight.
-- qcom,pwm-period:			PWM period in microseconds.
-- qcom,pwm-pmic-gpio:			PMIC gpio binding to backlight.
-- qcom,mdss-pan-broadcast-mode:		Boolean used to enable broadcast mode.
+- qcom,mdss-dsi-panel-name:		A string used as a descriptive name of the panel
 - qcom,cont-splash-enabled:		Boolean used to enable continuous splash mode.
-- qcom,fbc-enabled:			Boolean used to enable frame buffer compression mode.
-- qcom,fbc-mode-select:			An array of length 7 that specifies the fbc mode supported
-					by the panel. FBC enabled panels may or may not support
-					the modes specified here. Each entry will
-					have the format specified below:
-					--> compressed bpp supported by the panel
-					--> component packing
-					--> enable/disable quantization error calculation
-					--> Bias for CD
-					--> enable/disable PAT mode
-					--> enable/disable VLC mode
-					--> enable/disable BFLC mode
-- qcom,fbc-budget-ctl:			An array of length 3 that specifies the budget control settings
-					supported by the fbc enabled panel. Each entry will have the format
-					specified below:
-					--> per line extra budget
-					--> extra budget level
-					--> per block budget
-- qcom,fbc-lossy-mode:			An array of 3 that specifies the lossy mode settings
-					supported by the fbc enabled panel. Each entry will
-					have the format specified below:
-					--> lossless mode threshold
-					--> lossy mode threshold
-					--> lossy RGB threshold
-- qcom,mdss-pan-porch-values:		An array of size 6 that specifies the panel blanking values.
-- qcom,mdss-pan-underflow-clr:		Specifies the controller settings for the panel underflow clear
-					settings. Default value is 0xff.
-- qcom,mdss-pan-bl-ctrl:		A string that specifies the implementation of backlight
+- qcom,mdss-dsi-panel-broadcast-mode:	Boolean used to enable broadcast mode.
+- qcom,mdss-dsi-fbc-enable:		Boolean used to enable frame buffer compression mode.
+- qcom,mdss-dsi-fbc-bpp:		Compressed bpp supported by the panel.
+					Specified color order is used as default value.
+- qcom,mdss-dsi-fbc-packing:		Component packing.
+					0 = default value.
+- qcom,mdss-dsi-fbc-quant-error:	Boolean used to enable quantization error calculation.
+- qcom,mdss-dsi-fbc-bias:		Bias for CD.
+					0 = default value.
+- qcom,mdss-dsi-fbc-pat-mode:		Boolean used to enable PAT mode.
+- qcom,mdss-dsi-fbc-vlc-mode:		Boolean used to enable VLC mode.
+- qcom,mdss-dsi-fbc-bflc-mode:		Boolean used to enable BFLC mode.
+- qcom,mdss-dsi-fbc-h-line-budget:	Per line extra budget.
+					0 = default value.
+- qcom,mdss-dsi-fbc-budget-ctrl:		Extra budget level.
+					0 = default value.
+- qcom,mdss-dsi-fbc-block-budget:		Per block budget.
+					0 = default value.
+- qcom,mdss-dsi-fbc-lossless-threshold: Lossless mode threshold.
+					0 = default value.
+- qcom,mdss-dsi-fbc-lossy-threshold:	Lossy mode threshold.
+					0 = default value.
+- qcom,mdss-dsi-fbc-rgb-threshold:	Lossy RGB threshold.
+					0 = default value.
+- qcom,mdss-dsi-fbc-lossy-mode-idx:	Lossy mode index value.
+					0 = default value.
+- qcom,mdss-dsi-h-back-porch:		Horizontal back porch value in pixel.
+					6 = default value.
+- qcom,mdss-dsi-h-front-porch:		Horizontal front porch value in pixel.
+					6 = default value.
+- qcom,mdss-dsi-h-pulse-width:		Horizontal pulse width.
+					2 = default value.
+- qcom,mdss-dsi-h-sync-skew:		Horizontal sync skew value.
+					0 = default value.
+- qcom,mdss-dsi-v-back-porch:		Vertical back porch value in pixel.
+					6 = default value.
+- qcom,mdss-dsi-v-front-porch:		Vertical front porch value in pixel.
+					6 = default value.
+- qcom,mdss-dsi-v-pulse-width:		Vertical pulse width.
+					2 = default value.
+- qcom,mdss-dsi-h-left-border:		Horizontal left border in pixel.
+					0 = default value
+- qcom,mdss-dsi-h-right-border:		Horizontal right border in pixel.
+					0 = default value
+- qcom,mdss-dsi-v-top-border:		Vertical top border in pixel.
+					0 = default value
+- qcom,mdss-dsi-v-bottom-border:	Vertical bottom border in pixel.
+					0 = default value
+- qcom,mdss-dsi-underflow-color:	Specifies the controller settings for the
+					panel under flow color.
+					0xff = default value.
+- qcom,mdss-dsi-border-color:		Defines the border color value if border is present.
+					0 = default value.
+- qcom,mdss-dsi-bl-pmic-control-type:	A string that specifies the implementation of backlight
 					control for this panel.
 					"bl_ctrl_pwm" = Backlight controlled by PWM gpio.
 					"bl_ctrl_wled" = Backlight controlled by WLED.
-					"bl_ctrl_dcs_cmds" = Backlight controlled by DCS commands.
-- qcom,mdss-pan-bl-levels:		Specifies the backlight levels supported by the panel.
-					Default range is 1 to 255.
-
-- qcom,mdss-pan-dsi-mode:		Specifies the panel operating mode.
-					0 = enable video mode(default mode).
-					1 = enable command mode.
-- qcom,mdss-vsync-enable:		Specifies Tear Check configuration.
-					0 = TE disable.
-					1 = TE enable.
-- qcom,mdss-hw-vsync-mode:		Specifies TE type.
-					0 = software vsync.
-					1 = hardware vsync (TE gpio pin).
-- qcom,mdss-pan-te-sel:			Specifies TE operating mode.
+					"bl_ctrl_dcs" = Backlight controlled by DCS commands.
+					other: Unknown backlight control. (default)
+- qcom,mdss-dsi-bl-pmic-bank-select:	LPG channel for backlight.
+					Requred if blpmiccontroltype is PWM
+- qcom,mdss-dsi-bl-pmic-pwm-frequency:	PWM period in microseconds.
+					Requred if blpmiccontroltype is PWM
+- qcom,mdss-dsi-pwm-gpio:		PMIC gpio binding to backlight.
+					Requred if blpmiccontroltype is PWM
+- qcom,mdss-dsi-bl-min-level:		Specifies the min backlight level supported by the panel.
+					0 = default value.
+- qcom,mdss-dsi-bl-max-level:		Specifies the max backlight level supported by the panel.
+					255 = default value.
+- qcom,mdss-dsi-interleave-mode:	Specifies interleave mode.
+					0 = default value.
+- qcom,mdss-dsi-panel-type:		Specifies the panel operating mode.
+					"dsi_video_mode" = enable video mode (default).
+					"dsi_cmd_mode" = enable command mode.
+- qcom,mdss-dsi-te-check-enable:	Boolean to enable Tear Check configuration.
+- qcom,mdss-dsi-te-using-te-pin:	Boolean to specify whether using hardware vsync.
+- qcom,mdss-dsi-te-pin-select:		Specifies TE operating mode.
 					0 = TE through embedded dcs command
-					1 = TE through TE gpio pin.
-- qcom,mdss-pan-dsi-h-pulse-mode:	Specifies the pulse mode option for the panel.
+					1 = TE through TE gpio pin. (default)
+- qcom,mdss-dsi-te-dcs-command:		Inserts the dcs command.
+					1 = default value.
+- qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line:	Configures the scan line number that the dsi
+					pixel transfer will start on. Rasing this number
+					will result in delaying the start of the pixel
+					transfer.
+					0x2c = default value.
+- qcom,mdss-dsi-te-v-sync-continue-lines:	Represents the difference in number of lines
+					between estimated read pointer and write pointer
+					to allow the updating of all the lines except
+					the first line of the frame.
+					0x3c = default value.
+- qcom,mdss-dsi-h-sync-pulse:		Specifies the pulse mode option for the panel.
 					0 = Don't send hsa/he following vs/ve packet(default)
 					1 = Send hsa/he following vs/ve packet
-- qcom,mdss-pan-dsi-h-power-stop:	An Array of size 3 that specifies the power mode
-					during horizontal porch and sync periods of the panel.
-					0 = high speed mode(default mode).
-					1 = Low power mode for horizontal porches and sync pulse.
-- qcom,mdss-pan-dsi-bllp-power-stop:	An Array of size 2 that specifies the power mode
-					during blanking period and after EOF(end of frame).
-					0 = high speed mode(default mode).
-					1 = Low power mode during blanking and EOF.
-- qcom,mdss-pan-dsi-traffic-mode:	Specifies the panel traffic mode.
+- qcom,mdss-dsi-hfp-power-mode:		Boolean to determine DSI lane state during
+					horizontal front porch (HFP) blanking period.
+- qcom,mdss-dsi-hbp-power-mode:		Boolean to determine DSI lane state during
+					horizontal back porch (HBP) blanking period.
+- qcom,mdss-dsi-hsa-power-mode:		Boolean to determine DSI lane state during
+					horizontal sync active (HSA) mode.
+- qcom,mdss-dsi-bllp-eof-power-mode:	Boolean to determine DSI lane state during
+					blanking low power period (BLLP) EOF mode.
+- qcom,mdss-dsi-bllp-power-mode:	Boolean to determine DSI lane state during
+					blanking low power period (BLLP) mode.
+- qcom,mdss-dsi-traffic-mode:		Specifies the panel traffic mode.
 					0 = non burst with sync pulses (default mode).
 					1 = non burst with sync start event.
 					2 = burst mode.
-- qcom,mdss-pan-dsi-dst-format:		Specifies the destination format.
-					0 = DSI_VIDEO_DST_FORMAT_RGB565.
-					1 = DSI_VIDEO_DST_FORMAT_RGB666.
-					2 = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE.
-					3 = DSI_VIDEO_DST_FORMAT_RGB888 (Default format)
-					6 = DSI_CMD_DST_FORMAT_RGB565
-					7 = DSI_CMD_DST_FORMAT_RGB666
-					8 = DSI_CMD_DST_FORMAT_RGB888
-- qcom,mdss-pan-dsi-vc:			Specifies the virtual channel identefier.
+- qcom,mdss-dsi-pixel-packing:		Specifies if pixel packing is used (in case of RGB666).
+					0 = Tight packing (default value).
+					1 = Loose packing.
+- qcom,mdss-dsi-virtual-channel-id:	Specifies the virtual channel identefier.
 					0 = default value.
-- qcom,mdss-pan-dsi-rgb-swap:		Specifies the R, G and B channel ordering.
+- qcom,mdss-dsi-color-order:		Specifies the R, G and B channel ordering.
 					0 = DSI_RGB_SWAP_RGB (default value)
 					1 = DSI_RGB_SWAP_RBG
 					2 = DSI_RGB_SWAP_BGR
 					3 = DSI_RGB_SWAP_BRG
 					4 = DSI_RGB_SWAP_GRB
 					5 = DSI_RGB_SWAP_GBR
-- qcom,mdss-pan-dsi-data-lanes:		An array that specifies the data lanes enabled.
-					<1 1 0 0> = data lanes 1 and 2 are enabled.(default).
-- qcom,mdss-pan-dsi-dlane-swap:		Specifies the data lane swap configuration.
+- qcom,mdss-dsi-lane-0-state:		Boolean that specifies whether data lane 0 is enabled.
+- qcom,mdss-dsi-lane-1-state:		Boolean that specifies whether data lane 1 is enabled.
+- qcom,mdss-dsi-lane-2-state:		Boolean that specifies whether data lane 2 is enabled.
+- qcom,mdss-dsi-lane-3-state:		Boolean that specifies whether data lane 3 is enabled.
+- qcom,mdss-dsi-lane-map:		Specifies the data lane swap configuration.
 					0 = <0 1 2 3> (default value)
 					1 = <3 0 1 2>
 					2 = <2 3 0 1>
@@ -154,79 +187,121 @@
 					5 = <1 0 3 2>
 					6 = <2 1 0 3>
 					7 = <3 2 1 0>
-- qcom,mdss-pan-dsi-t-clk:		An array that specifies the byte clock cycles
-					before and after each mode switch.
-- qcom,mdss-pan-dsi-stream:		Specifies the packet stream to be used.
+- qcom,mdss-dsi-t-clk-post:		Specifies the byte clock cycles after mode switch.
+					0x03 = default value.
+- qcom,mdss-dsi-t-clk-pre:		Specifies the byte clock cycles before mode switch.
+					0x24 = default value.
+- qcom,mdss-dsi-stream:			Specifies the packet stream to be used.
 					0 = stream 0 (default)
 					1 = stream 1
-- qcom,mdss-pan-dsi-mdp-tr:		Specifies the trigger mechanism to be used for MDP path.
+- qcom,mdss-dsi-mdp-trigger:		Specifies the trigger mechanism to be used for MDP path.
 					0 = no trigger
 					2 = Tear check signal line used for trigger
-					4 = Triggered by software (default mode)
+					4 = Triggered by software (default)
 					6 = Software trigger and TE
-- qcom,mdss-pan-dsi-dma-tr:		Specifies the trigger mechanism to be used for DMA path.
+- qcom,mdss-dsi-dma-trigger:		Specifies the trigger mechanism to be used for DMA path.
 					0 = no trigger
 					2 = Tear check signal line used for trigger
-					4 = Triggered by software (default mode)
+					4 = Triggered by software (default)
 					5 = Software trigger and start/end of frame trigger.
 					6 = Software trigger and TE
-- qcom,mdss-pan-dsi-frame-rate:		Specifies the frame rate for the panel.
+- qcom,mdss-dsi-panel-framerate:	Specifies the frame rate for the panel.
 					60 = 60 frames per second (default)
-- qcom,on-cmds-dsi-state:		A string that Specifies the ctrl state for sending ON commands.
-					Supported modes are "DSI_LP_MODE" and "DSI_HS_MODE".
-- qcom,off-cmds-dsi-state:		A string that Specifies the ctrl state for sending ON commands.
-					Supported modes are "DSI_LP_MODE" and "DSI_HS_MODE".
+- qcom,mdss-dsi-panel-clockrate:	Specifies the panel clock speed in Hz.
+					0 = default value.
+- qcom,mdss-dsi-on-command-state:	String that specifies the ctrl state for sending ON commands.
+					"dsi_lp_mode" = DSI low power mode (default)
+					"dsi_hs_mode" = DSI high speed mode
+- qcom,mdss-dsi-off-command-state:	String that specifies the ctrl state for sending OFF commands.
+					"dsi_lp_mode" = DSI low power mode (default)
+					"dsi_hs_mode" = DSI high speed mode
 
 
-- qcom,panel-on-cmds: 			A byte stream formed by multiple dcs packets base on
-					qcom dsi controller protocol.
-					byte 0 : dcs data type
-					byte 1 : set to indicate this is an individual packet
-						(no chain).
-					byte 2 : virtual channel number
-					byte 3 : expect ack from client (dcs read command)
-					byte 4 : wait number of specified ms after dcs command
-						transmitted
-					byte 5, 6: 16 bits length in network byte order
-					byte 7 and beyond: number byte of payload
-
 Note, if a given optional qcom,* binding is not present, then the driver will configure
 the default values specified.
 
 Example:
-/ {
+&soc {
 	qcom,mdss_dsi_sim_video {
 		compatible = "qcom,mdss-dsi-panel";
-		label = "simulator video mode dsi panel";
+		qcom,mdss-dsi-panel-name = "simulator video mode dsi panel";
 		status = "disable";
-		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
-		qcom,mdss-pan-res = <640 480>;
-		qcom,mdss-pan-bpp = <24>;
-		qcom,mdss-pan-dest = "display_1";
-		qcom,mdss-pan-porch-values = <6 2 6 6 2 6>;
-		qcom,mdss-pan-underflow-clr = <0xff>;
-		qcom,mdss-pan-bl-levels = <1 15>;
-		qcom,mdss-pan-dsi-mode = <0>;
-		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
-		qcom,mdss-pan-dsi-h-power-stop = <1 1 1>;
-		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
-		qcom,mdss-pan-dsi-traffic-mode = <0>;
-		qcom,mdss-pan-dsi-dst-format = <3>;
-		qcom,mdss-pan-dsi-vc = <0>;
-		qcom,mdss-pan-dsi-rgb-swap = <0>;
-		qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
-		qcom,mdss-pan-dsi-t-clk = <0x24 0x03>;
-		qcom,mdss-pan-dsi-stream = <0>;
-		qcom,mdss-pan-dsi-mdp-tr = <0x04>;
-		qcom,mdss-pan-dsi-dma-tr = <0x04>;
-		qcom,mdss-pan-frame-rate = <60>;
-		qcom,panel-on-cmds = [32 01 00 00 00 00 02 00 00];
-		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [22 01 00 00 00 00 00];
-		qcom,off-cmds-dsi-state = "DSI LP MODE";
-		qcom,fbc-enabled;
-		qcom,fbc-mode = <12 0 1 2 1 1 1>;
-		qcom,fbc-budget-ctl = <675 5 91>;
-		qcom,fbc-lossy-mode = <0 0xc0 0 3>;
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-panel-width = <720>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-pixel-packing = <0>;
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-broadcast-mode;
+		qcom,mdss-dsi-fbc-enable;
+		qcom,mdss-dsi-fbc-bpp = <0>;
+		qcom,mdss-dsi-fbc-packing = <0>;
+		qcom,mdss-dsi-fbc-quant-error;
+		qcom,mdss-dsi-fbc-bias = <0>;
+		qcom,mdss-dsi-fbc-pat-mode;
+		qcom,mdss-dsi-fbc-vlc-mode;
+		qcom,mdss-dsi-fbc-bflc-mode;
+		qcom,mdss-dsi-fbc-h-line-budget = <0>;
+		qcom,mdss-dsi-fbc-budget-ctrl = <0>;
+		qcom,mdss-dsi-fbc-block-budget = <0>;
+		qcom,mdss-dsi-fbc-lossless-threshold = <0>;
+		qcom,mdss-dsi-fbc-lossy-threshold = <0>;
+		qcom,mdss-dsi-fbc-rgb-threshold = <0>;
+		qcom,mdss-dsi-fbc-lossy-mode-idx = <0>;
+		qcom,mdss-dsi-h-front-porch = <140>;
+		qcom,mdss-dsi-h-back-porch = <164>;
+		qcom,mdss-dsi-h-pulse-width = <8>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <6>;
+		qcom,mdss-dsi-v-front-porch = <1>;
+		qcom,mdss-dsi-v-pulse-width = <1>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = < 15>;
+		qcom,mdss-dsi-interleave-mode = <0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-te-check-enable;
+		qcom,mdss-dsi-te-using-te-pin;
+		qcom,mdss-dsi-te-dcs-command = <1>;
+		qcom,mdss-dsi-te-v-sync-continue-lines = <0x3c>;
+		qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line = <0x2c>;
+		qcom,mdss-dsi-te-pin-select = <1>;
+		qcom,mdss-dsi-h-sync-pulse = <1>;
+		qcom,mdss-dsi-hfp-power-mode;
+		qcom,mdss-dsi-hbp-power-mode;
+		qcom,mdss-dsi-hsa-power-mode;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-traffic-mode = <0>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-color-order = <0>;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-lane-2-state;
+		qcom,mdss-dsi-lane-3-state;
+		qcom,mdss-dsi-lane-map = <0>;
+		qcom,mdss-dsi-t-clk-post = <0x20>;
+		qcom,mdss-dsi-t-clk-pre = <0x2c>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-mdp-trigger = <0>;
+		qcom,mdss-dsi-dma-trigger = <0>;
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-panel-clockrate = <424000000>;
+		qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33
+					22 27 1e 03 04 00];
+		qcom,mdss-dsi-on-command = [32 01 00 00 00 00 02 00 00
+					29 01 00 00 10 00 02 FF 99];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command = [22 01 00 00 00 00 00];
+		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+		qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+		qcom,mdss-dsi-bl-pmic-pwm-frequency = <0>;
+		qcom,mdss-dsi-pwm-gpio = <&pm8941_mpps 5 0>;
 	};
 };
diff --git a/Documentation/devicetree/bindings/fb/mdss-edp.txt b/Documentation/devicetree/bindings/fb/mdss-edp.txt
index 578b07c..3d7e5a2 100644
--- a/Documentation/devicetree/bindings/fb/mdss-edp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-edp.txt
@@ -20,6 +20,7 @@
 						specific platforms.
 - qcom,mdss-fb-map:			pHandle that specifies the framebuffer to which the
 					interface is mapped.
+- gpio-panel-hpd :			gpio pin use for edp hpd
 
 Example:
 	mdss_edp: qcom,mdss_edp@fd923400 {
@@ -32,6 +33,8 @@
 		qcom,panel-lpg-channel = <7>; /* LPG Channel 8 */
 		qcom,panel-pwm-period = <53>;
 		status = "disable";
+		qcom,mdss-fb-map = <&mdss_fb0>;
+		gpio-panel-hpd = <&msmgpio 102 0>;
 	};
 
 
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 514160e..7ba9a88 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -126,6 +126,11 @@
 - qcom,mdss-has-wfd-blk: Boolean property to indicate the presence of dedicated
 			writeback wfd block in MDSS as opposed to writeback
 			block that is shared between rotator and wfd.
+- qcom,mdss-smp-mb-per-pipe:	Maximum number of shared memory pool blocks
+				restricted for a source surface pipe. If this
+				property is not specified, no such restriction
+				would be applied.
+
 Optional subnodes:
 Child nodes representing the frame buffer virtual devices.
 
@@ -135,8 +140,20 @@
 - qcom,mdss-mixer-swap: A boolean property that indicates if the mixer muxes
 			 need to be swapped based on the target panel.
 			 By default the property is not defined.
+- qcom,mdss-fb-split:	 Array of splitted framebuffer size. There should
+			 be only two values in this property. The values
+			 correspond to the left and right size respectively.
+			 MDP muxes two mixer output together before sending to
+			 the panel interface and these values are used to set
+			 each mixer width, so the sum of these two values
+			 should be equal to the panel x-resolution.
 
-
+			 Note that if the sum of two values is not equal to
+			 x-resolution or this subnode itself is not defined
+			 in device tree there are two cases: 1)split is not
+			 enabled if framebuffer size is less than max mixer
+			 width; 2) the defaut even split is enabled if frambuffer
+			 size is greater than max mixer width.
 
 Example:
 	qcom,mdss_mdp@fd900000 {
@@ -161,6 +178,7 @@
 		qcom,mdss-pipe-dma-fetch-id = <10 13>;
 		qcom,mdss-smp-data = <22 4096>;
 		qcom,mdss-rot-block-size = <64>;
+		qcom,mdss-smp-mb-per-pipe = <2>;
 		qcom,mdss-has-bwc;
 		qcom,mdss-has-decimation;
 		qcom,mdss-has-wfd-blk;
@@ -181,6 +199,7 @@
 			cell-index = <0>;
 			compatible = "qcom,mdss-fb";
 			qcom,mdss-mixer-swap;
+			qcom,mdss-fb-split = <480 240>
 		};
 	};
 
diff --git a/Documentation/devicetree/bindings/input/misc/bmp180.txt b/Documentation/devicetree/bindings/input/misc/bmp180.txt
new file mode 100644
index 0000000..13e0839
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/bmp180.txt
@@ -0,0 +1,35 @@
+Bosch BMP18x-series altimeter driver
+
+Required properties:
+
+ - compatible			: Should be "bosch,bmp180".
+ - reg					: i2c slave address of the device.
+ - vdd-supply		: Analog power supply needed to power device.
+ - vddio-supply		: Digital IO power supply needed for IO and I2C.
+ - bosch,chip-id		: Chip id for the bmp18x altimeter sensor.
+ - bosch,oversample	: Sensor default oversampling value.
+				Default oversampling value to be used at startup.
+				Value range is 0-3 with rising sensitivity.
+ - bosch,period	: Temperature measurement period (milliseconds).
+				Set to zero if unsure.
+
+Optional properties:
+
+ - bosch,sw-oversample	: Boolean to enable software oversampling if
+				this property is defined. Only take effect when
+				default_oversampling is 3.
+
+Example:
+	i2c@f9925000 {
+		bmp180@77 {
+			status = "okay";
+			reg = <0x77>;
+			compatible = "bosch,bmp180";
+			vdd-supply = <&pm8110_l19>;
+			vddio-supply = <&pm8110_l14>;
+			bosch,chip-id = <0x55>;
+			bosch,oversample = <3>;
+			bosch,period = <1000>;
+			bosch,sw-oversample;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/input/misc/mma8x5x.txt b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
new file mode 100644
index 0000000..854939c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
@@ -0,0 +1,39 @@
+Freescale MMA8x5x 3-Axis Orientation/Motion Detection Sensor series
+(MMA8451/MMA8452/MMA8453/MMA8652/MMA8653)
+
+The Freescale 3-Axis Orientation/Motion Detection Sensor is
+connected to host processor via i2c.
+The sensor can be polling for acceleration data or configure to
+generates interrupts when a motion is detected.
+
+Required properties:
+
+ - compatible		: should be "fsl,mma8x5x"
+ - reg			: i2c slave address of the device
+ - vdd-supply : power supply needed to power up the device.
+ - vio-supply	: power supply needed for device IO and to pullup i2c bus.
+ - fsl,sensors-position	: select from 0 to 7 depends on how the sensor is
+				 mounting on the board, this will decide how the 3-axis reading
+				 of data will be translated to X/Y/Z axis of acceleration data.
+
+Optional properties:
+ Sensor can work on polling mode or interrupt mode, following interrupt
+ is required if the sensor need to work on interrupt mode.
+ - interrupt-parent	: parent of interrupt.
+ - interrupts		: sensor signal interrupt to indicate new data ready or
+				 a motion is detected.
+ - fsl,irq-gpio	: First irq gpio which is to provide interrupts to host, same
+				 as "interrupts" node. It will also contain active low or active
+				 high information.
+
+Example:
+	fsl@1c {
+		compatible = "fsl,mma8x5x";
+		reg = <0x1c>;
+		interrupt-parent = <&msmgpio>;
+		interrupts = <81 0x2>;
+		vdd-supply = <&pm8110_l19>;
+		vio-supply = <&pm8110_l14>;
+		fsl,sensors-position = <5>;
+		fsl,irq-gpio = <&msmgpio 0x81 0x02>;
+	};
\ No newline at end of file
diff --git a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
index 6fe88a9..4c6ae93 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
@@ -35,6 +35,8 @@
 					needed during wakeup.
  - atmel,no-force-update	: flag that signifies whether force configuration
 					update is applicable or not
+ - atmel,no-lpm-support		: flag that signifies whether low power mode is
+					supported or not on this platform
 
 Example:
 	i2c@f9966000 {
diff --git a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
index 0f35e73..3720172 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
@@ -20,6 +20,7 @@
  - synaptics,panel-x		: panel x dimension
  - synaptics,panel-y		: panel y dimension
  - synaptics,fw-image-name	: name of firmware .img file in /etc/firmware
+ - synaptics,power-down		: fully power down regulators in suspend
 
 Example:
 	i2c@f9927000 { /* BLSP1 QUP5 */
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index ff95d43..b60760e 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -81,7 +81,9 @@
 - qcom,source-sel: select power source, default 1 (enabled)
 - qcom,mode-ctrl: select operation mode, default 0x60 = Mode Sink
 - qcom,mode: mode the led should operate in, options "pwm", "lpg" and "manual"
+- qcom,vin-ctrl: select input source, supported values are 0 to 3
 - qcom,use-blink: Use blink sysfs entry for switching into lpg mode.  For optimal use, set default mode to pwm.  All required lpg parameters must be supplied.
+- qcom,min-brightness - Lowest possible brightness supported on this LED other than 0.
 
 Required properties for PWM mode only:
 - qcom,pwm-channel: pwm channel the led will operate on
@@ -105,10 +107,13 @@
 - qcom,mode: mode the led should operate in, options "pwm" and "lpg"
 - qcom,pwm-channel: pwm channel the led will operate on
 - qcom,pwm-us: time the pwm device will modulate at (us)
-- qcom,row-src-sel-val: select source for rows. One bit is used for each row.
-			Specify 0 for vph_pwr and 1 for vbst for each row.
-- qcom,row-scan-val: select rows for scanning
-- qcom,row-scan-en: row scan enable
+- qcom,row-id: specify the id of the row. Supported values are 0 to 3.
+
+Optional properties for keypad backlight:
+- qcom,row-src-vbst: select source for rows. Specify for vbst and ignore it
+			for vph_pwr.
+- qcom,row-src-en: specify to enable row source
+- qcom,always-on: specify if the module has to be always on
 
 Required properties for PWM mode only:
 - qcom,pwm-us: time the pwm device will modulate at (us)
@@ -136,6 +141,8 @@
 			qcom,id = <6>;
 			qcom,source-sel = <1>;
 			qcom,mode-ctrl = <0x10>;
+			qcom,vin-ctrl = <0x03>;
+			qcom,min-brightness = <20>;
 		};
 	};
 
@@ -255,16 +262,33 @@
 
 	qcom,leds@e200 {
 		status = "okay";
-		qcom,kpdbl {
+
+		qcom,kpdbl1 {
 			label = "kpdbl";
-			linux,name = "button-backlight";
+			linux,name = "kpdbl-pwm-1";
 			qcom,mode = <0>;
 			qcom,pwm-channel = <8>;
 			qcom,pwm-us = <1000>;
 			qcom,id = <7>;
 			qcom,max-current = <20>;
-			qcom,row-src-sel-val = <0x00>;
-			qcom,row-scan-en = <0x01>;
-			qcom,row-scan-val = <0x01>;
+			qcom,row-id = <0>;
+			qcom,row-src-en;
+			qcom,always-on;
 		};
+
+		qcom,kpdbl2 {
+			label = "kpdbl";
+			linux,name = "kpdbl-lut-2";
+			qcom,mode = <1>;
+			qcom,pwm-channel = <9>;
+			qcom,pwm-us = <1000>;
+			qcom,start-idx = <1>;
+			qcom,duty-pcts = [00 00 00 00 64
+					64 00 00 00 00];
+			qcom,id = <7>;
+			qcom,max-current = <20>;
+			qcom,row-id = <1>;
+			qcom,row-src-en;
+		};
+
 	};
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index 583fbfa..b8156c3 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -18,6 +18,17 @@
     qcom,gpio-req-tbl-num property (in the same order)
 - qcom,gpio-req-tbl-label : should contain name of gpios present in
     qcom,gpio-req-tbl-num property (in the same order)
+
+Optional properties:
+- master0: qcom,cci-master0 - node should contain clock settings for
+    cci master 0 bus
+- master1: qcom,cci-master1 - node should contain clock settings for
+    cci master 1 bus
+
+[Second level nodes]
+* Qualcomm CCI clock settings
+
+Optional properties:
 - qcom,hw-thigh : should contain high period of the SCL clock in terms of CCI
     clock cycle
 - qcom,hw-tlow : should contain high period of the SCL clock in terms of CCI
@@ -31,7 +42,6 @@
 - qcom,hw-trdhld : should contain internal hold time for SDA
 - qcom,hw-tsp : should contain filtering of glitches
 
-[Second level nodes]
 * Qualcomm MSM Sensor
 
 MSM sensor node contains properties of camera sensor
@@ -95,6 +105,11 @@
     #gpio-cells specifying specific gpio (controller specific)
 - qcom,gpio-reset : should contain index to gpio used by sensors reset_n
 - qcom,gpio-standby : should contain index to gpio used by sensors standby_n
+- qcom,gpio-vio : should contain index to gpio used by sensors io vreg enable
+- qcom,gpio-vana : should contain index to gpio used by sensors analog vreg enable
+- qcom,gpio-vdig : should contain index to gpio used by sensors digital vreg enable
+- qcom,gpio-vaf : should contain index to gpio used by sensors af vreg enable
+- qcom,gpio-af-pwdm : should contain index to gpio used by sensors af pwdm_n
 - qcom,gpio-req-tbl-num : should contain index to gpios specific to this sensor
 - qcom,gpio-req-tbl-flags : should contain direction of gpios present in
     qcom,gpio-req-tbl-num property (in the same order)
@@ -170,16 +185,12 @@
                              "CCI_I2C_CLK0",
                              "CCI_I2C_DATA1",
                              "CCI_I2C_CLK1";
-       qcom,hw-thigh = <78>;
-       qcom,hw-tlow = <114>;
-       qcom,hw-tsu-sto = <28>;
-       qcom,hw-tsu-sta = <28>;
-       qcom,hw-thd-dat = <10>;
-       qcom,hw-thd-sta = <77>;
-       qcom,hw-tbuf = <118>;
-       qcom,hw-scl-stretch-en = <0>;
-       qcom,hw-trdhld = <6>;
-       qcom,hw-tsp = <1>;
+       master0: qcom,cci-master0 {
+                status = "disabled";
+       };
+       master1: qcom,cci-master1 {
+                status = "disabled";
+       };
 
         actuator0: qcom,actuator@18 {
                 cell-index = <0>;
@@ -230,3 +241,31 @@
                qcom,sensor-mode = <1>;
        };
    };
+
+   &master0 {
+           qcom,hw-thigh = <78>;
+           qcom,hw-tlow = <114>;
+           qcom,hw-tsu-sto = <28>;
+           qcom,hw-tsu-sta = <28>;
+           qcom,hw-thd-dat = <10>;
+           qcom,hw-thd-sta = <77>;
+           qcom,hw-tbuf = <118>;
+           qcom,hw-scl-stretch-en = <0>;
+           qcom,hw-trdhld = <6>;
+           qcom,hw-tsp = <1>;
+           status = "ok";
+   };
+
+   &master1 {
+           qcom,hw-thigh = <78>;
+           qcom,hw-tlow = <114>;
+           qcom,hw-tsu-sto = <28>;
+           qcom,hw-tsu-sta = <28>;
+           qcom,hw-thd-dat = <10>;
+           qcom,hw-thd-sta = <77>;
+           qcom,hw-tbuf = <118>;
+           qcom,hw-scl-stretch-en = <0>;
+           qcom,hw-trdhld = <6>;
+           qcom,hw-tsp = <1>;
+           status = "ok";
+   };
diff --git a/Documentation/devicetree/bindings/pil/pil-pronto.txt b/Documentation/devicetree/bindings/pil/pil-pronto.txt
index 85ccc5d..2cbf22c 100644
--- a/Documentation/devicetree/bindings/pil/pil-pronto.txt
+++ b/Documentation/devicetree/bindings/pil/pil-pronto.txt
@@ -13,6 +13,8 @@
 - interrupts: WCNSS to Apps watchdog bite interrupt
 - vdd_pronto_pll-supply: regulator to supply pronto pll.
 - qcom,firmware-name: Base name of the firmware image. Ex. "wcnss"
+
+Optional properties:
 - qcom,gpio-err-fatal: GPIO used by the wcnss to indicate error fatal to the Apps.
 - qcom,gpio-err-ready: GPIO used by the wcnss to indicate error ready to the Apps.
 - qcom,gpio-proxy-unvote: GPIO used by the wcnss to trigger proxy unvoting in
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
index a7a3f0c..d32279d 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
@@ -14,14 +14,14 @@
 - interrupts:         The lpass watchdog interrupt
 - vdd_cx-supply:      Reference to the regulator that supplies the vdd_cx domain.
 - qcom,firmware-name: Base name of the firmware image. Ex. "lpass"
-- qcom,gpio-err-fatal: GPIO used by the lpass to indicate error fatal to the apps.
-- qcom,gpio-err-ready: GPIO used by the lpass to indicate apps error service is ready.
-- qcom,gpio-force-stop: GPIO used by the apps to force the lpass to shutdown.
-- qcom,gpio-proxy-unvote: GPIO used by the lpass to indicate apps clock is ready.
 
 Optional properties:
 - vdd_pll-supply:     Reference to the regulator that supplies the PLL's rail.
 - qcom,vdd_pll:       Voltage to be set for the PLL's rail.
+- qcom,gpio-err-fatal: GPIO used by the lpass to indicate error fatal to the apps.
+- qcom,gpio-err-ready: GPIO used by the lpass to indicate apps error service is ready.
+- qcom,gpio-proxy-unvote: GPIO used by the lpass to indicate apps clock is ready.
+- qcom,gpio-force-stop: GPIO used by the apps to force the lpass to shutdown.
 
 Example:
 	qcom,lpass@fe200000 {
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index d6980ac..0a3789a 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -15,13 +15,6 @@
 - vdd_cx-supply:      Reference to the regulator that supplies the vdd_cx domain.
 - vdd_mx-supply:      Reference to the regulator that supplies the memory rail.
 - qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
-- qcom,gpio-err-fatal: GPIO used by the modem to indicate error fatal to the apps.
-- qcom,gpio-err-ready: GPIO used by the modem to indicate error ready to the apps.
-- qcom,gpio-proxy-unvote: GPIO used by the modem to trigger proxy unvoting in
-  the apps.
-- qcom,gpio-force-stop: GPIO used by the apps to force the modem to shutdown.
-- qcom,gpio-stop-ack: GPIO used by the modem to ack force stop or a graceful stop
-		      to the apps.
 
 Optional properties:
 - vdd_mss-supply:     Reference to the regulator that supplies the processor.
@@ -35,6 +28,13 @@
 - qcom,is-not-loadable: Boolean- Present if the image does not need to
 			be loaded.
 - qcom,pil-self-auth: Boolean- True if authentication is required.
+- qcom,gpio-err-fatal: GPIO used by the modem to indicate error fatal to the apps.
+- qcom,gpio-err-ready: GPIO used by the modem to indicate error ready to the apps.
+- qcom,gpio-proxy-unvote: GPIO used by the modem to trigger proxy unvoting in
+  the apps.
+- qcom,gpio-force-stop: GPIO used by the apps to force the modem to shutdown.
+- qcom,gpio-stop-ack: GPIO used by the modem to ack force stop or a graceful stop
+		      to the apps.
 
 Example:
 	qcom,mss@fc880000 {
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 3cac311..0672f14 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -13,6 +13,11 @@
 		to determine whether the BMS is using an internal or external
 		rsense to accumulate the Coulomb Counter and read current.
 
+Additionally, an optional subnode may be included:
+- qcom,battery-data : A phandle to a node containing the available batterydata
+		profiles. See the batterydata bindings documentation for more
+		details.
+
 Parent node required properties:
 - compatible : should be "qcom,qpnp-bms" for the BM driver.
 - qcom,r-sense-uohm : sensor resistance in in micro-ohms.
@@ -77,6 +82,10 @@
 			number of the FCC measurement cycles required to
 			generate an FCC update. This is applicable only
 			if the FCC learning is enabled.
+- qcom,fcc-resolution:	An integer which defines the fcc resolution used
+			for storing the FCC(mAh) in the 8-bit BMS register.
+			For example - A value of 10 indicates:
+			FCC value (in mAh) = (8-bit register value) * 10.
 
 Parent node optional properties:
 - qcom,ignore-shutdown-soc: A boolean that controls whether BMS will
@@ -138,6 +147,7 @@
 	qcom,high-ocv-correction-limit-uv = <50>;
 	qcom,hold-soc-est = <3>;
 	qcom,tm-temp-margin = <5000>;
+	qcom,battery-data = <&mtp_batterydata>;
 
 	qcom,bms-iadc@3800 {
 		reg = <0x3800 0x100>;
diff --git a/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt b/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt
index 83ce3f8..95be46c 100644
--- a/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt
@@ -11,17 +11,10 @@
 
 Required device bindings:
 - compatible:		should be "qcom,qpnp-pwm"
-- reg:			Offset and length of the controller's LPG channel register,
-			and LPG look-up table (LUT). The LPG look-up table is a
-			contiguous address space that is populated with PWM values.
-			The size of PWM value is 9 bit and the size of each
-			entry of the table is 8 bit. Thus, two entries are used
-			to fill each PWM value. The lower entry is used for PWM
-			LSB byte and higher entry is used for PWM MSB bit.
-- reg-names:		Names for the above registers.
+- reg:			Offset and length of the controller's LPG channel register.
+- reg-names:		Name for the above register.
 			"qpnp-lpg-channel-base" = physical base address of the
 			controller's LPG channel register.
-			"qpnp-lpg-lut-base" = physical base address of LPG LUT.
 - qcom,channel-id:	channel Id for the PWM.
 
 Optional device bindings:
@@ -52,12 +45,20 @@
 duty cycle percentages is populated. The size of the list cannot exceed
 the size of the LPG look-up table.
 
-- qcom,period:			PWM period time in microseconds.
-- qcom,duty-percents:		List of entries for look-up table
-- cell-index:			Index of look-up table that should be used to start
-				filling up the duty-pct list. start-idx + size of list
-				cannot exceed the size of look-up table.
-- label:			"lpg"
+- reg:			Offset and length of LPG look-up table (LUT). The LPG look-up table is a
+			contiguous address space that is populated with PWM values.
+			The size of PWM value is 9 bit and the size of each
+			entry of the table is 8 bit. Thus, two entries are used
+			to fill each PWM value. The lower entry is used for PWM
+			LSB byte and higher entry is used for PWM MSB bit.
+- reg-names:		Name for the above register.
+			"qpnp-lpg-lut-base" = physical base address of LPG LUT.
+- qcom,period:		PWM period time in microseconds.
+- qcom,duty-percents:	List of entries for look-up table
+- cell-index:		Index of look-up table that should be used to start
+			filling up the duty-pct list. start-idx + size of list
+			cannot exceed the size of look-up table.
+- label:		"lpg"
 
 
 Optional bindings to support LPG feature:
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index c799ffb..b618597 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -661,7 +661,9 @@
 		 prim-gpio-tert : Primary AUXPCM shares GPIOs with Tertiary MI2S
 
 Optional Properties:
-- qcom,us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
+- qcom,cdc-us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
+- qcom,cdc-lineout-spkr-gpios : GPIO which controls external PAs to enable Lineout1/2 speaker
+- qcom,cdc-vdd-spkr-gpios : GPIO which controls PA for VDD speaker
 
 Example:
 
@@ -675,4 +677,6 @@
 	qcom,prim-auxpcm-gpio-dout = <&msmgpio 66 0>;
 	qcom,prim-auxpcm-gpio-set = "prim-gpio-prim";
 	qcom,cdc-us-euro-gpios = <&msmgpio 69 0>;
+	qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
+	qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 3 0>;
 };
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index e724c62..f2707f6 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -73,6 +73,11 @@
   programs the CERR  to 3 by default. When this flag is true, CERR is set to
   zero and transaction errors are ignored.
 
+- hsic,reset-delay: If present then add the given delay time (ms) between
+  the reset and enumeration. Since some devices might take more than 100ms
+  for initialization when receiving the bus reset, add delay to avoid the
+  problem that enmueration is before device initialization done.
+
 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
   below optional properties:
     - qcom,msm_bus,name
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index b4bcaf6..a3a3807 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -8,6 +8,7 @@
 apm	Applied Micro Circuits Corporation (APM)
 arm	ARM Ltd.
 atmel	Atmel Corporation
+bosch	Bosch Sensortec GmbH
 cavium	Cavium, Inc.
 chrp	Common Hardware Reference Platform
 cortina	Cortina Systems, Inc.
diff --git a/arch/arm/boot/dts/apq8026-v1-cdp.dts b/arch/arm/boot/dts/apq8026-v1-cdp.dts
new file mode 100644
index 0000000..8c6daa6
--- /dev/null
+++ b/arch/arm/boot/dts/apq8026-v1-cdp.dts
@@ -0,0 +1,22 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+/include/ "apq8026-v1.dtsi"
+/include/ "msm8226-cdp.dtsi"
+
+/ {
+	model = "Qualcomm APQ 8026 CDP";
+	compatible = "qcom,apq8026-cdp", "qcom,apq8026", "qcom,cdp";
+	qcom,msm-id = <199 1 0>;
+};
diff --git a/arch/arm/boot/dts/apq8026-v1.dtsi b/arch/arm/boot/dts/apq8026-v1.dtsi
index f15a96f..7fbfcb5 100644
--- a/arch/arm/boot/dts/apq8026-v1.dtsi
+++ b/arch/arm/boot/dts/apq8026-v1.dtsi
@@ -22,3 +22,8 @@
 	model = "Qualcomm APQ 8026";
 	compatible = "qcom,apq8026";
 };
+
+&tsens {
+	qcom,sensors = <4>;
+	qcom,slope = <2901 2846 3038 2955>;
+};
diff --git a/arch/arm/boot/dts/apq8026-v2-cdp.dts b/arch/arm/boot/dts/apq8026-v2-cdp.dts
new file mode 100644
index 0000000..74608dd
--- /dev/null
+++ b/arch/arm/boot/dts/apq8026-v2-cdp.dts
@@ -0,0 +1,22 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+/include/ "apq8026-v2.dtsi"
+/include/ "msm8226-cdp.dtsi"
+
+/ {
+	model = "Qualcomm APQ 8026v2 CDP";
+	compatible = "qcom,apq8026-cdp", "qcom,apq8026", "qcom,cdp";
+	qcom,msm-id = <199 1 0x20000>;
+};
diff --git a/arch/arm/boot/dts/apq8026-v2.dtsi b/arch/arm/boot/dts/apq8026-v2.dtsi
index d87b500..4c0d3ce 100644
--- a/arch/arm/boot/dts/apq8026-v2.dtsi
+++ b/arch/arm/boot/dts/apq8026-v2.dtsi
@@ -22,3 +22,8 @@
 	model = "Qualcomm APQ 8026";
 	compatible = "qcom,apq8026";
 };
+
+&tsens {
+	qcom,sensors = <6>;
+	qcom,slope = <2901 2846 3038 2955 2901 2846>;
+};
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index 21e92ab..53e9b3b 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -191,10 +191,10 @@
 			"MIC BIAS2 External", "ANCRight Headset Mic",
 			"AMIC4", "MIC BIAS2 External",
 			"MIC BIAS2 External", "ANCLeft Headset Mic",
-			"AMIC5", "MIC BIAS1 External",
-			"MIC BIAS1 External", "Analog Mic6",
-			"AMIC6", "MIC BIAS1 External",
-			"MIC BIAS1 External", "Analog Mic7",
+			"AMIC5", "MIC BIAS4 External",
+			"MIC BIAS4 External", "Analog Mic6",
+			"AMIC6", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Analog Mic7",
 			"DMIC1", "MIC BIAS3 External",
 			"MIC BIAS3 External", "Digital Mic1",
 			"DMIC2", "MIC BIAS3 External",
@@ -208,11 +208,14 @@
 			"DMIC6", "MIC BIAS4 External",
 			"MIC BIAS4 External", "Digital Mic6";
 
+
 		qcom,prim-auxpcm-gpio-clk  = <&msmgpio 74 0>;
 		qcom,prim-auxpcm-gpio-sync = <&msmgpio 75 0>;
 		qcom,prim-auxpcm-gpio-din  = <&msmgpio 76 0>;
 		qcom,prim-auxpcm-gpio-dout = <&msmgpio 77 0>;
 		qcom,prim-auxpcm-gpio-set = "prim-gpio-tert";
+
+		qcom,cdc-micbias2-headset-only;
 	};
 
 	qcom,pronto@fb21b000 {
@@ -287,6 +290,7 @@
 };
 
 &usb3 {
+	interrupts = <0>;	/* remove pmic_id_irq; used by &usb_otg */
 	qcom,charging-disabled;
 	vbus_dwc3-supply = <0>;
 	dwc3@f9200000 {
@@ -296,8 +300,17 @@
 
 &slim_msm {
 	taiko_codec {
+		qcom,cdc-micbias1-ext-cap;
 		qcom,cdc-micbias2-ext-cap;
 		qcom,cdc-micbias3-ext-cap;
+		qcom,cdc-micbias4-ext-cap;
+
+		/* If boot isn't available, vph_pwr_vreg can be used instead */
+		cdc-vdd-spkdrv-supply = <&pm8941_boost>;
+		qcom,cdc-vdd-spkdrv-voltage = <5000000 5000000>;
+		qcom,cdc-vdd-spkdrv-current = <1250000>;
+
+		qcom,cdc-on-demand-supplies = "cdc-vdd-spkdrv";
 	};
 };
 
@@ -542,34 +555,32 @@
 	status = "disabled";
 };
 
-&spmi_bus {
-	qcom,pm8941@1 {
-		qcom,leds@d000 {
-			qcom,rgb_2 {
-				status = "ok";
-				qcom,default-state = "on";
-				qcom,turn-off-delay-ms = <1000>;
-			};
+&pm8941_lsid1 {
+	qcom,leds@d000 {
+		qcom,rgb_2 {
+			status = "ok";
+			qcom,default-state = "on";
+			qcom,turn-off-delay-ms = <1000>;
 		};
+	};
 
-		qcom,leds@d800 {
-			status = "okay";
-			qcom,wled_0 {
-				label = "wled";
-				linux,name = "wled:backlight";
-				linux,default-trigger = "bkl-trigger";
-				qcom,cs-out-en;
-				qcom,op-fdbck = <1>;
-				qcom,default-state = "on";
-				qcom,max-current = <20>;
-				qcom,ctrl-delay-us = <0>;
-				qcom,boost-curr-lim = <3>;
-				qcom,cp-sel = <0>;
-				qcom,switch-freq = <2>;
-				qcom,ovp-val = <1>;
-				qcom,num-strings = <1>;
-				qcom,id = <0>;
-			};
+	qcom,leds@d800 {
+		status = "okay";
+		qcom,wled_0 {
+			label = "wled";
+			linux,name = "wled:backlight";
+			linux,default-trigger = "bkl-trigger";
+			qcom,cs-out-en;
+			qcom,op-fdbck = <1>;
+			qcom,default-state = "on";
+			qcom,max-current = <20>;
+			qcom,ctrl-delay-us = <0>;
+			qcom,boost-curr-lim = <3>;
+			qcom,cp-sel = <0>;
+			qcom,switch-freq = <2>;
+			qcom,ovp-val = <1>;
+			qcom,num-strings = <1>;
+			qcom,id = <0>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/apq8084-coresight.dtsi b/arch/arm/boot/dts/apq8084-coresight.dtsi
index 610d80b..1905e3b 100644
--- a/arch/arm/boot/dts/apq8084-coresight.dtsi
+++ b/arch/arm/boot/dts/apq8084-coresight.dtsi
@@ -23,6 +23,7 @@
 		coresight-id = <0>;
 		coresight-name = "coresight-tmc-etr";
 		coresight-nr-inports = <1>;
+		coresight-ctis = <&cti0 &cti8>;
 	};
 
 	replicator: replicator@fc324000 {
@@ -50,6 +51,7 @@
 		coresight-child-list = <&replicator>;
 		coresight-child-ports = <0>;
 		coresight-default-sink;
+		coresight-ctis = <&cti0 &cti8>;
 	};
 
 	funnel_merg: funnel@fc323000 {
@@ -142,4 +144,144 @@
 
 		qcom,blk-size = <3>;
 	};
+
+	cti0: cti@fc310000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc310000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <15>;
+		coresight-name = "coresight-cti0";
+		coresight-nr-inports = <0>;
+	};
+
+	cti1: cti@fc311000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc311000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <16>;
+		coresight-name = "coresight-cti1";
+		coresight-nr-inports = <0>;
+	};
+
+	cti2: cti@fc312000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc312000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <17>;
+		coresight-name = "coresight-cti2";
+		coresight-nr-inports = <0>;
+	};
+
+	cti3: cti@fc313000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc313000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <18>;
+		coresight-name = "coresight-cti3";
+		coresight-nr-inports = <0>;
+	};
+
+	cti4: cti@fc314000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc314000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <19>;
+		coresight-name = "coresight-cti4";
+		coresight-nr-inports = <0>;
+	};
+
+	cti5: cti@fc315000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc315000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <20>;
+		coresight-name = "coresight-cti5";
+		coresight-nr-inports = <0>;
+	};
+
+	cti6: cti@fc316000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc316000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <21>;
+		coresight-name = "coresight-cti6";
+		coresight-nr-inports = <0>;
+	};
+
+	cti7: cti@fc317000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc317000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <22>;
+		coresight-name = "coresight-cti7";
+		coresight-nr-inports = <0>;
+	};
+
+	cti8: cti@fc318000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc318000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <23>;
+		coresight-name = "coresight-cti8";
+		coresight-nr-inports = <0>;
+	};
+
+	cti_l2: cti@fc340000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc340000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <24>;
+		coresight-name = "coresight-cti-l2";
+		coresight-nr-inports = <0>;
+	};
+
+	cti_cpu0: cti@fc341000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc341000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <25>;
+		coresight-name = "coresight-cti-cpu0";
+		coresight-nr-inports = <0>;
+	};
+
+	cti_cpu1: cti@fc342000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc342000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <26>;
+		coresight-name = "coresight-cti-cpu1";
+		coresight-nr-inports = <0>;
+	};
+
+	cti_cpu2: cti@fc343000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc343000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <27>;
+		coresight-name = "coresight-cti-cpu2";
+		coresight-nr-inports = <0>;
+	};
+
+	cti_cpu3: cti@fc344000 {
+		compatible = "arm,coresight-cti";
+		reg = <0xfc344000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <28>;
+		coresight-name = "coresight-cti-cpu3";
+		coresight-nr-inports = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/apq8084-mdss.dtsi b/arch/arm/boot/dts/apq8084-mdss.dtsi
index b9609cc..5c5cd1b 100644
--- a/arch/arm/boot/dts/apq8084-mdss.dtsi
+++ b/arch/arm/boot/dts/apq8084-mdss.dtsi
@@ -17,6 +17,9 @@
 		      <0xfd924000 0x1000>;
 		reg-names = "mdp_phys", "vbif_phys";
 		interrupts = <0 72 0>;
+		vdd-supply = <&gdsc_mdss>;
+
+		status = "disabled";
 
 		qcom,max-clk-rate = <320000000>;
 
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index 7ac286a..b027f7d 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -164,6 +164,37 @@
 		qcom,scl-gpio = <&msmgpio 11 0>;
 	};
 
+	qcom,usbbam@f9304000 {
+		compatible = "qcom,usb-bam-msm";
+		reg = <0xf9304000 0x5000>,
+		      <0xf92f880c 0x4>;
+		reg-names = "ssusb", "qscratch_ram1_reg";
+		interrupts = <0 132 0>;
+		interrupt-names = "ssusb";
+		qcom,usb-bam-num-pipes = <16>;
+		qcom,usb-bam-fifo-baseaddr = <0x00000000 0xf9200000>;
+		qcom,ignore-core-reset-ack;
+		qcom,disable-clk-gating;
+
+		qcom,pipe0 {
+			label = "ssusb-qdss-in-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>;
+			qcom,dst-bam-pipe-index = <2>;
+			qcom,data-fifo-offset = <0xf0000>;
+			qcom,data-fifo-size = <0x1800>;
+			qcom,descriptor-fifo-offset = <0xf4000>;
+			qcom,descriptor-fifo-size = <0x1400>;
+			qcom,reset-bam-on-connect;
+		};
+	};
+
 	usb3: qcom,ssusb@f9200000 {
 		compatible = "qcom,dwc-usb3-msm";
 		reg = <0xf9200000 0xfc000>,
@@ -198,7 +229,7 @@
 	tsens: tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
-		      <0xfc4b8000 0x1000>;
+		      <0xfc4bc000 0x1000>;
 		reg-names = "tsens_physical", "tsens_eeprom_physical";
 		interrupts = <0 184 0>;
 		qcom,sensors = <11>;
@@ -245,7 +276,7 @@
 
 	memory_hole: qcom,msm-mem-hole {
 		compatible = "qcom,msm-mem-hole";
-		qcom,memblock-remove = <0x0dc00000 0x2000000>; /* Address and Size of Hole */
+		qcom,memblock-remove = <0x0d200000 0x02c00000>; /* Address and Size of Hole */
 	};
 
 	qcom,ipc-spinlock@fd484000 {
@@ -304,6 +335,15 @@
 		interrupts = <0 28 0>;
 		status = "disabled";
 	};
+
+	qcom,wdt@f9017000 {
+		compatible = "qcom,msm-watchdog";
+		reg = <0xf9017000 0x1000>;
+		interrupts = <0 3 0>, <0 4 0>;
+		qcom,bark-time = <11000>;
+		qcom,pet-time = <10000>;
+		qcom,ipi-ping;
+	};
 };
 
 &gdsc_venus {
diff --git a/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
index 25c1851..c8d150a 100644
--- a/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
@@ -10,98 +10,76 @@
  * GNU General Public License for more details.
  */
 
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
 &soc {
 	qcom,mdss_dsi_hx8394a_720p_video {
 		compatible = "qcom,mdss-dsi-panel";
-		label = "hx8394a 720p video mode dsi panel";
 		status = "disable";
-		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
-		qcom,rst-gpio = <&msmgpio 25 0>;
-		qcom,mdss-pan-res = <720 1280>;
-		qcom,mdss-pan-bpp = <24>;
-		qcom,mdss-pan-dest = "display_1";
-		qcom,mdss-pan-porch-values = <59 60 79 10 2 7>;
-		qcom,mdss-pan-underflow-clr = <0xff>;
-		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
-		qcom,mdss-pan-bl-levels = <1 4095>;
-		qcom,mdss-pan-dsi-mode = <0>;
-		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
-		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
-		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
-		qcom,mdss-pan-dsi-traffic-mode = <2>;
-		qcom,mdss-pan-dsi-dst-format = <3>;
-		qcom,mdss-pan-dsi-vc = <0>;
-		qcom,mdss-pan-dsi-rgb-swap = <0>;
-		qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
-		qcom,mdss-pan-dsi-dlane-swap = <0>;
-		qcom,mdss-pan-dsi-t-clk = <0x2d 0x1f>;
-		qcom,mdss-pan-dsi-stream = <0>;
-		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
-		qcom,mdss-pan-dsi-dma-tr = <0x04>;
-		qcom,mdss-pan-dsi-frame-rate = <60>;
-		qcom,panel-phy-regulatorSettings = [07 09 03 00  /* Regualotor settings */
-						    20 00 01];
-		qcom,panel-phy-timingSettings = [8d 24 19 00 34 34
-						    1d 26 2a 03 04 00];
-		qcom,panel-phy-strengthCtrl = [ff 06];
-		qcom,panel-phy-bistCtrl = [00 00 b1 ff           /* BIST Ctrl settings */
-					   00 00];
-		qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
-					     00 00 00 00 05 00 00 01 97 /* lane1 config */
-					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
-					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
-					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
-		qcom,panel-on-cmds = [39 01 00 00 00 00 04
-						b9 ff 83 94
-					39 01 00 00 00 00 05
-						c7 00 10 00 10
-					39 01 00 00 00 00 02
-						bc 07
-					39 01 00 00 00 00 02
-						ba 13
-					39 01 00 00 00 00 10
-						b1 01 00 07 83 01
-						12 0f 32 38 29 29
-						50 02 00 00
-					39 01 00 00 00 00 07
-						b2 00 c8 09 05 00
-						71
-					39 01 00 00 00 00 02
-						cc 05
-					05 01 00 00 00 00 02 00 00
-					39 01 00 00 00 00 35
-						d5 00 00 00 00 0a
-						00 01 00 00 00 33
-						00 23 45 67 01 01
-						23 88 88 88 88 88
-						88 88 99 99 99 88
-						88 99 88 54 32 10
-						76 32 10 88 88 88
-						88 88 88 88 99 99
-						99 88 88 88 99
-					39 01 00 00 00 00 17
-						b4 80 08 32 10 00
-						32 15 08 32 12 20
-						33 05 4c 05 37 05
-						3f 1e 5f 5f 06
-					39 01 00 00 00 00 02
-						b6 00
-					39 01 00 00 00 00 23
-						e0 01 05 07 25 35
-						3f 0b 32 04 09 0e
-						10 13 10 14 16 1b
-						01 05 07 25 35 3f
-						0b 32 04 09 0e 10
-						13 10 14 16 1b
-					05 01 00 00 00 00 02 00 00
-					39 01 00 00 00 00 04
-						bf 06 00 10
-					05 01 00 00 c8 00 02 11 00
-					05 01 00 00 32 00 02 29 00];
+		qcom,mdss-dsi-panel-name = "hx8394a 720p video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <720>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-h-front-porch = <79>;
+		qcom,mdss-dsi-h-back-porch = <59>;
+		qcom,mdss-dsi-h-pulse-width = <60>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <10>;
+		qcom,mdss-dsi-v-front-porch = <7>;
+		qcom,mdss-dsi-v-pulse-width = <2>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-color-order = <0>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [39 01 00 00 00 00 04 b9 ff 83 94
+				39 01 00 00 00 00 05 c7 00 10 00 10
+				39 01 00 00 00 00 02 bc 07
+				39 01 00 00 00 00 02 ba 13
+				39 01 00 00 00 00 10 b1 01 00 07 83 01 12 0f 32 38 29 29 50 02 00 00
+				39 01 00 00 00 00 07 b2 00 c8 09 05 00 71
+				39 01 00 00 00 00 02 cc 05
+				05 01 00 00 00 00 02 00 00
+				39 01 00 00 00 00 35 d5 00 00 00 00 0a 00 01 00 00 00 33 00 23 45 67 01 01 23 88 88 88 88 88 88 88 99 99 99 88 88 99 88 54 32 10 76 32 10 88 88 88 88 88 88 88 99 99 99 88 88 88 99
+				39 01 00 00 00 00 17 b4 80 08 32 10 00 32 15 08 32 12 20 33 05 4c 05 37 05 3f 1e 5f 5f 06
+				39 01 00 00 00 00 02 b6 00
+				39 01 00 00 00 00 23 e0 01 05 07 25 35 3f 0b 32 04 09 0e 10 13 10 14 16 1b 01 05 07 25 35 3f 0b 32 04 09 0e 10 13 10 14 16 1b
+				05 01 00 00 00 00 02 00 00
+				39 01 00 00 00 00 04 bf 06 00 10
+				05 01 00 00 c8 00 02 11 00
+				05 01 00 00 32 00 02 29 00];
+		qcom,mdss-dsi-off-command = [05 01 00 00 0a 00 02 28 00
+				05 01 00 00 96 00 02 10 00];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+		qcom,mdss-dsi-h-sync-pulse = <1>;
+		qcom,mdss-dsi-traffic-mode = <2>;
+		qcom,mdss-dsi-lane-map = <0>;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-lane-2-state;
+		qcom,mdss-dsi-lane-3-state;
+		qcom,mdss-dsi-panel-timings = [8d 24 19 00 34 34 1d 26 2a 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x1f>;
+		qcom,mdss-dsi-t-clk-pre = <0x2d>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-dma-trigger = <4>;
+		qcom,mdss-dsi-mdp-trigger = <0>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
 
-		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [05 01 00 00 0a 00 02 28 00
-					05 01 00 00 96 00 02 10 00];
-		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
index 2a6bbf9..d0b4da8 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
@@ -10,55 +10,40 @@
  * GNU General Public License for more details.
  */
 
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
 &soc {
 	qcom,mdss_dsi_nt35590_720p_cmd {
 		compatible = "qcom,mdss-dsi-panel";
-		label = "nt35590 720p command mode dsi panel";
 		status = "disable";
-		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
-		qcom,rst-gpio = <&msmgpio 25 0>;
-		qcom,te-gpio = <&msmgpio 24 0>;
-		qcom,mdss-pan-res = <720 1280>;
-		qcom,mdss-pan-bpp = <24>;
-		qcom,mdss-pan-dest = "display_1";
-		qcom,mdss-pan-porch-values = <164 8 140 1 1 6>;
-		qcom,mdss-pan-underflow-clr = <0xff>;
-		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
-		qcom,mdss-pan-bl-levels = <1 4095>;
-		qcom,mdss-pan-dsi-mode = <1>;
-		qcom,mdss-vsync-enable = <1>;
-		qcom,mdss-hw-vsync-mode = <1>;
-		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
-		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
-		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
-		qcom,mdss-pan-dsi-traffic-mode = <2>;
-		qcom,mdss-pan-dsi-dst-format = <8>;
-		qcom,mdss-pan-insert-dcs-cmd = <1>;
-		qcom,mdss-pan-wr-mem-continue = <0x3c>;
-		qcom,mdss-pan-wr-mem-start = <0x2c>;
-		qcom,mdss-pan-te-sel = <1>;
-		qcom,mdss-pan-dsi-vc = <0>;
-		qcom,mdss-pan-dsi-rgb-swap = <0>;
-		qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
-		qcom,mdss-pan-dsi-dlane-swap = <0>;
-		qcom,mdss-pan-dsi-t-clk = <0x2c 0x20>;
-		qcom,mdss-pan-dsi-stream = <0>;
-		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
-		qcom,mdss-pan-dsi-dma-tr = <0x04>;
-		qcom,mdss-pan-dsi-frame-rate = <60>;
-		qcom,panel-phy-regulatorSettings = [07 09 03 00  /* Regualotor settings */
-						    20 00 01];
-		qcom,panel-phy-timingSettings = [7d 25 1d 00 37 33
-						    22 27 1e 03 04 00];
-		qcom,panel-phy-strengthCtrl = [ff 06];
-		qcom,panel-phy-bistCtrl = [00 00 b1 ff           /* BIST Ctrl settings */
-					   00 00];
-		qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
-					     00 00 00 00 05 00 00 01 97 /* lane1 config */
-					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
-					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
-					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
-		qcom,panel-on-cmds = [29 01 00 00 00 00 02 FF EE
+		qcom,mdss-dsi-panel-name = "nt35590 720p command mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <720>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-h-front-porch = <140>;
+		qcom,mdss-dsi-h-back-porch = <164>;
+		qcom,mdss-dsi-h-pulse-width = <8>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <1>;
+		qcom,mdss-dsi-v-front-porch = <6>;
+		qcom,mdss-dsi-v-pulse-width = <1>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-color-order = <0>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [29 01 00 00 00 00 02 FF EE
 					29 01 00 00 00 00 02 26 08
 					29 01 00 00 00 00 02 26 00
 					29 01 00 00 10 00 02 FF 00
@@ -522,10 +507,32 @@
 					29 01 00 00 00 00 02 6A 60
 					29 01 00 00 00 00 02 FF 00
 					29 01 00 00 78 00 02 29 00];
-
-		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
+		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
 					05 01 00 00 78 00 02 10 00];
-		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+		qcom,mdss-dsi-h-sync-pulse = <1>;
+		qcom,mdss-dsi-traffic-mode = <2>;
+		qcom,mdss-dsi-lane-map = <0>;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-lane-2-state;
+		qcom,mdss-dsi-lane-3-state;
+		qcom,mdss-dsi-te-pin-select = <1>;
+		qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line = <0x2c>;
+		qcom,mdss-dsi-te-dcs-command = <1>;
+		qcom,mdss-dsi-te-check-enable;
+		qcom,mdss-dsi-te-using-te-pin;
+		qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33 22 27 1e 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x20>;
+		qcom,mdss-dsi-t-clk-pre = <0x2c>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-dma-trigger = <4>;
+		qcom,mdss-dsi-mdp-trigger = <0>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
index d742b30..a171a5c 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -10,48 +10,40 @@
  * GNU General Public License for more details.
  */
 
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
 &soc {
 	qcom,mdss_dsi_nt35590_720p_video {
 		compatible = "qcom,mdss-dsi-panel";
-		label = "nt35590 720p video mode dsi panel";
 		status = "disable";
-		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
-		qcom,rst-gpio = <&msmgpio 25 0>;
-		qcom,mdss-pan-res = <720 1280>;
-		qcom,mdss-pan-bpp = <24>;
-		qcom,mdss-pan-dest = "display_1";
-		qcom,mdss-pan-porch-values = <164 8 140 1 1 6>;
-		qcom,mdss-pan-underflow-clr = <0xff>;
-		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
-		qcom,mdss-pan-bl-levels = <1 4095>;
-		qcom,mdss-pan-dsi-mode = <0>;
-		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
-		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
-		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
-		qcom,mdss-pan-dsi-traffic-mode = <2>;
-		qcom,mdss-pan-dsi-dst-format = <3>;
-		qcom,mdss-pan-dsi-vc = <0>;
-		qcom,mdss-pan-dsi-rgb-swap = <0>;
-		qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
-		qcom,mdss-pan-dsi-dlane-swap = <0>;
-		qcom,mdss-pan-dsi-t-clk = <0x2c 0x20>;
-		qcom,mdss-pan-dsi-stream = <0>;
-		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
-		qcom,mdss-pan-dsi-dma-tr = <0x04>;
-		qcom,mdss-pan-dsi-frame-rate = <60>;
-		qcom,panel-phy-regulatorSettings = [07 09 03 00  /* Regualotor settings */
-						    20 00 01];
-		qcom,panel-phy-timingSettings = [7d 25 1d 00 37 33
-						    22 27 1e 03 04 00];
-		qcom,panel-phy-strengthCtrl = [ff 06];
-		qcom,panel-phy-bistCtrl = [00 00 b1 ff           /* BIST Ctrl settings */
-					   00 00];
-		qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
-					     00 00 00 00 05 00 00 01 97 /* lane1 config */
-					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
-					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
-					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
-		qcom,panel-on-cmds = [29 01 00 00 00 00 02 FF EE
+		qcom,mdss-dsi-panel-name = "nt35590 720p video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <720>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-h-front-porch = <140>;
+		qcom,mdss-dsi-h-back-porch = <164>;
+		qcom,mdss-dsi-h-pulse-width = <8>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <1>;
+		qcom,mdss-dsi-v-front-porch = <6>;
+		qcom,mdss-dsi-v-pulse-width = <1>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-color-order = <0>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [29 01 00 00 00 00 02 FF EE
 					29 01 00 00 00 00 02 26 08
 					29 01 00 00 00 00 02 26 00
 					29 01 00 00 10 00 02 FF 00
@@ -516,10 +508,27 @@
 					29 01 00 00 00 00 02 FF 00
 					29 01 00 00 78 00 02 29 00
 					29 01 00 00 78 00 02 53 2C];
-
-		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
+		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
 					05 01 00 00 78 00 02 10 00];
-		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+		qcom,mdss-dsi-h-sync-pulse = <1>;
+		qcom,mdss-dsi-traffic-mode = <2>;
+		qcom,mdss-dsi-lane-map = <0>;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-lane-2-state;
+		qcom,mdss-dsi-lane-3-state;
+		qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33 22 27 1e 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x20>;
+		qcom,mdss-dsi-t-clk-pre = <0x2c>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-dma-trigger = <4>;
+		qcom,mdss-dsi-mdp-trigger = <0>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
index 1ecad71..998799a 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
@@ -10,48 +10,40 @@
  * GNU General Public License for more details.
  */
 
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
 &soc {
 	qcom,mdss_dsi_nt35596_1080p_video {
 		compatible = "qcom,mdss-dsi-panel";
-		label = "nt35596 1080p video mode dsi panel";
 		status = "disable";
-		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
-		qcom,rst-gpio = <&msmgpio 25 0>;
-		qcom,mdss-pan-res = <1080 1920>;
-		qcom,mdss-pan-bpp = <24>;
-		qcom,mdss-pan-dest = "display_1";
-		qcom,mdss-pan-porch-values = <32 8 32 18 2 2>;
-		qcom,mdss-pan-underflow-clr = <0xff>;
-		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
-		qcom,mdss-pan-bl-levels = <1 4095>;
-		qcom,mdss-pan-dsi-mode = <0>;
-		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
-		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
-		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
-		qcom,mdss-pan-dsi-traffic-mode = <2>;
-		qcom,mdss-pan-dsi-dst-format = <3>;
-		qcom,mdss-pan-dsi-vc = <0>;
-		qcom,mdss-pan-dsi-rgb-swap = <0>;
-		qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
-		qcom,mdss-pan-dsi-dlane-swap = <0>;
-		qcom,mdss-pan-dsi-t-clk = <0x38 0x1e>;
-		qcom,mdss-pan-dsi-stream = <0>;
-		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
-		qcom,mdss-pan-dsi-dma-tr = <0x04>;
-		qcom,mdss-pan-dsi-frame-rate = <60>;
-		qcom,panel-phy-regulatorSettings = [07 09 03 00  /* Regualotor settings */
-						    20 00 01];
-		qcom,panel-phy-timingSettings = [f9 3d 34 00 58 4d
-						    36 3f 53 03 04 00];
-		qcom,panel-phy-strengthCtrl = [ff 06];
-		qcom,panel-phy-bistCtrl = [00 00 b1 ff           /* BIST Ctrl settings */
-					   00 00];
-		qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
-					     00 00 00 00 05 00 00 01 97 /* lane1 config */
-					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
-					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
-					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
-		qcom,panel-on-cmds = [29 01 00 00 00 00 02 FF EE
+		qcom,mdss-dsi-panel-name = "nt35596 1080p video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <1080>;
+		qcom,mdss-dsi-panel-height = <1920>;
+		qcom,mdss-dsi-h-front-porch = <32>;
+		qcom,mdss-dsi-h-back-porch = <32>;
+		qcom,mdss-dsi-h-pulse-width = <8>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <18>;
+		qcom,mdss-dsi-v-front-porch = <2>;
+		qcom,mdss-dsi-v-pulse-width = <2>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-color-order = <0>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [29 01 00 00 00 00 02 FF EE
 			29 01 00 00 00 00 02 FB 01
 			29 01 00 00 00 00 02 1F 45
 			29 01 00 00 00 00 02 24 4F
@@ -571,10 +563,27 @@
 			29 01 00 00 00 00 02 FF 00
 			29 01 00 00 00 00 02 35 00
 			29 01 00 00 78 00 02 29 00];
-
-		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
+		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
 					05 01 00 00 78 00 02 10 00];
-		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+		qcom,mdss-dsi-h-sync-pulse = <1>;
+		qcom,mdss-dsi-traffic-mode = <2>;
+		qcom,mdss-dsi-lane-map = <0>;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-lane-2-state;
+		qcom,mdss-dsi-lane-3-state;
+		qcom,mdss-dsi-panel-timings = [f9 3d 34 00 58 4d 36 3f 53 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x1e>;
+		qcom,mdss-dsi-t-clk-pre = <0x38>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-dma-trigger = <4>;
+		qcom,mdss-dsi-mdp-trigger = <0>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
index 45d396c..7fe0f7f 100644
--- a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
@@ -10,58 +10,65 @@
  * GNU General Public License for more details.
  */
 
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
 &soc {
 	qcom,mdss_dsi_sharp_qhd_video {
 		compatible = "qcom,mdss-dsi-panel";
-		label = "sharp QHD LS043T1LE01 video mode dsi panel";
 		status = "disable";
-		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
-		qcom,enable-gpio = <&msmgpio 58 0>;
-		qcom,rst-gpio = <&pm8941_gpios 19 0>;
-		qcom,mdss-pan-res = <540 960>;
-		qcom,mdss-pan-bpp = <24>;
-		qcom,mdss-pan-dest = "display_1";
-		qcom,mdss-pan-porch-values = <80 32 48 15 10 3>; /* HBP, HPW, HFP, VBP, VPW, VFP */
-		qcom,mdss-pan-underflow-clr = <0xff>;
-		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
-		qcom,mdss-pan-bl-levels = <1 4095>;
-		qcom,mdss-pan-dsi-mode = <0>;
-		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
-		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
-		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
-		qcom,mdss-pan-dsi-traffic-mode = <0>;
-		qcom,mdss-pan-dsi-dst-format = <3>;
-		qcom,mdss-pan-dsi-vc = <0>;
-		qcom,mdss-pan-dsi-rgb-swap = <2>;
-		qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
-		qcom,mdss-pan-dsi-dlane-swap = <0>;
-		qcom,mdss-pan-dsi-t-clk = <0x1c 0x04>;
-		qcom,mdss-pan-dsi-stream = <0>;
-		qcom,mdss-pan-dsi-mdp-tr = <0x04>;
-		qcom,mdss-pan-dsi-dma-tr = <0x04>;
-		qcom,mdss-pan-frame-rate = <60>;
-		qcom,panel-phy-regulatorSettings = [07 09 03 00  /* Regulator settings */
-						    20 00 01];
-		qcom,panel-phy-timingSettings = [46 1d 20 00 39 3a
-						    21 21 32 03 04 00];
-		qcom,panel-phy-strengthCtrl = [ff 06];
-		qcom,panel-phy-bistCtrl = [00 00 b1 ff           /* BIST Ctrl settings */
-					   00 00];
-		qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
-					     00 00 00 00 05 00 00 01 97 /* lane1 config */
-					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
-					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
-					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
-		qcom,panel-on-cmds = [05 01 00 00 32 00 02 01 00 /* sw reset */
-					05 01 00 00 0a 00 02 11 00 /* exit sleep */
-					15 01 00 00 0a 00 02 53 2c /* backlight on */
-					15 01 00 00 0a 00 02 51 ff /* brightness max */
-					05 01 00 00 0a 00 02 29 00 /* display on */
-					15 01 00 00 0a 00 02 ae 03 /* set num of lanes */
-					15 01 00 00 0a 00 02 3a 77 /* rgb_888 */];
-		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [05 01 00 00 0a 00 02 28 00 /* display off */
-					05 01 00 00 78 00 02 10 00 /* enter sleep */];
-		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+		qcom,mdss-dsi-panel-name = "sharp QHD LS043T1LE01 video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <540>;
+		qcom,mdss-dsi-panel-height = <960>;
+		qcom,mdss-dsi-h-front-porch = <48>;
+		qcom,mdss-dsi-h-back-porch = <80>;
+		qcom,mdss-dsi-h-pulse-width = <32>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <15>;
+		qcom,mdss-dsi-v-front-porch = <3>;
+		qcom,mdss-dsi-v-pulse-width = <10>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-color-order = <2>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [05 01 00 00 32 00 02 01 00
+					05 01 00 00 0a 00 02 11 00
+					15 01 00 00 0a 00 02 53 2c
+					15 01 00 00 0a 00 02 51 ff
+					05 01 00 00 0a 00 02 29 00
+					15 01 00 00 0a 00 02 ae 03
+					15 01 00 00 0a 00 02 3a 77];
+		qcom,mdss-dsi-off-command = [05 01 00 00 0a 00 02 28 00
+					05 01 00 00 78 00 02 10 00];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+		qcom,mdss-dsi-h-sync-pulse = <1>;
+		qcom,mdss-dsi-traffic-mode = <0>;
+		qcom,mdss-dsi-lane-map = <0>;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-panel-timings = [46 1d 20 00 39 3a 21 21 32 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x1c>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-dma-trigger = <4>;
+		qcom,mdss-dsi-mdp-trigger = <4>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
index 5c37cf8..a824d45 100644
--- a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -10,115 +10,88 @@
  * GNU General Public License for more details.
  */
 
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
 &soc {
-
 	qcom,mdss_dsi_toshiba_720p_video {
 		compatible = "qcom,mdss-dsi-panel";
-		label = "toshiba 720p video mode dsi panel";
 		status = "disable";
-		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
-		qcom,enable-gpio = <&msmgpio 58 0>;
-		qcom,rst-gpio = <&pm8941_gpios 19 0>;
-		qcom,mdss-pan-res = <720 1280>;
-		qcom,mdss-pan-bpp = <24>;
-		qcom,mdss-pan-dest = "display_1";
-		qcom,mdss-pan-porch-values = <32 12 144 3 4 9>;
-		qcom,mdss-pan-underflow-clr = <0xff>;
-		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
-		qcom,mdss-pan-bl-levels = <1 4095>;
-		qcom,mdss-pan-dsi-mode = <0>;
-		qcom,mdss-pan-dsi-h-pulse-mode = <0>;
-		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
-		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
-		qcom,mdss-pan-dsi-traffic-mode = <1>;
-		qcom,mdss-pan-dsi-dst-format = <3>;
-		qcom,mdss-pan-dsi-vc = <0>;
-		qcom,mdss-pan-dsi-rgb-swap = <0>;
-		qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>;
-		qcom,mdss-pan-dsi-dlane-swap = <0>;
-		qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
-		qcom,mdss-pan-dsi-stream = <0>;
-		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
-		qcom,mdss-pan-dsi-dma-tr = <0x04>;
-		qcom,mdss-pan-dsi-frame-rate = <60>;
-		qcom,panel-phy-regulatorSettings = [07 09 03 00  /* Regualotor settings */
-						    20 00 01];
-		qcom,panel-phy-timingSettings = [b0 23 1b 00 94 93
-						    1e 25 15 03 04 00];
-		qcom,panel-phy-strengthCtrl = [ff 06];
-		qcom,panel-phy-bistCtrl = [00 00 b1 ff           /* BIST Ctrl settings */
-					   00 00];
-		qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
-					     00 00 00 00 05 00 00 01 97 /* lane1 config */
-					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
-					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
-					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
+		qcom,mdss-dsi-panel-name = "toshiba 720p video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <720>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-h-front-porch = <144>;
+		qcom,mdss-dsi-h-back-porch = <32>;
+		qcom,mdss-dsi-h-pulse-width = <12>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <3>;
+		qcom,mdss-dsi-v-front-porch = <9>;
+		qcom,mdss-dsi-v-pulse-width = <4>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-color-order = <0>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [23 01 00 00 0a 00 02 b0 00
+				23 01 00 00 0a 00 02 b2 00
+				23 01 00 00 0a 00 02 b3 0c
+				23 01 00 00 0a 00 02 b4 02
+				29 01 00 00 00 00 06 c0 40 02 7f c8 08
+				29 01 00 00 00 00 10 c1 00 a8 00 00 00 00 00 9d 08 27 00 00 00 00 00
+				29 01 00 00 00 00 06 c2 00 00 09 00 00
+				23 01 00 00 0a 00 02 c3 04
+				29 01 00 00 00 00 04 c4 4d 83 00
+				29 01 00 00 00 00 0b c6 12 00 08 71 00	00 00 80 00 04
+				23 01 00 00 0a 00 02 c7 22
+				29 01 00 00 00 00 05 c8 4c 0c 0c 0c
+				29 01 00 00 00 00 0e c9 00 40 00 16 32 2e 3a 43 3e 3c 45 79 3f
+				29 01 00 00 00 00 0e ca 00 46 1a 23 21 1c 25 31 2d 49 5f 7f 3f
+				29 01 00 00 00 00 0e cb 00 4c 20 3a 42 40 47 4b 42 3e 46 7e 3f
+				29 01 00 00 00 00 0e cc 00 41 19 21 1d 14 18 1f 1d 25 3f 73 3f
+				29 01 00 00 00 00 0e cd 23 79 5a 5f 57 4c 51 51 45 3f 4b 7f 3f
+				29 01 00 00 00 00 0e ce 00 40 14 20 1a 0e 0e 13 08 00 05 46 1c
+				29 01 00 00 00 00 04 d0 6a 64 01
+				29 01 00 00 00 00 03 d1 77 d4
+				23 01 00 00 0a 00 02 d3 33
+				29 01 00 00 00 00 03 d5 0f 0f
+				29 01 00 00 00 00 07 d8 34 64 23 25 62 32
+				29 01 00 00 00 00 0c de 10 7b 11 0a 00 00 00 00 00 00 00
+				29 01 00 00 00 00 09 fd 04 55 53 00 70	ff 10 73
+				23 01 00 00 0a 00 02 e2 00
+				05 01 00 00 78 00 02 11 00
+				05 01 00 00 32 00 02 29 00];
+		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
+				 05 01 00 00 78 00 02 10 00];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+		qcom,mdss-dsi-h-sync-pulse = <0>;
+		qcom,mdss-dsi-traffic-mode = <1>;
+		qcom,mdss-dsi-lane-map = <0>;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-lane-2-state;
+		qcom,mdss-dsi-lane-3-state;
+		qcom,mdss-dsi-panel-timings = [b0 23 1b 00 94 93 1e 25  15 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x1b>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-dma-trigger = <0x04>;
+		qcom,mdss-dsi-mdp-trigger = <0x0>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
 
-		qcom,panel-on-cmds = [23 01 00 00 0a 00 02 b0 00
-					23 01 00 00 0a 00 02 b2 00
-					23 01 00 00 0a 00 02 b3 0c
-					23 01 00 00 0a 00 02 b4 02
-					29 01 00 00 00 00 06
-						c0 40 02 7f c8 08
-					29 01 00 00 00 00 10
-						c1 00 a8 00 00 00
-						00 00 9d 08 27 00
-						00 00 00 00
-					29 01 00 00 00 00 06
-						c2 00 00 09 00 00
-					23 01 00 00 0a 00 02 c3 04
-					29 01 00 00 00 00 04
-						c4 4d 83 00
-					29 01 00 00 00 00 0b
-						c6 12 00 08 71 00
-						00 00 80 00 04
-					23 01 00 00 0a 00 02 c7 22
-					29 01 00 00 00 00 05
-						c8 4c 0c 0c 0c
-					29 01 00 00 00 00 0e
-						c9 00 40 00 16 32
-						2e 3a 43 3e 3c 45
-						79 3f
-					29 01 00 00 00 00 0e
-						ca 00 46 1a 23 21
-						1c 25 31 2d 49 5f
-						7f 3f
-					29 01 00 00 00 00 0e
-						cb 00 4c 20 3a 42
-						40 47 4b 42 3e 46
-						7e 3f
-					29 01 00 00 00 00 0e
-						cc 00 41 19 21 1d
-						14 18 1f 1d 25 3f
-						73 3f
-					29 01 00 00 00 00 0e
-						cd 23 79 5a 5f 57
-						4c 51 51 45 3f 4b
-						7f 3f
-					29 01 00 00 00 00 0e
-						ce 00 40 14 20 1a
-						0e 0e 13 08 00 05
-						46 1c
-					29 01 00 00 00 00 04
-						d0 6a 64 01
-					29 01 00 00 00 00 03 d1 77 d4
-					23 01 00 00 0a 00 02 d3 33
-					29 01 00 00 00 00 03 d5 0f 0f
-					29 01 00 00 00 00 07
-						d8 34 64 23 25 62
-						32
-					29 01 00 00 00 00 0c
-						de 10 7b 11 0a 00
-						00 00 00 00 00 00
-					29 01 00 00 00 00 09
-						fd 04 55 53 00 70
-						ff 10 73
-					23 01 00 00 0a 00 02 e2 00
-					05 01 00 00 78 00 02 11 00
-					05 01 00 00 32 00 02 29 00];
-		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
-					05 01 00 00 78 00 02 10 00];
-		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-v2-panel-hx8379a-wvga-video.dtsi b/arch/arm/boot/dts/dsi-v2-panel-hx8379a-wvga-video.dtsi
index b9ed050..befc29c 100644
--- a/arch/arm/boot/dts/dsi-v2-panel-hx8379a-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-v2-panel-hx8379a-wvga-video.dtsi
@@ -40,7 +40,7 @@
 		qcom,mdss-pan-dsi-mdp-tr = <0x0>;/*todo*/
 		qcom,mdss-pan-dsi-dma-tr = <0x04>;
 		qcom,mdss-pan-dsi-frame-rate = <60>;
-		qcom,panel-phy-regulatorSettings =[09 08 05 00 20 03];
+		qcom,panel-phy-regulatorSettings =[02 08 05 00 20 03];
 		qcom,panel-phy-timingSettings = [5D 12 0C  00 33 39
 						 10 16 15  03 04 00];
 		qcom,panel-phy-strengthCtrl = [ff 06];
diff --git a/arch/arm/boot/dts/dsi-v2-panel-otm8018b-fwvga-video.dtsi b/arch/arm/boot/dts/dsi-v2-panel-otm8018b-fwvga-video.dtsi
new file mode 100644
index 0000000..c2c64da
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-v2-panel-otm8018b-fwvga-video.dtsi
@@ -0,0 +1,261 @@
+/* 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.
+ */
+
+/ {
+	qcom,dsi_v2_otm8018b_fwvga_video {
+		compatible = "qcom,dsi-panel-v2";
+		label = "OTM8018B FWVGA video mode dsi panel";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+		qcom,rst-gpio = <&msmgpio 41 0>;
+		vdda-supply = <&pm8110_l19>;
+		vddio-supply=<&pm8110_l14>;
+		qcom,mdss-pan-res = <480 854>;
+		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
+		qcom,mdss-pan-porch-values = <54 8 80 16 2 12>;
+		qcom,mdss-pan-underflow-clr = <0xff>;
+		qcom,mdss-pan-bl-levels = <1 255>;
+		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+		qcom,mdss-pan-dsi-mode = <0>;
+		qcom,mdss-pan-dsi-h-pulse-mode = <0>;
+		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+		qcom,mdss-pan-dsi-traffic-mode = <1>;
+		qcom,mdss-pan-dsi-dst-format = <3>;
+		qcom,mdss-pan-dsi-vc = <0>;
+		qcom,mdss-pan-dsi-rgb-swap = <0>;
+		qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+		qcom,mdss-pan-dsi-dlane-swap = <1>;
+		qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
+		qcom,mdss-pan-dsi-stream = <0>;
+		qcom,mdss-pan-dsi-mdp-tr = <0x0>;/*todo*/
+		qcom,mdss-pan-dsi-dma-tr = <0x04>;
+		qcom,mdss-pan-dsi-frame-rate = <60>;
+		qcom,panel-phy-regulatorSettings =[02 08 05 00 20 03];
+		qcom,panel-phy-timingSettings = [8B 1F 14  00 45 4A
+						 19 23 23  03 04 00];
+		qcom,panel-phy-strengthCtrl = [ff 06];
+		qcom,panel-phy-bistCtrl = [03 03 00 00 0f 00];
+		qcom,panel-phy-laneConfig =
+					[80 45 00 00 01 66 /*lane0**/
+					80 45 00 00 01 66 /*lane1*/
+					80 45 00 00 01 66 /*lane2*/
+					80 45 00 00 01 66 /*lane3*/
+					40 67 00 00 01 88]; /*Clk*/
+
+		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+		qcom,panel-on-cmds = [
+					29 01 00 00 00 02
+						00 00
+					29 01 00 00 00 04
+						ff 80 09 01
+					29 01 00 00 00 02
+						00 80
+					29 01 00 00 00 03
+						ff 80 09
+					29 01 00 00 00 02
+						00 80
+					29 01 00 00 00 02
+						d6 48
+					29 01 00 00 00 02
+						00 03
+					29 01 00 00 00 02
+						ff 01
+					29 01 00 00 00 02
+						00 B4
+					29 01 00 00 00 02
+						C0 10
+					29 01 00 00 00 02
+						00 82
+					29 01 00 00 00 02
+						C5 A3
+					29 01 00 00 00 02
+						00 90
+					29 01 00 00 00 03
+						C5 96 87
+					29 01 00 00 00 02
+						00 00
+					29 01 00 00 00 03
+						D8 74 72
+					29 01 00 00 00 02
+						00 00
+					29 01 00 00 00 02
+						D9 56
+					29 01 00 00 00 02
+						00 00
+					29 01 00 00 00 11
+						E1 00 06 0A
+						07 03 16 08
+						0A 04 06 07
+						08 0F 23 22
+						05
+					29 01 00 00 00 02
+						00 00
+					29 01 00 00 00 11
+						E2 00 06 0A
+						07 03 16 08
+						0A 04 06 07
+						08 0F 23 22
+						05
+					29 01 00 00 00 02
+						00 81
+					29 01 00 00 00 02
+						C1 77
+					29 01 00 00 00 02
+						00 A0
+					29 01 00 00 00 02
+						C1 EA
+					29 01 00 00 00 02
+						00 A1
+					29 01 00 00 00 02
+						C1 08
+					29 01 00 00 00 02
+						00 89
+					29 01 00 00 00 02
+						C4 08
+					29 01 00 00 00 02
+						00 81
+					29 01 00 00 00 02
+						C4 83
+					29 01 00 00 00 02
+						00 92
+					29 01 00 00 00 02
+						C5 01
+					29 01 00 00 00 02
+						00 B1
+					29 01 00 00 00 02
+						C5 A9
+					29 01 00 00 00 02
+						00 92
+					29 01 00 00 00 02
+						B3 45
+					29 01 00 00 00 02
+						00 90
+					29 01 00 00 00 02
+						B3 02
+					29 01 00 00 00 02
+						00 80
+					29 01 00 00 00 06
+						C0 00 58 00
+						14 16
+					29 01 00 00 00 02
+						00 80
+					29 01 00 00 00 02
+						C4 30
+					29 01 00 00 00 02
+						00 90
+					29 01 00 00 00 07
+						C0 00 44 00
+						00 00 03
+					29 01 00 00 00 02
+						00 A6
+					29 01 00 00 00 04
+						C1 01 00 00
+					29 01 00 00 00 02
+						00 80
+					29 01 00 00 00 0D
+						CE 87 03 00
+						85 03 00 86
+						03 00 84 03
+						00
+					29 01 00 00 00 02
+						00 A0
+					29 01 00 00 00 0f
+						CE 38 03 03
+						58 00 00 00
+						38 02 03 59
+						00 00 00
+					29 01 00 00 00 02
+						00 B0
+					29 01 00 00 00 0f
+						CE 38 01 03
+						5A 00 00 00
+						38 00 03 5B
+						00 00 00
+					29 01 00 00 00 02
+						00 C0
+					29 01 00 00 00 0f
+						CE 30 00 03
+						5C 00 00 00
+						30 01 03 5D
+						00 00 00
+					29 01 00 00 00 02
+						00 D0
+					29 01 00 00 00 0f
+						CE 30 02 03
+						5E 00 00 00
+						30 03 03 5F
+						00 00 00
+					29 01 00 00 00 02
+						00 C7
+					29 01 00 00 00 02
+						CF 00
+					29 01 00 00 00 02
+						00 C9
+					29 01 00 00 00 02
+						CF 00
+					29 01 00 00 00 02
+						00 D0
+					29 01 00 00 00 02
+						CF 00
+					29 01 00 00 00 02
+						00 C4
+					29 01 00 00 00 07
+						CB 04 04 04
+						04 04 04
+					29 01 00 00 00 02
+						00 D9
+					29 01 00 00 00 07
+						CB 04 04 04
+						04 04 04
+					29 01 00 00 00 02
+						00 84
+					29 01 00 00 00 07
+						CC 0C 0A 10
+						0E 03 04
+					29 01 00 00 00 02
+						00 9E
+					29 01 00 00 00 02
+						CC 0B
+					29 01 00 00 00 02
+						00 A0
+					29 01 00 00 00 06
+						CC 09 0F 0D
+						01 02
+					29 01 00 00 00 02
+						00 B4
+					29 01 00 00 00 07
+						CC 0D 0F 09
+						0B 02 01
+					29 01 00 00 00 02
+						00 CE
+					29 01 00 00 00 02
+						CC 0E
+					29 01 00 00 00 02
+						00 D0
+					29 01 00 00 00 06
+						CC 10 0A 0C
+						04 03
+					29 01 00 00 00 02
+						00 00
+					29 01 00 00 00 04
+						ff ff ff ff
+					05 01 00 00 78 02
+						11 00
+					05 01 00 00 32 02
+						29 00
+					];
+		qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+					05 01 00 00 78 02 10 00];
+		qcom,off-cmds-dsi-state = "DSI_LP_MODE";
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi
new file mode 100644
index 0000000..f57a7bd
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi
@@ -0,0 +1,124 @@
+/* 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.
+ */
+
+/ {
+	qcom,dsi_v2_truly_wvga_video {
+		compatible = "qcom,dsi-panel-v2";
+		label = "Truly WVGA command mode dsi panel";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+		qcom,rst-gpio = <&msmgpio 41 0>;
+		qcom,mode-selection-gpio = <&msmgpio 7 0>;
+		qcom,te-gpio = <&msmgpio 12 0>;
+		vdda-supply = <&pm8110_l19>;
+		vddio-supply=<&pm8110_l14>;
+		qcom,mdss-pan-res = <480 800>;
+		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
+		qcom,mdss-pan-porch-values = <40 8 160 10 2 12>;
+		qcom,mdss-pan-underflow-clr = <0xff>;
+		qcom,mdss-pan-bl-levels = <1 255>;
+		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+		qcom,mdss-pan-dsi-mode = <1>;
+		qcom,mdss-pan-dsi-h-pulse-mode = <0>;
+		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+		qcom,mdss-pan-dsi-traffic-mode = <1>;
+		qcom,mdss-pan-dsi-dst-format = <8>;
+		qcom,mdss-pan-insert-dcs-cmd = <1>;
+		qcom,mdss-pan-wr-mem-continue = <0x3c>;
+		qcom,mdss-pan-wr-mem-start = <0x2c>;
+		qcom,mdss-pan-dsi-vc = <0>;
+		qcom,mdss-pan-dsi-rgb-swap = <0>;
+		qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+		qcom,mdss-pan-dsi-dlane-swap = <0>;
+		qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
+		qcom,mdss-pan-dsi-stream = <0>;
+		qcom,mdss-pan-dsi-mdp-tr = <0x02>;
+		qcom,mdss-pan-dsi-dma-tr = <0x04>;
+		qcom,mdss-pan-dsi-frame-rate = <60>;
+		qcom,panel-phy-regulatorSettings =[02 08 05 00 20 03];
+		qcom,panel-phy-timingSettings = [5D 12 0C  00 33 38
+						 10 16 1E 03 04 00];
+		qcom,panel-phy-strengthCtrl = [ff 06];
+		qcom,panel-phy-bistCtrl = [03 03 00 00 0f 00];
+		qcom,panel-phy-laneConfig =
+					[80 45 00 00 01 66 /*lane0**/
+					80 45 00 00 01 66 /*lane1*/
+					80 45 00 00 01 66 /*lane2*/
+					80 45 00 00 01 66 /*lane3*/
+					40 67 00 00 01 88]; /*Clk*/
+
+		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+		qcom,panel-on-cmds = [
+					05 01 00 00 00 02
+						01 00
+					23 01 00 00 00 02
+						b0 04
+					29 01 00 00 00 03
+						b3 02 00
+					23 01 00 00 00 02
+						bd 00
+					29 01 00 00 00 03
+						c0 18 66
+					29 01 00 00 00 10
+						c1 23 31 99 21 20 00 30 28 0c 0c
+						00 00 00 21 01
+					29 01 00 00 00 07
+						c2 00 06 06 01 03 00
+					29 01 00 00 00 19
+						c8 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 00 19
+						c9 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 00 19
+						ca 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 00 11
+						d0 29 03 ce a6 00 43 20 10 01 00
+						01 01 00 03 01 00
+					29 01 00 00 00 08
+						d1 18 0C 23 03 75 02 50
+					23 01 00 00 00 02
+						d3 11
+					29 01 00 00 00 03
+						d5 2a 2a
+					29 01 00 00 00 03
+						de 01 51
+					23 01 00 00 00 02
+						e6 51
+					23 01 00 00 00 02
+						fa 03
+					23 01 00 00 64 02
+						d6 28
+					15 01 00 00 00 02
+						36 41
+					39 01 00 00 00 05
+						2a 00 00 01 df
+					39 01 00 00 00 05
+						2b 00 00 03 1f
+					15 01 00 00 00 02
+						35 00
+					39 01 00 00 00 03
+						44 00 50
+					15 01 00 00 00 02
+						3a 77
+					05 01 00 00 7D 02
+						11 00
+					05 01 00 00 14 02
+						29 00
+					];
+		qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+					05 01 00 00 78 02 10 00];
+		qcom,off-cmds-dsi-state = "DSI_LP_MODE";
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
index 891eac3..8be8d71 100644
--- a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
@@ -41,7 +41,7 @@
 		qcom,mdss-pan-dsi-mdp-tr = <0x0>;/*todo*/
 		qcom,mdss-pan-dsi-dma-tr = <0x04>;
 		qcom,mdss-pan-dsi-frame-rate = <60>;
-		qcom,panel-phy-regulatorSettings =[09 08 05 00 20 03];
+		qcom,panel-phy-regulatorSettings =[02 08 05 00 20 03];
 		qcom,panel-phy-timingSettings = [5D 12 0C  00 33 38
 						 10 16 1E 03 04 00];
 		qcom,panel-phy-strengthCtrl = [ff 06];
@@ -69,7 +69,7 @@
 						c1 23 31 99 21 20 00 30 28 0c 0c
 						00 00 00 21 01
 					29 01 00 00 00 07
-						c2 10 06 06 01 03 00
+						c2 00 06 06 01 03 00
 					29 01 00 00 00 19
 						c8 04 10 18 20 2e 46 3c 28 1f 18
 						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
@@ -89,7 +89,7 @@
 					29 01 00 00 00 03
 						d5 2a 2a
 					29 01 00 00 00 03
-						de 01 41
+						de 01 51
 					23 01 00 00 00 02
 						e6 51
 					23 01 00 00 00 02
diff --git a/arch/arm/boot/dts/mpq8092-iommu-domains.dtsi b/arch/arm/boot/dts/mpq8092-iommu-domains.dtsi
new file mode 100644
index 0000000..25fca2a
--- /dev/null
+++ b/arch/arm/boot/dts/mpq8092-iommu-domains.dtsi
@@ -0,0 +1,31 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	qcom,iommu-domains {
+		compatible = "qcom,iommu-domains";
+
+		venus_domain_ns: qcom,iommu-domain1 {
+			label = "venus_ns";
+			qcom,iommu-contexts = <&venus_ns>;
+			qcom,virtual-addr-pool = <0x40000000 0x3f000000
+						  0x7f000000 0x1000000>;
+		};
+
+		venus_domain_cp: qcom,iommu-domain2 {
+			label = "venus_cp";
+			qcom,iommu-contexts = <&venus_cp>;
+			qcom,virtual-addr-pool = <0x1000000 0x3f000000>;
+			qcom,secure-domain;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/mpq8092-iommu.dtsi b/arch/arm/boot/dts/mpq8092-iommu.dtsi
index 4fb2b24..baec2d5 100644
--- a/arch/arm/boot/dts/mpq8092-iommu.dtsi
+++ b/arch/arm/boot/dts/mpq8092-iommu.dtsi
@@ -212,3 +212,20 @@
 				0x10
 				0x0>;
 };
+
+&vpu_iommu {
+	status = "ok";
+
+	interrupts = <0 300 0>;
+	vpu_cb_0: qcom,iommu-ctx@fdeec000 {
+		interrupts = <0 302 0>;
+	};
+
+	vpu_cb_1: qcom,iommu-ctx@fdeed000 {
+		interrupts = <0 302 0>;
+	};
+
+	vpu_cb_2: qcom,iommu-ctx@fdeee000 {
+		interrupts = <0 302 0>;
+	};
+};
diff --git a/arch/arm/boot/dts/mpq8092-rumi.dtsi b/arch/arm/boot/dts/mpq8092-rumi.dtsi
index 2016998..cc345d8 100644
--- a/arch/arm/boot/dts/mpq8092-rumi.dtsi
+++ b/arch/arm/boot/dts/mpq8092-rumi.dtsi
@@ -24,13 +24,13 @@
 	};
 
 	qcom,sdcc@f9824000 {
-		status = "disabled";
                 qcom,clk-rates = <400000 19200000>;
+		status = "ok";
         };
 
         qcom,sdcc@f98a4000 {
-		status = "disabled";
                 qcom,clk-rates = <400000 19200000>;
+		status = "ok";
         };
 
 	qcom,sps@f998000 {
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 2eaa32f..2f67f3e 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -21,6 +21,7 @@
 };
 
 /include/ "mpq8092-iommu.dtsi"
+/include/ "mpq8092-iommu-domains.dtsi"
 /include/ "msm-gdsc.dtsi"
 /include/ "mpq8092-ion.dtsi"
 
@@ -140,6 +141,38 @@
                 reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
 	};
 
+	usb@f9a55000 {
+		compatible = "qcom,hsusb-otg";
+		reg = <0xf9a55000 0x400>;
+		interrupts = <0 134 0>, <0 140 0>;
+		interrupt-names = "core_irq", "async_irq";
+
+		HSUSB_VDDCX-supply = <&pma8084_s8>;
+		HSUSB_1p8-supply = <&pma8084_l22>;
+		HSUSB_3p3-supply = <&pma8084_l24>;
+		qcom,vdd-voltage-level = <1050000 1050000>;
+
+		qcom,hsusb-otg-phy-type = <2>;
+		qcom,hsusb-otg-mode = <1>;
+		qcom,hsusb-otg-otg-control = <1>;
+		qcom,hsusb-otg-disable-reset;
+
+		qcom,msm_bus,name = "usb_otg";
+		qcom,msm_bus,num_cases = <3>;
+		qcom,msm_bus,active_only = <0>;
+		qcom,msm_bus,num_paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<87 512 0 0>,
+				<87 512 60000 960000>,
+				<87 512 6000  6000>;
+	};
+
+	android_usb@fe8050c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfe8050c8 0xc8>;
+		qcom,android-usb-swfi-latency = <1>;
+	};
+
 	spmi_bus: qcom,spmi@fc4c0000 {
 		cell-index = <0>;
 		compatible = "qcom,spmi-pmic-arb";
@@ -259,6 +292,10 @@
 	status = "ok";
 };
 
+&gdsc_vpu {
+	status = "ok";
+};
+
 &gdsc_oxili_gx {
 	status = "ok";
 };
diff --git a/arch/arm/boot/dts/msm-pm8110-rpm-regulator.dtsi b/arch/arm/boot/dts/msm-pm8110-rpm-regulator.dtsi
index 0de72b0..f940495 100644
--- a/arch/arm/boot/dts/msm-pm8110-rpm-regulator.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110-rpm-regulator.dtsi
@@ -182,7 +182,7 @@
 		regulator-l8 {
 			compatible = "qcom,rpm-regulator-smd";
 			regulator-name = "8110_l8";
-			qcom,set = <1>;
+			qcom,set = <3>;
 			status = "disabled";
 		};
 	};
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 0e446e2..4f3e461 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -62,10 +62,11 @@
 			qcom,vinmin-mv = <4200>;
 			qcom,vbatdet-mv = <4100>;
 			qcom,ibatmax-ma = <1500>;
-			qcom,ibatterm-ma = <200>;
+			qcom,ibatterm-ma = <100>;
 			qcom,ibatsafe-ma = <1500>;
 			qcom,thermal-mitigation = <1500 700 600 325>;
 			qcom,vbatdet-delta-mv = <350>;
+			qcom,resume-soc = <99>;
 			qcom,tchg-mins = <150>;
 
 			qcom,chgr@1000 {
@@ -609,5 +610,12 @@
 			label = "vibrator";
 			status = "disabled";
 		};
+
+		pwm@bc00 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xbc00 0x100>;
+			reg-names = "qpnp-lpg-channel-base";
+			qcom,channel-id = <0>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
index 1ee7076..23bb4ac 100644
--- a/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
@@ -198,7 +198,7 @@
 		regulator-l8 {
 			compatible = "qcom,rpm-regulator-smd";
 			regulator-name = "8226_l8";
-			qcom,set = <1>;
+			qcom,set = <3>;
 			status = "disabled";
 		};
 	};
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 2008e1e..d7c2155 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -32,10 +32,13 @@
 			reg = <0x800 0x100>;
 			interrupts = <0x0 0x8 0x0>,
 				     <0x0 0x8 0x1>,
-				     <0x0 0x8 0x4>;
-			interrupt-names = "kpdpwr", "resin", "resin-bark";
+				     <0x0 0x8 0x4>,
+				     <0x0 0x8 0x5>;
+			interrupt-names = "kpdpwr", "resin",
+					"resin-bark", "kpdpwr-resin-bark";
 			qcom,pon-dbc-delay = <15625>;
 			qcom,system-reset;
+			qcom,s3-debounce = <32>;
 
 			qcom,pon_1 {
 				qcom,pon-type = <0>;
@@ -52,6 +55,15 @@
 				qcom,s2-type = <1>;
 				linux,code = <114>;
 			};
+
+			qcom,pon_3 {
+				qcom,pon-type = <3>;
+				qcom,support-reset = <1>;
+				qcom,pull-up = <1>;
+				qcom,s1-timer = <6720>;
+				qcom,s2-timer = <2000>;
+				qcom,s2-type = <7>;
+			};
 		};
 
 		pm8226_chg: qcom,charger {
@@ -69,6 +81,7 @@
 			qcom,ibatterm-ma = <100>;
 			qcom,ibatsafe-ma = <1500>;
 			qcom,thermal-mitigation = <1500 700 600 325>;
+			qcom,resume-soc = <99>;
 			qcom,tchg-mins = <150>;
 
 			qcom,chgr@1000 {
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index e72c8cd..2460377 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -15,1384 +15,1419 @@
 	#size-cells = <0>;
 	interrupt-controller;
 	#interrupt-cells = <3>;
+};
 
-	qcom,pm8941@0 {
-		spmi-slave-container;
-		reg = <0x0>;
-		#address-cells = <1>;
-		#size-cells = <1>;
+&pm8941_lsid0 {
+	spmi-slave-container;
+	#address-cells = <1>;
+	#size-cells = <1>;
 
-		pm8941_misc: qcom,misc@900 {
-			compatible = "qcom,qpnp-misc";
-			reg = <0x900 0x100>;
+	pm8941_misc: qcom,misc@900 {
+		compatible = "qcom,qpnp-misc";
+		reg = <0x900 0x100>;
+	};
+
+	qcom,revid@100 {
+		compatible = "qcom,qpnp-revid";
+		reg = <0x100 0x100>;
+	};
+
+	qcom,temp-alarm@2400 {
+		compatible = "qcom,qpnp-temp-alarm";
+		reg = <0x2400 0x100>;
+		interrupts = <0x0 0x24 0x0>;
+		label = "pm8941_tz";
+		qcom,channel-num = <8>;
+		qcom,threshold-set = <0>;
+	};
+
+	qcom,power-on@800 {
+		compatible = "qcom,qpnp-power-on";
+		reg = <0x800 0x100>;
+		interrupts = <0x0 0x8 0x0>,
+			     <0x0 0x8 0x1>,
+			     <0x0 0x8 0x4>,
+			     <0x0 0x8 0x5>;
+		interrupt-names = "kpdpwr", "resin",
+				"resin-bark", "kpdpwr-resin-bark";
+		qcom,pon-dbc-delay = <15625>;
+		qcom,system-reset;
+		qcom,s3-debounce = <32>;
+
+		qcom,pon_1 {
+			qcom,pon-type = <0>;
+			qcom,pull-up = <1>;
+			linux,code = <116>;
 		};
 
-		qcom,revid@100 {
-			compatible = "qcom,qpnp-revid";
-			reg = <0x100 0x100>;
+		qcom,pon_2 {
+			qcom,pon-type = <1>;
+			qcom,support-reset = <1>;
+			qcom,pull-up = <1>;
+			qcom,s1-timer = <0>;
+			qcom,s2-timer = <2000>;
+			qcom,s2-type = <1>;
+			linux,code = <114>;
 		};
 
-		qcom,temp-alarm@2400 {
-			compatible = "qcom,qpnp-temp-alarm";
-			reg = <0x2400 0x100>;
-			interrupts = <0x0 0x24 0x0>;
-			label = "pm8941_tz";
-			qcom,channel-num = <8>;
-			qcom,threshold-set = <0>;
-		};
-
-		qcom,power-on@800 {
-			compatible = "qcom,qpnp-power-on";
-			reg = <0x800 0x100>;
-			interrupts = <0x0 0x8 0x0>,
-				     <0x0 0x8 0x1>,
-				     <0x0 0x8 0x4>,
-				     <0x0 0x8 0x5>;
-			interrupt-names = "kpdpwr", "resin",
-					"resin-bark", "kpdpwr-resin-bark";
-			qcom,pon-dbc-delay = <15625>;
-			qcom,system-reset;
-			qcom,s3-debounce = <32>;
-
-			qcom,pon_1 {
-				qcom,pon-type = <0>;
-				qcom,pull-up = <1>;
-				linux,code = <116>;
-			};
-
-			qcom,pon_2 {
-				qcom,pon-type = <1>;
-				qcom,support-reset = <1>;
-				qcom,pull-up = <1>;
-				qcom,s1-timer = <0>;
-				qcom,s2-timer = <2000>;
-				qcom,s2-type = <1>;
-				linux,code = <114>;
-			};
-
-			qcom,pon_3 {
-				qcom,pon-type = <3>;
-				qcom,support-reset = <1>;
-				qcom,s1-timer = <6720>;
-				qcom,s2-timer = <2000>;
-				qcom,s2-type = <7>;
-				qcom,pull-up = <1>;
-			};
-		};
-
-		bif_ctrl: qcom,bsi@1b00 {
-			compatible = "qcom,qpnp-bsi";
-			reg = <0x1b00 0x100>,
-			      <0x1208 0x1>;
-			reg-names = "bsi-base", "batt-id-status";
-			label = "pm8941-bsi";
-			interrupts = <0x0 0x1b 0x0>,
-				     <0x0 0x1b 0x1>,
-				     <0x0 0x1b 0x2>,
-				     <0x0 0x12 0x0>;
-			interrupt-names = "err",
-					  "rx",
-					  "tx",
-					  "batt-present";
-			qcom,channel-num = <0x31>;
-			qcom,pullup-ohms = <100000>;
-			qcom,vref-microvolts = <1800000>;
-			qcom,min-clock-period = <1000>;
-			qcom,max-clock-period = <160000>;
-			qcom,sample-rate = <4>;
-		};
-
-		pm8941_coincell: qcom,coincell@2800 {
-			compatible = "qcom,qpnp-coincell";
-			reg = <0x2800 0x100>;
-		};
-
-		pm8941_bms: qcom,bms {
-			spmi-dev-container;
-			compatible = "qcom,qpnp-bms";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			status = "disabled";
-
-			qcom,r-sense-uohm = <10000>;
-			qcom,v-cutoff-uv = <3400000>;
-			qcom,max-voltage-uv = <4200000>;
-			qcom,r-conn-mohm = <0>;
-			qcom,shutdown-soc-valid-limit = <20>;
-			qcom,adjust-soc-low-threshold = <15>;
-			qcom,ocv-voltage-high-threshold-uv = <3750000>;
-			qcom,ocv-voltage-low-threshold-uv = <3650000>;
-			qcom,low-soc-calculate-soc-threshold = <15>;
-			qcom,low-soc-calculate-soc-ms = <5000>;
-			qcom,calculate-soc-ms = <20000>;
-			qcom,chg-term-ua = <100000>;
-			qcom,batt-type = <0>;
-			qcom,low-voltage-threshold = <3420000>;
-			qcom,tm-temp-margin = <5000>;
-			qcom,low-ocv-correction-limit-uv = <100>;
-			qcom,high-ocv-correction-limit-uv = <50>;
-			qcom,hold-soc-est = <3>;
-
-			qcom,bms-iadc@3800 {
-				reg = <0x3800 0x100>;
-			};
-
-			qcom,bms-bms@4000 {
-				reg = <0x4000 0x100>;
-				interrupts =	<0x0 0x40 0x0>,
-						<0x0 0x40 0x1>,
-						<0x0 0x40 0x2>,
-						<0x0 0x40 0x3>,
-						<0x0 0x40 0x4>,
-						<0x0 0x40 0x5>,
-						<0x0 0x40 0x6>,
-						<0x0 0x40 0x7>;
-
-				interrupt-names = "cc_thr",
-						  "ocv_for_r",
-						  "good_ocv",
-						  "charge_begin",
-						  "ocv_thr",
-						  "sw_cc_thr",
-						  "vsense_avg",
-						  "vsense_for_r";
-
-			};
-		};
-
-		clkdiv@5b00 {
-			reg = <0x5b00 0x100>;
-			compatible = "qcom,qpnp-clkdiv";
-			qcom,cxo-freq = <19200000>;
-		};
-
-		clkdiv@5c00 {
-			reg = <0x5c00 0x100>;
-			compatible = "qcom,qpnp-clkdiv";
-			qcom,cxo-freq = <19200000>;
-		};
-
-		clkdiv@5d00 {
-			reg = <0x5d00 0x1000>;
-			compatible = "qcom,qpnp-clkdiv";
-			qcom,cxo-freq = <19200000>;
-		};
-
-		pm8941_chg: qcom,charger {
-			spmi-dev-container;
-			compatible = "qcom,qpnp-charger";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			status = "disabled";
-
-			qcom,vddmax-mv = <4200>;
-			qcom,vddsafe-mv = <4230>;
-			qcom,vinmin-mv = <4300>;
-			qcom,ibatmax-ma = <1500>;
-			qcom,ibatterm-ma = <100>;
-			qcom,ibatsafe-ma = <1500>;
-			qcom,thermal-mitigation = <1500 700 600 325>;
-			qcom,cool-bat-decidegc = <100>;
-			qcom,cool-bat-mv = <4100>;
-			qcom,ibatmax-warm-ma = <350>;
-			qcom,warm-bat-decidegc = <450>;
-			qcom,warm-bat-mv = <4100>;
-			qcom,ibatmax-cool-ma = <350>;
-			qcom,vbatdet-delta-mv = <100>;
-			qcom,resume-soc = <99>;
-			qcom,tchg-mins = <150>;
-
-			qcom,chgr@1000 {
-				status = "disabled";
-				reg = <0x1000 0x100>;
-				interrupts =	<0x0 0x10 0x0>,
-						<0x0 0x10 0x1>,
-						<0x0 0x10 0x2>,
-						<0x0 0x10 0x3>,
-						<0x0 0x10 0x4>,
-						<0x0 0x10 0x5>,
-						<0x0 0x10 0x6>,
-						<0x0 0x10 0x7>;
-
-				interrupt-names =	"vbat-det-lo",
-							"vbat-det-hi",
-							"chgwdog",
-							"state-change",
-							"trkl-chg-on",
-							"fast-chg-on",
-							"chg-failed",
-							"chg-done";
-			};
-
-			qcom,buck@1100 {
-				status = "disabled";
-				reg = <0x1100 0x100>;
-				interrupts =	<0x0 0x11 0x0>,
-						<0x0 0x11 0x1>,
-						<0x0 0x11 0x2>,
-						<0x0 0x11 0x3>,
-						<0x0 0x11 0x4>,
-						<0x0 0x11 0x5>,
-						<0x0 0x11 0x6>;
-
-				interrupt-names =	"vbat-ov",
-							"vreg-ov",
-							"overtemp",
-							"vchg-loop",
-							"ichg-loop",
-							"ibat-loop",
-							"vdd-loop";
-			};
-
-			qcom,bat-if@1200 {
-				status = "disabled";
-				reg = <0x1200 0x100>;
-				interrupts =	<0x0 0x12 0x0>,
-						<0x0 0x12 0x1>,
-						<0x0 0x12 0x2>,
-						<0x0 0x12 0x3>,
-						<0x0 0x12 0x4>;
-
-				interrupt-names =	"batt-pres",
-							"bat-temp-ok",
-							"bat-fet-on",
-							"vcp-on",
-							"psi";
-
-			};
-
-			pm8941_chg_otg: qcom,usb-chgpth@1300 {
-				status = "disabled";
-				reg = <0x1300 0x100>;
-				interrupts =	<0 0x13 0x0>,
-						<0 0x13 0x1>,
-						<0x0 0x13 0x2>;
-
-				interrupt-names =	"coarse-det-usb",
-							"usbin-valid",
-							"chg-gone";
-			};
-
-			qcom,dc-chgpth@1400 {
-				status = "disabled";
-				reg = <0x1400 0x100>;
-				interrupts =	<0x0 0x14 0x0>,
-						<0x0 0x14 0x1>;
-
-				interrupt-names =	"coarse-det-dc",
-							"dcin-valid";
-			};
-
-			pm8941_chg_boost: qcom,boost@1500 {
-				status = "disabled";
-				reg = <0x1500 0x100>;
-				interrupts =	<0x0 0x15 0x0>,
-						<0x0 0x15 0x1>;
-
-				interrupt-names =	"boost-pwr-ok",
-							"limit-error";
-			};
-
-			qcom,chg-misc@1600 {
-				status = "disabled";
-				reg = <0x1600 0x100>;
-			};
-		};
-
-		pm8941_gpios: gpios {
-			spmi-dev-container;
-			compatible = "qcom,qpnp-pin";
-			gpio-controller;
-			#gpio-cells = <2>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			label = "pm8941-gpio";
-
-			gpio@c000 {
-				reg = <0xc000 0x100>;
-				qcom,pin-num = <1>;
-			};
-
-			gpio@c100 {
-				reg = <0xc100 0x100>;
-				qcom,pin-num = <2>;
-			};
-
-			gpio@c200 {
-				reg = <0xc200 0x100>;
-				qcom,pin-num = <3>;
-			};
-
-			gpio@c300 {
-				reg = <0xc300 0x100>;
-				qcom,pin-num = <4>;
-			};
-
-			gpio@c400 {
-				reg = <0xc400 0x100>;
-				qcom,pin-num = <5>;
-			};
-
-			gpio@c500 {
-				reg = <0xc500 0x100>;
-				qcom,pin-num = <6>;
-			};
-
-			gpio@c600 {
-				reg = <0xc600 0x100>;
-				qcom,pin-num = <7>;
-			};
-
-			gpio@c700 {
-				reg = <0xc700 0x100>;
-				qcom,pin-num = <8>;
-			};
-
-			gpio@c800 {
-				reg = <0xc800 0x100>;
-				qcom,pin-num = <9>;
-			};
-
-			gpio@c900 {
-				reg = <0xc900 0x100>;
-				qcom,pin-num = <10>;
-			};
-
-			gpio@ca00 {
-				reg = <0xca00 0x100>;
-				qcom,pin-num = <11>;
-			};
-
-			gpio@cb00 {
-				reg = <0xcb00 0x100>;
-				qcom,pin-num = <12>;
-			};
-
-			gpio@cc00 {
-				reg = <0xcc00 0x100>;
-				qcom,pin-num = <13>;
-			};
-
-			gpio@cd00 {
-				reg = <0xcd00 0x100>;
-				qcom,pin-num = <14>;
-			};
-
-			gpio@ce00 {
-				reg = <0xce00 0x100>;
-				qcom,pin-num = <15>;
-			};
-
-			gpio@cf00 {
-				reg = <0xcf00 0x100>;
-				qcom,pin-num = <16>;
-			};
-
-			gpio@d000 {
-				reg = <0xd000 0x100>;
-				qcom,pin-num = <17>;
-			};
-
-			gpio@d100 {
-				reg = <0xd100 0x100>;
-				qcom,pin-num = <18>;
-			};
-
-			gpio@d200 {
-				reg = <0xd200 0x100>;
-				qcom,pin-num = <19>;
-			};
-
-			gpio@d300 {
-				reg = <0xd300 0x100>;
-				qcom,pin-num = <20>;
-			};
-
-			gpio@d400 {
-				reg = <0xd400 0x100>;
-				qcom,pin-num = <21>;
-			};
-
-			gpio@d500 {
-				reg = <0xd500 0x100>;
-				qcom,pin-num = <22>;
-			};
-
-			gpio@d600 {
-				reg = <0xd600 0x100>;
-				qcom,pin-num = <23>;
-			};
-
-			gpio@d700 {
-				reg = <0xd700 0x100>;
-				qcom,pin-num = <24>;
-			};
-
-			gpio@d800 {
-				reg = <0xd800 0x100>;
-				qcom,pin-num = <25>;
-			};
-
-			gpio@d900 {
-				reg = <0xd900 0x100>;
-				qcom,pin-num = <26>;
-			};
-
-			gpio@da00 {
-				reg = <0xda00 0x100>;
-				qcom,pin-num = <27>;
-			};
-
-			gpio@db00 {
-				reg = <0xdb00 0x100>;
-				qcom,pin-num = <28>;
-			};
-
-			gpio@dc00 {
-				reg = <0xdc00 0x100>;
-				qcom,pin-num = <29>;
-			};
-
-			gpio@dd00 {
-				reg = <0xdd00 0x100>;
-				qcom,pin-num = <30>;
-			};
-
-			gpio@de00 {
-				reg = <0xde00 0x100>;
-				qcom,pin-num = <31>;
-			};
-
-			gpio@df00 {
-				reg = <0xdf00 0x100>;
-				qcom,pin-num = <32>;
-			};
-
-			gpio@e000 {
-				reg = <0xe000 0x100>;
-				qcom,pin-num = <33>;
-			};
-
-			gpio@e100 {
-				reg = <0xe100 0x100>;
-				qcom,pin-num = <34>;
-			};
-
-			gpio@e200 {
-				reg = <0xe200 0x100>;
-				qcom,pin-num = <35>;
-			};
-
-			gpio@e300 {
-				reg = <0xe300 0x100>;
-				qcom,pin-num = <36>;
-			};
-		};
-
-		pm8941_mpps: mpps {
-			spmi-dev-container;
-			compatible = "qcom,qpnp-pin";
-			gpio-controller;
-			#gpio-cells = <2>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			label = "pm8941-mpp";
-
-			mpp@a000 {
-				reg = <0xa000 0x100>;
-				qcom,pin-num = <1>;
-			};
-
-			mpp@a100 {
-				reg = <0xa100 0x100>;
-				qcom,pin-num = <2>;
-			};
-
-			mpp@a200 {
-				reg = <0xa200 0x100>;
-				qcom,pin-num = <3>;
-			};
-
-			mpp@a300 {
-				reg = <0xa300 0x100>;
-				qcom,pin-num = <4>;
-			};
-
-			mpp@a400 {
-				reg = <0xa400 0x100>;
-				qcom,pin-num = <5>;
-			};
-
-			mpp@a500 {
-				reg = <0xa500 0x100>;
-				qcom,pin-num = <6>;
-			};
-
-			mpp@a600 {
-				reg = <0xa600 0x100>;
-				qcom,pin-num = <7>;
-			};
-
-			mpp@a700 {
-				reg = <0xa700 0x100>;
-				qcom,pin-num = <8>;
-			};
-		};
-
-		qcom,pm8941_rtc {
-			spmi-dev-container;
-			compatible = "qcom,qpnp-rtc";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			qcom,qpnp-rtc-write = <0>;
-			qcom,qpnp-rtc-alarm-pwrup = <0>;
-
-			qcom,pm8941_rtc_rw@6000 {
-				reg = <0x6000 0x100>;
-			};
-			qcom,pm8941_rtc_alarm@6100 {
-				reg = <0x6100 0x100>;
-				interrupts = <0x0 0x61 0x1>;
-			};
-		};
-
-		pm8941_vadc: vadc@3100 {
-			compatible = "qcom,qpnp-vadc";
-			reg = <0x3100 0x100>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts = <0x0 0x31 0x0>;
-			interrupt-names = "eoc-int-en-set";
-			qcom,adc-bit-resolution = <15>;
-			qcom,adc-vdd-reference = <1800>;
-
-			chan@0 {
-				label = "usb_in";
-				reg = <0>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <4>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@1 {
-				label = "dc_in";
-				reg = <1>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <4>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@2 {
-				label = "vchg_sns";
-				reg = <2>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <3>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@3 {
-				label = "spare1_div3";
-				reg = <3>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@4 {
-				label = "usb_id_mv";
-				reg = <4>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@5 {
-				label = "vcoin";
-				reg = <5>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@6 {
-				label = "vbat_sns";
-				reg = <6>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@7 {
-				label = "vph_pwr";
-				reg = <7>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@8 {
-				label = "die_temp";
-				reg = <8>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <3>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@9 {
-				label = "ref_625mv";
-				reg = <9>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@a {
-				label = "ref_1250v";
-				reg = <0xa>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@30 {
-				label = "batt_therm";
-				reg = <0x30>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <1>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@31 {
-				label = "batt_id";
-				reg = <0x31>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@b2 {
-				label = "xo_therm_pu2";
-				reg = <0xb2>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <4>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@b3 {
-				label = "msm_therm";
-				reg = <0xb3>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@b4 {
-				label = "emmc_therm";
-				reg = <0xb4>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@b5 {
-				label = "pa_therm0";
-				reg = <0xb5>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@b7 {
-				label = "pa_therm1";
-				reg = <0xb7>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@b8 {
-				label = "quiet_therm";
-				reg = <0xb8>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@b9 {
-				label = "usb_id";
-				reg = <0xb9>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@39 {
-				label = "usb_id_nopull";
-				reg = <0x39>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-			};
-		};
-
-		pm8941_iadc: iadc@3600 {
-			compatible = "qcom,qpnp-iadc";
-			reg = <0x3600 0x100>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts = <0x0 0x36 0x0>;
-			interrupt-names = "eoc-int-en-set";
-			qcom,adc-bit-resolution = <16>;
-			qcom,adc-vdd-reference = <1800>;
-
-			chan@0 {
-				label = "internal_rsense";
-				reg = <0>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-		};
-
-		pm8941_adc_tm: qcom,vadc@3400 {
-			compatible = "qcom,qpnp-adc-tm";
-			reg = <0x3400 0x100>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts =	<0x0 0x34 0x0>,
-					<0x0 0x34 0x3>,
-				     <0x0 0x34 0x4>;
-			interrupt-names =	"eoc-int-en-set",
-						"high-thr-en-set",
-						"low-thr-en-set";
-			qcom,adc-bit-resolution = <15>;
-			qcom,adc-vdd-reference = <1800>;
-
-			/* Channel Node */
-			chan@b9 {
-				label = "usb_id";
-				reg = <0xb9>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <3>;
-				qcom,btm-channel-number = <0x48>;
-			};
-
-			chan@30 {
-				label = "batt_therm";
-				reg = <0x30>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <1>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <3>;
-				qcom,btm-channel-number = <0x68>;
-			};
-
-			chan@8 {
-				label = "die_temp";
-				reg = <8>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <3>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <3>;
-				qcom,btm-channel-number = <0x70>;
-			};
-
-			chan@6 {
-				label = "vbat_sns";
-				reg = <6>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <3>;
-				qcom,btm-channel-number = <0x78>;
-			};
-
-			chan@b5 {
-				label = "pa_therm0";
-				reg = <0xb5>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <3>;
-				qcom,btm-channel-number = <0x80>;
-				qcom,thermal-node;
-			};
-
-			chan@b7 {
-				label = "pa_therm1";
-				reg = <0xb7>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <3>;
-				qcom,btm-channel-number = <0x88>;
-				qcom,thermal-node;
-			};
-
-			chan@b4 {
-				label = "emmc_therm";
-				reg = <0xb4>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <3>;
-				qcom,btm-channel-number = <0x90>;
-				qcom,thermal-node;
-			};
-
-			chan@b3 {
-				label = "msm_therm";
-				reg = <0xb3>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <3>;
-				qcom,btm-channel-number = <0x98>;
-				qcom,thermal-node;
-			};
+		qcom,pon_3 {
+			qcom,pon-type = <3>;
+			qcom,support-reset = <1>;
+			qcom,s1-timer = <6720>;
+			qcom,s2-timer = <2000>;
+			qcom,s2-type = <7>;
+			qcom,pull-up = <1>;
 		};
 	};
 
-	qcom,pm8941@1 {
-		spmi-slave-container;
-		reg = <0x1>;
+	bif_ctrl: qcom,bsi@1b00 {
+		compatible = "qcom,qpnp-bsi";
+		reg = <0x1b00 0x100>,
+		      <0x1208 0x1>;
+		reg-names = "bsi-base", "batt-id-status";
+		label = "pm8941-bsi";
+		interrupts = <0x0 0x1b 0x0>,
+			     <0x0 0x1b 0x1>,
+			     <0x0 0x1b 0x2>,
+			     <0x0 0x12 0x0>;
+		interrupt-names = "err",
+				  "rx",
+				  "tx",
+				  "batt-present";
+		qcom,channel-num = <0x31>;
+		qcom,pullup-ohms = <100000>;
+		qcom,vref-microvolts = <1800000>;
+		qcom,min-clock-period = <1000>;
+		qcom,max-clock-period = <160000>;
+		qcom,sample-rate = <4>;
+	};
+
+	pm8941_coincell: qcom,coincell@2800 {
+		compatible = "qcom,qpnp-coincell";
+		reg = <0x2800 0x100>;
+	};
+
+	pm8941_bms: qcom,bms {
+		spmi-dev-container;
+		compatible = "qcom,qpnp-bms";
 		#address-cells = <1>;
 		#size-cells = <1>;
+		status = "disabled";
 
-		regulator@1400 {
-			regulator-name = "8941_s1";
-			spmi-dev-container;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "qcom,qpnp-regulator";
-			reg = <0x1400 0x300>;
-			status = "disabled";
+		qcom,r-sense-uohm = <10000>;
+		qcom,v-cutoff-uv = <3400000>;
+		qcom,max-voltage-uv = <4200000>;
+		qcom,r-conn-mohm = <0>;
+		qcom,shutdown-soc-valid-limit = <20>;
+		qcom,adjust-soc-low-threshold = <15>;
+		qcom,ocv-voltage-high-threshold-uv = <3750000>;
+		qcom,ocv-voltage-low-threshold-uv = <3650000>;
+		qcom,low-soc-calculate-soc-threshold = <15>;
+		qcom,low-soc-calculate-soc-ms = <5000>;
+		qcom,calculate-soc-ms = <20000>;
+		qcom,chg-term-ua = <100000>;
+		qcom,batt-type = <0>;
+		qcom,low-voltage-threshold = <3420000>;
+		qcom,tm-temp-margin = <5000>;
+		qcom,low-ocv-correction-limit-uv = <100>;
+		qcom,high-ocv-correction-limit-uv = <50>;
+		qcom,hold-soc-est = <3>;
 
-			qcom,ctl@1400 {
-				reg = <0x1400 0x100>;
-			};
-			qcom,ps@1500 {
-				reg = <0x1500 0x100>;
-			};
-			qcom,freq@1600 {
-				reg = <0x1600 0x100>;
-			};
+		qcom,bms-iadc@3800 {
+			reg = <0x3800 0x100>;
 		};
 
-		regulator@1700 {
-			regulator-name = "8941_s2";
-			spmi-dev-container;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "qcom,qpnp-regulator";
-			reg = <0x1700 0x300>;
-			status = "disabled";
-
-			qcom,ctl@1700 {
-				reg = <0x1700 0x100>;
-			};
-			qcom,ps@1800 {
-				reg = <0x1800 0x100>;
-			};
-			qcom,freq@1900 {
-				reg = <0x1900 0x100>;
-			};
-		};
-
-		regulator@1a00 {
-			regulator-name = "8941_s3";
-			spmi-dev-container;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "qcom,qpnp-regulator";
-			reg = <0x1a00 0x300>;
-			status = "disabled";
-
-			qcom,ctl@1a00 {
-				reg = <0x1a00 0x100>;
-			};
-			qcom,ps@1b00 {
-				reg = <0x1b00 0x100>;
-			};
-			qcom,freq@1c00 {
-				reg = <0x1c00 0x100>;
-			};
-		};
-
-		regulator@a000 {
-			regulator-name = "8941_boost";
-			reg = <0xa000 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@4000 {
-			regulator-name = "8941_l1";
+		qcom,bms-bms@4000 {
 			reg = <0x4000 0x100>;
-			compatible = "qcom,qpnp-regulator";
+			interrupts =	<0x0 0x40 0x0>,
+					<0x0 0x40 0x1>,
+					<0x0 0x40 0x2>,
+					<0x0 0x40 0x3>,
+					<0x0 0x40 0x4>,
+					<0x0 0x40 0x5>,
+					<0x0 0x40 0x6>,
+					<0x0 0x40 0x7>;
+
+			interrupt-names = "cc_thr",
+					  "ocv_for_r",
+					  "good_ocv",
+					  "charge_begin",
+					  "ocv_thr",
+					  "sw_cc_thr",
+					  "vsense_avg",
+					  "vsense_for_r";
+		};
+	};
+
+	clkdiv@5b00 {
+		reg = <0x5b00 0x100>;
+		compatible = "qcom,qpnp-clkdiv";
+		qcom,cxo-freq = <19200000>;
+	};
+
+	clkdiv@5c00 {
+		reg = <0x5c00 0x100>;
+		compatible = "qcom,qpnp-clkdiv";
+		qcom,cxo-freq = <19200000>;
+	};
+
+	clkdiv@5d00 {
+		reg = <0x5d00 0x1000>;
+		compatible = "qcom,qpnp-clkdiv";
+		qcom,cxo-freq = <19200000>;
+	};
+
+	pm8941_chg: qcom,charger {
+		spmi-dev-container;
+		compatible = "qcom,qpnp-charger";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		status = "disabled";
+
+		qcom,vddmax-mv = <4200>;
+		qcom,vddsafe-mv = <4230>;
+		qcom,vinmin-mv = <4300>;
+		qcom,ibatmax-ma = <1500>;
+		qcom,ibatterm-ma = <100>;
+		qcom,ibatsafe-ma = <1500>;
+		qcom,thermal-mitigation = <1500 700 600 325>;
+		qcom,cool-bat-decidegc = <100>;
+		qcom,cool-bat-mv = <4100>;
+		qcom,ibatmax-warm-ma = <350>;
+		qcom,warm-bat-decidegc = <450>;
+		qcom,warm-bat-mv = <4100>;
+		qcom,ibatmax-cool-ma = <350>;
+		qcom,vbatdet-delta-mv = <100>;
+		qcom,resume-soc = <99>;
+		qcom,tchg-mins = <150>;
+
+		qcom,chgr@1000 {
 			status = "disabled";
+			reg = <0x1000 0x100>;
+			interrupts =	<0x0 0x10 0x0>,
+					<0x0 0x10 0x1>,
+					<0x0 0x10 0x2>,
+					<0x0 0x10 0x3>,
+					<0x0 0x10 0x4>,
+					<0x0 0x10 0x5>,
+					<0x0 0x10 0x6>,
+					<0x0 0x10 0x7>;
+
+			interrupt-names =	"vbat-det-lo",
+						"vbat-det-hi",
+						"chgwdog",
+						"state-change",
+						"trkl-chg-on",
+						"fast-chg-on",
+						"chg-failed",
+						"chg-done";
 		};
 
-		regulator@4100 {
-			regulator-name = "8941_l2";
-			reg = <0x4100 0x100>;
-			compatible = "qcom,qpnp-regulator";
+		qcom,buck@1100 {
 			status = "disabled";
+			reg = <0x1100 0x100>;
+			interrupts =	<0x0 0x11 0x0>,
+					<0x0 0x11 0x1>,
+					<0x0 0x11 0x2>,
+					<0x0 0x11 0x3>,
+					<0x0 0x11 0x4>,
+					<0x0 0x11 0x5>,
+					<0x0 0x11 0x6>;
+
+			interrupt-names =	"vbat-ov",
+						"vreg-ov",
+						"overtemp",
+						"vchg-loop",
+						"ichg-loop",
+						"ibat-loop",
+						"vdd-loop";
 		};
 
-		regulator@4200 {
-			regulator-name = "8941_l3";
-			reg = <0x4200 0x100>;
-			compatible = "qcom,qpnp-regulator";
+		qcom,bat-if@1200 {
 			status = "disabled";
+			reg = <0x1200 0x100>;
+			interrupts =	<0x0 0x12 0x0>,
+					<0x0 0x12 0x1>,
+					<0x0 0x12 0x2>,
+					<0x0 0x12 0x3>,
+					<0x0 0x12 0x4>;
+
+			interrupt-names =	"batt-pres",
+						"bat-temp-ok",
+						"bat-fet-on",
+						"vcp-on",
+						"psi";
+
 		};
 
-		regulator@4300 {
-			regulator-name = "8941_l4";
-			reg = <0x4300 0x100>;
-			compatible = "qcom,qpnp-regulator";
+		pm8941_chg_otg: qcom,usb-chgpth@1300 {
 			status = "disabled";
+			reg = <0x1300 0x100>;
+			interrupts =	<0 0x13 0x0>,
+					<0 0x13 0x1>,
+					<0x0 0x13 0x2>;
+
+			interrupt-names =	"coarse-det-usb",
+						"usbin-valid",
+						"chg-gone";
 		};
 
-		regulator@4400 {
-			regulator-name = "8941_l5";
-			reg = <0x4400 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			qcom,force-type = <0x04 0x10>;
+		qcom,dc-chgpth@1400 {
 			status = "disabled";
+			reg = <0x1400 0x100>;
+			interrupts =	<0x0 0x14 0x0>,
+					<0x0 0x14 0x1>;
+
+			interrupt-names =	"coarse-det-dc",
+						"dcin-valid";
 		};
 
-		regulator@4500 {
-			regulator-name = "8941_l6";
-			reg = <0x4500 0x100>;
-			compatible = "qcom,qpnp-regulator";
+		pm8941_chg_boost: qcom,boost@1500 {
 			status = "disabled";
+			reg = <0x1500 0x100>;
+			interrupts =	<0x0 0x15 0x0>,
+					<0x0 0x15 0x1>;
+
+			interrupt-names =	"boost-pwr-ok",
+						"limit-error";
 		};
 
-		regulator@4600 {
-			regulator-name = "8941_l7";
-			reg = <0x4600 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			qcom,force-type = <0x04 0x10>;
+		qcom,chg-misc@1600 {
 			status = "disabled";
+			reg = <0x1600 0x100>;
 		};
+	};
 
-		regulator@4700 {
-			regulator-name = "8941_l8";
-			reg = <0x4700 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
+	pm8941_gpios: gpios {
+		spmi-dev-container;
+		compatible = "qcom,qpnp-pin";
+		gpio-controller;
+		#gpio-cells = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		label = "pm8941-gpio";
 
-		regulator@4800 {
-			regulator-name = "8941_l9";
-			reg = <0x4800 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@4900 {
-			regulator-name = "8941_l10";
-			reg = <0x4900 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@4a00 {
-			regulator-name = "8941_l11";
-			reg = <0x4a00 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@4b00 {
-			regulator-name = "8941_l12";
-			reg = <0x4b00 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@4c00 {
-			regulator-name = "8941_l13";
-			reg = <0x4c00 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@4d00 {
-			regulator-name = "8941_l14";
-			reg = <0x4d00 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@4e00 {
-			regulator-name = "8941_l15";
-			reg = <0x4e00 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@4f00 {
-			regulator-name = "8941_l16";
-			reg = <0x4f00 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@5000 {
-			regulator-name = "8941_l17";
-			reg = <0x5000 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@5100 {
-			regulator-name = "8941_l18";
-			reg = <0x5100 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@5200 {
-			regulator-name = "8941_l19";
-			reg = <0x5200 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@5300 {
-			regulator-name = "8941_l20";
-			reg = <0x5300 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@5400 {
-			regulator-name = "8941_l21";
-			reg = <0x5400 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@5500 {
-			regulator-name = "8941_l22";
-			reg = <0x5500 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@5600 {
-			regulator-name = "8941_l23";
-			reg = <0x5600 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@5700 {
-			regulator-name = "8941_l24";
-			reg = <0x5700 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@8000 {
-			regulator-name = "8941_lvs1";
-			reg = <0x8000 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@8100 {
-			regulator-name = "8941_lvs2";
-			reg = <0x8100 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@8200 {
-			regulator-name = "8941_lvs3";
-			reg = <0x8200 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@8300 {
-			regulator-name = "8941_mvs1";
-			reg = <0x8300 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		regulator@8400 {
-			regulator-name = "8941_mvs2";
-			reg = <0x8400 0x100>;
-			compatible = "qcom,qpnp-regulator";
-			status = "disabled";
-		};
-
-		qcom,vibrator@c000 {
-			compatible = "qcom,qpnp-vibrator";
+		gpio@c000 {
 			reg = <0xc000 0x100>;
-			label = "vibrator";
-			status = "disabled";
+			qcom,pin-num = <1>;
 		};
 
-		qcom,leds@d000 {
-			compatible = "qcom,leds-qpnp";
+		gpio@c100 {
+			reg = <0xc100 0x100>;
+			qcom,pin-num = <2>;
+		};
+
+		gpio@c200 {
+			reg = <0xc200 0x100>;
+			qcom,pin-num = <3>;
+		};
+
+		gpio@c300 {
+			reg = <0xc300 0x100>;
+			qcom,pin-num = <4>;
+		};
+
+		gpio@c400 {
+			reg = <0xc400 0x100>;
+			qcom,pin-num = <5>;
+		};
+
+		gpio@c500 {
+			reg = <0xc500 0x100>;
+			qcom,pin-num = <6>;
+		};
+
+		gpio@c600 {
+			reg = <0xc600 0x100>;
+			qcom,pin-num = <7>;
+		};
+
+		gpio@c700 {
+			reg = <0xc700 0x100>;
+			qcom,pin-num = <8>;
+		};
+
+		gpio@c800 {
+			reg = <0xc800 0x100>;
+			qcom,pin-num = <9>;
+		};
+
+		gpio@c900 {
+			reg = <0xc900 0x100>;
+			qcom,pin-num = <10>;
+		};
+
+		gpio@ca00 {
+			reg = <0xca00 0x100>;
+			qcom,pin-num = <11>;
+		};
+
+		gpio@cb00 {
+			reg = <0xcb00 0x100>;
+			qcom,pin-num = <12>;
+		};
+
+		gpio@cc00 {
+			reg = <0xcc00 0x100>;
+			qcom,pin-num = <13>;
+		};
+
+		gpio@cd00 {
+			reg = <0xcd00 0x100>;
+			qcom,pin-num = <14>;
+		};
+
+		gpio@ce00 {
+			reg = <0xce00 0x100>;
+			qcom,pin-num = <15>;
+		};
+
+		gpio@cf00 {
+			reg = <0xcf00 0x100>;
+			qcom,pin-num = <16>;
+		};
+
+		gpio@d000 {
 			reg = <0xd000 0x100>;
-			label = "rgb";
+			qcom,pin-num = <17>;
 		};
 
-		qcom,leds@d100 {
-			compatible = "qcom,leds-qpnp";
+		gpio@d100 {
 			reg = <0xd100 0x100>;
-			label = "rgb";
+			qcom,pin-num = <18>;
 		};
 
-		qcom,leds@d200 {
-			compatible = "qcom,leds-qpnp";
+		gpio@d200 {
 			reg = <0xd200 0x100>;
-			label = "rgb";
+			qcom,pin-num = <19>;
 		};
 
-		qcom,leds@d300 {
-			compatible = "qcom,leds-qpnp";
+		gpio@d300 {
 			reg = <0xd300 0x100>;
-			label = "flash";
-			flash_boost-supply = <&pm8941_chg_boost>;
+			qcom,pin-num = <20>;
 		};
 
-		qcom,leds@d400 {
-			compatible = "qcom,leds-qpnp";
+		gpio@d400 {
 			reg = <0xd400 0x100>;
-			label = "flash";
+			qcom,pin-num = <21>;
 		};
 
-		qcom,leds@d500 {
-			compatible = "qcom,leds-qpnp";
+		gpio@d500 {
 			reg = <0xd500 0x100>;
-			label = "flash";
+			qcom,pin-num = <22>;
 		};
 
-		qcom,leds@d600 {
-			compatible = "qcom,leds-qpnp";
+		gpio@d600 {
 			reg = <0xd600 0x100>;
-			label = "flash";
+			qcom,pin-num = <23>;
 		};
 
-		qcom,leds@d700 {
-			compatible = "qcom,leds-qpnp";
+		gpio@d700 {
 			reg = <0xd700 0x100>;
-			label = "flash";
+			qcom,pin-num = <24>;
 		};
 
-		qcom,leds@d800 {
-			compatible = "qcom,leds-qpnp";
+		gpio@d800 {
 			reg = <0xd800 0x100>;
-			label = "wled";
+			qcom,pin-num = <25>;
 		};
 
-		qcom,leds@d900 {
-			compatible = "qcom,leds-qpnp";
+		gpio@d900 {
 			reg = <0xd900 0x100>;
-			label = "wled";
+			qcom,pin-num = <26>;
 		};
 
-		qcom,leds@da00 {
-			compatible = "qcom,leds-qpnp";
+		gpio@da00 {
 			reg = <0xda00 0x100>;
-			label = "wled";
+			qcom,pin-num = <27>;
 		};
 
-		qcom,leds@db00 {
-			compatible = "qcom,leds-qpnp";
+		gpio@db00 {
 			reg = <0xdb00 0x100>;
-			label = "wled";
+			qcom,pin-num = <28>;
 		};
 
-		qcom,leds@dc00 {
-			compatible = "qcom,leds-qpnp";
+		gpio@dc00 {
 			reg = <0xdc00 0x100>;
-			label = "wled";
+			qcom,pin-num = <29>;
 		};
 
-		qcom,leds@dd00 {
-			compatible = "qcom,leds-qpnp";
+		gpio@dd00 {
 			reg = <0xdd00 0x100>;
-			label = "wled";
+			qcom,pin-num = <30>;
 		};
 
-		qcom,leds@de00 {
-			compatible = "qcom,leds-qpnp";
+		gpio@de00 {
 			reg = <0xde00 0x100>;
-			label = "wled";
+			qcom,pin-num = <31>;
 		};
 
-		qcom,leds@df00 {
-			compatible = "qcom,leds-qpnp";
+		gpio@df00 {
 			reg = <0xdf00 0x100>;
-			label = "wled";
+			qcom,pin-num = <32>;
 		};
 
-		qcom,leds@e000 {
-			compatible = "qcom,leds-qpnp";
+		gpio@e000 {
 			reg = <0xe000 0x100>;
-			label = "wled";
+			qcom,pin-num = <33>;
 		};
 
-		qcom,leds@e100 {
-			compatible = "qcom,leds-qpnp";
+		gpio@e100 {
 			reg = <0xe100 0x100>;
-			label = "wled";
+			qcom,pin-num = <34>;
 		};
 
-		pwm@b100 {
-			compatible = "qcom,qpnp-pwm";
-			reg = <0xb100 0x100>,
-			      <0xb042 0x7e>;
-			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
-			qcom,channel-id = <0>;
+		gpio@e200 {
+			reg = <0xe200 0x100>;
+			qcom,pin-num = <35>;
 		};
 
-		pwm@b200 {
-			compatible = "qcom,qpnp-pwm";
-			reg = <0xb200 0x100>,
-			      <0xb042 0x7e>;
-			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
-			qcom,channel-id = <1>;
+		gpio@e300 {
+			reg = <0xe300 0x100>;
+			qcom,pin-num = <36>;
+		};
+	};
+
+	pm8941_mpps: mpps {
+		spmi-dev-container;
+		compatible = "qcom,qpnp-pin";
+		gpio-controller;
+		#gpio-cells = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		label = "pm8941-mpp";
+
+		mpp@a000 {
+			reg = <0xa000 0x100>;
+			qcom,pin-num = <1>;
 		};
 
-		pwm@b300 {
-			compatible = "qcom,qpnp-pwm";
-			reg = <0xb300 0x100>,
-			      <0xb042 0x7e>;
-			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
-			qcom,channel-id = <2>;
+		mpp@a100 {
+			reg = <0xa100 0x100>;
+			qcom,pin-num = <2>;
 		};
 
-		pwm@b400 {
-			compatible = "qcom,qpnp-pwm";
-			reg = <0xb400 0x100>,
-			      <0xb042 0x7e>;
-			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
-			qcom,channel-id = <3>;
+		mpp@a200 {
+			reg = <0xa200 0x100>;
+			qcom,pin-num = <3>;
 		};
 
-		pwm@b500 {
-			compatible = "qcom,qpnp-pwm";
-			reg = <0xb500 0x100>,
-			      <0xb042 0x7e>;
-			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
-			qcom,channel-id = <4>;
+		mpp@a300 {
+			reg = <0xa300 0x100>;
+			qcom,pin-num = <4>;
 		};
 
-		pwm@b600 {
-			compatible = "qcom,qpnp-pwm";
-			reg = <0xb600 0x100>,
-			      <0xb042 0x7e>;
-			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
-			qcom,channel-id = <5>;
+		mpp@a400 {
+			reg = <0xa400 0x100>;
+			qcom,pin-num = <5>;
 		};
 
-		pwm@b700 {
-			compatible = "qcom,qpnp-pwm";
-			reg = <0xb700 0x100>,
-			      <0xb042 0x7e>;
-			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
-			qcom,channel-id = <6>;
+		mpp@a500 {
+			reg = <0xa500 0x100>;
+			qcom,pin-num = <6>;
 		};
 
-		pwm@b800 {
-			compatible = "qcom,qpnp-pwm";
-			reg = <0xb800 0x100>,
-			      <0xb042 0x7e>;
-			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
-			qcom,channel-id = <7>;
+		mpp@a600 {
+			reg = <0xa600 0x100>;
+			qcom,pin-num = <7>;
 		};
+
+		mpp@a700 {
+			reg = <0xa700 0x100>;
+			qcom,pin-num = <8>;
+		};
+	};
+
+	qcom,pm8941_rtc {
+		spmi-dev-container;
+		compatible = "qcom,qpnp-rtc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		qcom,qpnp-rtc-write = <0>;
+		qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+		qcom,pm8941_rtc_rw@6000 {
+			reg = <0x6000 0x100>;
+		};
+		qcom,pm8941_rtc_alarm@6100 {
+			reg = <0x6100 0x100>;
+			interrupts = <0x0 0x61 0x1>;
+		};
+	};
+
+	pm8941_vadc: vadc@3100 {
+		compatible = "qcom,qpnp-vadc";
+		reg = <0x3100 0x100>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupts = <0x0 0x31 0x0>;
+		interrupt-names = "eoc-int-en-set";
+		qcom,adc-bit-resolution = <15>;
+		qcom,adc-vdd-reference = <1800>;
+
+		chan@0 {
+			label = "usb_in";
+			reg = <0>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <4>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@1 {
+			label = "dc_in";
+			reg = <1>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <4>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@2 {
+			label = "vchg_sns";
+			reg = <2>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <3>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@3 {
+			label = "spare1_div3";
+			reg = <3>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <1>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@4 {
+			label = "usb_id_mv";
+			reg = <4>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <1>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@5 {
+			label = "vcoin";
+			reg = <5>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <1>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@6 {
+			label = "vbat_sns";
+			reg = <6>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <1>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@7 {
+			label = "vph_pwr";
+			reg = <7>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <1>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@8 {
+			label = "die_temp";
+			reg = <8>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <3>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@9 {
+			label = "ref_625mv";
+			reg = <9>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@a {
+			label = "ref_1250v";
+			reg = <0xa>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@30 {
+			label = "batt_therm";
+			reg = <0x30>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <1>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@31 {
+			label = "batt_id";
+			reg = <0x31>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@b2 {
+			label = "xo_therm_pu2";
+			reg = <0xb2>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <4>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@b3 {
+			label = "msm_therm";
+			reg = <0xb3>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <2>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@b4 {
+			label = "emmc_therm";
+			reg = <0xb4>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <2>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@b5 {
+			label = "pa_therm0";
+			reg = <0xb5>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <2>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@b7 {
+			label = "pa_therm1";
+			reg = <0xb7>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <2>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@b8 {
+			label = "quiet_therm";
+			reg = <0xb8>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <2>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@b9 {
+			label = "usb_id";
+			reg = <0xb9>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <0>;
+		};
+
+		chan@39 {
+			label = "usb_id_nopull";
+			reg = <0x39>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <0>;
+		};
+	};
+
+	pm8941_iadc: iadc@3600 {
+		compatible = "qcom,qpnp-iadc";
+		reg = <0x3600 0x100>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupts = <0x0 0x36 0x0>;
+		interrupt-names = "eoc-int-en-set";
+		qcom,adc-bit-resolution = <16>;
+		qcom,adc-vdd-reference = <1800>;
+
+		chan@0 {
+			label = "internal_rsense";
+			reg = <0>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <1>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <0>;
+		};
+	};
+
+	pm8941_adc_tm: qcom,vadc@3400 {
+		compatible = "qcom,qpnp-adc-tm";
+		reg = <0x3400 0x100>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupts =	<0x0 0x34 0x0>,
+				<0x0 0x34 0x3>,
+			     <0x0 0x34 0x4>;
+		interrupt-names =	"eoc-int-en-set",
+					"high-thr-en-set",
+					"low-thr-en-set";
+		qcom,adc-bit-resolution = <15>;
+		qcom,adc-vdd-reference = <1800>;
+
+		/* Channel Node */
+		chan@b9 {
+			label = "usb_id";
+			reg = <0xb9>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <2>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <3>;
+			qcom,btm-channel-number = <0x48>;
+		};
+
+		chan@30 {
+			label = "batt_therm";
+			reg = <0x30>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <1>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <3>;
+			qcom,btm-channel-number = <0x68>;
+		};
+
+		chan@8 {
+			label = "die_temp";
+			reg = <8>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <3>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <3>;
+			qcom,btm-channel-number = <0x70>;
+		};
+
+		chan@6 {
+			label = "vbat_sns";
+			reg = <6>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <1>;
+			qcom,calibration-type = "absolute";
+			qcom,scale-function = <0>;
+			qcom,hw-settle-time = <0>;
+			qcom,fast-avg-setup = <3>;
+			qcom,btm-channel-number = <0x78>;
+		};
+
+		chan@b5 {
+			label = "pa_therm0";
+			reg = <0xb5>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <2>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <3>;
+			qcom,btm-channel-number = <0x80>;
+			qcom,thermal-node;
+		};
+
+		chan@b7 {
+			label = "pa_therm1";
+			reg = <0xb7>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <2>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <3>;
+			qcom,btm-channel-number = <0x88>;
+			qcom,thermal-node;
+		};
+
+		chan@b4 {
+			label = "emmc_therm";
+			reg = <0xb4>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <2>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <3>;
+			qcom,btm-channel-number = <0x90>;
+			qcom,thermal-node;
+		};
+
+		chan@b3 {
+			label = "msm_therm";
+			reg = <0xb3>;
+			qcom,decimation = <0>;
+			qcom,pre-div-channel-scaling = <0>;
+			qcom,calibration-type = "ratiometric";
+			qcom,scale-function = <2>;
+			qcom,hw-settle-time = <2>;
+			qcom,fast-avg-setup = <3>;
+			qcom,btm-channel-number = <0x98>;
+			qcom,thermal-node;
+		};
+	};
+};
+
+&pm8941_lsid1 {
+	spmi-slave-container;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	regulator@1400 {
+		regulator-name = "8941_s1";
+		spmi-dev-container;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "qcom,qpnp-regulator";
+		reg = <0x1400 0x300>;
+		status = "disabled";
+
+		qcom,ctl@1400 {
+			reg = <0x1400 0x100>;
+		};
+		qcom,ps@1500 {
+			reg = <0x1500 0x100>;
+		};
+		qcom,freq@1600 {
+			reg = <0x1600 0x100>;
+		};
+	};
+
+	regulator@1700 {
+		regulator-name = "8941_s2";
+		spmi-dev-container;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "qcom,qpnp-regulator";
+		reg = <0x1700 0x300>;
+		status = "disabled";
+
+		qcom,ctl@1700 {
+			reg = <0x1700 0x100>;
+		};
+		qcom,ps@1800 {
+			reg = <0x1800 0x100>;
+		};
+		qcom,freq@1900 {
+			reg = <0x1900 0x100>;
+		};
+	};
+
+	regulator@1a00 {
+		regulator-name = "8941_s3";
+		spmi-dev-container;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "qcom,qpnp-regulator";
+		reg = <0x1a00 0x300>;
+		status = "disabled";
+
+		qcom,ctl@1a00 {
+			reg = <0x1a00 0x100>;
+		};
+		qcom,ps@1b00 {
+			reg = <0x1b00 0x100>;
+		};
+		qcom,freq@1c00 {
+			reg = <0x1c00 0x100>;
+		};
+	};
+
+	regulator@a000 {
+		regulator-name = "8941_boost";
+		reg = <0xa000 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4000 {
+		regulator-name = "8941_l1";
+		reg = <0x4000 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4100 {
+		regulator-name = "8941_l2";
+		reg = <0x4100 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4200 {
+		regulator-name = "8941_l3";
+		reg = <0x4200 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4300 {
+		regulator-name = "8941_l4";
+		reg = <0x4300 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4400 {
+		regulator-name = "8941_l5";
+		reg = <0x4400 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		qcom,force-type = <0x04 0x10>;
+		status = "disabled";
+	};
+
+	regulator@4500 {
+		regulator-name = "8941_l6";
+		reg = <0x4500 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4600 {
+		regulator-name = "8941_l7";
+		reg = <0x4600 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		qcom,force-type = <0x04 0x10>;
+		status = "disabled";
+	};
+
+	regulator@4700 {
+		regulator-name = "8941_l8";
+		reg = <0x4700 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4800 {
+		regulator-name = "8941_l9";
+		reg = <0x4800 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4900 {
+		regulator-name = "8941_l10";
+		reg = <0x4900 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4a00 {
+		regulator-name = "8941_l11";
+		reg = <0x4a00 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4b00 {
+		regulator-name = "8941_l12";
+		reg = <0x4b00 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4c00 {
+		regulator-name = "8941_l13";
+		reg = <0x4c00 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4d00 {
+		regulator-name = "8941_l14";
+		reg = <0x4d00 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4e00 {
+		regulator-name = "8941_l15";
+		reg = <0x4e00 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@4f00 {
+		regulator-name = "8941_l16";
+		reg = <0x4f00 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@5000 {
+		regulator-name = "8941_l17";
+		reg = <0x5000 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@5100 {
+		regulator-name = "8941_l18";
+		reg = <0x5100 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@5200 {
+		regulator-name = "8941_l19";
+		reg = <0x5200 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@5300 {
+		regulator-name = "8941_l20";
+		reg = <0x5300 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@5400 {
+		regulator-name = "8941_l21";
+		reg = <0x5400 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@5500 {
+		regulator-name = "8941_l22";
+		reg = <0x5500 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@5600 {
+		regulator-name = "8941_l23";
+		reg = <0x5600 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@5700 {
+		regulator-name = "8941_l24";
+		reg = <0x5700 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@8000 {
+		regulator-name = "8941_lvs1";
+		reg = <0x8000 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@8100 {
+		regulator-name = "8941_lvs2";
+		reg = <0x8100 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@8200 {
+		regulator-name = "8941_lvs3";
+		reg = <0x8200 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@8300 {
+		regulator-name = "8941_mvs1";
+		reg = <0x8300 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	regulator@8400 {
+		regulator-name = "8941_mvs2";
+		reg = <0x8400 0x100>;
+		compatible = "qcom,qpnp-regulator";
+		status = "disabled";
+	};
+
+	qcom,vibrator@c000 {
+		compatible = "qcom,qpnp-vibrator";
+		reg = <0xc000 0x100>;
+		label = "vibrator";
+		status = "disabled";
+	};
+
+	qcom,leds@d000 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xd000 0x100>;
+		label = "rgb";
+	};
+
+	qcom,leds@d100 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xd100 0x100>;
+		label = "rgb";
+	};
+
+	qcom,leds@d200 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xd200 0x100>;
+		label = "rgb";
+	};
+
+	qcom,leds@d300 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xd300 0x100>;
+		label = "flash";
+		flash_boost-supply = <&pm8941_chg_boost>;
+	};
+
+	qcom,leds@d400 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xd400 0x100>;
+		label = "flash";
+	};
+
+	qcom,leds@d500 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xd500 0x100>;
+		label = "flash";
+	};
+
+	qcom,leds@d600 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xd600 0x100>;
+		label = "flash";
+	};
+
+	qcom,leds@d700 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xd700 0x100>;
+		label = "flash";
+	};
+
+	qcom,leds@d800 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xd800 0x100>;
+		label = "wled";
+	};
+
+	qcom,leds@d900 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xd900 0x100>;
+		label = "wled";
+	};
+
+	qcom,leds@da00 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xda00 0x100>;
+		label = "wled";
+	};
+
+	qcom,leds@db00 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xdb00 0x100>;
+		label = "wled";
+	};
+
+	qcom,leds@dc00 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xdc00 0x100>;
+		label = "wled";
+	};
+
+	qcom,leds@dd00 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xdd00 0x100>;
+		label = "wled";
+	};
+
+	qcom,leds@de00 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xde00 0x100>;
+		label = "wled";
+	};
+
+	qcom,leds@df00 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xdf00 0x100>;
+		label = "wled";
+	};
+
+	qcom,leds@e000 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xe000 0x100>;
+		label = "wled";
+	};
+
+	qcom,leds@e100 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xe100 0x100>;
+		label = "wled";
+	};
+
+	qcom,leds@e200 {
+		compatible = "qcom,leds-qpnp";
+		reg = <0xe200 0x100>;
+		label = "kpdbl";
+	};
+
+	pwm@b100 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xb100 0x100>,
+		      <0xb042 0x7e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <0>;
+	};
+
+	pwm@b200 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xb200 0x100>,
+		      <0xb042 0x7e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <1>;
+	};
+
+	pwm@b300 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xb300 0x100>,
+		      <0xb042 0x7e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <2>;
+	};
+
+	pwm@b400 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xb400 0x100>,
+		      <0xb042 0x7e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <3>;
+	};
+
+	pwm@b500 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xb500 0x100>,
+		      <0xb042 0x7e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <4>;
+	};
+
+	pwm@b600 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xb600 0x100>,
+		      <0xb042 0x7e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <5>;
+	};
+
+	pwm@b700 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xb700 0x100>,
+		      <0xb042 0x7e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <6>;
+	};
+
+	pwm@b800 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xb800 0x100>,
+		      <0xb042 0x7e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <7>;
+	};
+
+	pwm@e400 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xe400 0x100>,
+		      <0xe342 0x1e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <8>;
+	};
+
+	pwm@e500 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xe500 0x100>,
+		      <0xe342 0x1e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <9>;
+	};
+
+	pwm@e600 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xe600 0x100>,
+		      <0xe342 0x1e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <10>;
+	};
+
+	pwm@e700 {
+		compatible = "qcom,qpnp-pwm";
+		reg = <0xe700 0x100>,
+		      <0xe342 0x1e>;
+		reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+		qcom,channel-id = <11>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm-pma8084-rpm-regulator.dtsi b/arch/arm/boot/dts/msm-pma8084-rpm-regulator.dtsi
new file mode 100644
index 0000000..31796dd
--- /dev/null
+++ b/arch/arm/boot/dts/msm-pma8084-rpm-regulator.dtsi
@@ -0,0 +1,712 @@
+/* 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.
+ */
+
+&rpm_bus {
+	rpm-regulator-smpa1 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s1 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa2 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s2 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s2";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa3 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s3 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s4 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s4";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa5 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s5 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s5";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa6 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <6>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s6 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s6";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa7 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <7>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s7 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s7";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa8 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <8>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s8 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s8";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa9 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <9>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s9 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s9";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa10 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <10>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s10 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s10";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa11 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <11>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s11 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s11";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa12 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <12>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s12 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s12";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l1 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l2 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l2";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l3 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l4 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l4";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l5 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l5";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <6>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l6 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l6";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <7>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l7 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l7";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <8>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l8 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l8";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <9>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l9 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l9";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <10>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l10 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l10";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <11>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l11 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l11";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <12>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l12 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l12";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa13 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <13>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l13 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l13";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <14>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l14 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l14";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <15>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l15 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l15";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <16>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l16 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l16";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <17>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l17 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l17";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <18>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l18 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l18";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa19 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <19>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l19 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l19";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa20 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <20>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l20 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l20";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa21 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <21>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l21 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l21";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa22 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <22>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l22 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l22";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa23 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <23>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l23 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l23";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa24 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <24>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l24 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l24";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa25 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <25>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l25 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l25";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa26 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <26>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l26 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l26";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa27 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <27>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l27 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_l27";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-vsa1 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "vsa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <2>;
+		status = "disabled";
+
+		regulator-lvs1 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_lvs1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-vsa2 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "vsa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <2>;
+		status = "disabled";
+
+		regulator-lvs2 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_lvs2";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-vsa3 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "vsa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <2>;
+		status = "disabled";
+
+		regulator-lvs3 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_lvs3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-vsa4 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "vsa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <2>;
+		status = "disabled";
+
+		regulator-lvs4 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_lvs4";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-vsa5 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "vsa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <2>;
+		status = "disabled";
+
+		regulator-mvs1 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_mvs1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm-pma8084.dtsi b/arch/arm/boot/dts/msm-pma8084.dtsi
index 42c48f8..ecbfc53 100644
--- a/arch/arm/boot/dts/msm-pma8084.dtsi
+++ b/arch/arm/boot/dts/msm-pma8084.dtsi
@@ -22,6 +22,68 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 
+		qcom,revid@100 {
+			compatible = "qcom,qpnp-revid";
+			reg = <0x100 0x100>;
+		};
+
+		qcom,power-on@800 {
+			compatible = "qcom,qpnp-power-on";
+			reg = <0x800 0x100>;
+			interrupts = <0x0 0x8 0x0>,
+				     <0x0 0x8 0x1>,
+				     <0x0 0x8 0x4>,
+				     <0x0 0x8 0x5>;
+			interrupt-names = "kpdpwr", "resin",
+					"resin-bark", "kpdpwr-resin-bark";
+			qcom,pon-dbc-delay = <15625>;
+			qcom,system-reset;
+			qcom,s3-debounce = <32>;
+
+			qcom,pon_1 {
+				qcom,pon-type = <0>;
+				qcom,pull-up = <1>;
+				linux,code = <116>;
+			};
+
+			qcom,pon_2 {
+				qcom,pon-type = <1>;
+				qcom,support-reset = <1>;
+				qcom,pull-up = <1>;
+				qcom,s1-timer = <0>;
+				qcom,s2-timer = <2000>;
+				qcom,s2-type = <1>;
+				linux,code = <114>;
+			};
+
+			qcom,pon_3 {
+				qcom,pon-type = <3>;
+				qcom,support-reset = <1>;
+				qcom,s1-timer = <6720>;
+				qcom,s2-timer = <2000>;
+				qcom,s2-type = <7>;
+				qcom,pull-up = <1>;
+			};
+		};
+
+		pma8084_misc: qcom,misc@900 {
+			compatible = "qcom,qpnp-misc";
+			reg = <0x900 0x100>;
+		};
+
+		qcom,temp-alarm@2400 {
+			compatible = "qcom,qpnp-temp-alarm";
+			reg = <0x2400 0x100>;
+			interrupts = <0x0 0x24 0x0>;
+			label = "pma8084_tz";
+			qcom,threshold-set = <0>;
+		};
+
+		qcom,coincell@2800 {
+			compatible = "qcom,qpnp-coincell";
+			reg = <0x2800 0x100>;
+		};
+
 		pma8084_gpios: gpios {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-pin";
@@ -261,6 +323,23 @@
 			qcom,adc-bit-resolution = <15>;
 			qcom,adc-vdd-reference = <1800>;
 		};
+
+		qcom,rtc {
+			compatible = "qcom,qpnp-rtc";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			qcom,qpnp-rtc-write = <0>;
+			qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+			qcom,rtc_rw@6000 {
+				reg = <0x6000 0x100>;
+			};
+			qcom,rtc_alarm@6100 {
+				reg = <0x6100 0x100>;
+				interrupts = <0x0 0x61 0x1>;
+			};
+		};
 	};
 
 	qcom,pma8084@1 {
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
index 3935dbb..fb24a25 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
@@ -68,6 +68,57 @@
 		qcom,cci-master = <0>;
 	};
 
+	actuator1: qcom,actuator@18 {
+		cell-index = <4>;
+		reg = <0x18>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+	};
+
+	qcom,camera@6c {
+		compatible = "qcom,ov12830";
+		reg = <0x6c>;
+		qcom,slave-id = <0x20 0x300a 0xc830>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,actuator-src = <&actuator1>;
+		qcom,led-flash-src = <&led_flash0>;
+		qcom,mount-angle = <270>;
+		qcom,sensor-name = "skuf_ov12830_p12v01c";
+		cam_vdig-supply = <&pm8226_l5>;
+		cam_vana-supply = <&pm8226_l19>;
+		cam_vio-supply = <&pm8226_lvs1>;
+		cam_vaf-supply = <&pm8226_l15>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+                             "cam_vaf";
+		qcom,cam-vreg-type = <0 1 0 0>;
+		qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>;
+		qcom,cam-vreg-max-voltage = <1200000 0  2850000 2800000>;
+		qcom,cam-vreg-op-mode = <120000 0 0 80000 100000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 26 0>,
+			<&msmgpio 37 0>,
+			<&msmgpio 36 0>,
+			<&msmgpio 22 0>,
+			<&msmgpio 34 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-vdig = <3>;
+		qcom,gpio-af-pwdm = <4>;
+		qcom,gpio-req-tbl-num = <0 1 2 3 4>;
+		qcom,gpio-req-tbl-flags = <1 0 0 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+			"CAM_RESET1",
+			"CAM_STANDBY",
+			"CAM_VDIG",
+			"CAM_AF_PWDM";
+		qcom,csi-lane-assign = <0x4320>;
+		qcom,csi-lane-mask = <0x1f>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+	};
+
 	qcom,camera@6d {
 		compatible = "qcom,ov9724";
 		reg = <0x6d>;
@@ -105,4 +156,45 @@
 		qcom,cci-master = <0>;
 		status = "ok";
 	};
+
+	qcom,camera@6a {
+		compatible = "qcom,ov5648";
+		reg = <0x6a>;
+		qcom,slave-id = <0x6c 0x300a 0x5648>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <270>;
+		qcom,sensor-name = "skuf_ov5648_p5v23c";
+		cam_vdig-supply = <&pm8226_l5>;
+		cam_vana-supply = <&pm8226_l19>;
+		cam_vio-supply = <&pm8226_lvs1>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-type = <0 1 0>;
+		qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+		qcom,cam-vreg-op-mode = <200000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 26 0>,
+				<&msmgpio 28 0>,
+				<&msmgpio 35 0>,
+				<&msmgpio 21 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-vdig = <3>;
+		qcom,gpio-req-tbl-num = <0 1 2 3>;
+		qcom,gpio-req-tbl-flags = <1 0 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+				"CAM_RESET",
+				"CAM_STANDBY",
+				"CAM_VDIG";
+		qcom,gpio-set-tbl-num = <1 1>;
+		qcom,gpio-set-tbl-flags = <0 2>;
+		qcom,gpio-set-tbl-delay = <1000 4000>;
+		qcom,csi-lane-assign = <0x4320>;
+		qcom,csi-lane-mask = <0x3>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+		status = "ok";
+	};
 };
diff --git a/arch/arm/boot/dts/msm8226-camera.dtsi b/arch/arm/boot/dts/msm8226-camera.dtsi
index ec0092d..617d738 100644
--- a/arch/arm/boot/dts/msm8226-camera.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera.dtsi
@@ -125,15 +125,39 @@
 		qcom,gpio-tbl-flags = <1 1>;
 		qcom,gpio-tbl-label = "CCI_I2C_DATA0",
 				      "CCI_I2C_CLK0";
-		qcom,hw-thigh = <78>;
-		qcom,hw-tlow = <114>;
-		qcom,hw-tsu-sto = <28>;
-		qcom,hw-tsu-sta = <28>;
-		qcom,hw-thd-dat = <10>;
-		qcom,hw-thd-sta = <77>;
-		qcom,hw-tbuf = <118>;
-		qcom,hw-scl-stretch-en = <0>;
-		qcom,hw-trdhld = <6>;
-		qcom,hw-tsp = <1>;
+		master0: qcom,cci-master0 {
+			status = "disabled";
+		};
+		master1: qcom,cci-master1 {
+			status = "disabled";
+		};
 	};
 };
+
+&master0 {
+	qcom,hw-thigh = <78>;
+	qcom,hw-tlow = <114>;
+	qcom,hw-tsu-sto = <28>;
+	qcom,hw-tsu-sta = <28>;
+	qcom,hw-thd-dat = <10>;
+	qcom,hw-thd-sta = <77>;
+	qcom,hw-tbuf = <118>;
+	qcom,hw-scl-stretch-en = <0>;
+	qcom,hw-trdhld = <6>;
+	qcom,hw-tsp = <1>;
+	status = "ok";
+};
+
+&master1 {
+	qcom,hw-thigh = <78>;
+	qcom,hw-tlow = <114>;
+	qcom,hw-tsu-sto = <28>;
+	qcom,hw-tsu-sta = <28>;
+	qcom,hw-thd-dat = <10>;
+	qcom,hw-thd-sta = <77>;
+	qcom,hw-tbuf = <118>;
+	qcom,hw-scl-stretch-en = <0>;
+	qcom,hw-trdhld = <6>;
+	qcom,hw-tsp = <1>;
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index e5683fb..d94b41d 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -35,6 +35,7 @@
 			synaptics,irq-gpio = <&msmgpio 17 0x2008>;
 			synaptics,button-map = <139 102 158>;
 			synaptics,i2c-pull-up;
+			synaptics,power-down;
 		};
 	};
 
@@ -75,7 +76,7 @@
 			compatible = "micrel,ks8851";
 			reg = <3>;
 			interrupt-parent = <&msmgpio>;
-			interrupts = <0 115 0>;
+			interrupts = <115 0x8>;
 			spi-max-frequency = <4800000>;
 			rst-gpio = <&msmgpio 114 0>;
 			vdd-io-supply = <&pm8226_lvs1>;
@@ -114,8 +115,6 @@
 
 &sdcc1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
@@ -140,8 +139,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
@@ -227,6 +224,16 @@
 	status = "ok";
 };
 
+&sdcc3 {
+	qcom,sup-voltages = <1800 1800>;
+	status = "disabled";
+};
+
+&sdhc_3 {
+	qcom,sup-voltages = <1800 1800>;
+	status = "disabled";
+};
+
 &spmi_bus {
 	qcom,pm8226@0 {
 		qcom,leds@a100 {
@@ -261,8 +268,12 @@
 				qcom,mode-ctrl = <0x60>;
 				qcom,pwm-channel = <0>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
@@ -283,8 +294,12 @@
 				qcom,source-sel = <10>;
 				qcom,pwm-channel = <5>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index 11f6369..cbfdfc9 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -16,6 +16,8 @@
 		reg = <0xfc322000 0x1000>,
 		      <0xfc37c000 0x3000>;
 		reg-names = "tmc-base", "bam-base";
+		interrupts = <0 166 0>;
+		interrupt-names = "byte-cntr-irq";
 
 		qcom,memory-reservation-type = "EBI1";
 		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index f580897..5f991fb 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -36,6 +36,7 @@
 		qcom,mdss-wb-off = <0x00011100 0x00013100>;
 		qcom,mdss-intf-off = <0x00000000 0x00021300>;
 		qcom,mdss-rot-block-size = <64>;
+		qcom,mdss-smp-mb-per-pipe = <2>;
 
 		qcom,vbif-settings = <0x004 0x00000001>,
 				     <0x0D8 0x00000707>,
@@ -61,14 +62,54 @@
 		label = "MDSS DSI CTRL->0";
 		cell-index = <0>;
 		reg = <0xfd922800 0x600>;
+		qcom,mdss-fb-map = <&mdss_fb0>;
 		vdd-supply = <&pm8226_l15>;
 		vddio-supply = <&pm8226_l8>;
 		vdda-supply = <&pm8226_l4>;
-		qcom,supply-names = "vdd", "vddio", "vdda";
-		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>;
+		qcom,platform-reset-gpio = <&msmgpio 25 1>;
+		qcom,platform-te-gpio = <&msmgpio 24 0>;
+		qcom,platform-strength-ctrl = [ff 06];
+		qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];
+		qcom,platform-regulator-settings = [07 09 03 00 20 00 01];
+		qcom,platform-lane-config = [00 00 00 00 00 00 00 01 97
+			00 00 00 00 05 00 00 01 97
+			00 00 00 00 0a 00 00 01 97
+			00 00 00 00 0f 00 00 01 97
+			00 c0 00 00 00 00 00 01 bb];
+		qcom,platform-reset-sequence = <1 20 0 1 1 20>;
+		qcom,platform-supply-entry1 {
+			qcom,supply-name = "vdd";
+			qcom,supply-min-voltage = <2800000>;
+			qcom,supply-max-voltage = <2800000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-pre-on-sleep = <0>;
+			qcom,supply-post-on-sleep = <0>;
+			qcom,supply-pre-off-sleep = <0>;
+			qcom,supply-post-off-sleep = <0>;
+		};
+		qcom,platform-supply-entry2 {
+			qcom,supply-name = "vddio";
+			qcom,supply-min-voltage = <1800000>;
+			qcom,supply-max-voltage = <1800000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-pre-on-sleep = <0>;
+			qcom,supply-post-on-sleep = <0>;
+			qcom,supply-pre-off-sleep = <0>;
+			qcom,supply-post-off-sleep = <0>;
+		};
+		qcom,platform-supply-entry3 {
+			qcom,supply-name = "vdda";
+			qcom,supply-min-voltage = <1200000>;
+			qcom,supply-max-voltage = <1200000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-pre-on-sleep = <0>;
+			qcom,supply-post-on-sleep = <20>;
+			qcom,supply-pre-off-sleep = <0>;
+			qcom,supply-post-off-sleep = <0>;
+		};
 	};
 
 	qcom,mdss_wb_panel {
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 0df3feb..825e853 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -35,6 +35,7 @@
 			synaptics,irq-gpio = <&msmgpio 17 0x2008>;
 			synaptics,button-map = <139 102 158>;
 			synaptics,i2c-pull-up;
+			synaptics,power-down;
 		};
 	};
 
@@ -86,7 +87,7 @@
 			compatible = "micrel,ks8851";
 			reg = <3>;
 			interrupt-parent = <&msmgpio>;
-			interrupts = <0 115 0>;
+			interrupts = <115 0x8>;
 			spi-max-frequency = <4800000>;
 			rst-gpio = <&msmgpio 114 0>;
 			vdd-io-supply = <&pm8226_lvs1>;
@@ -131,8 +132,6 @@
 
 &sdcc1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
@@ -157,8 +156,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
@@ -275,8 +272,12 @@
 				qcom,mode-ctrl = <0x60>;
 				qcom,pwm-channel = <0>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
@@ -297,8 +298,12 @@
 				qcom,source-sel = <10>;
 				qcom,pwm-channel = <5>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-pm.dtsi
index d9bd5e8..ef0a55e 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-pm.dtsi
@@ -20,12 +20,12 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x00>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-ctl = <0x8>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
 	};
 
 	qcom,spm@f9099000 {
@@ -37,12 +37,12 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x00>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-ctl = <0x8>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
 	};
 
 	qcom,spm@f90a9000 {
@@ -54,12 +54,12 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x00>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-ctl = <0x8>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
 	};
 
 	qcom,spm@f90b9000 {
@@ -71,12 +71,12 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x00>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-ctl = <0x8>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
 	};
 
 	qcom,spm@f9012000 {
@@ -95,68 +95,22 @@
 		qcom,vctl-port = <0x0>;
 		qcom,phase-port = <0x1>;
 		qcom,pfm-port = <0x2>;
-		qcom,saw2-spm-cmd-ret = [00 03 00 7b 0f];
+		qcom,saw2-spm-cmd-ret = [00 03 00 0f];
 		qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
-				11 07 01 b0 4e c0 d0 12 e0 6b 50 02 32
-				50 f0 7b 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
-	};
-
-	qcom,lpm-resources {
-		compatible = "qcom,lpm-resources";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		qcom,lpm-resources@0 {
-			reg = <0x0>;
-			qcom,name = "vdd-dig";
-			qcom,type = <0x61706d73>;	/* "smpa" */
-			qcom,id = <0x01>;
-			qcom,key = <0x6e726f63>;	/* "corn" */
-			qcom,init-value = <3>;		/* SVS SOC */
-		};
-
-		qcom,lpm-resources@1 {
-			reg = <0x1>;
-			qcom,name = "vdd-mem";
-			qcom,type = <0x616F646C>;	/* "ldoa" */
-			qcom,id = <0x03>;
-			qcom,key = <0x6e726f63>;	/* "corn" */
-			qcom,init-value = <3>;		/* SVS SOC */
-		};
-
-		qcom,lpm-resources@2 {
-			reg = <0x2>;
-			qcom,name = "pxo";
-			qcom,type = <0x306b6c63>;	/* "clk0" */
-			qcom,id = <0x00>;
-			qcom,key = <0x62616e45>;	/* "Enab" */
-			qcom,init-value = "xo_on";
-		};
-
-		qcom,lpm-resources@3 {
-			reg = <0x3>;
-			qcom,name = "l2";
-			qcom,local-resource-type;
-			qcom,init-value = "l2_cache_retention";
-		};
+				11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+				50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
 	};
 
 	qcom,lpm-levels {
 		compatible = "qcom,lpm-levels";
+		qcom,default-l2-state = "l2_cache_active";
 		#address-cells = <1>;
 		#size-cells = <0>;
 
 		qcom,lpm-level@0 {
 			reg = <0x0>;
 			qcom,mode = "wfi";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
 			qcom,latency-us = <1>;
 			qcom,ss-power = <784>;
 			qcom,energy-overhead = <190000>;
@@ -166,14 +120,7 @@
 		qcom,lpm-level@1 {
 			reg = <0x1>;
 			qcom,mode = "standalone_pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
 			qcom,latency-us = <3000>;
 			qcom,ss-power = <725>;
 			qcom,energy-overhead = <99500>;
@@ -183,15 +130,8 @@
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_retention";
-			qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
-			qcom,latency-us = <8000>;
+			qcom,latency-us = <20000>;
 			qcom,ss-power = <138>;
 			qcom,energy-overhead = <1208400>;
 			qcom,time-overhead = <9200>;
@@ -200,64 +140,12 @@
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <4>; /* NORMAL */
-			qcom,vdd-mem-lower-bound = <3>;  /* SVS SOC */
-			qcom,vdd-dig-upper-bound = <4>;  /* NORMAL */
-			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
-			qcom,latency-us = <9000>;
+			qcom,latency-us = <30000>;
 			qcom,ss-power = <110>;
 			qcom,energy-overhead = <1250300>;
 			qcom,time-overhead = <9500>;
 		};
-
-		qcom,lpm-level@4 {
-			reg = <0x4>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,latency-us = <16300>;
-			qcom,ss-power = <63>;
-			qcom,energy-overhead = <2128000>;
-			qcom,time-overhead = <24200>;
-		};
-
-		qcom,lpm-level@5 {
-			reg = <0x5>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <4>; /* NORMAL */
-			qcom,vdd-mem-lower-bound = <3>;  /* SVS SOC */
-			qcom,vdd-dig-upper-bound = <4>;  /* NORMAL */
-			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
-			qcom,latency-us = <24000>;
-			qcom,ss-power = <10>;
-			qcom,energy-overhead = <3202600>;
-			qcom,time-overhead = <33000>;
-		};
-
-		qcom,lpm-level@6 {
-			reg = <0x6>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <3>; /* SVS SOC */
-			qcom,vdd-mem-lower-bound = <1>; /* RETENTION */
-			qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
-			qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
-			qcom,latency-us = <26000>;
-			qcom,ss-power = <2>;
-			qcom,energy-overhead = <4252000>;
-			qcom,time-overhead = <38000>;
-		};
 	};
 
 	qcom,pm-boot {
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index db0620f..55d8691 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -31,6 +31,7 @@
 			synaptics,irq-gpio = <&msmgpio 17 0x2008>;
 			synaptics,button-map = <139 102 158>;
 			synaptics,i2c-pull-up;
+			synaptics,power-down;
 		};
 		focaltech@38 {
 			compatible = "focaltech,5x06";
@@ -98,7 +99,7 @@
 			compatible = "micrel,ks8851";
 			reg = <3>;
 			interrupt-parent = <&msmgpio>;
-			interrupts = <0 115 0>;
+			interrupts = <115 0x8>;
 			spi-max-frequency = <4800000>;
 			rst-gpio = <&msmgpio 114 0>;
 			vdd-io-supply = <&pm8226_lvs1>;
@@ -129,8 +130,6 @@
 
 &sdcc1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
@@ -155,8 +154,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
@@ -180,7 +177,7 @@
 &sdcc2 {
 	vdd-supply = <&pm8226_l18>;
 	qcom,vdd-voltage-level = <2950000 2950000>;
-	qcom,vdd-current-level = <9000 800000>;
+	qcom,vdd-current-level = <9000 400000>;
 
 	vdd-io-supply = <&pm8226_l21>;
 	qcom,vdd-io-voltage-level = <1800000 2950000>;
@@ -196,7 +193,7 @@
 
 	qcom,xpc;
 	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
-	qcom,current-limit = <600>;
+	qcom,current-limit = <400>;
 
 	#address-cells = <0>;
 	interrupt-parent = <&sdcc2>;
@@ -215,7 +212,7 @@
 &sdhc_2 {
 	vdd-supply = <&pm8226_l18>;
 	qcom,vdd-voltage-level = <2950000 2950000>;
-	qcom,vdd-current-level = <9000 800000>;
+	qcom,vdd-current-level = <9000 400000>;
 
 	vdd-io-supply = <&pm8226_l21>;
 	qcom,vdd-io-voltage-level = <1800000 2950000>;
@@ -265,7 +262,7 @@
 			qcom,led_mpp_4 {
 				label = "mpp";
 				linux,name = "green";
-				linux,default-trigger = "none";
+				linux,default-trigger = "battery-full";
 				qcom,default-state = "off";
 				qcom,max-current = <40>;
 				qcom,current-setting = <5>;
@@ -276,8 +273,12 @@
 				qcom,mode-ctrl = <0x60>;
 				qcom,pwm-channel = <0>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
@@ -287,7 +288,7 @@
 			qcom,led_mpp_6 {
 				label = "mpp";
 				linux,name = "red";
-				linux,default-trigger = "none";
+				linux,default-trigger = "battery-charging";
 				qcom,default-state = "off";
 				qcom,max-current = <40>;
 				qcom,current-setting = <5>;
@@ -298,8 +299,12 @@
 				qcom,source-sel = <10>;
 				qcom,pwm-channel = <5>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
@@ -423,5 +428,17 @@
 	tapan_codec {
 		qcom,cdc-micbias1-ext-cap;
 	};
+};
 
+&pm8226_vadc {
+	chan@30 {
+		label = "batt_therm";
+		reg = <0x30>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <6>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 7f78c84..d587b77 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -30,19 +30,22 @@
 	apc_vreg_corner: regulator@f9018000 {
 		status = "okay";
 		compatible = "qcom,cpr-regulator";
-		reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b80b0 8>,
-			<0xfc4bc450 16>;
-		reg-names = "rbcpr", "rbcpr_clk", "pvs_efuse", "cpr_efuse";
+		reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b8000 0x1000>;
+		reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
 		interrupts = <0 15 0>;
 		regulator-name = "apc_corner";
 		regulator-min-microvolt = <1>;
 		regulator-max-microvolt = <3>;
-		qcom,num-efuse-bits = <5>;
+
+		qcom,pvs-fuse-redun-sel = <22 24 3 2>;
+		qcom,pvs-fuse = <22 6 5>;
+		qcom,pvs-fuse-redun = <22 27 5>;
+
 		qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
 					2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
-		qcom,pvs-corner-ceiling-slow = <1155000 1160000 1275000>;
-		qcom,pvs-corner-ceiling-nom  =  <975000 1075000 1200000>;
-		qcom,pvs-corner-ceiling-fast =  <900000 1000000 1140000>;
+		qcom,pvs-corner-ceiling-slow = <1050000 1160000 1275000>;
+		qcom,pvs-corner-ceiling-nom  = <1050000 1075000 1200000>;
+		qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
 		vdd-apc-supply = <&pm8226_s2>;
 
 		vdd-mx-supply = <&pm8226_l3_ao>;
@@ -63,6 +66,16 @@
 		qcom,vdd-apc-step-down-limit = <1>;
 		qcom,cpr-apc-volt-step = <5000>;
 
+		qcom,cpr-fuse-redun-sel = <138 57 1 1>;
+		qcom,cpr-fuse-row = <138>;
+		qcom,cpr-fuse-bp-cpr-disable = <36>;
+		qcom,cpr-fuse-bp-scheme = <37>;
+		qcom,cpr-fuse-target-quot = <24 12 0>;
+		qcom,cpr-fuse-ro-sel = <54 38 41>;
+		qcom,cpr-fuse-redun-row = <139>;
+		qcom,cpr-fuse-redun-target-quot = <24 12 0>;
+		qcom,cpr-fuse-redun-ro-sel = <46 36 39>;
+
 		qcom,cpr-enable;
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
index d36e93e..45c26c5 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
@@ -27,5 +27,6 @@
 &soc {
         qcom,mdss_dsi_hx8394a_720p_video {
                 status = "ok";
+		qcom,cont-splash-enabled;
         };
 };
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
index 8520ae3..936f87f 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
@@ -30,4 +30,86 @@
 		status = "ok";
 		qcom,mdss-pan-bl-ctrl = "bl_ctrl_dcs";
 	};
+
+	sound {
+		qcom,model = "msm8226-tapan-skuf-snd-card";
+
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"SPK_OUT", "MCLK",
+			"SPK_OUT", "EXT_VDD_SPKR",
+			"Lineout_1 amp", "LINEOUT1",
+			"Lineout_2 amp", "LINEOUT2",
+			"AMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS1 External",
+			"MIC BIAS1 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic";
+
+		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+		qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
+		qcom,cdc-vdd-spkr-gpios;
+		qcom,cdc-us-euro-gpios;
+	};
+};
+
+&spmi_bus {
+	qcom,pm8226@0 {
+		qcom,leds@a300 {
+			status = "disabled";
+		};
+
+		qcom,leds@a500 {
+			status = "disabled";
+		};
+	};
+};
+
+&pm8226_mpps {
+	mpp@a300 { /* MPP 4 */
+		/* camera2_id */
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <3>; /* AMUX 8 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* camera_id */
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <1>; /* AMUX 6 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+	};
+
+};
+
+&pm8226_vadc {
+	chan@13 {
+		label = "camera2_id";
+		reg = <0x13>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@15 {
+		label = "camera_id";
+		reg = <0x15>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8226-v1.dtsi b/arch/arm/boot/dts/msm8226-v1.dtsi
index d471bec..2833673 100644
--- a/arch/arm/boot/dts/msm8226-v1.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1.dtsi
@@ -17,3 +17,38 @@
  */
 
 /include/ "msm8226.dtsi"
+
+&tsens {
+	qcom,sensors = <4>;
+	qcom,slope = <2901 2846 3038 2955>;
+};
+
+&gdsc_venus {
+	qcom,skip-logic-collapse;
+	qcom,retain-periph;
+	qcom,retain-mem;
+};
+
+&gdsc_mdss {
+	qcom,skip-logic-collapse;
+	qcom,retain-periph;
+	qcom,retain-mem;
+};
+
+&gdsc_jpeg {
+	qcom,skip-logic-collapse;
+	qcom,retain-periph;
+	qcom,retain-mem;
+};
+
+&gdsc_vfe {
+	qcom,skip-logic-collapse;
+	qcom,retain-periph;
+	qcom,retain-mem;
+};
+
+&gdsc_oxili_cx {
+	qcom,skip-logic-collapse;
+	qcom,retain-periph;
+	qcom,retain-mem;
+};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
index f35e2e4..4cdbada 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
@@ -29,5 +29,6 @@
 &soc {
         qcom,mdss_dsi_hx8394a_720p_video {
                 status = "ok";
+		qcom,cont-splash-enabled;
         };
 };
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
index 1c43589..b34fb94 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
@@ -31,4 +31,86 @@
 		status = "ok";
 		qcom,mdss-pan-bl-ctrl = "bl_ctrl_dcs";
 	};
+
+	sound {
+		qcom,model = "msm8226-tapan-skuf-snd-card";
+
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"SPK_OUT", "MCLK",
+			"SPK_OUT", "EXT_VDD_SPKR",
+			"Lineout_1 amp", "LINEOUT1",
+			"Lineout_2 amp", "LINEOUT2",
+			"AMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS1 External",
+			"MIC BIAS1 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic";
+
+		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+		qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
+		qcom,cdc-vdd-spkr-gpios;
+		qcom,cdc-us-euro-gpios;
+	};
+};
+
+&spmi_bus {
+	qcom,pm8226@0 {
+		qcom,leds@a300 {
+			status = "disabled";
+		};
+
+		qcom,leds@a500 {
+			status = "disabled";
+		};
+	};
+};
+
+&pm8226_mpps {
+	mpp@a300 { /* MPP 4 */
+		/* camera2_id */
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <3>; /* AMUX 8 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* camera_id */
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <1>; /* AMUX 6 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+	};
+
+};
+
+&pm8226_vadc {
+	chan@13 {
+		label = "camera2_id";
+		reg = <0x13>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@15 {
+		label = "camera_id";
+		reg = <0x15>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index 2148e1d..1dab78a 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -42,9 +42,9 @@
 &apc_vreg_corner {
 	qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
 				2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3>;
-	qcom,pvs-corner-ceiling-slow = <1160000 1160000 1280000>;
-	qcom,pvs-corner-ceiling-nom  =  <980000 1080000 1200000>;
-	qcom,pvs-corner-ceiling-fast =  <900000 1000000 1140000>;
+	qcom,pvs-corner-ceiling-slow = <1050000 1160000 1280000>;
+	qcom,pvs-corner-ceiling-nom  = <1050000 1080000 1200000>;
+	qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
 	qcom,cpr-step-quotient = <30>;
 	qcom,cpr-up-threshold = <0>;
 	qcom,cpr-down-threshold = <5>;
@@ -63,3 +63,8 @@
 		reg-names = "rcg_base", "pte_efuse";
 	};
 };
+
+&tsens {
+	qcom,sensors = <6>;
+	qcom,slope = <2901 2846 3038 2955 2901 2846>;
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 42c1247..b836100 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -21,6 +21,7 @@
 		spi0 = &spi_0;
 		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
 		sdhc2 = &sdhc_2; /* SDC2 SD card slot */
+		sdhc3 = &sdhc_3; /* SDC3 SDIO slot */
 	};
 
 	memory {
@@ -762,6 +763,95 @@
 		status = "disabled";
 	};
 
+	sdcc3: qcom,sdcc@f9864000 {
+		cell-index = <3>;
+		compatible = "qcom,msm-sdcc";
+		reg = <0xf9864000 0x800>,
+			<0xf9864800 0x100>,
+			<0xf9844000 0x7000>;
+		reg-names = "core_mem", "dml_mem", "bam_mem";
+
+		qcom,bus-width = <4>;
+		gpios = <&msmgpio 44 0>, /* CLK */
+			<&msmgpio 43 0>, /* CMD */
+			<&msmgpio 42 0>, /* DATA0 */
+			<&msmgpio 41 0>, /* DATA1 */
+			<&msmgpio 40 0>, /* DATA2 */
+			<&msmgpio 39 0>; /* DATA3 */
+		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
+		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+
+		qcom,msm-bus,name = "sdcc3";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
+				<79 512 1600 3200>,    /* 400 KB/s*/
+				<79 512 80000 160000>, /* 20 MB/s */
+				<79 512 100000 200000>, /* 25 MB/s */
+				<79 512 200000 400000>, /* 50 MB/s */
+				<79 512 400000 800000>, /* 100 MB/s */
+				<79 512 400000 800000>, /* 200 MB/s */
+				<79 512 2048000 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+						100000000 200000000 4294967295>;
+
+		#address-cells = <0>;
+		interrupt-parent = <&sdcc3>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 127 0
+			      1 &intc 0 223 0
+			      2 &msmgpio 41 0x8>;
+		interrupt-names = "core_irq", "bam_irq", "sdiowakeup_irq";
+
+		status = "disabled";
+	};
+
+	sdhc_3: sdhci@f9864900 {
+		compatible = "qcom,sdhci-msm";
+		reg = <0xf9864900 0x11c>, <0xf9864000 0x800>;
+		reg-names = "hc_mem", "core_mem";
+
+		qcom,bus-width = <4>;
+		gpios = <&msmgpio 44 0>, /* CLK */
+			<&msmgpio 43 0>, /* CMD */
+			<&msmgpio 42 0>, /* DATA0 */
+			<&msmgpio 41 0>, /* DATA1 */
+			<&msmgpio 40 0>, /* DATA2 */
+			<&msmgpio 39 0>; /* DATA3 */
+		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
+		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+
+		qcom,msm-bus,name = "sdhc3";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
+				<79 512 1600 3200>,    /* 400 KB/s*/
+				<79 512 80000 160000>, /* 20 MB/s */
+				<79 512 100000 200000>, /* 25 MB/s */
+				<79 512 200000 400000>, /* 50 MB/s */
+				<79 512 400000 800000>, /* 100 MB/s */
+				<79 512 400000 800000>, /* 200 MB/s */
+				<79 512 2048000 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+						100000000 200000000 4294967295>;
+
+		#address-cells = <0>;
+		interrupt-parent = <&sdhc_3>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 127 0
+			      1 &intc 0 224 0
+			      2 &msmgpio 41 0x8>;
+		interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+		status = "disabled";
+	};
+
 	spmi_bus: qcom,spmi@fc4c0000 {
 		cell-index = <0>;
 		compatible = "qcom,spmi-pmic-arb";
@@ -935,7 +1025,7 @@
 	tsens: tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
-		      <0xfc4b8000 0x1000>;
+		      <0xfc4bc000 0x1000>;
 		reg-names = "tsens_physical", "tsens_eeprom_physical";
 		interrupts = <0 184 0>;
 		qcom,sensors = <4>;
@@ -954,6 +1044,21 @@
 		qcom,core-limit-temp = <80>;
 		qcom,core-temp-hysteresis = <10>;
 		qcom,core-control-mask = <0xe>;
+		qcom,vdd-restriction-temp = <5>;
+		qcom,vdd-restriction-temp-hysteresis = <10>;
+		vdd-dig-supply = <&pm8226_s1_floor_corner>;
+
+		qcom,vdd-dig-rstr{
+			qcom,vdd-rstr-reg = "vdd-dig";
+			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
+			qcom,min-level = <1>; /* No Request */
+		};
+
+		qcom,vdd-apps-rstr{
+			qcom,vdd-rstr-reg = "vdd-apps";
+			qcom,levels = <600000 787200 998400>;
+			qcom,freq-req;
+		};
 	};
 
 	spi_0: spi@f9923000 { /* BLSP1 QUP1 */
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 6b61317..b0c0191 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -42,6 +42,7 @@
 		atmel,display-coords = <0 0 480 800>;
 		atmel,i2c-pull-up;
 		atmel,no-force-update;
+		atmel,no-lpm-support;
 		atmel,cfg_1 {
 			atmel,family-id = <0x81>;
 			atmel,variant-id = <0x15>;
@@ -222,9 +223,13 @@
 				qcom,default-state = "on";
 				qcom,max-current = <40>;
 				qcom,id = <6>;
-				qcom,source-sel = <1>;
+				qcom,source-sel = <8>;
 				qcom,mode-ctrl = <0x10>;
-				qcom,mode = "manual";
+				qcom,pwm-channel = <0>;
+				qcom,pwm-us = <14>;
+				qcom,vin-ctrl = <0x03>;
+				qcom,mode = "pwm";
+				qcom,min-brightness = <19>;
 			};
 		};
 	};
@@ -242,8 +247,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8110_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2900000 2900000>;
 	qcom,vdd-current-level = <200 400000>;
 
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 352ccf1..221ace4 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -42,6 +42,7 @@
 		atmel,display-coords = <0 0 480 800>;
 		atmel,i2c-pull-up;
 		atmel,no-force-update;
+		atmel,no-lpm-support;
 		atmel,cfg_1 {
 			atmel,family-id = <0x81>;
 			atmel,variant-id = <0x15>;
@@ -105,6 +106,27 @@
 			invn,gpio-en = <&pm8110_gpios 2 0x2>;
 			invn,poll-interval = <200>;
 		};
+
+		bmp180@77 {
+			reg = <0x77>;
+			compatible = "bosch,bmp18x";
+			vdd-supply = <&pm8110_l19>;
+			vddio-supply = <&pm8110_l14>;
+			bosch,chip-id = <0x55>;
+			bosch,oversample = <3>;
+			bosch,period = <1000>;
+		};
+
+		mma8x5x@1d {
+			reg = <0x1d>;
+			compatible = "fsl,mma8x5x";
+			interrupt-parent = <&msmgpio>;
+			interrupts = <81 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vio-supply = <&pm8110_l14>;
+			fsl,irq-gpio = <&msmgpio 81 0x00>;
+			fsl,sensors-position = <5>;
+		};
 	};
 
 	gen-vkeys {
@@ -171,7 +193,7 @@
 
 		cdc-vdda-h-supply = <&pm8110_l6>;
 		qcom,cdc-vdda-h-voltage = <1800000 1800000>;
-		qcom,cdc-vdda-h-current = <250000>;
+		qcom,cdc-vdda-h-current = <25000>;
 
 		cdc-vdd-px-supply = <&pm8110_l6>;
 		qcom,cdc-vdd-px-voltage = <1800000 1800000>;
@@ -239,9 +261,13 @@
 				qcom,default-state = "on";
 				qcom,max-current = <40>;
 				qcom,id = <6>;
-				qcom,source-sel = <1>;
+				qcom,source-sel = <8>;
 				qcom,mode-ctrl = <0x10>;
-				qcom,mode = "manual";
+				qcom,pwm-channel = <0>;
+				qcom,pwm-us = <14>;
+				qcom,vin-ctrl = <0x03>;
+				qcom,mode = "pwm";
+				qcom,min-brightness = <19>;
 			};
 		};
 	};
@@ -259,8 +285,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8110_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2900000 2900000>;
 	qcom,vdd-current-level = <200 400000>;
 
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index c48eaf7..d31a65c 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -20,12 +20,12 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x00>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-ctl = <0x8>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
 	};
 
 	qcom,spm@f9099000 {
@@ -37,13 +37,13 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x00>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-ctl = <0x8>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
-	};
+		qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
+		};
 
 	qcom,spm@f90a9000 {
 		compatible = "qcom,spm-v2";
@@ -54,7 +54,7 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x00>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-ctl = <0x8>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
 				0b 94 5b 80 10 06 26 30 0f];
@@ -71,12 +71,12 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x00>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-ctl = <0x8>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
-				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+				0b 94 5b 80 10 26 30 0f];
 	};
 
 	qcom,spm@f9012000 {
@@ -95,68 +95,22 @@
 		qcom,vctl-port = <0x0>;
 		qcom,phase-port = <0x1>;
 		qcom,pfm-port = <0x2>;
-		qcom,saw2-spm-cmd-ret = [00 03 00 7b 0f];
+		qcom,saw2-spm-cmd-ret = [00 03 00 0f];
 		qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
-				11 07 01 b0 4e c0 d0 12 e0 6b 50 02 32
-				50 f0 7b 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
-	};
-
-	qcom,lpm-resources {
-		compatible = "qcom,lpm-resources";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		qcom,lpm-resources@0 {
-			reg = <0x0>;
-			qcom,name = "vdd-dig";
-			qcom,type = <0x61706d73>;	/* "smpa" */
-			qcom,id = <0x01>;
-			qcom,key = <0x6e726f63>;	/* "corn" */
-			qcom,init-value = <3>;		/* SVS SOC */
-		};
-
-		qcom,lpm-resources@1 {
-			reg = <0x1>;
-			qcom,name = "vdd-mem";
-			qcom,type = <0x616F646C>;	/* "ldoa" */
-			qcom,id = <0x03>;
-			qcom,key = <0x6e726f63>;	/* "corn" */
-			qcom,init-value = <3>;		/* SVS SOC */
-		};
-
-		qcom,lpm-resources@2 {
-			reg = <0x2>;
-			qcom,name = "pxo";
-			qcom,type = <0x306b6c63>;	/* "clk0" */
-			qcom,id = <0x00>;
-			qcom,key = <0x62616e45>;	/* "Enab" */
-			qcom,init-value = "xo_on";
-		};
-
-		qcom,lpm-resources@3 {
-			reg = <0x3>;
-			qcom,name = "l2";
-			qcom,local-resource-type;
-			qcom,init-value = "l2_cache_retention";
-		};
+				11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+				50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
 	};
 
 	qcom,lpm-levels {
 		compatible = "qcom,lpm-levels";
+		qcom,default-l2-state = "l2_cache_active";
 		#address-cells = <1>;
 		#size-cells = <0>;
 
 		qcom,lpm-level@0 {
 			reg = <0x0>;
 			qcom,mode = "wfi";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
 			qcom,latency-us = <1>;
 			qcom,ss-power = <784>;
 			qcom,energy-overhead = <190000>;
@@ -166,14 +120,7 @@
 		qcom,lpm-level@1 {
 			reg = <0x1>;
 			qcom,mode = "standalone_pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
 			qcom,latency-us = <3000>;
 			qcom,ss-power = <725>;
 			qcom,energy-overhead = <99500>;
@@ -183,15 +130,8 @@
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_retention";
-			qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
-			qcom,latency-us = <8000>;
+			qcom,latency-us = <20000>;
 			qcom,ss-power = <138>;
 			qcom,energy-overhead = <1208400>;
 			qcom,time-overhead = <9200>;
@@ -200,64 +140,12 @@
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <4>; /* NORMAL */
-			qcom,vdd-mem-lower-bound = <3>;  /* SVS SOC */
-			qcom,vdd-dig-upper-bound = <4>;  /* NORMAL */
-			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
-			qcom,latency-us = <9000>;
+			qcom,latency-us = <30000>;
 			qcom,ss-power = <110>;
 			qcom,energy-overhead = <1250300>;
 			qcom,time-overhead = <9500>;
 		};
-
-		qcom,lpm-level@4 {
-			reg = <0x4>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,latency-us = <16300>;
-			qcom,ss-power = <63>;
-			qcom,energy-overhead = <2128000>;
-			qcom,time-overhead = <24200>;
-		};
-
-		qcom,lpm-level@5 {
-			reg = <0x5>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <4>; /* NORMAL */
-			qcom,vdd-mem-lower-bound = <3>;  /* SVS SOC */
-			qcom,vdd-dig-upper-bound = <4>;  /* NORMAL */
-			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
-			qcom,latency-us = <24000>;
-			qcom,ss-power = <10>;
-			qcom,energy-overhead = <3202600>;
-			qcom,time-overhead = <33000>;
-		};
-
-		qcom,lpm-level@6 {
-			reg = <0x6>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <3>; /* SVS SOC */
-			qcom,vdd-mem-lower-bound = <1>; /* RETENTION */
-			qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
-			qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
-			qcom,latency-us = <26000>;
-			qcom,ss-power = <2>;
-			qcom,energy-overhead = <4252000>;
-			qcom,time-overhead = <38000>;
-		};
 	};
 
 	qcom,pm-boot {
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
index da02345..aeaf8ca 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
+++ b/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
@@ -24,3 +24,24 @@
 				  <163 0>, <164 0>, <166 0>;
 };
 
+&soc {
+    sound {
+        qcom,model = "msm8x10-skuaa-snd-card";
+
+        qcom,audio-routing =
+            "RX_BIAS", "MCLK",
+            "INT_LDO_H", "MCLK",
+            "Lineout amp", "LINEOUT",
+            "MIC BIAS Internal1", "Handset Mic",
+            "MIC BIAS Internal2", "Headset Mic",
+            "AMIC1", "MIC BIAS Internal1",
+            "AMIC2", "MIC BIAS Internal2";
+
+        qcom,ext-spk-amp-gpio = <&msmgpio 92 0x0>;
+    };
+};
+
+&pm8110_bms {
+	status = "ok";
+	qcom,batt-type = <5>;
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
index 0d79cd5..c435038 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
@@ -13,6 +13,8 @@
 /dts-v1/;
 
 /include/ "msm8610-qrd.dtsi"
+/include/ "dsi-v2-panel-otm8018b-fwvga-video.dtsi"
+/include/ "msm8612-qrd-camera-sensor.dtsi"
 
 / {
 	model = "Qualcomm MSM 8610 QRD";
@@ -21,3 +23,64 @@
 	qcom,msm-id = <147 0>, <165 0>, <161 0>, <162 0>,
 				  <163 0>, <164 0>, <166 0>;
 };
+
+&soc {
+    sound {
+        qcom,model = "msm8x10-skuab-snd-card";
+
+        qcom,audio-routing =
+            "RX_BIAS", "MCLK",
+            "INT_LDO_H", "MCLK",
+            "Lineout amp", "LINEOUT",
+            "MIC BIAS Internal1", "Handset Mic",
+            "MIC BIAS Internal2", "Headset Mic",
+            "AMIC1", "MIC BIAS Internal1",
+            "AMIC2", "MIC BIAS Internal2";
+
+        qcom,ext-spk-amp-gpio = <&msmgpio 92 0x0>;
+    };
+    i2c@f9923000{
+		focaltech@38{
+			compatible = "focaltech,5x06";
+			reg = <0x38>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <1 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vcc_i2c-supply = <&pm8110_l14>;
+			focaltech,family-id = <0x06>;
+			focaltech,reset-gpio = <&msmgpio 0 0x00>;
+			focaltech,irq-gpio = <&msmgpio 1 0x00>;
+			focaltech,display-coords = <0 0 480 854>;
+			focaltech,panel-coords = <0 0 480 946>;
+			focaltech,button-map= <139 102 158>;
+			focaltech,no-force-update;
+			focaltech,i2c-pull-up;
+		};
+	};
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "ft5x06_ts";
+		qcom,disp-maxx = <480>;
+		qcom,disp-maxy = <854>;
+		qcom,panel-maxx = <481>;
+		qcom,panel-maxy = <946>;
+		qcom,key-codes = <139 102 158>;
+		qcom,y-offset = <0>;
+	};
+    i2c@f9925000 {
+		fsl@1c {
+			compatible = "fsl,mma8x5x";
+			reg = <0x1c>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <81 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vio-supply = <&pm8110_l14>;
+			fsl,irq-gpio = <&msmgpio 81 0x00>;
+			fsl,sensors-position = <5>;
+		};
+	};
+
+	qcom,dsi_v2_otm8018b_fwvga_video {
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 7a93c49..ea47d45 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -124,51 +124,6 @@
 		};
 	};
 
-	i2c@f9927000  {
-                        msm8x10_wcd_codec@0d{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x0d>;
-                        cdc-vdda-cp-supply = <&pm8110_s4>;
-                        qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
-                        qcom,cdc-vdda-cp-current = <650000>;
-
-                        cdc-vdda-h-supply = <&pm8110_l6>;
-                        qcom,cdc-vdda-h-voltage = <1800000 1800000>;
-                        qcom,cdc-vdda-h-current = <250000>;
-
-                        cdc-vdd-px-supply = <&pm8110_l6>;
-                        qcom,cdc-vdd-px-voltage = <1800000 1800000>;
-                        qcom,cdc-vdd-px-current = <10000>;
-
-                        cdc-vdd-1p2v-supply = <&pm8110_l4>;
-                        qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
-                        qcom,cdc-vdd-1p2v-current = <5000>;
-
-                        cdc-vdd-mic-bias-supply = <&pm8110_l20>;
-                        qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
-                        qcom,cdc-vdd-mic-bias-current = <25000>;
-
-                        qcom,cdc-micbias-cfilt-sel = <0x0>;
-                        qcom,cdc-micbias-cfilt-mv = <1800000>;
-                        qcom,cdc-mclk-clk-rate = <12288000>;
-                };
-
-                msm8x10_wcd_codec@77{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x77>;
-                };
-
-                msm8x10_wcd_codec@66{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x66>;
-                };
-
-                msm8x10_wcd_codec@55{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x55>;
-                };
-	};
-
     sound {
         qcom,audio-routing =
             "RX_BIAS", "MCLK",
@@ -180,6 +135,58 @@
     };
 };
 
+&i2c_cdc  {
+	msm8x10_wcd_codec@0d{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x0d>;
+		cdc-vdda-cp-supply = <&pm8110_s4>;
+		qcom,cdc-vdda-cp-voltage = <1800000 2150000>;
+		qcom,cdc-vdda-cp-current = <650000>;
+
+		cdc-vdda-h-supply = <&pm8110_l6>;
+		qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdda-h-current = <25000>;
+
+		cdc-vdd-px-supply = <&pm8110_l6>;
+		qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-px-current = <10000>;
+
+		cdc-vdd-1p2v-supply = <&pm8110_l4>;
+		qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
+		qcom,cdc-vdd-1p2v-current = <5000>;
+
+		cdc-vdd-mic-bias-supply = <&pm8110_l20>;
+		qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+		qcom,cdc-vdd-mic-bias-current = <25000>;
+
+		qcom,cdc-micbias-cfilt-sel = <0x0>;
+		qcom,cdc-micbias-cfilt-mv = <1800000>;
+		qcom,cdc-mclk-clk-rate = <12288000>;
+
+		qcom,cdc-static-supplies = "cdc-vdda-h",
+						"cdc-vdd-px",
+						"cdc-vdd-1p2v";
+
+		qcom,cdc-on-demand-supplies = "cdc-vdda-cp",
+						"cdc-vdd-mic-bias";
+	};
+
+	msm8x10_wcd_codec@77{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x77>;
+	};
+
+	msm8x10_wcd_codec@66{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x66>;
+	};
+
+	msm8x10_wcd_codec@55{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x55>;
+	};
+};
+
 &spmi_bus {
 	qcom,pm8110@0 {
 		qcom,leds@a100 {
@@ -206,9 +213,13 @@
 				qcom,default-state = "on";
 				qcom,max-current = <40>;
 				qcom,id = <6>;
-				qcom,source-sel = <1>;
+				qcom,source-sel = <8>;
 				qcom,mode-ctrl = <0x10>;
-				qcom,mode = "manual";
+				qcom,pwm-channel = <0>;
+				qcom,pwm-us = <14>;
+				qcom,vin-ctrl = <0x03>;
+				qcom,mode = "pwm";
+				qcom,min-brightness = <19>;
 			};
 		};
 	};
@@ -226,8 +237,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8110_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2900000 2900000>;
 	qcom,vdd-current-level = <200 400000>;
 
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 0d47e5d..34cbd99 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -30,19 +30,22 @@
 	apc_vreg_corner: regulator@f9018000 {
 		status = "okay";
 		compatible = "qcom,cpr-regulator";
-		reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b80b0 8>,
-			<0xfc4bc450 16>;
-		reg-names = "rbcpr", "rbcpr_clk", "pvs_efuse", "cpr_efuse";
+		reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b8000 0x1000>;
+		reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
 		interrupts = <0 15 0>;
 		regulator-name = "apc_corner";
 		regulator-min-microvolt = <1>;
 		regulator-max-microvolt = <3>;
-		qcom,num-efuse-bits = <5>;
-		qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
-					2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
-		qcom,pvs-corner-ceiling-slow = <1150000 1150000 1275000>;
-		qcom,pvs-corner-ceiling-nom  =  <975000 1075000 1200000>;
-		qcom,pvs-corner-ceiling-fast =  <900000 1000000 1140000>;
+
+		qcom,pvs-fuse-redun-sel = <53 25 3 2>;
+		qcom,pvs-fuse = <23 6 5>;
+		qcom,pvs-fuse-redun = <61 47 5>;
+
+		qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+					1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1>;
+		qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000>;
+		qcom,pvs-corner-ceiling-nom  = <1050000 1075000 1200000>;
+		qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
 		vdd-apc-supply = <&pm8110_s2>;
 
 		vdd-mx-supply = <&pm8110_l3_ao>;
@@ -51,17 +54,31 @@
 
 		qcom,cpr-ref-clk = <19200>;
 		qcom,cpr-timer-delay = <5000>;
-		qcom,cpr-timer-cons-up = <1>;
+		qcom,cpr-timer-cons-up = <0>;
 		qcom,cpr-timer-cons-down = <2>;
 		qcom,cpr-irq-line = <0>;
 		qcom,cpr-step-quotient = <15>;
-		qcom,cpr-up-threshold = <1>;
-		qcom,cpr-down-threshold = <2>;
+		qcom,cpr-up-threshold = <0>;
+		qcom,cpr-down-threshold = <10>;
 		qcom,cpr-idle-clocks = <5>;
 		qcom,cpr-gcnt-time = <1>;
 		qcom,vdd-apc-step-up-limit = <1>;
 		qcom,vdd-apc-step-down-limit = <1>;
 		qcom,cpr-apc-volt-step = <5000>;
+
+		qcom,cpr-fuse-redun-sel = <53 25 3 2>;
+		qcom,cpr-fuse-row = <61>;
+		qcom,cpr-fuse-bp-cpr-disable = <39>;
+		qcom,cpr-fuse-bp-scheme = <40>;
+		qcom,cpr-fuse-target-quot = <27 15 3>;
+		qcom,cpr-fuse-ro-sel = <47 41 44>;
+		qcom,cpr-fuse-redun-row = <52>;
+		qcom,cpr-fuse-redun-bp-cpr-disable = <24>;
+		qcom,cpr-fuse-redun-bp-scheme = <25>;
+		qcom,cpr-fuse-redun-target-quot = <32 12 0>;
+		qcom,cpr-fuse-redun-ro-sel = <44 26 29>;
+
+		qcom,cpr-enable;
 	};
 };
 
@@ -182,6 +199,7 @@
 			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1200000>;
 			qcom,init-voltage = <1200000>;
+			regulator-always-on;
 			status = "okay";
 		};
 	};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index c9e88a8..79543b1 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -215,9 +215,10 @@
 		reg = <0xf9a55000 0x400>;
 		interrupts = <0 134 0>, <0 140 0>;
 		interrupt-names = "core_irq", "async_irq";
-		HSUSB_VDDCX-supply = <&pm8110_s1>;
+		hsusb_vdd_dig-supply = <&pm8110_s1_corner>;
 		HSUSB_1p8-supply = <&pm8110_l10>;
 		HSUSB_3p3-supply = <&pm8110_l20>;
+		qcom,vdd-voltage-level = <1 5 7>;
 
 		qcom,hsusb-otg-phy-init-seq =
 			<0x44 0x80 0x68 0x81 0x24 0x82 0x13 0x83 0xffffffff>;
@@ -253,8 +254,6 @@
 		interrupt-names = "core_irq", "bam_irq";
 
 		vdd-supply = <&pm8110_l17>;
-		qcom,vdd-always-on;
-		qcom,vdd-lpm-sup;
 		qcom,vdd-voltage-level = <2900000 2900000>;
 		qcom,vdd-current-level = <9000 400000>;
 
@@ -701,6 +700,7 @@
 		gpios = <&msmgpio 23 0>, <&msmgpio 24 0>, <&msmgpio 25 0>, <&msmgpio 26 0>, <&msmgpio 27 0>;
 		qcom,has-pronto-hw;
 		qcom,wlan-rx-buff-count = <256>;
+		qcom,has-autodetect-xo;
 	};
 
 	qcom,mss@fc880000 {
@@ -754,7 +754,7 @@
 	tsens: tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
-		      <0xfc4b8000 0x1000>;
+		      <0xfc4bc000 0x1000>;
 		reg-names = "tsens_physical", "tsens_eeprom_physical";
 		interrupts = <0 184 0>;
 		qcom,sensors = <2>;
@@ -776,16 +776,16 @@
 		qcom,core-control-mask = <0xe>;
 		qcom,vdd-restriction-temp = <5>;
 		qcom,vdd-restriction-temp-hysteresis = <10>;
-		vdd_dig-supply = <&pm8110_s1_floor_corner>;
+		vdd-dig-supply = <&pm8110_s1_floor_corner>;
 
 		qcom,vdd-dig-rstr{
-			qcom,vdd-rstr-reg = "vdd_dig";
+			qcom,vdd-rstr-reg = "vdd-dig";
 			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
 			qcom,min-level = <1>; /* No Request */
 		};
 
 		qcom,vdd-apps-rstr{
-			qcom,vdd-rstr-reg = "vdd_apps";
+			qcom,vdd-rstr-reg = "vdd-apps";
 			qcom,levels = <600000 787200 998400>;
 			qcom,freq-req;
 		};
@@ -914,6 +914,11 @@
 				<55 512 393600 3936000>;
 	};
 
+	cpu-pmu {
+		compatible = "arm,cortex-a7-pmu";
+		qcom,irq-is-percpu;
+		interrupts = <1 7 0xf00>;
+	};
 };
 
 &gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
new file mode 100644
index 0000000..25554eb
--- /dev/null
+++ b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+&i2c {
+
+	qcom,camera@20 {
+		compatible = "shinetech,s5k4e1";
+		reg = <0x20>;
+		qcom,slave-id = <0x20 0x0000 0x4e10>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "SKUAB_ST_s5k4e1";
+		cam_vdig-supply = <&pm8110_l2>;
+		cam_vana-supply = <&pm8110_l19>;
+		cam_vio-supply = <&pm8110_l14>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-type = <0 0 0>;
+		qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-op-mode = <200000 8000 80000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 13 0>,
+			<&msmgpio 21 0>,
+			<&msmgpio 20 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+			"CAM_RESET1",
+			"CAM_STANDBY";
+		qcom,csi-lane-assign = <0xe4>;
+		qcom,csi-lane-mask = <0x3>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <1>;
+		qcom,sensor-type = <0>;
+		qcom,cci-master = <0>;
+	};
+	qcom,camera@78 {
+		compatible = "shinetech,gc0339";
+		reg = <0x78>;
+		qcom,slave-id = <0x42 0x00 0xc8>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "skuab_shinetech_gc0339";
+		cam_vdig-supply = <&pm8110_l14>;
+		cam_vana-supply = <&pm8110_l19>;
+		cam_vio-supply = <&pm8110_l14>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-type = <0 1 0>;
+		qcom,cam-vreg-min-voltage = <1800000 1800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1800000 1800000 2850000>;
+		qcom,cam-vreg-op-mode = <200000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 14 0>,
+				<&msmgpio 15 0>,
+				<&msmgpio 85 0>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+				"CAM_RESET",
+				"CAM_STANDBY";
+		qcom,gpio-set-tbl-num = <1 1>;
+		qcom,gpio-set-tbl-flags = <0 2>;
+		qcom,gpio-set-tbl-delay = <1000 4000>;
+		qcom,csi-lane-assign = <0xe4>;
+		qcom,csi-lane-mask = <0x3>;
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index d15459c..f46b714 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -73,3 +73,8 @@
 	qcom,cpr-down-threshold = <5>;
 	qcom,cpr-apc-volt-step = <10000>;
 };
+
+&tsens {
+	qcom,sensors = <6>;
+	qcom,slope = <2901 2846 3038 2955 2901 2846>;
+};
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index 456b079..4be2b38 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -196,18 +196,42 @@
 		qcom,gpio-tbl-num = <0 1 2 3>;
 		qcom,gpio-tbl-flags = <1 1 1 1>;
 		qcom,gpio-tbl-label = "CCI_I2C_DATA0",
-					"CCI_I2C_CLK0",
-					"CCI_I2C_DATA1",
-					"CCI_I2C_CLK1";
-		qcom,hw-thigh = <78>;
-		qcom,hw-tlow = <114>;
-		qcom,hw-tsu-sto = <28>;
-		qcom,hw-tsu-sta = <28>;
-		qcom,hw-thd-dat = <10>;
-		qcom,hw-thd-sta = <77>;
-		qcom,hw-tbuf = <118>;
-		qcom,hw-scl-stretch-en = <0>;
-		qcom,hw-trdhld = <6>;
-		qcom,hw-tsp = <1>;
+				      "CCI_I2C_CLK0",
+				      "CCI_I2C_DATA1",
+				      "CCI_I2C_CLK1";
+		master0: qcom,cci-master0 {
+			status = "disabled";
+		};
+		master1: qcom,cci-master1 {
+			status = "disabled";
+		};
 	};
 };
+
+&master0 {
+	qcom,hw-thigh = <78>;
+	qcom,hw-tlow = <114>;
+	qcom,hw-tsu-sto = <28>;
+	qcom,hw-tsu-sta = <28>;
+	qcom,hw-thd-dat = <10>;
+	qcom,hw-thd-sta = <77>;
+	qcom,hw-tbuf = <118>;
+	qcom,hw-scl-stretch-en = <0>;
+	qcom,hw-trdhld = <6>;
+	qcom,hw-tsp = <1>;
+	status = "ok";
+};
+
+&master1 {
+	qcom,hw-thigh = <78>;
+	qcom,hw-tlow = <114>;
+	qcom,hw-tsu-sto = <28>;
+	qcom,hw-tsu-sta = <28>;
+	qcom,hw-thd-dat = <10>;
+	qcom,hw-thd-sta = <77>;
+	qcom,hw-tbuf = <118>;
+	qcom,hw-scl-stretch-en = <0>;
+	qcom,hw-trdhld = <6>;
+	qcom,hw-tsp = <1>;
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index bcdaf1b..e66ea25 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -15,6 +15,12 @@
 /include/ "msm8974-leds.dtsi"
 /include/ "msm8974-camera-sensor-cdp.dtsi"
 
+/ {
+	aliases {
+		serial0 = &blsp1_uart1;
+	};
+};
+
 &soc {
 	serial@f991e000 {
 		status = "ok";
@@ -252,63 +258,61 @@
 	};
 };
 
-&spmi_bus {
-	qcom,pm8941@1 {
-		qcom,leds@d800 {
-			status = "okay";
-			qcom,wled_0 {
-				label = "wled";
-				linux,name = "wled:backlight";
-				linux,default-trigger = "bkl-trigger";
-				qcom,cs-out-en;
-				qcom,op-fdbck = <1>;
-				qcom,default-state = "on";
-				qcom,max-current = <25>;
-				qcom,ctrl-delay-us = <0>;
-				qcom,boost-curr-lim = <3>;
-				qcom,cp-sel = <0>;
-				qcom,switch-freq = <2>;
-				qcom,ovp-val = <2>;
-				qcom,num-strings = <1>;
-				qcom,id = <0>;
-			};
+&pm8941_lsid1 {
+	qcom,leds@d800 {
+		status = "okay";
+		qcom,wled_0 {
+			label = "wled";
+			linux,name = "wled:backlight";
+			linux,default-trigger = "bkl-trigger";
+			qcom,cs-out-en;
+			qcom,op-fdbck = <1>;
+			qcom,default-state = "on";
+			qcom,max-current = <25>;
+			qcom,ctrl-delay-us = <0>;
+			qcom,boost-curr-lim = <3>;
+			qcom,cp-sel = <0>;
+			qcom,switch-freq = <2>;
+			qcom,ovp-val = <2>;
+			qcom,num-strings = <1>;
+			qcom,id = <0>;
 		};
+	};
 
-		qcom,leds@d900 {
-			status = "disabled";
-		};
+	qcom,leds@d900 {
+		status = "disabled";
+	};
 
-		qcom,leds@da00 {
-			status = "disabled";
-		};
+	qcom,leds@da00 {
+		status = "disabled";
+	};
 
-		qcom,leds@db00 {
-			status = "disabled";
-		};
+	qcom,leds@db00 {
+		status = "disabled";
+	};
 
-		qcom,leds@dc00 {
-			status = "disabled";
-		};
+	qcom,leds@dc00 {
+		status = "disabled";
+	};
 
-		qcom,leds@dd00 {
-			status = "disabled";
-		};
+	qcom,leds@dd00 {
+		status = "disabled";
+	};
 
-		qcom,leds@de00 {
-			status = "disabled";
-		};
+	qcom,leds@de00 {
+		status = "disabled";
+	};
 
-		qcom,leds@df00 {
-			status = "disabled";
-		};
+	qcom,leds@df00 {
+		status = "disabled";
+	};
 
-		qcom,leds@e000 {
-			status = "disabled";
-		};
+	qcom,leds@e000 {
+		status = "disabled";
+	};
 
-		qcom,leds@e100 {
-			status = "disabled";
-		};
+	qcom,leds@e100 {
+		status = "disabled";
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8974-clock.dtsi b/arch/arm/boot/dts/msm8974-clock.dtsi
index bed5d70..8d90771 100644
--- a/arch/arm/boot/dts/msm8974-clock.dtsi
+++ b/arch/arm/boot/dts/msm8974-clock.dtsi
@@ -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,18 +10,14 @@
  * GNU General Public License for more details.
  */
 
-&spmi_bus {
+&pm8941_lsid0 {
+	pm8941_clkdiv1: clkdiv@5b00 {
+		qcom,cxo-div = <2>;
+	};
 
-	qcom,pm8941@0 {
+	pm8941_clkdiv2: clkdiv@5c00 {
+	};
 
-		pm8941_clkdiv1: clkdiv@5b00 {
-			qcom,cxo-div = <2>;
-		};
-
-		pm8941_clkdiv2: clkdiv@5c00 {
-		};
-
-		pm8941_clkdiv3: clkdiv@5d00 {
-		};
+	pm8941_clkdiv3: clkdiv@5d00 {
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index e41adac..9fd0cd9 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -16,6 +16,8 @@
 		reg = <0xfc322000 0x1000>,
 		      <0xfc37c000 0x3000>;
 		reg-names = "tmc-base", "bam-base";
+		interrupts = <0 166 0>;
+		interrupt-names = "byte-cntr-irq";
 
 		qcom,memory-reservation-type = "EBI1";
 		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 638e6dd..7f714e8 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -14,6 +14,12 @@
 /include/ "msm8974-camera-sensor-fluid.dtsi"
 /include/ "msm8974-leds.dtsi"
 
+/ {
+	aliases {
+		serial0 = &blsp1_uart1;
+	};
+};
+
 &soc {
 	serial@f991e000 {
 		status = "ok";
@@ -251,63 +257,61 @@
 	};
 };
 
-&spmi_bus {
-	qcom,pm8941@1 {
-		qcom,leds@d800 {
-			status = "okay";
-			qcom,wled_0 {
-				label = "wled";
-				linux,name = "wled:backlight";
-				linux,default-trigger = "bkl-trigger";
-				qcom,cs-out-en;
-				qcom,op-fdbck = <1>;
-				qcom,default-state = "on";
-				qcom,max-current = <25>;
-				qcom,ctrl-delay-us = <0>;
-				qcom,boost-curr-lim = <3>;
-				qcom,cp-sel = <0>;
-				qcom,switch-freq = <2>;
-				qcom,ovp-val = <2>;
-				qcom,num-strings = <1>;
-				qcom,id = <0>;
-			};
+&pm8941_lsid1 {
+	qcom,leds@d800 {
+		status = "okay";
+		qcom,wled_0 {
+			label = "wled";
+			linux,name = "wled:backlight";
+			linux,default-trigger = "bkl-trigger";
+			qcom,cs-out-en;
+			qcom,op-fdbck = <1>;
+			qcom,default-state = "on";
+			qcom,max-current = <25>;
+			qcom,ctrl-delay-us = <0>;
+			qcom,boost-curr-lim = <3>;
+			qcom,cp-sel = <0>;
+			qcom,switch-freq = <2>;
+			qcom,ovp-val = <2>;
+			qcom,num-strings = <1>;
+			qcom,id = <0>;
 		};
+	};
 
-		qcom,leds@d900 {
-			status = "disabled";
-		};
+	qcom,leds@d900 {
+		status = "disabled";
+	};
 
-		qcom,leds@da00 {
-			status = "disabled";
-		};
+	qcom,leds@da00 {
+		status = "disabled";
+	};
 
-		qcom,leds@db00 {
-			status = "disabled";
-		};
+	qcom,leds@db00 {
+		status = "disabled";
+	};
 
-		qcom,leds@dc00 {
-			status = "disabled";
-		};
+	qcom,leds@dc00 {
+		status = "disabled";
+	};
 
-		qcom,leds@dd00 {
-			status = "disabled";
-		};
+	qcom,leds@dd00 {
+		status = "disabled";
+	};
 
-		qcom,leds@de00 {
-			status = "disabled";
-		};
+	qcom,leds@de00 {
+		status = "disabled";
+	};
 
-		qcom,leds@df00 {
-			status = "disabled";
-		};
+	qcom,leds@df00 {
+		status = "disabled";
+	};
 
-		qcom,leds@e000 {
-			status = "disabled";
-		};
+	qcom,leds@e000 {
+		status = "disabled";
+	};
 
-		qcom,leds@e100 {
-			status = "disabled";
-		};
+	qcom,leds@e100 {
+		status = "disabled";
 	};
 };
 
@@ -408,6 +412,7 @@
 	qcom,min-fcc-learning-soc = <20>;
 	qcom,min-fcc-ocv-pc = <30>;
 	qcom,min-fcc-learning-samples = <5>;
+	qcom,fcc-resolution = <10>;
 	status = "ok";
 };
 
@@ -659,14 +664,14 @@
 		interrupt-parent = <&msmgpio>;
 		spi-max-frequency = <960000>;
 		qcom,channels = <31>;
-		qcom,gain = <100 100 100 50 100 100 1 100 1 50
-				1 100 1 100 50 50 50 50 50 50
-				100 50 100 50 50 50 50 50 50 50
-				50>;
-		qcom,rsense = <2 2 2 200 20 2 1 2 1 30
-				1 10 1 30 50 30 500 30 100 30
-				100 500 20 200 1000 20 1000 1000 70 200
-				50>;
-		qcom,channel-type = <0x1540>;
+		qcom,gain = <100 100 100 100 100 100 100 100 100 100
+				100 100 100 100 100 100 1 1 1 1
+				1 1 1 1 1 1 1 1 1 1
+				1>;
+		qcom,rsense = <10 10 10 10 100 200 500 10 10 10
+				200 200 10 500 10 10 1 1 1 1
+				1 1 1 1 1 1 1 1 1 1
+				1>;
+		qcom,channel-type = <0xf0000000>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-leds.dtsi b/arch/arm/boot/dts/msm8974-leds.dtsi
index 5e91f45..06abbd8 100644
--- a/arch/arm/boot/dts/msm8974-leds.dtsi
+++ b/arch/arm/boot/dts/msm8974-leds.dtsi
@@ -11,119 +11,172 @@
  * GNU General Public License for more details.
  */
 
-&spmi_bus {
-	qcom,pm8941@1 {
-		qcom,leds@d000 {
-			status = "okay";
-			qcom,rgb_0 {
-				label = "rgb";
-				linux,name = "led:rgb_red";
-				qcom,mode = "pwm";
-				qcom,pwm-channel = <6>;
-				qcom,pwm-us = <1000>;
-				qcom,max-current = <12>;
-				qcom,default-state = "off";
-				qcom,id = <3>;
-				linux,default-trigger =
-					"battery-charging";
-			};
-
-			qcom,rgb_1 {
-				label = "rgb";
-				linux,name = "led:rgb_green";
-				qcom,mode = "pwm";
-				qcom,pwm-channel = <5>;
-				qcom,pwm-us = <1000>;
-				qcom,max-current = <12>;
-				qcom,default-state = "off";
-				qcom,id = <4>;
-				linux,default-trigger = "battery-full";
-			};
-
-			qcom,rgb_2 {
-				label = "rgb";
-				linux,name = "led:rgb_blue";
-				qcom,mode = "pwm";
-				qcom,pwm-channel = <4>;
-				qcom,pwm-us = <1000>;
-				qcom,max-current = <12>;
-				qcom,id = <5>;
-				status = "disabled";
-			};
+&pm8941_lsid1 {
+	qcom,leds@d000 {
+		status = "okay";
+		qcom,rgb_0 {
+			label = "rgb";
+			linux,name = "led:rgb_red";
+			qcom,mode = "pwm";
+			qcom,pwm-channel = <6>;
+			qcom,pwm-us = <1000>;
+			qcom,max-current = <12>;
+			qcom,default-state = "off";
+			qcom,id = <3>;
+			linux,default-trigger =
+				"battery-charging";
 		};
 
-		qcom,leds@d100 {
-			status = "disabled";
+		qcom,rgb_1 {
+			label = "rgb";
+			linux,name = "led:rgb_green";
+			qcom,mode = "pwm";
+			qcom,pwm-channel = <5>;
+			qcom,pwm-us = <1000>;
+			qcom,max-current = <12>;
+			qcom,default-state = "off";
+			qcom,id = <4>;
+			linux,default-trigger = "battery-full";
 		};
 
-		qcom,leds@d200 {
-			status = "disabled";
-		};
-
-		qcom,leds@d300 {
-			status = "okay";
-			pm8941_flash0: qcom,flash_0 {
-				qcom,max-current = <1000>;
-				qcom,default-state = "off";
-				qcom,headroom = <3>;
-				qcom,duration = <1280>;
-				qcom,clamp-curr = <200>;
-				qcom,startup-dly = <3>;
-				qcom,safety-timer;
-				label = "flash";
-				linux,default-trigger =
-					"flash0_trigger";
-				qcom,id = <1>;
-				linux,name = "led:flash_0";
-				qcom,current = <625>;
-			};
-
-			pm8941_flash1: qcom,flash_1 {
-				qcom,max-current = <1000>;
-				qcom,default-state = "off";
-				qcom,headroom = <3>;
-				qcom,duration = <1280>;
-				qcom,clamp-curr = <200>;
-				qcom,startup-dly = <3>;
-				qcom,safety-timer;
-				linux,default-trigger =
-					"flash1_trigger";
-				label = "flash";
-				qcom,id = <2>;
-				linux,name = "led:flash_1";
-				qcom,current = <625>;
-			};
-
-			pm8941_torch: qcom,flash_torch {
-				qcom,max-current = <200>;
-				qcom,default-state = "off";
-				qcom,headroom = <0>;
-				qcom,startup-dly = <1>;
-				linux,default-trigger =
-					"torch_trigger";
-				label = "flash";
-				qcom,id = <2>;
-				linux,name = "led:flash_torch";
-				qcom,current = <200>;
-				qcom,torch-enable;
-			};
-		};
-
-		qcom,leds@d400 {
-			status = "disabled";
-		};
-
-		qcom,leds@d500 {
-			status = "disabled";
-		};
-
-		qcom,leds@d600 {
-			status = "disabled";
-		};
-
-		qcom,leds@d700 {
+		qcom,rgb_2 {
+			label = "rgb";
+			linux,name = "led:rgb_blue";
+			qcom,mode = "pwm";
+			qcom,pwm-channel = <4>;
+			qcom,pwm-us = <1000>;
+			qcom,max-current = <12>;
+			qcom,id = <5>;
 			status = "disabled";
 		};
 	};
-};
 
+	qcom,leds@d100 {
+		status = "disabled";
+	};
+
+	qcom,leds@d200 {
+		status = "disabled";
+	};
+
+	qcom,leds@d300 {
+		status = "okay";
+		pm8941_flash0: qcom,flash_0 {
+			qcom,max-current = <1000>;
+			qcom,default-state = "off";
+			qcom,headroom = <3>;
+			qcom,duration = <1280>;
+			qcom,clamp-curr = <200>;
+			qcom,startup-dly = <3>;
+			qcom,safety-timer;
+			label = "flash";
+			linux,default-trigger =
+				"flash0_trigger";
+			qcom,id = <1>;
+			linux,name = "led:flash_0";
+			qcom,current = <625>;
+		};
+
+		pm8941_flash1: qcom,flash_1 {
+			qcom,max-current = <1000>;
+			qcom,default-state = "off";
+			qcom,headroom = <3>;
+			qcom,duration = <1280>;
+			qcom,clamp-curr = <200>;
+			qcom,startup-dly = <3>;
+			qcom,safety-timer;
+			linux,default-trigger =
+				"flash1_trigger";
+			label = "flash";
+			qcom,id = <2>;
+			linux,name = "led:flash_1";
+			qcom,current = <625>;
+		};
+
+		pm8941_torch: qcom,flash_torch {
+			qcom,max-current = <200>;
+			qcom,default-state = "off";
+			qcom,headroom = <0>;
+			qcom,startup-dly = <1>;
+			linux,default-trigger =
+				"torch_trigger";
+			label = "flash";
+			qcom,id = <2>;
+			linux,name = "led:flash_torch";
+			qcom,current = <200>;
+			qcom,torch-enable;
+		};
+	};
+
+	qcom,leds@d400 {
+		status = "disabled";
+	};
+
+	qcom,leds@d500 {
+		status = "disabled";
+	};
+
+	qcom,leds@d600 {
+		status = "disabled";
+	};
+
+	qcom,leds@d700 {
+		status = "disabled";
+	};
+
+	qcom,leds@e200 {
+		status = "okay";
+
+		qcom,kpdbl1 {
+			label = "kpdbl";
+			linux,name = "kpdbl-pwm-1";
+			qcom,mode = "pwm";
+			qcom,pwm-channel = <8>;
+			qcom,pwm-us = <1000>;
+			qcom,id = <7>;
+			qcom,max-current = <20>;
+			qcom,row-id = <0>;
+			qcom,row-src-en;
+			qcom,always-on;
+		};
+
+		qcom,kpdbl2 {
+			label = "kpdbl";
+			linux,name = "kpdbl-lut-2";
+			qcom,mode = "lpg";
+			qcom,pwm-channel = <9>;
+			qcom,pwm-us = <1000>;
+			qcom,start-idx = <1>;
+			qcom,duty-pcts = [00 00 00 00 64
+					64 00 00 00 00];
+			qcom,id = <7>;
+			qcom,max-current = <20>;
+			qcom,row-id = <1>;
+			qcom,row-src-en;
+		};
+
+		qcom,kpdbl3 {
+			label = "kpdbl";
+			linux,name = "kpdbl-pwm-3";
+			qcom,mode = "pwm";
+			qcom,pwm-channel = <10>;
+			qcom,pwm-us = <1000>;
+			qcom,id = <7>;
+			qcom,max-current = <20>;
+			qcom,row-id = <2>;
+			qcom,row-src-en;
+		};
+
+		qcom,kpdbl4 {
+			label = "kpdbl";
+			linux,name = "kpdbl-pwm-4";
+			qcom,mode = "pwm";
+			qcom,pwm-channel = <11>;
+			qcom,pwm-us = <1000>;
+			qcom,id = <7>;
+			qcom,max-current = <20>;
+			qcom,row-id = <3>;
+			qcom,row-src-en;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index ddf5b60..51cb226 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -13,6 +13,12 @@
 /include/ "msm8974-leds.dtsi"
 /include/ "msm8974-camera-sensor-liquid.dtsi"
 
+/ {
+	aliases {
+		serial0 = &blsp1_uart1;
+	};
+};
+
 &soc {
 	serial@f991e000 {
 		status = "ok";
@@ -770,26 +776,24 @@
 		interrupt-parent = <&msmgpio>;
 		spi-max-frequency = <960000>;
 		qcom,channels = <31>;
-		qcom,gain = <50 50 50 50 50 100 50 50 50 50
-				50 50 50 50 100 50 50 50 50 100
+		qcom,gain = <50 50 50 50 50 100 50 100 50 50
+				100 50 50 50 50 50 50 50 50 50
 				50 50 50 100 50 50 50 1 1 1
 				1>;
-		qcom,rsense = <40 10 10 25 10 1000 75 25 10 25
-				33 500 200 10 500 100 33 200 25 100
-				75 500 50 200 5 5 3 1 1 1
-				1>;
+		qcom,rsense = <50 100 500 10 25 1000 40 200 200 5
+				500 500 75 10 5 25 33 75 25 200
+				10 25 33 100 10 10 3 1000 1000 1000
+				1000>;
 		qcom,channel-type = <0xf0000000>;
 	};
 };
 
-&spmi_bus {
-	qcom,pm8941@1 {
-		qcom,leds@d000 {
-			qcom,rgb_2 {
-				status = "ok";
-				qcom,default-state = "on";
-				qcom,turn-off-delay-ms = <1000>;
-			};
+&pm8941_lsid1 {
+	qcom,leds@d000 {
+		qcom,rgb_2 {
+			status = "ok";
+			qcom,default-state = "on";
+			qcom,turn-off-delay-ms = <1000>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 46bb71a..f8a8fa6 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -86,6 +86,50 @@
 		vddio-supply = <&pm8941_l12>;
 		vdda-supply = <&pm8941_l2>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
+		qcom,platform-reset-gpio = <&pm8941_gpios 19 1>;
+		qcom,platform-enable-gpio = <&msmgpio 58 1>;
+		qcom,platform-reset-sequence = <1 20 0 200 1 20 2>;
+		qcom,platform-strength-ctrl = [ff 06];
+		qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];
+		qcom,platform-regulator-settings = [07 09 03 00 20 00 01];
+		qcom,platform-lane-config = [00 00 00 00 00 00 00 01 97
+			00 00 00 00 05 00 00 01 97
+			00 00 00 00 0a 00 00 01 97
+			00 00 00 00 0f 00 00 01 97
+			00 c0 00 00 00 00 00 01 bb];
+		qcom,platform-supply-entry1 {
+				qcom,supply-name = "vdd";
+				qcom,supply-min-voltage = <3000000>;
+				qcom,supply-max-voltage = <3000000>;
+				qcom,supply-enable-load = <100000>;
+				qcom,supply-disable-load = <100>;
+				qcom,supply-pre-on-sleep = <0>;
+				qcom,supply-post-on-sleep = <20>;
+				qcom,supply-pre-off-sleep = <0>;
+				qcom,supply-post-off-sleep = <0>;
+		};
+		qcom,platform-supply-entry2 {
+				qcom,supply-name = "vddio";
+				qcom,supply-min-voltage = <1800000>;
+				qcom,supply-max-voltage = <1800000>;
+				qcom,supply-enable-load = <100000>;
+				qcom,supply-disable-load = <100>;
+				qcom,supply-pre-on-sleep = <0>;
+				qcom,supply-post-on-sleep = <20>;
+				qcom,supply-pre-off-sleep = <0>;
+				qcom,supply-post-off-sleep = <0>;
+		};
+		qcom,platform-supply-entry3 {
+				qcom,supply-name = "vdda";
+				qcom,supply-min-voltage = <1200000>;
+				qcom,supply-max-voltage = <1200000>;
+				qcom,supply-enable-load = <100000>;
+				qcom,supply-disable-load = <100>;
+				qcom,supply-pre-on-sleep = <0>;
+				qcom,supply-post-on-sleep = <0>;
+				qcom,supply-pre-off-sleep = <0>;
+				qcom,supply-post-off-sleep = <0>;
+		};
 	};
 
 	mdss_dsi1: qcom,mdss_dsi@fd922e00 {
@@ -145,5 +189,6 @@
 		qcom,panel-pwm-period = <53>;
 		status = "disable";
 		qcom,mdss-fb-map = <&mdss_fb0>;
+		gpio-panel-hpd = <&msmgpio 102 0>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 4af48cc..4ee56ad 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -14,6 +14,12 @@
 /include/ "msm8974-camera-sensor-mtp.dtsi"
 /include/ "msm8974-leds.dtsi"
 
+/ {
+	aliases {
+		serial0 = &blsp1_uart1;
+	};
+};
+
 &soc {
 	serial@f991e000 {
 		status = "ok";
@@ -192,63 +198,61 @@
 	};
 };
 
-&spmi_bus {
-	qcom,pm8941@1 {
-		qcom,leds@d800 {
-			status = "okay";
-			qcom,wled_0 {
-				label = "wled";
-				linux,name = "wled:backlight";
-				linux,default-trigger = "bkl-trigger";
-				qcom,cs-out-en;
-				qcom,op-fdbck = <1>;
-				qcom,default-state = "on";
-				qcom,max-current = <25>;
-				qcom,ctrl-delay-us = <0>;
-				qcom,boost-curr-lim = <3>;
-				qcom,cp-sel = <0>;
-				qcom,switch-freq = <2>;
-				qcom,ovp-val = <2>;
-				qcom,num-strings = <1>;
-				qcom,id = <0>;
-			};
+&pm8941_lsid1 {
+	qcom,leds@d800 {
+		status = "okay";
+		qcom,wled_0 {
+			label = "wled";
+			linux,name = "wled:backlight";
+			linux,default-trigger = "bkl-trigger";
+			qcom,cs-out-en;
+			qcom,op-fdbck = <1>;
+			qcom,default-state = "on";
+			qcom,max-current = <25>;
+			qcom,ctrl-delay-us = <0>;
+			qcom,boost-curr-lim = <3>;
+			qcom,cp-sel = <0>;
+			qcom,switch-freq = <2>;
+			qcom,ovp-val = <2>;
+			qcom,num-strings = <1>;
+			qcom,id = <0>;
 		};
+	};
 
-		qcom,leds@d900 {
-			status = "disabled";
-		};
+	qcom,leds@d900 {
+		status = "disabled";
+	};
 
-		qcom,leds@da00 {
-			status = "disabled";
-		};
+	qcom,leds@da00 {
+		status = "disabled";
+	};
 
-		qcom,leds@db00 {
-			status = "disabled";
-		};
+	qcom,leds@db00 {
+		status = "disabled";
+	};
 
-		qcom,leds@dc00 {
-			status = "disabled";
-		};
+	qcom,leds@dc00 {
+		status = "disabled";
+	};
 
-		qcom,leds@dd00 {
-			status = "disabled";
-		};
+	qcom,leds@dd00 {
+		status = "disabled";
+	};
 
-		qcom,leds@de00 {
-			status = "disabled";
-		};
+	qcom,leds@de00 {
+		status = "disabled";
+	};
 
-		qcom,leds@df00 {
-			status = "disabled";
-		};
+	qcom,leds@df00 {
+		status = "disabled";
+	};
 
-		qcom,leds@e000 {
-			status = "disabled";
-		};
+	qcom,leds@e000 {
+		status = "disabled";
+	};
 
-		qcom,leds@e100 {
-			status = "disabled";
-		};
+	qcom,leds@e100 {
+		status = "disabled";
 	};
 };
 
@@ -357,6 +361,7 @@
 	qcom,min-fcc-learning-soc = <20>;
 	qcom,min-fcc-ocv-pc = <30>;
 	qcom,min-fcc-learning-samples = <5>;
+	qcom,fcc-resolution = <10>;
 	status = "ok";
 };
 
@@ -667,21 +672,6 @@
 	};
 };
 
-&pm8841_mpps {
-
-	mpp@a000 { /* MPP 1 */
-	};
-
-	mpp@a100 { /* MPP 2 */
-	};
-
-	mpp@a200 { /* MPP 3 */
-	};
-
-	mpp@a300 { /* MPP 4 */
-	};
-};
-
 &slim_msm {
 	taiko_codec {
 		qcom,cdc-micbias1-ext-cap;
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index d9d5aaa..eae9032 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -13,48 +13,44 @@
 
 /* QPNP controlled regulators: */
 
-&spmi_bus {
+&pm8941_lsid1 {
+	pm8941_boost: regulator@a000 {
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		qcom,enable-time = <500>;
+		status = "okay";
+	};
 
-	qcom,pm8941@1 {
+	pm8941_mvs1: regulator@8300 {
+		parent-supply = <&pm8941_chg_otg>;
+		qcom,enable-time = <1000>;
+		qcom,pull-down-enable = <1>;
+		interrupts = <0x1 0x83 0x2>;
+		interrupt-names = "ocp";
+		qcom,ocp-enable = <1>;
+		qcom,ocp-max-retries = <10>;
+		qcom,ocp-retry-delay = <30>;
+		qcom,soft-start-enable = <1>;
+		qcom,vs-soft-start-strength = <0>;
+		qcom,hpm-enable = <1>;
+		qcom,auto-mode-enable = <0>;
+		status = "okay";
+	};
 
-		pm8941_boost: regulator@a000 {
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
-			qcom,enable-time = <500>;
-			status = "okay";
-		};
-
-		pm8941_mvs1: regulator@8300 {
-			parent-supply = <&pm8941_chg_otg>;
-			qcom,enable-time = <1000>;
-			qcom,pull-down-enable = <1>;
-			interrupts = <0x1 0x83 0x2>;
-			interrupt-names = "ocp";
-			qcom,ocp-enable = <1>;
-			qcom,ocp-max-retries = <10>;
-			qcom,ocp-retry-delay = <30>;
-			qcom,soft-start-enable = <1>;
-			qcom,vs-soft-start-strength = <0>;
-			qcom,hpm-enable = <1>;
-			qcom,auto-mode-enable = <0>;
-			status = "okay";
-		};
-
-		pm8941_mvs2: regulator@8400 {
-			parent-supply = <&pm8941_boost>;
-			qcom,enable-time = <1000>;
-			qcom,pull-down-enable = <1>;
-			interrupts = <0x1 0x84 0x2>;
-			interrupt-names = "ocp";
-			qcom,ocp-enable = <1>;
-			qcom,ocp-max-retries = <10>;
-			qcom,ocp-retry-delay = <30>;
-			qcom,soft-start-enable = <1>;
-			qcom,vs-soft-start-strength = <0>;
-			qcom,hpm-enable = <1>;
-			qcom,auto-mode-enable = <0>;
-			status = "okay";
-		};
+	pm8941_mvs2: regulator@8400 {
+		parent-supply = <&pm8941_boost>;
+		qcom,enable-time = <1000>;
+		qcom,pull-down-enable = <1>;
+		interrupts = <0x1 0x84 0x2>;
+		interrupt-names = "ocp";
+		qcom,ocp-enable = <1>;
+		qcom,ocp-max-retries = <10>;
+		qcom,ocp-retry-delay = <30>;
+		qcom,soft-start-enable = <1>;
+		qcom,vs-soft-start-strength = <0>;
+		qcom,hpm-enable = <1>;
+		qcom,auto-mode-enable = <0>;
+		status = "okay";
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index 288a703..7362b64 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -129,64 +129,16 @@
 				50 02 32 50 0f];
 	};
 
-	qcom,lpm-resources {
-		compatible = "qcom,lpm-resources";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		qcom,lpm-resources@0 {
-			reg = <0x0>;
-			qcom,name = "vdd-dig";
-			qcom,type = <0x62706d73>;	/* "smpb" */
-			qcom,id = <0x02>;
-			qcom,key = <0x6e726f63>;	/* "corn" */
-			qcom,init-value = <6>;		/* Super Turbo */
-		};
-
-		qcom,lpm-resources@1 {
-			reg = <0x1>;
-			qcom,name = "vdd-mem";
-			qcom,type = <0x62706d73>;	/* "smpb" */
-			qcom,id = <0x01>;
-			qcom,key = <0x7675>;		/* "uv" */
-			qcom,init-value = <1050000>;	/* Super Turbo */
-		};
-
-		qcom,lpm-resources@2 {
-			reg = <0x2>;
-			qcom,name = "pxo";
-			qcom,type = <0x306b6c63>;	/* "clk0" */
-			qcom,id = <0x00>;
-			qcom,key = <0x62616e45>;	/* "Enab" */
-			qcom,init-value = "xo_on";
-		};
-
-		qcom,lpm-resources@3 {
-			reg = <0x3>;
-			qcom,name = "l2";
-			qcom,local-resource-type;
-			qcom,init-value = "l2_cache_retention";
-		};
-	};
-
 	qcom,lpm-levels {
 		compatible = "qcom,lpm-levels";
+		qcom,default-l2-state = "l2_cache_retention";
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		qcom,use-qtimer;
-
 		qcom,lpm-level@0 {
 			reg = <0x0>;
 			qcom,mode = "wfi";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
 			qcom,latency-us = <1>;
 			qcom,ss-power = <784>;
 			qcom,energy-overhead = <190000>;
@@ -196,14 +148,7 @@
 		qcom,lpm-level@1 {
 			reg = <0x1>;
 			qcom,mode = "retention";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
 			qcom,latency-us = <75>;
 			qcom,ss-power = <735>;
 			qcom,energy-overhead = <77341>;
@@ -214,14 +159,7 @@
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = "standalone_pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
 			qcom,latency-us = <95>;
 			qcom,ss-power = <725>;
 			qcom,energy-overhead = <99500>;
@@ -231,15 +169,8 @@
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_gdhs";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
-			qcom,latency-us = <2000>;
+			qcom,latency-us = <20000>;
 			qcom,ss-power = <138>;
 			qcom,energy-overhead = <1208400>;
 			qcom,time-overhead = <3200>;
@@ -248,79 +179,12 @@
 		qcom,lpm-level@4 {
 			reg = <0x4>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO  */
-			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
-			qcom,latency-us = <3000>;
+			qcom,latency-us = <30000>;
 			qcom,ss-power = <110>;
 			qcom,energy-overhead = <1250300>;
 			qcom,time-overhead = <3500>;
 		};
-
-		qcom,lpm-level@5 {
-			reg = <0x5>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_gdhs";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,latency-us = <3000>;
-			qcom,ss-power = <68>;
-			qcom,energy-overhead = <1350200>;
-			qcom,time-overhead = <4000>;
-		};
-
-		qcom,lpm-level@6 {
-			reg = <0x6>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,latency-us = <10300>;
-			qcom,ss-power = <63>;
-			qcom,energy-overhead = <2128000>;
-			qcom,time-overhead = <18200>;
-		};
-
-		qcom,lpm-level@7 {
-			reg = <0x7>;
-			qcom,mode= "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <950000>; /* NORMAL */
-			qcom,vdd-mem-lower-bound = <950000>;  /* SVS SOC */
-			qcom,vdd-dig-upper-bound = <4>;  /* NORMAL */
-			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
-			qcom,latency-us = <18000>;
-			qcom,ss-power = <10>;
-			qcom,energy-overhead = <3202600>;
-			qcom,time-overhead = <27000>;
-		};
-
-		qcom,lpm-level@8 {
-			reg = <0x8>;
-			qcom,mode= "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
-			qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
-			qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
-			qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
-			qcom,latency-us = <20000>;
-			qcom,ss-power = <2>;
-			qcom,energy-overhead = <4252000>;
-			qcom,time-overhead = <32000>;
-		};
 	};
 
 	qcom,pm-boot {
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index caec2dc..7b801da 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -17,6 +17,21 @@
  */
 
 /include/ "msm8974.dtsi"
+
+/include/ "msm-pm8x41-rpm-regulator.dtsi"
+/include/ "msm-pm8841.dtsi"
+&spmi_bus {
+	pm8941_lsid0: qcom,pm8941@0 {
+		reg = <0x0>;
+	};
+	pm8941_lsid1: qcom,pm8941@1 {
+		reg = <0x1>;
+	};
+};
+/include/ "msm-pm8941.dtsi"
+/include/ "msm8974-regulator.dtsi"
+/include/ "msm8974-clock.dtsi"
+
 /include/ "msm8974-v1-iommu.dtsi"
 /include/ "msm8974-v1-iommu-domains.dtsi"
 /include/ "msm8974-v1-pm.dtsi"
@@ -50,6 +65,7 @@
 /* CoreSight */
 &tmc_etr {
 	qcom,reset-flush-race;
+	qcom,byte-cntr-absent;
 };
 
 &stm {
diff --git a/arch/arm/boot/dts/msm8974-v2-iommu.dtsi b/arch/arm/boot/dts/msm8974-v2-iommu.dtsi
index 03f7e80..5efa17d 100644
--- a/arch/arm/boot/dts/msm8974-v2-iommu.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-iommu.dtsi
@@ -42,14 +42,14 @@
 				0x2034
 				0x2038>;
 
-	qcom,iommu-bfb-data =  <0xFFFFFFFF
-				0xFFFFFFFF
-				0x00000004
-				0x00000008
-				0x00000000
-				0x00013205
-				0x00004000
-				0x00014020
+	qcom,iommu-bfb-data =  <0xffffffff
+				0xffffffff
+				0x4
+				0x8
+				0x0
+				0x13205
+				0x4000
+				0x14020
 				0x0
 				0x94
 				0x114
@@ -116,8 +116,8 @@
 				0x2010
 				0x2014>;
 
-	qcom,iommu-bfb-data =  <0x3FFF
-				0x00000000
+	qcom,iommu-bfb-data =  <0xffff
+				0x0
 				0x4
 				0x4
 				0x0
@@ -125,8 +125,8 @@
 				0x10
 				0x50
 				0x0
-				0x00002804
-				0x00009614
+				0x2804
+				0x9614
 				0x0
 				0x0
 				0x0
@@ -157,14 +157,14 @@
 				0x201c
 				0x2020>;
 
-	qcom,iommu-bfb-data =  <0xFFFFF
-				0x00000000
-				0x00000004
-				0x00000010
-				0x00000000
-				0x00006800
-				0x00006221
-				0x00016231
+	qcom,iommu-bfb-data =  <0xffffffff
+				0x0
+				0x4
+				0x10
+				0x0
+				0x6800
+				0x6221
+				0x16231
 				0x0
 				0x34
 				0x74
@@ -197,14 +197,14 @@
 				0x2414
 				0x2008>;
 
-	qcom,iommu-bfb-data =  <0x00000003
+	qcom,iommu-bfb-data =  <0x3
 				0x0
-				0x00000004
-				0x00000010
-				0x00000000
-				0x00000000
-				0x00000000
-				0x00000020
+				0x4
+				0x10
+				0x0
+				0x0
+				0x0
+				0x20
 				0x0
 				0x1
 				0x81
@@ -236,7 +236,7 @@
 				0x2020>;
 
 	qcom,iommu-bfb-data =  <0xffffffff
-				0x00000000
+				0x0
 				0x4
 				0x8
 				0x0
@@ -244,8 +244,8 @@
 				0x20
 				0x78
 				0x0
-				0x00003c08
-				0x0000b41e
+				0x3c08
+				0xb41e
 				0x0
 				0x0
 				0x0
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index a162bb7..1235c6e 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -125,64 +125,16 @@
 				50 02 32 50 0f];
 	};
 
-	qcom,lpm-resources {
-		compatible = "qcom,lpm-resources";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		qcom,lpm-resources@0 {
-			reg = <0x0>;
-			qcom,name = "vdd-dig";
-			qcom,type = <0x62706d73>;	/* "smpb" */
-			qcom,id = <0x02>;
-			qcom,key = <0x6e726f63>;	/* "corn" */
-			qcom,init-value = <6>;		/* Super Turbo */
-		};
-
-		qcom,lpm-resources@1 {
-			reg = <0x1>;
-			qcom,name = "vdd-mem";
-			qcom,type = <0x62706d73>;	/* "smpb" */
-			qcom,id = <0x01>;
-			qcom,key = <0x7675>;		/* "uv" */
-			qcom,init-value = <1050000>;	/* Super Turbo */
-		};
-
-		qcom,lpm-resources@2 {
-			reg = <0x2>;
-			qcom,name = "pxo";
-			qcom,type = <0x306b6c63>;	/* "clk0" */
-			qcom,id = <0x00>;
-			qcom,key = <0x62616e45>;	/* "Enab" */
-			qcom,init-value = "xo_on";
-		};
-
-		qcom,lpm-resources@3 {
-			reg = <0x3>;
-			qcom,name = "l2";
-			qcom,local-resource-type;
-			qcom,init-value = "l2_cache_retention";
-		};
-	};
-
 	qcom,lpm-levels {
 		compatible = "qcom,lpm-levels";
+		qcom,default-l2-state = "l2_cache_retention";
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		qcom,use-qtimer;
-
 		qcom,lpm-level@0 {
 			reg = <0x0>;
 			qcom,mode = "wfi";
-			qcom,xo = "xo_on";
-			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
+			qcom,l2 = "l2_cache_retention";
 			qcom,latency-us = <1>;
 			qcom,ss-power = <715>;
 			qcom,energy-overhead = <17700>;
@@ -192,14 +144,7 @@
 		qcom,lpm-level@1 {
 			reg = <0x1>;
 			qcom,mode = "retention";
-			qcom,xo = "xo_on";
-			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
+			qcom,l2 = "l2_cache_retention";
 			qcom,latency-us = <35>;
 			qcom,ss-power = <542>;
 			qcom,energy-overhead = <34920>;
@@ -210,14 +155,7 @@
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = "standalone_pc";
-			qcom,xo = "xo_on";
-			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
+			qcom,l2 = "l2_cache_retention";
 			qcom,latency-us = <300>;
 			qcom,ss-power = <476>;
 			qcom,energy-overhead = <225300>;
@@ -227,32 +165,19 @@
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "standalone_pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_gdhs";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
-			qcom,latency-us = <300>;
+			qcom,latency-us = <320>;
 			qcom,ss-power = <476>;
 			qcom,energy-overhead = <225300>;
-			qcom,time-overhead = <350>;
+			qcom,time-overhead = <375>;
 		};
 
 		qcom,lpm-level@4 {
 			reg = <0x4>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_gdhs";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
 			qcom,gpio-detectable;
-			qcom,latency-us = <2817>;
+			qcom,latency-us = <20000>;
 			qcom,ss-power = <163>;
 			qcom,energy-overhead = <1577736>;
 			qcom,time-overhead = <5067>;
@@ -261,64 +186,12 @@
 		qcom,lpm-level@5 {
 			reg = <0x5>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO  */
-			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
-			qcom,latency-us = <3922>;
+			qcom,latency-us = <30000>;
 			qcom,ss-power = <83>;
 			qcom,energy-overhead = <2274420>;
 			qcom,time-overhead = <6605>;
 		};
-
-		qcom,lpm-level@6 {
-			reg = <0x6>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,latency-us = <4922>;
-			qcom,ss-power = <68>;
-			qcom,energy-overhead = <2568180>;
-			qcom,time-overhead = <8812>;
-		};
-
-		qcom,lpm-level@7 {
-			reg = <0x7>;
-			qcom,mode= "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <950000>; /* NORMAL */
-			qcom,vdd-mem-lower-bound = <950000>;  /* SVS SOC */
-			qcom,vdd-dig-upper-bound = <4>;  /* NORMAL */
-			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
-			qcom,latency-us = <5890>;
-			qcom,ss-power = <60>;
-			qcom,energy-overhead = <2675900>;
-			qcom,time-overhead = <10140>;
-		};
-
-		qcom,lpm-level@8 {
-			reg = <0x8>;
-			qcom,mode= "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
-			qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
-			qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
-			qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
-			qcom,latency-us = <8500>;
-			qcom,ss-power = <18>;
-			qcom,energy-overhead = <3286600>;
-			qcom,time-overhead = <15760>;
-		};
 	};
 
 	qcom,pm-boot {
diff --git a/arch/arm/boot/dts/msm8974-v2.2-cdp.dts b/arch/arm/boot/dts/msm8974-v2.2-cdp.dts
new file mode 100644
index 0000000..c1f4a8b
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2.2-cdp.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2.2.dtsi"
+/include/ "msm8974-cdp.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2.2 CDP";
+	compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
+	qcom,msm-id = <126 1 0x20002>,
+		      <185 1 0x20002>,
+		      <186 1 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.2-fluid.dts b/arch/arm/boot/dts/msm8974-v2.2-fluid.dts
new file mode 100644
index 0000000..207db37
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2.2-fluid.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2.2.dtsi"
+/include/ "msm8974-fluid.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2.2 FLUID";
+	compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
+	qcom,msm-id = <126 3 0x20002>,
+		      <185 3 0x20002>,
+		      <186 3 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.2-liquid.dts b/arch/arm/boot/dts/msm8974-v2.2-liquid.dts
new file mode 100644
index 0000000..36e6e9c
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2.2-liquid.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2.2.dtsi"
+/include/ "msm8974-liquid.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2.2 LIQUID";
+	compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
+	qcom,msm-id = <126 9 0x20002>,
+		      <185 9 0x20002>,
+		      <186 9 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.2-mtp.dts b/arch/arm/boot/dts/msm8974-v2.2-mtp.dts
new file mode 100644
index 0000000..0593f6e
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2.2-mtp.dts
@@ -0,0 +1,28 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2.2.dtsi"
+/include/ "msm8974-mtp.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2.2 MTP";
+	compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
+	qcom,msm-id = <126 8 0x20002>,
+		      <185 8 0x20002>,
+		      <186 8 0x20002>;
+};
+
+&pm8941_chg {
+	qcom,bpd-detection = "bpd_thm";
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.2.dtsi b/arch/arm/boot/dts/msm8974-v2.2.dtsi
new file mode 100644
index 0000000..09455b1
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2.2.dtsi
@@ -0,0 +1,105 @@
+/* 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.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi file.
+ */
+
+/include/ "msm8974-v2.dtsi"
+
+/* GPU overrides */
+&msm_gpu {
+	/* Updated chip ID */
+	qcom,chipid = <0x03030001>;
+
+	qcom,initial-pwrlevel = <4>;
+
+	/* Updated bus bandwidth requirements */
+	qcom,msm-bus,vectors-KBps =
+		/* Off */
+		<26 512 0 0>, <89 604 0 0>,
+		/* SVS */
+		<26 512 0 2400000>, <89 604 0 3000000>,
+		/* Nominal / SVS */
+		<26 512 0 4656000>, <89 604 0 3000000>,
+		/* Nominal */
+		<26 512 0 4656000>, <89 604 0 5120000>,
+		/* Turbo / Nominal */
+		<26 512 0 7464000>, <89 604 0 5120000>,
+		/* Turbo */
+		<26 512 0 7464000>, <89 604 0 6400000>;
+
+	qcom,gpu-pwrlevels {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "qcom,gpu-pwrlevels";
+
+		qcom,gpu-pwrlevel@0 {
+			reg = <0>;
+			qcom,gpu-freq = <450000000>;
+			qcom,bus-freq = <5>;
+			qcom,io-fraction = <33>;
+		};
+
+		qcom,gpu-pwrlevel@1 {
+			reg = <1>;
+			qcom,gpu-freq = <389000000>;
+			qcom,bus-freq = <4>;
+			qcom,io-fraction = <33>;
+		};
+
+		qcom,gpu-pwrlevel@2 {
+			reg = <2>;
+			qcom,gpu-freq = <389000000>;
+			qcom,bus-freq = <3>;
+			qcom,io-fraction = <66>;
+		};
+
+		qcom,gpu-pwrlevel@3 {
+			reg = <3>;
+			qcom,gpu-freq = <320000000>;
+			qcom,bus-freq = <4>;
+			qcom,io-fraction = <66>;
+		};
+
+		qcom,gpu-pwrlevel@4 {
+			reg = <4>;
+			qcom,gpu-freq = <320000000>;
+			qcom,bus-freq = <3>;
+			qcom,io-fraction = <66>;
+		};
+
+		qcom,gpu-pwrlevel@5 {
+			reg = <5>;
+			qcom,gpu-freq = <200000000>;
+			qcom,bus-freq = <2>;
+			qcom,io-fraction = <100>;
+		};
+
+		qcom,gpu-pwrlevel@6 {
+			reg = <6>;
+			qcom,gpu-freq = <200000000>;
+			qcom,bus-freq = <1>;
+			qcom,io-fraction = <100>;
+		};
+
+		qcom,gpu-pwrlevel@7 {
+			reg = <7>;
+			qcom,gpu-freq = <27000000>;
+			qcom,bus-freq = <0>;
+			qcom,io-fraction = <0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 0240039..0b3b60f 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -17,6 +17,21 @@
  */
 
 /include/ "msm8974.dtsi"
+
+/include/ "msm-pm8x41-rpm-regulator.dtsi"
+/include/ "msm-pm8841.dtsi"
+&spmi_bus {
+	pm8941_lsid0: qcom,pm8941@0 {
+		reg = <0x0>;
+	};
+	pm8941_lsid1: qcom,pm8941@1 {
+		reg = <0x1>;
+	};
+};
+/include/ "msm-pm8941.dtsi"
+/include/ "msm8974-regulator.dtsi"
+/include/ "msm8974-clock.dtsi"
+
 /include/ "msm8974-v2-iommu.dtsi"
 /include/ "msm8974-v2-iommu-domains.dtsi"
 /include/ "msm8974-v2-pm.dtsi"
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 181eb9a..59e8dac 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -227,7 +227,7 @@
 		status = "disabled";
 	};
 
-	serial@f991e000 {
+	blsp1_uart1: serial@f991e000 {
 		compatible = "qcom,msm-lsuart-v14";
 		reg = <0xf991e000 0x1000>;
 		interrupts = <0 108 0>;
@@ -1286,9 +1286,9 @@
 				<1 618 0 800>;
         };
 
-	qseecom: qcom,qseecom@7f00000 {
+	qseecom: qcom,qseecom@7b00000 {
 		compatible = "qcom,qseecom";
-		reg = <0x7f00000 0x500000>;
+		reg = <0x7b00000 0x500000>;
 		reg-names = "secapp-region";
 		qcom,disk-encrypt-pipe-pair = <2>;
 		qcom,hlos-ce-hw-instance = <1>;
@@ -1364,7 +1364,7 @@
 	tsens: tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
-		      <0xfc4b8000 0x1000>;
+		      <0xfc4bc000 0x1000>;
 		reg-names = "tsens_physical", "tsens_eeprom_physical";
 		interrupts = <0 184 0>;
 		qcom,sensors = <11>;
@@ -1487,24 +1487,24 @@
 		qcom,vdd-restriction-temp-hysteresis = <10>;
 		qcom,pmic-sw-mode-temp = <85>;
 		qcom,pmic-sw-mode-temp-hysteresis = <75>;
-		qcom,pmic-sw-mode-regs = "vdd_dig";
-		vdd_dig-supply = <&pm8841_s2_floor_corner>;
-		vdd_gfx-supply = <&pm8841_s4_floor_corner>;
+		qcom,pmic-sw-mode-regs = "vdd-dig";
+		vdd-dig-supply = <&pm8841_s2_floor_corner>;
+		vdd-gfx-supply = <&pm8841_s4_floor_corner>;
 
 		qcom,vdd-dig-rstr{
-			qcom,vdd-rstr-reg = "vdd_dig";
+			qcom,vdd-rstr-reg = "vdd-dig";
 			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
 			qcom,min-level = <1>; /* No Request */
 		};
 
 		qcom,vdd-gfx-rstr{
-			qcom,vdd-rstr-reg = "vdd_gfx";
+			qcom,vdd-rstr-reg = "vdd-gfx";
 			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
 			qcom,min-level = <1>; /* No Request */
 		};
 
 		qcom,vdd-apps-rstr{
-			qcom,vdd-rstr-reg = "vdd_apps";
+			qcom,vdd-rstr-reg = "vdd-apps";
 			qcom,levels = <1881600 1958400 2265600>;
 			qcom,freq-req;
 		};
@@ -1519,7 +1519,7 @@
 
         memory_hole: qcom,msm-mem-hole {
                 compatible = "qcom,msm-mem-hole";
-                qcom,memblock-remove = <0x7f00000 0x8000000>; /* Address and Size of Hole */
+                qcom,memblock-remove = <0x7b00000 0x8400000>; /* Address and Size of Hole */
         };
 
 	uart7: uart@f995d000 { /*BLSP #2, UART #7 */
@@ -1690,9 +1690,3 @@
 &gdsc_usb_hsic {
 	status = "ok";
 };
-
-/include/ "msm-pm8x41-rpm-regulator.dtsi"
-/include/ "msm-pm8841.dtsi"
-/include/ "msm-pm8941.dtsi"
-/include/ "msm8974-regulator.dtsi"
-/include/ "msm8974-clock.dtsi"
diff --git a/arch/arm/boot/dts/msm8974pro-ab-mtp.dts b/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
index 002baf7..d1566ae 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
@@ -26,3 +26,7 @@
 		      <217 8 0x10000>,
 		      <218 8 0x10000>;
 };
+
+&sdhc_1 {
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ab.dtsi b/arch/arm/boot/dts/msm8974pro-ab.dtsi
index 9240514..88687bd 100644
--- a/arch/arm/boot/dts/msm8974pro-ab.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ab.dtsi
@@ -17,3 +17,25 @@
  */
 
 /include/ "msm8974pro.dtsi"
+
+/include/ "msm-pm8x41-rpm-regulator.dtsi"
+/include/ "msm-pm8841.dtsi"
+&spmi_bus {
+	pm8941_lsid0: qcom,pm8941@0 {
+		reg = <0x0>;
+	};
+	pm8941_lsid1: qcom,pm8941@1 {
+		reg = <0x1>;
+	};
+};
+/include/ "msm-pm8941.dtsi"
+/include/ "msm8974-regulator.dtsi"
+/include/ "msm8974-clock.dtsi"
+
+&krait_pdn {
+	qcom,use-phase-switching;
+};
+
+&tspp {
+	vdd_cx-supply = <&pm8841_s2_corner>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-mtp.dts b/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
index c5042b7..b8df576 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
@@ -12,8 +12,8 @@
 
 /dts-v1/;
 
-/include/ "msm8974pro-ac.dtsi"
-/include/ "msm8974-mtp.dtsi"
+/include/ "msm8974pro-ac-pm8941.dtsi"
+/include/ "msm8974pro-ac-mtp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8974Pro-AC MTP";
@@ -23,3 +23,7 @@
 		      <213 8 0x10000>,
 		      <216 8 0x10000>;
 };
+
+&sdhc_1 {
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi b/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
new file mode 100644
index 0000000..250afd2
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
@@ -0,0 +1,302 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "msm8974-mtp.dtsi"
+
+&cci {
+	qcom,camera@6e {
+		qcom,vdd-cx-supply = <&pma8084_s2>;
+		cam_vdig-supply = <&pma8084_l3>;
+		cam_vana-supply = <&pma8084_l17>;
+		cam_vio-supply = <&pma8084_lvs4>;
+		cam_vaf-supply = <&pma8084_l23>;
+	};
+
+	qcom,camera@20 {
+		qcom,vdd-cx-supply = <&pma8084_s2>;
+		cam_vdig-supply = <&pma8084_l3>;
+		cam_vana-supply = <&pma8084_l17>;
+		cam_vio-supply = <&pma8084_lvs4>;
+		cam_vaf-supply = <&pma8084_l23>;
+	};
+
+	qcom,camera@6c {
+		qcom,vdd-cx-supply = <&pma8084_s2>;
+		cam_vdig-supply = <&pma8084_l3>;
+		cam_vana-supply = <&pma8084_l17>;
+		cam_vio-supply = <&pma8084_lvs4>;
+	};
+
+	qcom,camera@90 {
+		qcom,vdd-cx-supply = <&pma8084_s2>;
+		cam_vdig-supply = <&pma8084_l3>;
+		cam_vana-supply = <&pma8084_l17>;
+		cam_vio-supply = <&pma8084_lvs4>;
+	};
+};
+
+&soc {
+	i2c@f9924000 {
+		atmel_mxt_ts@4a {
+			vdd_ana-supply = <&pma8084_l18>;
+			vcc_i2c-supply = <&pma8084_lvs1>;
+		};
+	};
+
+	i2c@f9967000 {
+		isa1200@48 {
+			vcc_i2c-supply = <&pma8084_s4>;
+		};
+	};
+
+	qcom,ssusb@f9200000 {
+		vbus_dwc3-supply = <&pm8941_mvs1>;
+	};
+
+	qcom,mdss_dsi_toshiba_720p_video {
+		qcom,rst-gpio = <&pma8084_gpios 20 0>;
+	};
+
+	gpio_keys {
+		camera_snapshot {
+			gpios = <&pma8084_gpios 3 0x1>;
+		};
+
+		camera_focus {
+			gpios = <&pma8084_gpios 4 0x1>;
+		};
+
+		vol_up {
+			gpios = <&pma8084_gpios 5 0x1>;
+		};
+	};
+
+	spi@f9923000 {
+		ethernet-switch@2 {
+			rst-gpio = <&pma8084_mpps 6 0>;
+		};
+	};
+};
+
+&sdhc_1 {
+	vdd-supply = <&pma8084_l20>;
+	vdd-io-supply = <&pma8084_s4>;
+};
+
+&sdhc_2 {
+	vdd-supply = <&pma8084_l21>;
+	vdd-io-supply = <&pma8084_l13>;
+};
+
+&pma8084_gpios {
+	gpio@c000 { /* GPIO 1 */
+		/* Unused */
+		qcom,mode = <0>;		/* Digital input */
+		qcom,pull = <0>;		/* Pull up 30 uA */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c100 { /* GPIO 2 */
+		/* Unused */
+		qcom,mode = <0>;		/* Digital input */
+		qcom,pull = <0>;		/* Pull up 30 uA */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c200 { /* GPIO 3 */
+		/* Snapshot button */
+		qcom,mode = <0>;		/* Digital input */
+		qcom,pull = <0>;		/* Pull up 30 uA */
+		qcom,vin-sel = <2>;		/* PMA8084 S4 = 1.8 V */
+		qcom,src-sel = <0>;		/* Constant */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c300 { /* GPIO 4 */
+		/* Focus button */
+		qcom,mode = <0>;		/* Digital input */
+		qcom,pull = <0>;		/* Pull up 30 uA */
+		qcom,vin-sel = <2>;		/* PMA8084 S4 = 1.8 V */
+		qcom,src-sel = <0>;		/* Constant */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c400 { /* GPIO 5 */
+		/* Volume up button */
+		qcom,mode = <0>;		/* Digital input */
+		qcom,pull = <0>;		/* Pull up 30 uA */
+		qcom,vin-sel = <2>;		/* PMA8084 S4 = 1.8 V */
+		qcom,src-sel = <0>;		/* Constant */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c500 { /* GPIO 6 */
+		/* Flash LED now */
+		qcom,mode = <0>;		/* Digital input */
+		qcom,pull = <4>;		/* Pull down */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c600 { /* GPIO 7 */
+		/* GRFC_12 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+		/* Unused */
+		qcom,mode = <0>;		/* Digital input */
+		qcom,pull = <0>;		/* Pull up 30 uA */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c800 { /* GPIO 9 */
+		/* Unused */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,out-strength = <1>;	/* Low */
+		qcom,src-sel = <2>;		/* Function 1  */
+		qcom,master-en = <1>;
+	};
+
+	gpio@c900 { /* GPIO 10 */
+		/* NFC clock request */
+		qcom,mode = <0>;		/* Digital input */
+		qcom,pull = <4>;		/* Pull down */
+		qcom,master-en = <1>;
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+		/* Unused */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,out-strength = <1>;	/* Low */
+		qcom,src-sel = <2>;		/* Function 1  */
+		qcom,master-en = <1>;
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+		/* Unused */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,out-strength = <1>;	/* Low */
+		qcom,src-sel = <2>;		/* Function 1  */
+		qcom,master-en = <1>;
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+		/* TS_CHGR_IN */
+		qcom,mode = <0>;		/* Digital input */
+		qcom,pull = <4>;		/* Pull down */
+		qcom,master-en = <1>;
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+		/* Unused */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,out-strength = <1>;	/* Low */
+		qcom,src-sel = <2>;		/* Function 1  */
+		qcom,master-en = <1>;
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+		/* Codec clock */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;		/* CMOS */
+		qcom,vin-sel = <2>;		/* PMA8084 S4 = 1.8 V */
+		qcom,out-strength = <1>;	/* Low */
+		qcom,src-sel = <2>;		/* Function 1 - DIVCLK1 */
+		qcom,master-en = <1>;
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+		/* Haptics clock */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;		/* CMOS */
+		qcom,vin-sel = <2>;		/* PMA8084 S4 = 1.8 V */
+		qcom,out-strength = <3>;	/* High */
+		qcom,src-sel = <3>;       	/* Function 2 - SLEEPCLK3  */
+		qcom,master-en = <1>;
+	};
+
+	gpio@d000 { /* GPIO 17 */
+		/* QPA clock */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+		/* Unused */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+		/* BOOST_BYP */
+	};
+
+	gpio@d300 { /* GPIO 20 */
+		/* Display enable */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;		/* CMOS */
+		qcom,vin-sel = <2>;		/* PMA8084 S4 = 1.8 V */
+		qcom,out-strength = <1>;	/* Low */
+		qcom,src-sel = <0>;		/* Constant */
+		qcom,master-en = <1>;
+	};
+
+	gpio@d400 { /* GPIO 21 */
+		/* BATT_GONE */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+		/* BATT_REM_ALARM */
+	};
+};
+
+&pma8084_mpps {
+	mpp@a000 { /* MPP 1 */
+		/* SDC_UIM_VBIAS */
+		status = "disabled";
+	};
+
+	mpp@a100 { /* MPP 2 */
+		/* PM8941_PON_1 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+		/* VREF_DAC */
+	};
+
+	mpp@a300 { /* MPP 4 */
+		/* Unused */
+	};
+
+	mpp@a400 { /* MPP 5 */
+		/* Unused */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* SPI ethernet enable */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;		/* CMOS */
+		qcom,vin-sel = <2>;		/* PMA8084 S4 = 1.8V > 1.6V */
+		qcom,src-sel = <0>;		/* Constant */
+		qcom,out-strength = <1>;	/* Low */
+		qcom,master-en = <1>;
+	};
+
+	mpp@a600 { /* MPP 7 */
+		/* NFC disable */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,out-strength = <1>;	/* Low */
+		qcom,master-en = <1>;
+	};
+
+	mpp@a700 { /* MPP 8 */
+		/* Unused */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,out-strength = <1>;	/* Low */
+		qcom,master-en = <1>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi b/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
new file mode 100644
index 0000000..4d10ded
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
@@ -0,0 +1,250 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "msm8974pro-ac.dtsi"
+&spmi_bus {
+	pm8941_lsid0: qcom,pm8941@2 {
+		reg = <0x2>;
+	};
+	pm8941_lsid1: qcom,pm8941@3 {
+		reg = <0x3>;
+	};
+};
+/include/ "msm-pm8941.dtsi"
+
+&pma8084_vadc {
+	status = "disabled";
+};
+
+&pma8084_adc_tm {
+	status = "disabled";
+};
+
+&pm8941_lsid0 {
+	qcom,power-on@800 {
+		status = "disabled";
+	};
+
+	clkdiv@5b00 {
+		status = "disabled";
+	};
+
+	clkdiv@5c00 {
+		status = "disabled";
+	};
+
+	clkdiv@5d00 {
+		status = "disabled";
+	};
+
+	qcom,pm8941_rtc {
+		status = "disabled";
+	};
+
+	gpios {
+		status = "disabled";
+	};
+
+	mpps {
+		status = "disabled";
+	};
+};
+
+&pm8941_lsid1 {
+	pm8941_boost: regulator@a000 {
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		qcom,enable-time = <500>;
+		status = "okay";
+	};
+
+	pm8941_mvs1: regulator@8300 {
+		parent-supply = <&pm8941_chg_otg>;
+		qcom,enable-time = <1000>;
+		qcom,pull-down-enable = <1>;
+		interrupts = <0x3 0x83 0x2>;
+		interrupt-names = "ocp";
+		qcom,ocp-enable = <1>;
+		qcom,ocp-max-retries = <10>;
+		qcom,ocp-retry-delay = <30>;
+		qcom,soft-start-enable = <1>;
+		qcom,vs-soft-start-strength = <0>;
+		qcom,hpm-enable = <1>;
+		qcom,auto-mode-enable = <0>;
+		status = "okay";
+	};
+};
+
+&pma8084_mvs1 {
+	parent-supply = <&pm8941_boost>;
+};
+
+&pm8941_chg {
+	otg-parent-supply = <&pm8941_boost>;
+};
+
+&pm8941_chg_boost {
+	regulator-min-microvolt = <5000000>;
+	regulator-max-microvolt = <5000000>;
+	regulator-name = "8941_smbb_boost";
+};
+
+&pm8941_chg_otg {
+	regulator-name = "8941_smbb_otg";
+};
+
+/* Correct PM8941 local slave ID 0 to use global SID 4 for all interrupts. */
+&pm8941_lsid0 {
+	qcom,temp-alarm@2400 {
+		interrupts = <0x2 0x24 0x0>;
+	};
+
+	qcom,power-on@800 {
+		interrupts = <0x2 0x8 0x0>,
+			     <0x2 0x8 0x1>,
+			     <0x2 0x8 0x4>,
+			     <0x2 0x8 0x5>;
+		interrupt-names = "kpdpwr", "resin",
+				"resin-bark", "kpdpwr-resin-bark";
+	};
+
+	qcom,bsi@1b00 {
+		interrupts = <0x2 0x1b 0x0>,
+			     <0x2 0x1b 0x1>,
+			     <0x2 0x1b 0x2>,
+			     <0x2 0x12 0x0>;
+		interrupt-names = "err",
+				  "rx",
+				  "tx",
+				  "batt-present";
+	};
+
+	qcom,bms {
+		qcom,bms-bms@4000 {
+			interrupts =	<0x2 0x40 0x0>,
+					<0x2 0x40 0x1>,
+					<0x2 0x40 0x2>,
+					<0x2 0x40 0x3>,
+					<0x2 0x40 0x4>,
+					<0x2 0x40 0x5>,
+					<0x2 0x40 0x6>,
+					<0x2 0x40 0x7>;
+			interrupt-names = "cc_thr",
+					  "ocv_for_r",
+					  "good_ocv",
+					  "charge_begin",
+					  "ocv_thr",
+					  "sw_cc_thr",
+					  "vsense_avg",
+					  "vsense_for_r";
+		};
+	};
+
+	qcom,charger {
+		qcom,chgr@1000 {
+			interrupts =	<0x2 0x10 0x0>,
+					<0x2 0x10 0x1>,
+					<0x2 0x10 0x2>,
+					<0x2 0x10 0x3>,
+					<0x2 0x10 0x4>,
+					<0x2 0x10 0x5>,
+					<0x2 0x10 0x6>,
+					<0x2 0x10 0x7>;
+			interrupt-names =	"vbat-det-lo",
+						"vbat-det-hi",
+						"chgwdog",
+						"state-change",
+						"trkl-chg-on",
+						"fast-chg-on",
+						"chg-failed",
+						"chg-done";
+		};
+
+		qcom,buck@1100 {
+			interrupts =	<0x2 0x11 0x0>,
+					<0x2 0x11 0x1>,
+					<0x2 0x11 0x2>,
+					<0x2 0x11 0x3>,
+					<0x2 0x11 0x4>,
+					<0x2 0x11 0x5>,
+					<0x2 0x11 0x6>;
+			interrupt-names =	"vbat-ov",
+						"vreg-ov",
+						"overtemp",
+						"vchg-loop",
+						"ichg-loop",
+						"ibat-loop",
+						"vdd-loop";
+		};
+
+		qcom,bat-if@1200 {
+			interrupts =	<0x2 0x12 0x0>,
+					<0x2 0x12 0x1>,
+					<0x2 0x12 0x2>,
+					<0x2 0x12 0x3>,
+					<0x2 0x12 0x4>;
+			interrupt-names =	"batt-pres",
+						"bat-temp-ok",
+						"bat-fet-on",
+						"vcp-on",
+						"psi";
+		};
+
+		qcom,usb-chgpth@1300 {
+			interrupts =	<0x2 0x13 0x0>,
+					<0x2 0x13 0x1>,
+					<0x2 0x13 0x2>;
+			interrupt-names =	"coarse-det-usb",
+						"usbin-valid",
+						"chg-gone";
+		};
+
+		qcom,dc-chgpth@1400 {
+			interrupts =	<0x2 0x14 0x0>,
+					<0x2 0x14 0x1>;
+			interrupt-names =	"coarse-det-dc",
+						"dcin-valid";
+		};
+
+		qcom,boost@1500 {
+			interrupts =	<0x2 0x15 0x0>,
+					<0x2 0x15 0x1>;
+			interrupt-names =	"boost-pwr-ok",
+						"limit-error";
+		};
+	};
+
+	qcom,pm8941_rtc {
+		qcom,pm8941_rtc_alarm@6100 {
+			interrupts = <0x2 0x61 0x1>;
+		};
+	};
+
+	vadc@3100 {
+		interrupts = <0x2 0x31 0x0>;
+		interrupt-names = "eoc-int-en-set";
+	};
+
+	iadc@3600 {
+		interrupts = <0x2 0x36 0x0>;
+		interrupt-names = "eoc-int-en-set";
+	};
+
+	qcom,vadc@3400 {
+		interrupts =	<0x2 0x34 0x0>,
+				<0x2 0x34 0x3>,
+				<0x2 0x34 0x4>;
+		interrupt-names =	"eoc-int-en-set",
+					"high-thr-en-set",
+					"low-thr-en-set";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-regulator.dtsi b/arch/arm/boot/dts/msm8974pro-ac-regulator.dtsi
new file mode 100644
index 0000000..9d7f316
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ac-regulator.dtsi
@@ -0,0 +1,566 @@
+/* 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.
+ */
+
+
+/* QPNP controlled regulators: */
+
+&spmi_bus {
+	qcom,pma8084@1 {
+		pma8084_mvs1: regulator@8400 {
+			qcom,enable-time = <1000>;
+			qcom,pull-down-enable = <1>;
+			interrupts = <0x1 0x84 0x2>;
+			interrupt-names = "ocp";
+			qcom,ocp-enable = <1>;
+			qcom,ocp-max-retries = <10>;
+			qcom,ocp-retry-delay = <30>;
+			qcom,soft-start-enable = <1>;
+			qcom,vs-soft-start-strength = <0>;
+			qcom,hpm-enable = <1>;
+			qcom,auto-mode-enable = <0>;
+			status = "okay";
+		};
+	};
+};
+
+/* RPM controlled regulators: */
+
+&rpm_bus {
+	rpm-regulator-smpa1 {
+		status = "okay";
+		pma8084_s1: regulator-s1 {
+			regulator-min-microvolt = <675000>;
+			regulator-max-microvolt = <1050000>;
+			status = "okay";
+		};
+		pma8084_s1_ao: regulator-s1-ao {
+			regulator-name = "8084_s1_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <675000>;
+			regulator-max-microvolt = <1050000>;
+			status = "okay";
+			compatible = "qcom,rpm-regulator-smd";
+		};
+		pma8084_s1_so: regulator-s1-so {
+			regulator-name = "8084_s1_so";
+			qcom,set = <2>;
+			regulator-min-microvolt = <675000>;
+			regulator-max-microvolt = <1050000>;
+			qcom,init-voltage = <675000>;
+			status = "okay";
+			compatible = "qcom,rpm-regulator-smd";
+		};
+	};
+
+	rpm-regulator-smpa2 {
+		status = "okay";
+		pma8084_s2: regulator-s2 {
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1050000>;
+			status = "okay";
+		};
+		pma8084_s2_corner: regulator-s2-corner {
+			regulator-name = "8084_s2_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+			compatible = "qcom,rpm-regulator-smd";
+			qcom,consumer-supplies = "vdd_dig", "";
+		};
+		pma8084_s2_corner_ao: regulator-s2-corner-ao {
+			regulator-name = "8084_s2_corner_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+			compatible = "qcom,rpm-regulator-smd";
+		};
+		pma8084_s2_floor_corner: regulator-s2-floor-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s2_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
+	};
+
+
+	rpm-regulator-smpa3 {
+		status = "okay";
+		pma8084_s3: regulator-s3 {
+			regulator-min-microvolt = <1300000>;
+			regulator-max-microvolt = <1300000>;
+			qcom,init-voltage = <1300000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		status = "okay";
+		pma8084_s4: regulator-s4 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-smpa5 {
+		status = "okay";
+		pma8084_s5: regulator-s5 {
+			regulator-min-microvolt = <2150000>;
+			regulator-max-microvolt = <2150000>;
+			qcom,init-voltage = <2150000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-smpa6 {
+		status = "okay";
+		pma8084_s6: regulator-s6 {
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
+			qcom,init-voltage = <1050000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-smpa7 {
+		status = "okay";
+		pma8084_s7: regulator-s7 {
+			regulator-min-microvolt = <815000>;
+			regulator-max-microvolt = <900000>;
+			status = "okay";
+		};
+		pma8084_s7_corner: regulator-s7-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s7_corner";
+			qcom,set = <3>;
+			qcom,use-voltage-corner;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,init-voltage-corner = <3>; /* SVS SOC */
+		};
+		pma8084_s7_floor_corner: regulator-s7-floor-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8084_s7_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		status = "okay";
+		pma8084_l1: regulator-l1 {
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,init-voltage = <1225000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		status = "okay";
+		pma8084_l2: regulator-l2 {
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		status = "okay";
+		pma8084_l3: regulator-l3 {
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,init-voltage = <1225000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		status = "okay";
+		pma8084_l4: regulator-l4 {
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,init-voltage = <1225000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		status = "okay";
+		pma8084_l5: regulator-l5 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		status = "okay";
+		pma8084_l6: regulator-l6 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		status = "okay";
+		pma8084_l7: regulator-l7 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		status = "okay";
+		pma8084_l8: regulator-l8 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		status = "okay";
+		pma8084_l9: regulator-l9 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <2950000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		status = "okay";
+		pma8084_l10: regulator-l10 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <2950000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+		status = "okay";
+		pma8084_l11: regulator-l11 {
+			regulator-min-microvolt = <1300000>;
+			regulator-max-microvolt = <1300000>;
+			qcom,init-voltage = <1300000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		status = "okay";
+		pma8084_l12: regulator-l12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			status = "okay";
+		};
+		pma8084_l12_ao: regulator-l12-ao {
+			regulator-name = "8084_l12_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			status = "okay";
+			compatible = "qcom,rpm-regulator-smd";
+		};
+	};
+
+	rpm-regulator-ldoa13 {
+		status = "okay";
+		pma8084_l13: regulator-l13 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <2950000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		status = "okay";
+		pma8084_l14: regulator-l14 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		status = "okay";
+		pma8084_l15: regulator-l15 {
+			regulator-min-microvolt = <2050000>;
+			regulator-max-microvolt = <2050000>;
+			qcom,init-voltage = <2050000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		status = "okay";
+		pma8084_l16: regulator-l16 {
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <2700000>;
+			qcom,init-voltage = <2700000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		status = "okay";
+		pma8084_l17: regulator-l17 {
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,init-voltage = <2850000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		status = "okay";
+		pma8084_l18: regulator-l18 {
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,init-voltage = <2850000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa19 {
+		status = "okay";
+		pma8084_l19: regulator-l19 {
+			regulator-min-microvolt = <2900000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <2900000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa20 {
+		status = "okay";
+		pma8084_l20: regulator-l20 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <2950000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa21 {
+		status = "okay";
+		pma8084_l21: regulator-l21 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <2950000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa22 {
+		status = "okay";
+		pma8084_l22: regulator-l22 {
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,init-voltage = <3000000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa23 {
+		status = "okay";
+		pma8084_l23: regulator-l23 {
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,init-voltage = <3000000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa24 {
+		status = "okay";
+		pma8084_l24: regulator-l24 {
+			regulator-min-microvolt = <3075000>;
+			regulator-max-microvolt = <3075000>;
+			qcom,init-voltage = <3075000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa25 {
+		status = "okay";
+		pma8084_l25: regulator-l25 {
+			regulator-min-microvolt = <2100000>;
+			regulator-max-microvolt = <2100000>;
+			qcom,init-voltage = <2100000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa26 {
+		status = "okay";
+		pma8084_l26: regulator-l26 {
+			regulator-min-microvolt = <2050000>;
+			regulator-max-microvolt = <2050000>;
+			qcom,init-voltage = <2050000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa27 {
+		status = "okay";
+		pma8084_l27: regulator-l27 {
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-vsa1 {
+		status = "okay";
+		pma8084_lvs1: regulator-lvs1 {
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-vsa2 {
+		status = "okay";
+		pma8084_lvs2: regulator-lvs2 {
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-vsa3 {
+		status = "okay";
+		pma8084_lvs3: regulator-lvs3 {
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-vsa4 {
+		status = "okay";
+		pma8084_lvs4: regulator-lvs4 {
+			status = "okay";
+		};
+	};
+};
+
+&soc {
+	krait_pdn: krait-pdn@f9011000 {
+		reg = <0xf9011000 0x1000>,
+		      <0xfc4b80b0 8>;
+		reg-names = "apcs_gcc", "phase-scaling-efuse";
+		compatible = "qcom,krait-pdn";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		qcom,pfm-threshold = <73>;
+
+		krait0_vreg: regulator@f9088000 {
+			compatible = "qcom,krait-regulator";
+			regulator-name = "krait0";
+			reg = <0xf9088000 0x1000>, /* APCS_ALIAS0_KPSS_ACS */
+				<0xf908a800 0x1000>; /* APCS_ALIAS0_KPSS_MDD */
+			reg-names = "acs", "mdd";
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1100000>;
+			qcom,headroom-voltage = <150000>;
+			qcom,retention-voltage = <675000>;
+			qcom,ldo-default-voltage = <750000>;
+			qcom,ldo-threshold-voltage = <850000>;
+			qcom,ldo-delta-voltage = <50000>;
+			qcom,cpu-num = <0>;
+		};
+
+		krait1_vreg: regulator@f9098000 {
+			compatible = "qcom,krait-regulator";
+			regulator-name = "krait1";
+			reg = <0xf9098000 0x1000>, /* APCS_ALIAS1_KPSS_ACS */
+				<0xf909a800 0x1000>; /* APCS_ALIAS1_KPSS_MDD */
+			reg-names = "acs", "mdd";
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1100000>;
+			qcom,headroom-voltage = <150000>;
+			qcom,retention-voltage = <675000>;
+			qcom,ldo-default-voltage = <750000>;
+			qcom,ldo-threshold-voltage = <850000>;
+			qcom,ldo-delta-voltage = <50000>;
+			qcom,cpu-num = <1>;
+		};
+
+		krait2_vreg: regulator@f90a8000 {
+			compatible = "qcom,krait-regulator";
+			regulator-name = "krait2";
+			reg = <0xf90a8000 0x1000>, /* APCS_ALIAS2_KPSS_ACS */
+				<0xf90aa800 0x1000>; /* APCS_ALIAS2_KPSS_MDD */
+			reg-names = "acs", "mdd";
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1100000>;
+			qcom,headroom-voltage = <150000>;
+			qcom,retention-voltage = <675000>;
+			qcom,ldo-default-voltage = <750000>;
+			qcom,ldo-threshold-voltage = <850000>;
+			qcom,ldo-delta-voltage = <50000>;
+			qcom,cpu-num = <2>;
+		};
+
+		krait3_vreg: regulator@f90b8000 {
+			compatible = "qcom,krait-regulator";
+			regulator-name = "krait3";
+			reg = <0xf90b8000 0x1000>, /* APCS_ALIAS3_KPSS_ACS */
+				<0xf90ba800 0x1000>; /* APCS_ALIAS3_KPSS_MDD */
+			reg-names = "acs", "mdd";
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1100000>;
+			qcom,headroom-voltage = <150000>;
+			qcom,retention-voltage = <675000>;
+			qcom,ldo-default-voltage = <750000>;
+			qcom,ldo-threshold-voltage = <850000>;
+			qcom,ldo-delta-voltage = <50000>;
+			qcom,cpu-num = <3>;
+		};
+	};
+
+	/* SPI expects a regulator device, but no hardware is present. */
+	spi_eth_vreg: spi_eth_phy_vreg {
+		compatible = "regulator-fixed";
+		regulator-name = "ethernet_phy";
+		regulator-always-on;
+	};
+
+	/*
+	 * vph_pwr_vreg represents the unregulated battery voltage supply
+	 * VPH_PWR that is present whenever the device is powered on.
+	 */
+	vph_pwr_vreg: vph_pwr_vreg {
+		compatible = "regulator-fixed";
+		status = "disabled";
+		regulator-name = "vph_pwr";
+		regulator-always-on;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac.dtsi b/arch/arm/boot/dts/msm8974pro-ac.dtsi
index 9240514..032c256 100644
--- a/arch/arm/boot/dts/msm8974pro-ac.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac.dtsi
@@ -17,3 +17,174 @@
  */
 
 /include/ "msm8974pro.dtsi"
+
+/include/ "msm-pma8084-rpm-regulator.dtsi"
+/include/ "msm-pma8084.dtsi"
+/include/ "msm8974pro-ac-regulator.dtsi"
+
+/*
+ * Override PM8841 and PM8941 resources with proper PMA8084 resources for
+ * MSM8974Pro AC.
+ */
+
+&soc {
+	qcom,csid@fda08000  {
+		qcom,mipi-csi-vdd-supply = <&pma8084_l12>;
+	};
+
+	qcom,csid@fda08400 {
+		qcom,mipi-csi-vdd-supply = <&pma8084_l12>;
+	};
+
+	qcom,csid@fda08800 {
+		qcom,mipi-csi-vdd-supply = <&pma8084_l12>;
+	};
+
+	qcom,csid@fda08C00 {
+		qcom,mipi-csi-vdd-supply = <&pma8084_l12>;
+	};
+
+	tpiu@fc318000 {
+		vdd-supply = <&pma8084_l21>;
+	};
+
+	qcom,mdss_dsi@fd922800 {
+		vdd-supply = <&pma8084_l22>;
+		vddio-supply = <&pma8084_l12>;
+		vdda-supply = <&pma8084_l2>;
+	};
+
+	qcom,mdss_dsi@fd922e00 {
+		vdd-supply = <&pma8084_l22>;
+		vddio-supply = <&pma8084_l12>;
+		vdda-supply = <&pma8084_l2>;
+	};
+
+	qcom,hdmi_tx@fd922100 {
+		hpd-5v-supply = <&pma8084_mvs1>;
+		core-vdda-supply = <&pma8084_l12>;
+		core-vcc-supply = <&pma8084_s4>;
+	};
+
+	qcom,mdss_edp@fd923400 {
+		vdda-supply = <&pma8084_l12>;
+	};
+
+	usb@f9a55000 {
+		HSUSB_VDDCX-supply = <&pma8084_s2_corner>;
+		HSUSB_1p8-supply = <&pma8084_l6>;
+		HSUSB_3p3-supply = <&pma8084_l24>;
+	};
+
+	qcom,sdcc@f9824000 {
+		vdd-supply = <&pma8084_l20>;
+		vdd-io-supply = <&pma8084_s4>;
+	};
+
+	qcom,sdcc@f98a4000 {
+		vdd-supply = <&pma8084_l21>;
+		vdd-io-supply = <&pma8084_l13>;
+	};
+
+	slim@fe12f000 {
+		taiko_codec {
+			cdc-vdd-buck-supply = <&pma8084_s5>;
+			cdc-vdd-tx-h-supply = <&pma8084_s4>;
+			cdc-vdd-rx-h-supply = <&pma8084_s4>;
+			cdc-vddpx-1-supply = <&pma8084_s4>;
+			cdc-vdd-a-1p2v-supply = <&pma8084_l1>;
+			cdc-vddcx-1-supply = <&pma8084_l1>;
+			cdc-vddcx-2-supply = <&pma8084_l1>;
+		};
+	};
+
+	qcom,acpuclk@f9000000 {
+		krait0_mem-supply = <&pma8084_s1_ao>;
+		krait1_mem-supply = <&pma8084_s1_ao>;
+		krait2_mem-supply = <&pma8084_s1_ao>;
+		krait3_mem-supply = <&pma8084_s1_ao>;
+		krait0_dig-supply = <&pma8084_s2_corner_ao>;
+		krait1_dig-supply = <&pma8084_s2_corner_ao>;
+		krait2_dig-supply = <&pma8084_s2_corner_ao>;
+		krait3_dig-supply = <&pma8084_s2_corner_ao>;
+		krait0_hfpll-supply = <&pma8084_l12_ao>;
+		krait1_hfpll-supply = <&pma8084_l12_ao>;
+		krait2_hfpll-supply = <&pma8084_l12_ao>;
+		krait3_hfpll-supply = <&pma8084_l12_ao>;
+		l2_hfpll-supply = <&pma8084_l12_ao>;
+	};
+
+	qcom,ssusb@f9200000 {
+		ssusb_vdd_dig-supply = <&pma8084_s2_corner>;
+		SSUSB_1p8-supply = <&pma8084_l6>;
+		hsusb_vdd_dig-supply = <&pma8084_s2_corner>;
+		HSUSB_1p8-supply = <&pma8084_l6>;
+		HSUSB_3p3-supply = <&pma8084_l24>;
+	};
+
+	qcom,ehci-host@f9a55000 {
+		HSUSB_VDDCX-supply = <&pma8084_s2>;
+		HSUSB_1p8-supply = <&pma8084_l6>;
+		HSUSB_3p3-supply = <&pma8084_l24>;
+	};
+
+	qcom,gdsc@fd8c4024 {
+		parent-supply = <&pma8084_s7_corner>;
+	};
+
+	qcom,lpass@fe200000 {
+		vdd_cx-supply = <&pma8084_s2_corner>;
+	};
+
+	qcom,mss@fc880000 {
+		vdd_mss-supply = <&pma8084_s6>;
+		vdd_cx-supply = <&pma8084_s2_corner>;
+		vdd_mx-supply = <&pma8084_s1>;
+		vdd_pll-supply = <&pma8084_l12>;
+	};
+
+	qcom,pronto@fb21b000 {
+		vdd_pronto_pll-supply = <&pma8084_l12>;
+	};
+
+	qcom,wcnss-wlan@fb000000 {
+		qcom,pronto-vddmx-supply = <&pma8084_s1>;
+		qcom,pronto-vddcx-supply = <&pma8084_s2>;
+		qcom,pronto-vddpx-supply = <&pma8084_s4>;
+		qcom,iris-vddxo-supply = <&pma8084_l6>;
+		qcom,iris-vddrfa-supply = <&pma8084_l11>;
+		qcom,iris-vddpa-supply = <&pma8084_l19>;
+		qcom,iris-vdddig-supply = <&pma8084_s4>;
+	};
+
+	qcom,msm-thermal {
+		vdd-dig-supply = <&pma8084_s2_floor_corner>;
+		vdd-gfx-supply = <&pma8084_s7_floor_corner>;
+	};
+
+	qcom,lpm-resources {
+		qcom,lpm-resources@0 {
+			qcom,name = "vdd-dig";
+			qcom,type = <0x61706d73>;	/* "smpa" */
+			qcom,id = <2>;
+		};
+
+		qcom,lpm-resources@1 {
+			qcom,name = "vdd-mem";
+			qcom,type = <0x61706d73>;	/* "smpa" */
+			qcom,id = <1>;
+		};
+	};
+
+	sound {
+		qcom,cdc-mclk-gpios = <&pma8084_gpios 15 0>;
+	};
+};
+
+&krait_pdn {
+	qcom,use-phase-switching;
+};
+
+&tspp {
+	vdd_cx-supply = <&pma8084_s2_corner>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index 96e78ac..b80eb0f 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -37,7 +37,7 @@
 /* GPU overrides */
 &msm_gpu {
 	/* Updated chip ID */
-	qcom,chipid = <0x03030001>;
+	qcom,chipid = <0x03030002>;
 
 	/* Updated bus bandwidth requirements */
 	qcom,msm-bus,vectors-KBps =
@@ -53,6 +53,55 @@
 		<26 512 0 7464000>, <89 604 0 5120000>,
 		/* Turbo */
 		<26 512 0 7464000>, <89 604 0 6400000>;
+
+       qcom,gpu-pwrlevels {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               compatible = "qcom,gpu-pwrlevels";
+
+               qcom,gpu-pwrlevel@0 {
+                       reg = <0>;
+                       qcom,gpu-freq = <550000000>;
+                       qcom,bus-freq = <5>;
+                       qcom,io-fraction = <33>;
+               };
+
+               qcom,gpu-pwrlevel@1 {
+                       reg = <1>;
+                       qcom,gpu-freq = <320000000>;
+                       qcom,bus-freq = <4>;
+                       qcom,io-fraction = <66>;
+               };
+
+               qcom,gpu-pwrlevel@2 {
+                       reg = <2>;
+                       qcom,gpu-freq = <320000000>;
+                       qcom,bus-freq = <3>;
+                       qcom,io-fraction = <66>;
+               };
+
+               qcom,gpu-pwrlevel@3 {
+                       reg = <3>;
+                       qcom,gpu-freq = <200000000>;
+                       qcom,bus-freq = <2>;
+                       qcom,io-fraction = <100>;
+               };
+
+               qcom,gpu-pwrlevel@4 {
+                       reg = <4>;
+                       qcom,gpu-freq = <200000000>;
+                       qcom,bus-freq = <1>;
+                       qcom,io-fraction = <100>;
+               };
+
+               qcom,gpu-pwrlevel@5 {
+                       reg = <5>;
+                       qcom,gpu-freq = <27000000>;
+                       qcom,bus-freq = <0>;
+                       qcom,io-fraction = <0>;
+               };
+       };
 };
 
 &mdss_mdp {
@@ -128,11 +177,3 @@
 					<0x42 0x2>,
 					<0x120 0x3>;
 };
-
-&krait_pdn {
-	qcom,use-phase-switching;
-};
-
-&tspp {
-	vdd_cx-supply = <&pm8841_s2_corner>;
-};
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index 60472c8..4a903b7 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -16,6 +16,8 @@
 		reg = <0xfc322000 0x1000>,
 		      <0xfc37c000 0x3000>;
 		reg-names = "tmc-base", "bam-base";
+		interrupts = <0 166 0>;
+		interrupt-names = "byte-cntr-irq";
 
 		qcom,memory-reservation-type = "EBI1";
 		qcom,memory-reservation-size = <0x20000>; /* 128K EBI1 buffer */
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 24c6143..7989f2b 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -28,57 +28,16 @@
 		3e 0f];
 	};
 
-	qcom,lpm-resources {
-		compatible = "qcom,lpm-resources";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		qcom,lpm-resources@0 {
-			reg = <0x0>;
-			qcom,name = "vdd-dig";
-			qcom,type = <0x616F646C>;       /* "ldoa" */
-			qcom,id = <0x0A>;
-			qcom,key = <0x6e726f63>;	/* "corn" */
-			qcom,init-value = <5>;		/* Super Turbo */
-		};
-
-		qcom,lpm-resources@1 {
-			reg = <0x1>;
-			qcom,name = "vdd-mem";
-			qcom,type = <0x616F646C>;       /* "ldoa" */
-			qcom,id = <0x0C>;
-			qcom,key =  <0x7675>;		/* "uv" */
-			qcom,init-value = <1050000>;	/* Super Turbo */
-		};
-
-		qcom,lpm-resources@2 {
-			reg = <0x2>;
-			qcom,name = "pxo";
-			qcom,type = <0x306b6c63>;	/* "clk0" */
-			qcom,id = <0x00>;
-			qcom,key = <0x62616e45>;	/* "Enab" */
-			qcom,init-value = "xo_on";
-		};
-	};
-
 	qcom,lpm-levels {
 		compatible = "qcom,lpm-levels";
+		qcom,no-l2-saw;
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		qcom,use-qtimer;
-
 		qcom,lpm-level@0 {
 			reg = <0x0>;
 			qcom,mode = "wfi";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
 			qcom,latency-us = <100>;
 			qcom,ss-power = <8000>;
 			qcom,energy-overhead = <100000>;
@@ -88,14 +47,7 @@
 		qcom,lpm-level@1 {
 			reg = <0x1>;
 			qcom,mode = "standalone_pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
 			qcom,latency-us = <2000>;
 			qcom,ss-power = <5000>;
 			qcom,energy-overhead = <60100000>;
@@ -105,15 +57,8 @@
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_gdhs";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
-			qcom,latency-us = <3500>;
+			qcom,latency-us = <20000>;
 			qcom,ss-power = <5000>;
 			qcom,energy-overhead = <60350000>;
 			qcom,time-overhead = <6300>;
@@ -122,66 +67,12 @@
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
-			qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
-			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
-			qcom,irqs-detectable;
-			qcom,gpio-detectable;
-			qcom,latency-us = <4500>;
+			qcom,latency-us = <30000>;
 			qcom,ss-power = <5000>;
 			qcom,energy-overhead = <60350000>;
 			qcom,time-overhead = <7300>;
 		};
-
-		qcom,lpm-level@4 {
-			reg = <0x4>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,irqs-detectable;
-			qcom,latency-us = <6800>;
-			qcom,ss-power = <2000>;
-			qcom,energy-overhead = <71850000>;
-			qcom,time-overhead = <13300>;
-		};
-
-		qcom,lpm-level@5 {
-			reg = <0x5>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
-			qcom,irqs-detectable;
-			qcom,latency-us = <8000>;
-			qcom,ss-power = <1800>;
-			qcom,energy-overhead = <71950000>;
-			qcom,time-overhead = <15300>;
-		};
-
-		qcom,lpm-level@6 {
-			reg = <0x6>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
-			qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
-			qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
-			qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
-			qcom,latency-us = <9800>;
-			qcom,ss-power = <0>;
-			qcom,energy-overhead = <76350000>;
-			qcom,time-overhead = <28300>;
-		};
 	};
 
 	qcom,pm-boot {
@@ -271,8 +162,9 @@
 			<37 71>;
 	};
 
-	qcom,pm-8x60 {
+	qcom,pm-8x60@fe805664 {
 		compatible = "qcom,pm-8x60";
+		reg = <0xfe805664 0x40>;
 		qcom,pc-mode = "tz_l2_ext";
 		qcom,use-sync-timer;
 	};
diff --git a/arch/arm/boot/dts/msm9625-regulator.dtsi b/arch/arm/boot/dts/msm9625-regulator.dtsi
index ee48b7f..eb56d1c 100644
--- a/arch/arm/boot/dts/msm9625-regulator.dtsi
+++ b/arch/arm/boot/dts/msm9625-regulator.dtsi
@@ -194,6 +194,15 @@
 			qcom,use-voltage-corner;
 			status = "okay";
 		};
+		pm8019_l10_floor_corner: regulator-l10-floor-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8019_l10_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
 	};
 
 	rpm-regulator-ldoa11 {
diff --git a/arch/arm/boot/dts/msm9625-v1.dtsi b/arch/arm/boot/dts/msm9625-v1.dtsi
index b238ba5..daf774b 100644
--- a/arch/arm/boot/dts/msm9625-v1.dtsi
+++ b/arch/arm/boot/dts/msm9625-v1.dtsi
@@ -48,6 +48,7 @@
 /* CoreSight */
 &tmc_etr {
 	qcom,reset-flush-race;
+	qcom,byte-cntr-absent;
 };
 
 &stm {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index f5e930d..59d7ba0 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -511,7 +511,7 @@
 	tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
-		      <0xfc4b8000 0x1000>;
+		      <0xfc4bc000 0x1000>;
 		reg-names = "tsens_physical", "tsens_eeprom_physical";
 		interrupts = <0 184 0>;
 		qcom,sensors = <5>;
@@ -529,10 +529,10 @@
 		qcom,freq-control-mask = <0x0>;
 		qcom,vdd-restriction-temp = <5>;
 		qcom,vdd-restriction-temp-hysteresis = <10>;
-		vdd_dig-supply = <&pm8019_l10_corner>;
+		vdd-dig-supply = <&pm8019_l10_floor_corner>;
 
 		qcom,vdd-dig-rstr{
-			qcom,vdd-rstr-reg = "vdd_dig";
+			qcom,vdd-rstr-reg = "vdd-dig";
 			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
 			qcom,min-level = <1>; /* No Request */
 		};
diff --git a/arch/arm/boot/dts/msmkrypton-smp2p.dtsi b/arch/arm/boot/dts/msmkrypton-smp2p.dtsi
new file mode 100644
index 0000000..fcd2880
--- /dev/null
+++ b/arch/arm/boot/dts/msmkrypton-smp2p.dtsi
@@ -0,0 +1,122 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+&soc {
+	qcom,smp2p-modem {
+		compatible = "qcom,smp2p";
+		reg = <0xf9011008 0x4>;
+		qcom,remote-pid = <1>;
+		qcom,irq-bitmask = <0x4000>;
+		interrupts = <0 27 1>;
+	};
+
+	qcom,smp2p-adsp {
+		compatible = "qcom,smp2p";
+		reg = <0xf9011008 0x4>;
+		qcom,remote-pid = <2>;
+		qcom,irq-bitmask = <0x400>;
+		interrupts = <0 158 1>;
+	};
+
+	smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <7>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_7_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_7_in";
+		gpios = <&smp2pgpio_smp2p_7_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <7>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_7_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_7_out";
+		gpios = <&smp2pgpio_smp2p_7_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+		gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+		gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <2>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_2_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_2_in";
+		gpios = <&smp2pgpio_smp2p_2_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_2_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_2_out";
+		gpios = <&smp2pgpio_smp2p_2_out 0 0>;
+	};
+
+};
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index ba6377c..cdaf964 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -20,6 +20,8 @@
 	soc: soc { };
 };
 
+/include/ "msmkrypton-smp2p.dtsi"
+
 &soc {
 	#address-cells = <1>;
 	#size-cells = <1>;
@@ -50,6 +52,11 @@
 		reg = <0xfe807800 0x1000>; /* Address and size of IMEM */
 	};
 
+	qcom,msm-mem-hole {
+		compatible = "qcom,msm-mem-hole";
+		qcom,memblock-remove = <0x02000000 0x06000000>; /* Address and Size of Hole */
+	};
+
 	timer@f9020000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -123,6 +130,15 @@
 		status = "disabled";
 	};
 
+	qcom,sps@f9980000 {
+		compatible = "qcom,msm_sps";
+		reg = <0xf9984000 0x15000>,
+		      <0xf9999000 0xb000>,
+		      <0xfe803000 0xd000>,
+			  <0xfe805000 0x1000>;
+		interrupts = <0 94 0>;
+	};
+
 	spi_6: spi@f9928000 { /* BLSP1 QUP6 */
 		cell-index = <0>;
 		compatible = "qcom,spi-qup-v2";
@@ -137,4 +153,68 @@
 		<&msmgpio 20 0>; /* MOSI */
 		cs-gpios = <&msmgpio 22 0>;
 	};
+
+	qcom,ipc-spinlock@fd484000 {
+		compatible = "qcom,ipc-spinlock-sfpb";
+		reg = <0xfd484000 0x400>;
+		qcom,num-locks = <8>;
+	};
+
+	qcom,smem@2200000 {
+		compatible = "qcom,smem";
+		reg = <0x2200000 0x100000>,
+			<0xf9011000 0x1000>,
+			<0xfc428000 0x4000>;
+		reg-names = "smem", "irq-reg-base", "aux-mem1";
+
+		qcom,smd-modem {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <0>;
+			qcom,smd-irq-offset = <0x8>;
+			qcom,smd-irq-bitmask = <0x1000>;
+			qcom,pil-string = "modem";
+			interrupts = <0 25 1>;
+		};
+
+		qcom,smsm-modem {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <0>;
+			qcom,smsm-irq-offset = <0x8>;
+			qcom,smsm-irq-bitmask = <0x2000>;
+			interrupts = <0 26 1>;
+		};
+
+		qcom,smd-adsp {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <1>;
+			qcom,smd-irq-offset = <0x8>;
+			qcom,smd-irq-bitmask = <0x100>;
+			qcom,pil-string = "adsp";
+			interrupts = <0 156 1>;
+		};
+
+		qcom,smsm-adsp {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <1>;
+			qcom,smsm-irq-offset = <0x8>;
+			qcom,smsm-irq-bitmask = <0x200>;
+			interrupts = <0 157 1>;
+		};
+
+		qcom,smd-rpm {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <15>;
+			qcom,smd-irq-offset = <0x8>;
+			qcom,smd-irq-bitmask = <0x1>;
+			interrupts = <0 168 1>;
+			qcom,irq-no-suspend;
+		};
+	};
+
+	rpm_bus: qcom,rpm-smd {
+		compatible = "qcom,rpm-smd";
+		rpm-channel-name = "rpm_requests";
+		rpm-channel-type = <15>; /* SMD_APPS_RPM */
+		rpm-standalone = <1>;
+	};
 };
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
index fdf2680..251bef2 100644
--- a/arch/arm/boot/dts/msmsamarium.dtsi
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -217,4 +217,21 @@
 		interrupts = <0 29 1>;
 		qcom,rx-ring-size = <64>;
 	};
+
+	spmi_bus: qcom,spmi@fc4c0000 {
+		compatible = "qcom,spmi-pmic-arb";
+		reg = <0xfc4cf000 0x1000>,
+		      <0Xfc4cb000 0x1000>,
+		      <0Xfc4ca000 0x1000>;
+		reg-names = "core", "intr", "cnfg";
+		interrupts = <0 190 0>;
+		qcom,pmic-arb-channel = <0>;
+		qcom,pmic-arb-ee = <0>;
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cell-index = <0>;
+		qcom,not-wakeup;     /* Needed until MPM is fully configured. */
+	};
 };
diff --git a/arch/arm/common/cpaccess.c b/arch/arm/common/cpaccess.c
index 3572e5a..cca0b39 100644
--- a/arch/arm/common/cpaccess.c
+++ b/arch/arm/common/cpaccess.c
@@ -385,6 +385,12 @@
 	}
 
 	sema_init(&cp_sem, 1);
+
+	/*
+	 * Make the target instruction writeable when built as a module
+	 */
+	set_memory_rw((unsigned long)&cpaccess_dummy_inst & PAGE_MASK, 1);
+
 	return 0;
 
 exit1:
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index 2965607..fef6543 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -52,6 +52,8 @@
 CONFIG_MSM_RPM_REGULATOR_SMD=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_SYSMON_COMM=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_VENUS=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_MSM_MEMORY_DUMP=y
@@ -404,3 +406,4 @@
 CONFIG_CORESIGHT_FUNNEL=y
 CONFIG_CORESIGHT_REPLICATOR=y
 CONFIG_CORESIGHT_STM=y
+CONFIG_USB_BAM=y
diff --git a/arch/arm/configs/mpq8092_defconfig b/arch/arm/configs/mpq8092_defconfig
index c870208..0ee406a 100644
--- a/arch/arm/configs/mpq8092_defconfig
+++ b/arch/arm/configs/mpq8092_defconfig
@@ -239,6 +239,7 @@
 CONFIG_INPUT_UINPUT=y
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
 CONFIG_I2C=y
@@ -285,6 +286,7 @@
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 # CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
 CONFIG_USB=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
@@ -304,6 +306,11 @@
 CONFIG_USB_STORAGE_KARMA=y
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_G_ANDROID=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 452cd8a..f49b5f7 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -56,6 +56,7 @@
 CONFIG_MSM_PIL_VENUS=y
 CONFIG_MSM_PIL_PRONTO=y
 CONFIG_MSM_TZ_LOG=y
+CONFIG_MSM_SMCMOD=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_MSM_MEMORY_DUMP=y
@@ -222,6 +223,7 @@
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_KS8851=y
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
 CONFIG_PPP=y
@@ -287,6 +289,7 @@
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 # CONFIG_MSM_CAMERA is not set
 CONFIG_OV8825=y
+CONFIG_OV12830=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_CPP=y
 CONFIG_MSM_CCI=y
@@ -297,6 +300,7 @@
 CONFIG_MSMB_CAMERA=y
 CONFIG_OV9724=y
 CONFIG_MT9M114=y
+CONFIG_OV5648=y
 CONFIG_MSMB_JPEG=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_WFD=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index fa86cc8..aced8f2 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -56,6 +56,7 @@
 CONFIG_MSM_PIL_VENUS=y
 CONFIG_MSM_PIL_PRONTO=y
 CONFIG_MSM_TZ_LOG=y
+CONFIG_MSM_SMCMOD=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_MSM_MEMORY_DUMP=y
@@ -71,6 +72,7 @@
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_XPU_ERR_FATAL=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
@@ -223,6 +225,7 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
+CONFIG_KS8851=y
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
 CONFIG_PPP=y
@@ -290,6 +293,7 @@
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 # CONFIG_MSM_CAMERA is not set
 CONFIG_OV8825=y
+CONFIG_OV12830=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_CPP=y
 CONFIG_MSM_CCI=y
@@ -300,6 +304,7 @@
 CONFIG_MSMB_CAMERA=y
 CONFIG_OV9724=y
 CONFIG_MT9M114=y
+CONFIG_OV5648=y
 CONFIG_MSMB_JPEG=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_WFD=y
@@ -454,6 +459,7 @@
 CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 29ef385..0db08db 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -28,6 +28,7 @@
 # CONFIG_SLUB_DEBUG is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -37,7 +38,6 @@
 CONFIG_IOSCHED_TEST=y
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM8610=y
-CONFIG_ARCH_MSM8226=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
@@ -82,6 +82,7 @@
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_COMPACTION=y
+CONFIG_CP_ACCESS=y
 CONFIG_USE_OF=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -241,6 +242,9 @@
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
+CONFIG_INPUT_MPU3050=y
+CONFIG_BMP18X=y
+CONFIG_BMP18X_I2C=y
 CONFIG_MSM_BUSPM_DEV=m
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
@@ -274,6 +278,8 @@
 CONFIG_OV8825=y
 CONFIG_s5k4e1=y
 CONFIG_HI256=y
+CONFIG_OV12830=y
+CONFIG_OV5648=y
 CONFIG_MSM_CAMERA_SENSOR=y
 # CONFIG_MSM_CPP is not set
 CONFIG_MSM_CCI=y
@@ -310,7 +316,6 @@
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
-CONFIG_SND_SOC_MSM8226=y
 CONFIG_SND_SOC_MSM8X10=y
 CONFIG_UHID=y
 CONFIG_HID_APPLE=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 1e1b35a..cfd346e 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -26,6 +26,7 @@
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -35,7 +36,6 @@
 CONFIG_IOSCHED_TEST=y
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM8610=y
-CONFIG_ARCH_MSM8226=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
@@ -71,6 +71,7 @@
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_XPU_ERR_FATAL=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
@@ -80,6 +81,7 @@
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_COMPACTION=y
+CONFIG_CP_ACCESS=y
 CONFIG_USE_OF=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -239,6 +241,9 @@
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
+CONFIG_INPUT_MPU3050=y
+CONFIG_BMP18X=y
+CONFIG_BMP18X_I2C=y
 CONFIG_MSM_BUSPM_DEV=m
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
@@ -272,6 +277,7 @@
 CONFIG_OV8825=y
 CONFIG_s5k4e1=y
 CONFIG_HI256=y
+CONFIG_OV12830=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_CCI=y
 CONFIG_MSM_CSIPHY=y
@@ -283,6 +289,7 @@
 CONFIG_OV9724=y
 CONFIG_SP1628=y
 CONFIG_GC0339=y
+CONFIG_OV5648=y
 CONFIG_MSMB_JPEG=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_WFD=y
@@ -328,7 +335,6 @@
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
-CONFIG_SND_SOC_MSM8226=y
 CONFIG_SND_SOC_MSM8X10=y
 CONFIG_UHID=y
 CONFIG_HID_APPLE=y
@@ -416,6 +422,7 @@
 CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_SET_MODULE_RONX=y
 CONFIG_KEYS=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index a26d8e6..f2f6558 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -81,7 +81,6 @@
 CONFIG_MSM_L1_ERR_LOG=y
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
-CONFIG_MSM_UARTDM_Core_v14=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 8447dd55..71742a5 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -86,7 +86,6 @@
 CONFIG_MSM_CACHE_DUMP=y
 CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
-CONFIG_MSM_UARTDM_Core_v14=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_MSM_XPU_ERR_FATAL=y
 CONFIG_STRICT_MEMORY_RWX=y
@@ -499,6 +498,7 @@
 CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_CPU_FREQ_SWITCH_PROFILER=y
 CONFIG_DYNAMIC_DEBUG=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index 6471673..9a5aaf0 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -115,6 +115,7 @@
 CONFIG_NETFILTER_XT_MATCH_ESP=y
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
 CONFIG_IP_SET=y
 CONFIG_NF_CONNTRACK_IPV4=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 863e14f..3f34690 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -119,6 +119,7 @@
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
 CONFIG_NETFILTER_XT_MATCH_LIMIT=y
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
 CONFIG_IP_SET=y
 CONFIG_NF_CONNTRACK_IPV4=y
diff --git a/arch/arm/configs/msmkrypton_defconfig b/arch/arm/configs/msmkrypton_defconfig
index f073d2b..b04acb5 100644
--- a/arch/arm/configs/msmkrypton_defconfig
+++ b/arch/arm/configs/msmkrypton_defconfig
@@ -38,7 +38,12 @@
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
 CONFIG_MSM_IPC_LOGGING=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
 CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_MSM_UARTDM_Core_v14=y
 CONFIG_NO_HZ=y
@@ -104,6 +109,9 @@
 CONFIG_SPI_SPIDEV=m
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 03fb936..5c8b3bf4 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -320,4 +320,12 @@
 	.size \name , . - \name
 	.endm
 
+	.macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req
+#ifndef CONFIG_CPU_USE_DOMAINS
+	adds	\tmp, \addr, #\size - 1
+	sbcccs	\tmp, \tmp, \limit
+	bcs	\bad
+#endif
+	.endm
+
 #endif /* __ASM_ASSEMBLER_H__ */
diff --git a/arch/arm/include/asm/smcmod.h b/arch/arm/include/asm/smcmod.h
index 06918c4..6225c1e 100644
--- a/arch/arm/include/asm/smcmod.h
+++ b/arch/arm/include/asm/smcmod.h
@@ -108,6 +108,45 @@
 	uint32_t return_val; /* out */
 } __packed;
 
+/**
+ * struct smcmod_decrypt_req - used to decrypt image fragments.
+ * @service_id - requested service.
+ * @command_id - requested command.
+ * @operation - specifies metadata parsing or image fragment decrypting.
+ * @request - describes request parameters depending on operation.
+ * @response - this is the response of the request.
+ */
+struct smcmod_decrypt_req {
+	uint32_t service_id;
+	uint32_t command_id;
+#define SMCMOD_DECRYPT_REQ_OP_METADATA	1
+#define SMCMOD_DECRYPT_REQ_OP_IMG_FRAG	2
+	uint32_t operation;
+	union {
+		struct {
+			uint32_t len;
+			uint32_t ion_fd;
+		} metadata;
+		struct {
+			uint32_t ctx_id;
+			uint32_t last_frag;
+			uint32_t frag_len;
+			uint32_t ion_fd;
+			uint32_t offset;
+		} img_frag;
+	} request;
+	union {
+		struct {
+			uint32_t status;
+			uint32_t ctx_id;
+			uint32_t end_offset;
+		} metadata;
+		struct {
+			uint32_t status;
+		} img_frag;
+	} response;
+};
+
 #define SMCMOD_IOC_MAGIC	0x97
 
 /* Number chosen to avoid any conflicts */
@@ -120,4 +159,7 @@
 #define SMCMOD_IOCTL_SEND_MSG_DIGEST_CMD \
 	_IOWR(SMCMOD_IOC_MAGIC, 35, struct smcmod_msg_digest_req)
 #define SMCMOD_IOCTL_GET_VERSION _IOWR(SMCMOD_IOC_MAGIC, 36, uint32_t)
+#define SMCMOD_IOCTL_SEND_DECRYPT_CMD \
+	_IOWR(SMCMOD_IOC_MAGIC, 37, struct smcmod_decrypt_req)
+
 #endif /* __SMCMOD_H_ */
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 71f6536..0a070e9 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -101,28 +101,39 @@
 extern int __get_user_2(void *);
 extern int __get_user_4(void *);
 
-#define __get_user_x(__r2,__p,__e,__s,__i...)				\
+#define __GUP_CLOBBER_1	"lr", "cc"
+#ifdef CONFIG_CPU_USE_DOMAINS
+#define __GUP_CLOBBER_2	"ip", "lr", "cc"
+#else
+#define __GUP_CLOBBER_2 "lr", "cc"
+#endif
+#define __GUP_CLOBBER_4	"lr", "cc"
+
+#define __get_user_x(__r2,__p,__e,__l,__s)				\
 	   __asm__ __volatile__ (					\
 		__asmeq("%0", "r0") __asmeq("%1", "r2")			\
+		__asmeq("%3", "r1")					\
 		"bl	__get_user_" #__s				\
 		: "=&r" (__e), "=r" (__r2)				\
-		: "0" (__p)						\
-		: __i, "cc")
+		: "0" (__p), "r" (__l)					\
+		: __GUP_CLOBBER_##__s)
 
 #define get_user(x,p)							\
 	({								\
+		unsigned long __limit = current_thread_info()->addr_limit - 1; \
 		register const typeof(*(p)) __user *__p asm("r0") = (p);\
 		register unsigned long __r2 asm("r2");			\
+		register unsigned long __l asm("r1") = __limit;		\
 		register int __e asm("r0");				\
 		switch (sizeof(*(__p))) {				\
 		case 1:							\
-			__get_user_x(__r2, __p, __e, 1, "lr");		\
-	       		break;						\
+			__get_user_x(__r2, __p, __e, __l, 1);		\
+			break;						\
 		case 2:							\
-			__get_user_x(__r2, __p, __e, 2, "r3", "lr");	\
+			__get_user_x(__r2, __p, __e, __l, 2);		\
 			break;						\
 		case 4:							\
-	       		__get_user_x(__r2, __p, __e, 4, "lr");		\
+			__get_user_x(__r2, __p, __e, __l, 4);		\
 			break;						\
 		default: __e = __get_user_bad(); break;			\
 		}							\
@@ -135,31 +146,34 @@
 extern int __put_user_4(void *, unsigned int);
 extern int __put_user_8(void *, unsigned long long);
 
-#define __put_user_x(__r2,__p,__e,__s)					\
+#define __put_user_x(__r2,__p,__e,__l,__s)				\
 	   __asm__ __volatile__ (					\
 		__asmeq("%0", "r0") __asmeq("%2", "r2")			\
+		__asmeq("%3", "r1")					\
 		"bl	__put_user_" #__s				\
 		: "=&r" (__e)						\
-		: "0" (__p), "r" (__r2)					\
+		: "0" (__p), "r" (__r2), "r" (__l)			\
 		: "ip", "lr", "cc")
 
 #define put_user(x,p)							\
 	({								\
+		unsigned long __limit = current_thread_info()->addr_limit - 1; \
 		register const typeof(*(p)) __r2 asm("r2") = (x);	\
 		register const typeof(*(p)) __user *__p asm("r0") = (p);\
+		register unsigned long __l asm("r1") = __limit;		\
 		register int __e asm("r0");				\
 		switch (sizeof(*(__p))) {				\
 		case 1:							\
-			__put_user_x(__r2, __p, __e, 1);		\
+			__put_user_x(__r2, __p, __e, __l, 1);		\
 			break;						\
 		case 2:							\
-			__put_user_x(__r2, __p, __e, 2);		\
+			__put_user_x(__r2, __p, __e, __l, 2);		\
 			break;						\
 		case 4:							\
-			__put_user_x(__r2, __p, __e, 4);		\
+			__put_user_x(__r2, __p, __e, __l, 4);		\
 			break;						\
 		case 8:							\
-			__put_user_x(__r2, __p, __e, 8);		\
+			__put_user_x(__r2, __p, __e, __l, 8);		\
 			break;						\
 		default: __e = __put_user_bad(); break;			\
 		}							\
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index 11093a7..9b06bb4 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -16,8 +16,9 @@
  * __get_user_X
  *
  * Inputs:	r0 contains the address
+ *		r1 contains the address limit, which must be preserved
  * Outputs:	r0 is the error code
- *		r2, r3 contains the zero-extended value
+ *		r2 contains the zero-extended value
  *		lr corrupted
  *
  * No other registers must be altered.  (see <asm/uaccess.h>
@@ -27,33 +28,39 @@
  * Note also that it is intended that __get_user_bad is not global.
  */
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/errno.h>
 #include <asm/domain.h>
 
 ENTRY(__get_user_1)
+	check_uaccess r0, 1, r1, r2, __get_user_bad
 1: TUSER(ldrb)	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
 ENDPROC(__get_user_1)
 
 ENTRY(__get_user_2)
-#ifdef CONFIG_THUMB2_KERNEL
-2: TUSER(ldrb)	r2, [r0]
-3: TUSER(ldrb)	r3, [r0, #1]
+	check_uaccess r0, 2, r1, r2, __get_user_bad
+#ifdef CONFIG_CPU_USE_DOMAINS
+rb	.req	ip
+2:	ldrbt	r2, [r0], #1
+3:	ldrbt	rb, [r0], #0
 #else
-2: TUSER(ldrb)	r2, [r0], #1
-3: TUSER(ldrb)	r3, [r0]
+rb	.req	r0
+2:	ldrb	r2, [r0]
+3:	ldrb	rb, [r0, #1]
 #endif
 #ifndef __ARMEB__
-	orr	r2, r2, r3, lsl #8
+	orr	r2, r2, rb, lsl #8
 #else
-	orr	r2, r3, r2, lsl #8
+	orr	r2, rb, r2, lsl #8
 #endif
 	mov	r0, #0
 	mov	pc, lr
 ENDPROC(__get_user_2)
 
 ENTRY(__get_user_4)
+	check_uaccess r0, 4, r1, r2, __get_user_bad
 4: TUSER(ldr)	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index 7db2599..3d73dcb 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -16,6 +16,7 @@
  * __put_user_X
  *
  * Inputs:	r0 contains the address
+ *		r1 contains the address limit, which must be preserved
  *		r2, r3 contains the value
  * Outputs:	r0 is the error code
  *		lr corrupted
@@ -27,16 +28,19 @@
  * Note also that it is intended that __put_user_bad is not global.
  */
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/errno.h>
 #include <asm/domain.h>
 
 ENTRY(__put_user_1)
+	check_uaccess r0, 1, r1, ip, __put_user_bad
 1: TUSER(strb)	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
 ENDPROC(__put_user_1)
 
 ENTRY(__put_user_2)
+	check_uaccess r0, 2, r1, ip, __put_user_bad
 	mov	ip, r2, lsr #8
 #ifdef CONFIG_THUMB2_KERNEL
 #ifndef __ARMEB__
@@ -60,12 +64,14 @@
 ENDPROC(__put_user_2)
 
 ENTRY(__put_user_4)
+	check_uaccess r0, 4, r1, ip, __put_user_bad
 4: TUSER(str)	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
 ENDPROC(__put_user_4)
 
 ENTRY(__put_user_8)
+	check_uaccess r0, 8, r1, ip, __put_user_bad
 #ifdef CONFIG_THUMB2_KERNEL
 5: TUSER(str)	r2, [r0]
 6: TUSER(str)	r3, [r0, #4]
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 174a576..b80949c 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -282,7 +282,6 @@
 	select QMI_ENCDEC
 	select DONT_MAP_HOLE_AFTER_MEMBANK0
 	select MSM_ULTRASOUND_B
-	select MSM_LPM_TEST
 	select MSM_RPM_LOG
 	select ARCH_WANT_KMAP_ATOMIC_FLUSH
 
@@ -307,6 +306,10 @@
 	select MEMORY_HOLE_CARVEOUT
 	select DONT_MAP_HOLE_AFTER_MEMBANK0
 	select QMI_ENCDEC
+	select MSM_SPM_V2
+	select MSM_L2_SPM
+	select MSM_PM8X60 if PM
+	select MSM_RPM_SMD
 
 config ARCH_MPQ8092
 	bool "MPQ8092"
@@ -429,6 +432,8 @@
 	select GPIO_MSM_V3
 	select MAY_HAVE_SPARSE_IRQ
 	select SPARSE_IRQ
+	select MEMORY_HOLE_CARVEOUT
+	select QMI_ENCDEC
 
 config ARCH_MSM8610
 	bool "MSM8610"
@@ -2172,12 +2177,12 @@
 config MSM_SMCMOD
 	tristate "Secure Monitor Call (SMC) Module"
 	default n
-	depends on (ARCH_FSM9XXX && ION && ION_MSM && MSM_SCM)
+	depends on (ION && ION_MSM && MSM_SCM)
 	help
 	  Enable support for smcmod driver. This driver provides a mechanism
 	  to execute the Secure Monitor Call (SMC) to switch from non-secure
-	  to secure execution in the fsm9xxx targets. This module utilizes Ion
-	  for buffer management.
+	  to secure execution in the fsm9xxx and msm8x26 targets. This module
+	  utilizes Ion for buffer management.
 
 config MSM_SUBSYSTEM_RESTART
 	bool "MSM Subsystem Restart"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index e5a2bb84f..8c42b8d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -309,6 +309,7 @@
 obj-$(CONFIG_ARCH_MSM8226) += acpuclock-8226.o acpuclock-cortex.o
 obj-$(CONFIG_ARCH_MSM8610) += board-8610.o board-8610-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8610) += clock-local2.o clock-pll.o clock-8610.o clock-rpm.o clock-voter.o
+obj-$(CONFIG_ARCH_MSM8610) += acpuclock-8226.o acpuclock-cortex.o
 obj-$(CONFIG_ARCH_MSM8610) += clock-dsi-8610.o
 obj-$(CONFIG_ARCH_MSMKRYPTON) += clock-local2.o clock-pll.o clock-krypton.o clock-rpm.o clock-voter.o
 
@@ -330,7 +331,7 @@
 obj-$(CONFIG_MSM_SDIO_SMEM) += sdio_smem.o
 obj-$(CONFIG_MSM_RPM) += rpm.o rpm_resources.o
 obj-$(CONFIG_MSM_LPM_TEST) += test-lpm.o
-obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o lpm_levels.o lpm_resources.o
+obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o lpm_levels.o
 obj-$(CONFIG_MSM_MPM_OF) += mpm-of.o
 obj-$(CONFIG_MSM_MPM) += mpm.o
 obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o rpm_master_stat.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 8b0acc6..3505afe 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -99,8 +99,10 @@
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-skuf.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-skuf.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-xpm.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-cdp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-mtp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-xpm.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-cdp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-mtp.dtb
 
 # FSM9XXX
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 4b6477b..6d848d2 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -270,7 +270,7 @@
 	[7]  = { {  806400, HFPLL, 1,  42 }, LVL_NOM,   950000, 4 },
 	[8]  = { {  883200, HFPLL, 1,  46 }, LVL_NOM,   950000, 5 },
 	[9]  = { {  960000, HFPLL, 1,  50 }, LVL_NOM,   950000, 5 },
-	[10] = { { 1036800, HFPLL, 1,  54 }, LVL_NOM,   950000, 6 },
+	[10] = { { 1036800, HFPLL, 1,  54 }, LVL_NOM,   950000, 5 },
 	[11] = { { 1113600, HFPLL, 1,  58 }, LVL_HIGH, 1050000, 6 },
 	[12] = { { 1190400, HFPLL, 1,  62 }, LVL_HIGH, 1050000, 6 },
 	[13] = { { 1267200, HFPLL, 1,  66 }, LVL_HIGH, 1050000, 7 },
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index b5a7552..21a940d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -232,6 +232,7 @@
 /* A2 power collaspe */
 #define UL_TIMEOUT_DELAY 1000	/* in ms */
 #define ENABLE_DISCONNECT_ACK	0x1
+#define SHUTDOWN_TIMEOUT_MS	500
 static void toggle_apps_ack(void);
 static void reconnect_to_bam(void);
 static void disconnect_to_bam(void);
@@ -272,6 +273,7 @@
 static int power_management_only_mode;
 static int in_ssr;
 static int ssr_skipped_disconnect;
+static struct completion shutdown_completion;
 
 struct outside_notify_func {
 	void (*notify)(void *, int, unsigned long);
@@ -1066,6 +1068,7 @@
 		goto fail;
 	}
 	polling_mode = 0;
+	complete_all(&shutdown_completion);
 	release_wakelock();
 
 	/* handle any rx packets before interrupt was enabled */
@@ -1266,6 +1269,7 @@
 					" not disabled\n", __func__, ret);
 				break;
 			}
+			INIT_COMPLETION(shutdown_completion);
 			grab_wakelock();
 			polling_mode = 1;
 			/*
@@ -1745,6 +1749,14 @@
 	struct list_head *node;
 	struct rx_pkt_info *info;
 	unsigned long flags;
+	unsigned long time_remaining;
+
+	time_remaining = wait_for_completion_timeout(&shutdown_completion,
+			msecs_to_jiffies(SHUTDOWN_TIMEOUT_MS));
+	if (time_remaining == 0) {
+		pr_err("%s: shutdown completion timed out\n", __func__);
+		ssrestart_check();
+	}
 
 	bam_connection_is_active = 0;
 
@@ -2365,6 +2377,8 @@
 	init_completion(&ul_wakeup_ack_completion);
 	init_completion(&bam_connection_completion);
 	init_completion(&dfab_unvote_completion);
+	init_completion(&shutdown_completion);
+	complete_all(&shutdown_completion);
 	INIT_DELAYED_WORK(&ul_timeout_work, ul_timeout);
 	INIT_DELAYED_WORK(&queue_rx_work, queue_rx_work_func);
 	wake_lock_init(&bam_wakelock, WAKE_LOCK_SUSPEND, "bam_dmux_wakelock");
diff --git a/arch/arm/mach-msm/batterydata-lib.c b/arch/arm/mach-msm/batterydata-lib.c
index 2be591c..42a59d1 100644
--- a/arch/arm/mach-msm/batterydata-lib.c
+++ b/arch/arm/mach-msm/batterydata-lib.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
@@ -13,7 +13,7 @@
 #define pr_fmt(fmt)	"%s: " fmt, __func__
 
 #include <linux/module.h>
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
 
 int linear_interpolate(int y0, int x0, int y1, int x1, int x)
 {
diff --git a/arch/arm/mach-msm/bms-batterydata-desay.c b/arch/arm/mach-msm/bms-batterydata-desay.c
index e2b62be..1e168cd 100644
--- a/arch/arm/mach-msm/bms-batterydata-desay.c
+++ b/arch/arm/mach-msm/bms-batterydata-desay.c
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
 
 static struct single_row_lut desay_5200_fcc_temp = {
 	.x		= {-20, 0, 25, 40},
diff --git a/arch/arm/mach-msm/bms-batterydata-oem.c b/arch/arm/mach-msm/bms-batterydata-oem.c
index e4c42d7..634b4dd 100644
--- a/arch/arm/mach-msm/bms-batterydata-oem.c
+++ b/arch/arm/mach-msm/bms-batterydata-oem.c
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
 
 static struct single_row_lut fcc_temp = {
 	.x		= {-20, 0, 25, 40, 65},
diff --git a/arch/arm/mach-msm/bms-batterydata-qrd-4v2-1300mah.c b/arch/arm/mach-msm/bms-batterydata-qrd-4v2-1300mah.c
index a2c6391..7e4b2fd 100644
--- a/arch/arm/mach-msm/bms-batterydata-qrd-4v2-1300mah.c
+++ b/arch/arm/mach-msm/bms-batterydata-qrd-4v2-1300mah.c
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
 
 static struct single_row_lut fcc_temp = {
 	.x = {-20, 0, 25, 40, 60},
diff --git a/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c b/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c
index 8adf8ca..46c1bbe 100644
--- a/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c
+++ b/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c
@@ -9,7 +9,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
 
 static struct single_row_lut fcc_temp = {
 	.x		= {-20, 0, 25, 40, 60},
diff --git a/arch/arm/mach-msm/bms-batterydata.c b/arch/arm/mach-msm/bms-batterydata.c
index dc98c57..75bf5a1 100644
--- a/arch/arm/mach-msm/bms-batterydata.c
+++ b/arch/arm/mach-msm/bms-batterydata.c
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
 
 static struct single_row_lut fcc_temp = {
 	.x		= {-20, 0, 25, 40, 65},
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index dd6c9ec..094765f 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.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
@@ -21,6 +21,7 @@
 #include <mach/msm_bus_board.h>
 #include <mach/board.h>
 #include <mach/gpiomux.h>
+#include <mach/socinfo.h>
 #include "devices.h"
 #include "board-8064.h"
 #include "board-storage-common-a.h"
@@ -238,6 +239,10 @@
 	400000, 24000000, 48000000, 96000000
 };
 
+static unsigned int sdc1_sup_clk_rates_all[] = {
+	400000, 24000000, 48000000, 96000000, 192000000
+};
+
 static struct mmc_platform_data sdc1_data = {
 	.ocr_mask       = MMC_VDD_27_28 | MMC_VDD_28_29,
 #ifdef CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT
@@ -331,8 +336,16 @@
 
 void __init apq8064_init_mmc(void)
 {
-	if (apq8064_sdc1_pdata)
+	if (apq8064_sdc1_pdata) {
+		/* 8064 v2 supports upto 200MHz clock on SDC1 slot */
+		if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2) {
+			apq8064_sdc1_pdata->sup_clk_table =
+					sdc1_sup_clk_rates_all;
+			apq8064_sdc1_pdata->sup_clk_cnt	=
+					ARRAY_SIZE(sdc1_sup_clk_rates_all);
+		}
 		apq8064_add_sdcc(1, apq8064_sdc1_pdata);
+	}
 
 	if (apq8064_sdc2_pdata)
 		apq8064_add_sdcc(2, apq8064_sdc2_pdata);
diff --git a/arch/arm/mach-msm/board-8084.c b/arch/arm/mach-msm/board-8084.c
index 2a6bbb7..8f35a29 100644
--- a/arch/arm/mach-msm/board-8084.c
+++ b/arch/arm/mach-msm/board-8084.c
@@ -29,6 +29,8 @@
 #include <mach/socinfo.h>
 #include <mach/clk-provider.h>
 #include <mach/msm_smem.h>
+#include <mach/rpm-smd.h>
+#include "spm.h"
 #include "board-dt.h"
 #include "clock.h"
 #include "devices.h"
@@ -88,6 +90,8 @@
 	msm_smem_init();
 	msm_init_modem_notifier_list();
 	msm_smd_init();
+	msm_rpm_driver_init();
+	msm_spm_device_init();
 	msm_clock_init(&msm8084_clock_init_data);
 	tsens_tm_init_driver();
 }
diff --git a/arch/arm/mach-msm/board-8092.c b/arch/arm/mach-msm/board-8092.c
index 56826c7..500731c 100644
--- a/arch/arm/mach-msm/board-8092.c
+++ b/arch/arm/mach-msm/board-8092.c
@@ -73,6 +73,8 @@
 }
 
 static struct of_dev_auxdata mpq8092_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
+			"msm_otg", NULL),
 	OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
 			"msm_serial_hsl.0", NULL),
 	OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF9922000, \
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index a32031d..78a73c4 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -85,12 +85,6 @@
 	.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 wcnss_5wire_suspend_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv  = GPIOMUX_DRV_2MA,
@@ -205,12 +199,6 @@
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
-	{
-		.gpio      = 22,		/* BLSP1 QUP1 SPI_CS_ETH */
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &gpio_spi_cs_eth_config,
-		},
-	},
 	{					/*  NFC   */
 		.gpio      = 10,		/* BLSP1 QUP3 I2C_DAT */
 		.settings = {
@@ -394,6 +382,20 @@
 		},
 	},
 	{
+		.gpio = 22, /* CAM1_VDD */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &cam_settings[4],
+		},
+	},
+	{
+		.gpio = 34, /* CAM1 VCM_PWDN */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &cam_settings[4],
+		},
+	},
+	{
 		.gpio = 35, /* CAM2_STANDBY_N */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[3],
@@ -468,6 +470,91 @@
 	},
 };
 
+#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
+static struct gpiomux_setting sdc3_clk_actv_cfg = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting sdc3_cmd_data_0_3_actv_cfg = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting sdc3_suspend_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting sdc3_data_1_suspend_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config msm8226_sdc3_configs[] __initdata = {
+	{
+		/* DAT3 */
+		.gpio      = 39,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+		},
+	},
+	{
+		/* DAT2 */
+		.gpio      = 40,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+		},
+	},
+	{
+		/* DAT1 */
+		.gpio      = 41,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_data_1_suspend_cfg,
+		},
+	},
+	{
+		/* DAT0 */
+		.gpio      = 42,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+		},
+	},
+	{
+		/* CMD */
+		.gpio      = 43,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+		},
+	},
+	{
+		/* CLK */
+		.gpio      = 44,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_clk_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+		},
+	},
+};
+
+static void msm_gpiomux_sdc3_install(void)
+{
+	msm_gpiomux_install(msm8226_sdc3_configs,
+			    ARRAY_SIZE(msm8226_sdc3_configs));
+}
+#else
+static void msm_gpiomux_sdc3_install(void) {}
+#endif /* CONFIG_MMC_MSM_SDC3_SUPPORT */
+
 void __init msm8226_init_gpiomux(void)
 {
 	int rc;
@@ -500,4 +587,6 @@
 	if (of_board_is_cdp() || of_board_is_mtp() || of_board_is_xpm())
 		msm_gpiomux_install(usb_otg_sw_configs,
 					ARRAY_SIZE(usb_otg_sw_configs));
+
+	msm_gpiomux_sdc3_install();
 }
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 5ad6175..aff2d75 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -51,7 +51,6 @@
 #include "platsmp.h"
 #include "spm.h"
 #include "pm.h"
-#include "lpm_resources.h"
 #include "modem_notifier.h"
 
 static struct memtype_reserve msm8226_reserve_table[] __initdata = {
@@ -75,10 +74,14 @@
 			"msm_sdcc.1", NULL),
 	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98A4000, \
 			"msm_sdcc.2", NULL),
+	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF9864000, \
+			"msm_sdcc.3", NULL),
 	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9824900, \
 			"msm_sdcc.1", NULL),
 	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF98A4900, \
 			"msm_sdcc.2", NULL),
+	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9864900, \
+			"msm_sdcc.3", NULL),
 	{}
 };
 
@@ -112,7 +115,6 @@
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
-	msm_lpmrs_module_init();
 	msm_spm_device_init();
 	msm_pm_sleep_status_init();
 	rpm_regulator_smd_driver_init();
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index 8949609..01f1468 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -16,6 +16,7 @@
 #include <mach/board.h>
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
+#include <mach/socinfo.h>
 
 static struct gpiomux_setting gpio_spi_config = {
 	.func = GPIOMUX_FUNC_1,
@@ -59,6 +60,30 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+static struct gpiomux_setting focaltech_int_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting focaltech_int_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting focaltech_reset_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting focaltech_reset_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
 static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv  = GPIOMUX_DRV_2MA,
@@ -239,6 +264,48 @@
 	},
 };
 
+static struct msm_gpiomux_config msm_focaltech_configs[] __initdata = {
+	{
+		.gpio      = 0,		/* TOUCH RESET */
+		.settings = {
+			[GPIOMUX_ACTIVE] = &focaltech_reset_act_cfg,
+			[GPIOMUX_SUSPENDED] = &focaltech_reset_sus_cfg,
+		},
+	},
+	{
+		.gpio      = 1,		/* TOUCH INT */
+		.settings = {
+			[GPIOMUX_ACTIVE] = &focaltech_int_act_cfg,
+			[GPIOMUX_SUSPENDED] = &focaltech_int_sus_cfg,
+		},
+	},
+	{
+		.gpio      = 86,		/* BLSP1 QUP4 SPI_DATA_MOSI */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+	{
+		.gpio      = 87,		/* BLSP1 QUP4 SPI_DATA_MISO */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+	{
+		.gpio      = 89,		/* BLSP1 QUP4 SPI_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+	{
+		.gpio      = 88,		/* BLSP1 QUP4 SPI_CS */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+};
+
+
 static struct msm_gpiomux_config wcnss_5wire_interface[] = {
 	{
 		.gpio = 23,
@@ -455,11 +522,17 @@
 	}
 
 	msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
-	msm_gpiomux_install(msm_atmel_configs,
+	if (of_board_is_qrd()) {
+		msm_gpiomux_install(msm_focaltech_configs,
+			ARRAY_SIZE(msm_focaltech_configs));
+	} else {
+		msm_gpiomux_install(msm_atmel_configs,
 			ARRAY_SIZE(msm_atmel_configs));
+	}
 	msm_gpiomux_install(wcnss_5wire_interface,
 			ARRAY_SIZE(wcnss_5wire_interface));
-	msm_gpiomux_install(msm_lcd_configs, ARRAY_SIZE(msm_lcd_configs));
+	msm_gpiomux_install_nowrite(msm_lcd_configs,
+				ARRAY_SIZE(msm_lcd_configs));
 	msm_gpiomux_install(msm_keypad_configs,
 				ARRAY_SIZE(msm_keypad_configs));
 	msm_gpiomux_install(sd_card_det, ARRAY_SIZE(sd_card_det));
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index c6c9d14..d175bb4 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -52,7 +52,6 @@
 #include "platsmp.h"
 #include "spm.h"
 #include "pm.h"
-#include "lpm_resources.h"
 #include "modem_notifier.h"
 
 static struct memtype_reserve msm8610_reserve_table[] __initdata = {
@@ -107,7 +106,6 @@
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
-	msm_lpmrs_module_init();
 	msm_spm_device_init();
 	msm_pm_sleep_status_init();
 	rpm_regulator_smd_driver_init();
diff --git a/arch/arm/mach-msm/board-8930-gpiomux.c b/arch/arm/mach-msm/board-8930-gpiomux.c
index 4298d96..62e8122 100644
--- a/arch/arm/mach-msm/board-8930-gpiomux.c
+++ b/arch/arm/mach-msm/board-8930-gpiomux.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
@@ -726,6 +726,96 @@
 	}
 };
 
+#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+static struct gpiomux_setting sdcc2_clk_actv_cfg = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting sdcc2_cmd_data_0_3_actv_cfg = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting sdcc2_suspend_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting sdcc2_data_1_suspend_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+/**
+ * DAT_0 to DAT_3 lines (gpio 89 - 92) are shared with ethernet
+ * CMD line (gpio 97) is shared with USB
+ * CLK line (gpio 98) is shared with battery alarm in
+ */
+static struct msm_gpiomux_config msm8960_sdcc2_configs[] __initdata = {
+	{
+		/* DATA_3 */
+		.gpio      = 92,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdcc2_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdcc2_suspend_cfg,
+		},
+	},
+	{
+		/* DATA_2 */
+		.gpio      = 91,
+		.settings = {
+		[GPIOMUX_ACTIVE]    = &sdcc2_cmd_data_0_3_actv_cfg,
+		[GPIOMUX_SUSPENDED] = &sdcc2_suspend_cfg,
+		},
+	},
+	{
+		/* DATA_1 */
+		.gpio      = 90,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdcc2_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdcc2_data_1_suspend_cfg,
+		},
+	},
+	{
+		/* DATA_0 */
+		.gpio      = 89,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdcc2_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdcc2_suspend_cfg,
+		},
+	},
+	{
+		/* CMD */
+		.gpio      = 97,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdcc2_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdcc2_suspend_cfg,
+		},
+	},
+	{
+		/* CLK */
+		.gpio      = 98,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdcc2_clk_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdcc2_suspend_cfg,
+		},
+	},
+};
+
+static void msm_gpiomux_sdc2_install(void)
+{
+	msm_gpiomux_install(msm8960_sdcc2_configs,
+			    ARRAY_SIZE(msm8960_sdcc2_configs));
+}
+#else
+static void msm_gpiomux_sdc2_install(void) {}
+#endif /* CONFIG_MMC_MSM_SDC2_SUPPORT */
+
 int __init msm8930_init_gpiomux(void)
 {
 	int rc = msm_gpiomux_init(NR_GPIO_IRQS);
@@ -802,5 +892,7 @@
 
 	msm_gpiomux_install(msm_sitar_config, ARRAY_SIZE(msm_sitar_config));
 
+	msm_gpiomux_sdc2_install();
+
 	return 0;
 }
diff --git a/arch/arm/mach-msm/board-8930-regulator-pm8038.c b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
index 8ed93ea..8e04003 100644
--- a/arch/arm/mach-msm/board-8930-regulator-pm8038.c
+++ b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
@@ -99,6 +99,7 @@
 	REGULATOR_SUPPLY("mhl_iovcc18",		"0-0039"),
 	REGULATOR_SUPPLY("vdd-io",		"spi0.0"),
 	REGULATOR_SUPPLY("vdd-phy",		"spi0.0"),
+	REGULATOR_SUPPLY("sdc_vdd",		"msm_sdcc.2"),
 };
 VREG_CONSUMERS(L12) = {
 	REGULATOR_SUPPLY("8038_l12",		NULL),
diff --git a/arch/arm/mach-msm/board-8930-regulator-pm8917.c b/arch/arm/mach-msm/board-8930-regulator-pm8917.c
index cdc419f..e63fbdd 100644
--- a/arch/arm/mach-msm/board-8930-regulator-pm8917.c
+++ b/arch/arm/mach-msm/board-8930-regulator-pm8917.c
@@ -81,6 +81,7 @@
 	REGULATOR_SUPPLY("cam_vana",		"4-006c"),
 	REGULATOR_SUPPLY("cam_vana",		"4-0048"),
 	REGULATOR_SUPPLY("cam_vana",            "4-0020"),
+	REGULATOR_SUPPLY("sdc_vdd",             "msm_sdcc.2"),
 };
 VREG_CONSUMERS(L12) = {
 	REGULATOR_SUPPLY("8917_l12",		NULL),
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
index d045040..fec87ae 100644
--- a/arch/arm/mach-msm/board-8930-storage.c
+++ b/arch/arm/mach-msm/board-8930-storage.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
@@ -49,6 +49,13 @@
 		.lpm_uA = 9000,
 		.hpm_uA = 200000, /* 200mA */
 	},
+	/* SDCC2 : SDIO slot connected */
+	[SDCC2] = {
+		.name = "sdc_vdd",
+		.high_vol_level = 1800000,
+		.low_vol_level = 1800000,
+		.hpm_uA = 200000, /* 200mA */
+	},
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
 		.name = "sdc_vdd",
@@ -94,7 +101,7 @@
 		 * during sleep.
 		 */
 		.lpm_uA = 2000,
-	}
+	},
 };
 
 static struct msm_mmc_slot_reg_data mmc_slot_vreg_data[MAX_SDCC_CONTROLLER] = {
@@ -103,6 +110,10 @@
 		.vdd_data = &mmc_vdd_reg_data[SDCC1],
 		.vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
 	},
+	/* SDCC2 : SDIO card slot connected */
+	[SDCC2] = {
+		.vdd_data = &mmc_vdd_reg_data[SDCC2],
+	},
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
 		.vdd_data = &mmc_vdd_reg_data[SDCC3],
@@ -170,6 +181,15 @@
 	{TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
 };
 
+static struct msm_mmc_gpio sdc2_gpio[] = {
+	{92, "sdc2_dat_3"},
+	{91, "sdc2_dat_2"},
+	{90, "sdc2_dat_1"},
+	{89, "sdc2_dat_0"},
+	{97, "sdc2_cmd"},
+	{98, "sdc2_clk"}
+};
+
 static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
 	[SDCC1] = {
 		.on = sdc1_pad_pull_on_cfg,
@@ -207,10 +227,21 @@
 	},
 };
 
+static struct msm_mmc_gpio_data mmc_gpio_data[MAX_SDCC_CONTROLLER] = {
+	[SDCC2] = {
+		.gpio = sdc2_gpio,
+		.size = ARRAY_SIZE(sdc2_gpio),
+	},
+};
+
 static struct msm_mmc_pin_data mmc_slot_pin_data[MAX_SDCC_CONTROLLER] = {
 	[SDCC1] = {
 		.pad_data = &mmc_pad_data[SDCC1],
 	},
+	[SDCC2] = {
+		.is_gpio = true,
+		.gpio_data = &mmc_gpio_data[SDCC2],
+	},
 	[SDCC3] = {
 		.pad_data = &mmc_pad_data[SDCC3],
 	},
@@ -248,6 +279,23 @@
 };
 #endif
 
+#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+static unsigned int sdc2_sup_clk_rates[] = {
+	400000, 24000000, 48000000
+};
+
+static struct mmc_platform_data msm8960_sdc2_data = {
+	.ocr_mask       = MMC_VDD_165_195 | MMC_VDD_27_28 | MMC_VDD_28_29,
+	.mmc_bus_width  = MMC_CAP_4_BIT_DATA,
+	.sup_clk_table  = sdc2_sup_clk_rates,
+	.sup_clk_cnt    = ARRAY_SIZE(sdc2_sup_clk_rates),
+	.vreg_data      = &mmc_slot_vreg_data[SDCC2],
+	.pin_data       = &mmc_slot_pin_data[SDCC2],
+	.sdiowakeup_irq = MSM_GPIO_TO_INT(90),
+	.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
+};
+#endif
+
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
 static struct mmc_platform_data msm8960_sdc3_data = {
 	.ocr_mask       = MMC_VDD_27_28 | MMC_VDD_28_29,
@@ -300,6 +348,10 @@
 	/* SDC1 : eMMC card connected */
 	msm_add_sdcc(1, &msm8960_sdc1_data);
 #endif
+#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+	/* SDC2: SDIO slot for WLAN */
+	msm_add_sdcc(2, &msm8960_sdc2_data);
+#endif
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
 	/*
 	 * All 8930 platform boards using the 1.2 SoC have been reworked so that
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 6432c93..6165c32 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -177,7 +177,15 @@
 static struct gpiomux_setting gpio_epm_config = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv  = GPIOMUX_DRV_2MA,
-	.pull = GPIOMUX_PULL_DOWN,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_HIGH,
+};
+
+static struct gpiomux_setting gpio_epm_marker_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv  = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_HIGH,
 };
 
 static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
@@ -526,6 +534,18 @@
 			[GPIOMUX_SUSPENDED] = &gpio_epm_config,
 		},
 	},
+	{
+		.gpio      = 85,		/* EPM MARKER2 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_epm_marker_config,
+		},
+	},
+	{
+		.gpio      = 96,		/* EPM MARKER1 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_epm_marker_config,
+		},
+	},
 };
 
 static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
@@ -825,6 +845,135 @@
 	},
 };
 
+static struct msm_gpiomux_config msm_sensor_configs_dragonboard[] __initdata = {
+	{
+		.gpio = 15, /* CAM_MCLK0 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+		},
+	},
+	{
+		.gpio = 16, /* CAM_MCLK1 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+		},
+	},
+	{
+		.gpio = 17, /* CAM_MCLK2 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+		},
+	},
+	{
+		.gpio = 18, /* WEBCAM1_RESET_N / CAM_MCLK3 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &cam_settings[4],
+		},
+	},
+	{
+		.gpio = 19, /* CCI_I2C_SDA0 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+		},
+	},
+	{
+		.gpio = 20, /* CCI_I2C_SCL0 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+		},
+	},
+	{
+		.gpio = 21, /* CCI_I2C_SDA1 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+		},
+	},
+	{
+		.gpio = 22, /* CCI_I2C_SCL1 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+		},
+	},
+	{
+		.gpio = 23, /* FLASH_LED_EN */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 24, /* FLASH_LED_NOW */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 25, /* WEBCAM2_RESET_N */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 26, /* CAM_IRQ */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+		},
+	},
+	{
+		.gpio = 27, /* OIS_SYNC */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 28, /* WEBCAM1_STANDBY */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 89, /* CAM1_STANDBY_N */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 90, /* CAM1_RST_N */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 91, /* CAM2_STANDBY_N */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 94, /* CAM2_RST_N */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+};
+
 static struct gpiomux_setting auxpcm_act_cfg = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_8MA,
@@ -1198,7 +1347,9 @@
 	}
 
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
-	msm_gpiomux_install(msm_eth_configs, ARRAY_SIZE(msm_eth_configs));
+	if (!(of_board_is_dragonboard() && machine_is_apq8074()))
+		msm_gpiomux_install(msm_eth_configs, \
+			ARRAY_SIZE(msm_eth_configs));
 #endif
 	msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
 	msm_gpiomux_install(msm_blsp2_uart7_configs,
@@ -1215,7 +1366,12 @@
 		msm_gpiomux_install(hap_lvl_shft_config,
 				ARRAY_SIZE(hap_lvl_shft_config));
 
-	msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
+	if (of_board_is_dragonboard() && machine_is_apq8074())
+		msm_gpiomux_install(msm_sensor_configs_dragonboard, \
+				ARRAY_SIZE(msm_sensor_configs_dragonboard));
+	else
+		msm_gpiomux_install(msm_sensor_configs, \
+				ARRAY_SIZE(msm_sensor_configs));
 
 	msm_gpiomux_install(&sd_card_det, 1);
 
@@ -1223,7 +1379,8 @@
 	    of_board_is_dragonboard()))
 		msm_gpiomux_sdc3_install();
 
-	msm_gpiomux_sdc4_install();
+	if (!(of_board_is_dragonboard() && machine_is_apq8074()))
+		msm_gpiomux_sdc4_install();
 
 	msm_gpiomux_install(msm_taiko_config, ARRAY_SIZE(msm_taiko_config));
 
@@ -1247,7 +1404,8 @@
 	if (of_board_is_cdp())
 		msm_gpiomux_install(msm8974_sec_auxpcm_configs,
 				 ARRAY_SIZE(msm8974_sec_auxpcm_configs));
-	else
+	else if (of_board_is_liquid() || of_board_is_fluid() ||
+						of_board_is_mtp())
 		msm_gpiomux_install(msm_epm_configs,
 				ARRAY_SIZE(msm_epm_configs));
 
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 68af757..80a957f 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -45,8 +45,8 @@
 #include "clock.h"
 #include "devices.h"
 #include "spm.h"
+#include "pm.h"
 #include "modem_notifier.h"
-#include "lpm_resources.h"
 #include "platsmp.h"
 
 
@@ -96,7 +96,6 @@
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
-	msm_lpmrs_module_init();
 	msm_pm_sleep_status_init();
 	rpm_regulator_smd_driver_init();
 	msm_spm_device_init();
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index fad2efc..058789a 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -42,7 +42,6 @@
 #include <mach/msm_smem.h>
 #include "clock.h"
 #include "modem_notifier.h"
-#include "lpm_resources.h"
 #include "spm.h"
 
 #define MSM_KERNEL_EBI_SIZE	0x51000
@@ -117,6 +116,10 @@
 			"usb_bam", NULL),
 	OF_DEV_AUXDATA("qcom,hsic-host", 0xF9A15000, \
 			"msm_hsic_host", NULL),
+	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF98A4900, \
+		       "msm_sdcc.2", NULL),
+	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9864900, \
+		       "msm_sdcc.3", NULL),
 	{}
 };
 
@@ -236,7 +239,6 @@
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
-	msm_lpmrs_module_init();
 	rpm_regulator_smd_driver_init();
 	msm_spm_device_init();
 	msm_clock_init(&msm9625_clock_init_data);
diff --git a/arch/arm/mach-msm/board-krypton.c b/arch/arm/mach-msm/board-krypton.c
index 0d06b83..8ceccf4 100644
--- a/arch/arm/mach-msm/board-krypton.c
+++ b/arch/arm/mach-msm/board-krypton.c
@@ -24,12 +24,31 @@
 #include <mach/msm_iomap.h>
 #include <mach/msm_memtypes.h>
 #include <mach/msm_smd.h>
+#include <mach/rpm-smd.h>
 #include <mach/restart.h>
 #include <mach/socinfo.h>
 #include <mach/clk-provider.h>
+#include <mach/msm_smem.h>
 #include "board-dt.h"
 #include "clock.h"
 #include "devices.h"
+#include "modem_notifier.h"
+
+static struct memtype_reserve msmkrypton_reserve_table[] __initdata = {
+	[MEMTYPE_EBI1] = {
+		.flags = MEMTYPE_FLAGS_1M_ALIGN,
+	},
+};
+
+static int msmkrypton_paddr_to_memtype(unsigned int paddr)
+{
+	return MEMTYPE_EBI1;
+}
+
+static struct reserve_info msmkrypton_reserve_info __initdata = {
+	.memtype_reserve_table = msmkrypton_reserve_table,
+	.paddr_to_memtype = msmkrypton_paddr_to_memtype,
+};
 
 static struct of_dev_auxdata msmkrypton_auxdata_lookup[] __initdata = {
 	{}
@@ -43,10 +62,18 @@
  */
 void __init msmkrypton_add_drivers(void)
 {
+	msm_smem_init();
+	msm_init_modem_notifier_list();
 	msm_smd_init();
+	msm_rpm_driver_init();
 	msm_clock_init(&msmkrypton_clock_init_data);
 }
 
+static void __init msmkrypton_early_memory(void)
+{
+	reserve_info = &msmkrypton_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_hole, msmkrypton_reserve_table);
+}
 static void __init msmkrypton_map_io(void)
 {
 	msm_map_msmkrypton_io();
@@ -74,5 +101,6 @@
 	.handle_irq = gic_handle_irq,
 	.timer = &msm_dt_timer,
 	.dt_compat = msmkrypton_dt_match,
+	.init_very_early = msmkrypton_early_memory,
 	.restart = msm_restart,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-samarium.c b/arch/arm/mach-msm/board-samarium.c
index be09b54..6133983 100644
--- a/arch/arm/mach-msm/board-samarium.c
+++ b/arch/arm/mach-msm/board-samarium.c
@@ -44,6 +44,8 @@
 	CLK_DUMMY("core_clk",	USB_HS_SYSTEM_CLK, "msm_otg", OFF),
 	CLK_DUMMY("iface_clk",	USB_HS_AHB_CLK,    "msm_otg", OFF),
 	CLK_DUMMY("xo",         CXO_OTG_CLK,       "msm_otg", OFF),
+	CLK_DUMMY("dfab_clk",	DFAB_CLK,	"msm_sps", OFF),
+	CLK_DUMMY("dma_bam_pclk",	DMA_BAM_P_CLK,	"msm_sps", OFF),
 };
 
 static struct clock_init_data msm_dummy_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index f52bc28..97b8448 100644
--- a/arch/arm/mach-msm/cache_erp.c
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -17,6 +17,7 @@
 #include <linux/errno.h>
 #include <linux/proc_fs.h>
 #include <linux/cpu.h>
+#include <linux/seq_file.h>
 #include <linux/io.h>
 #include <mach/msm-krait-l2-accessors.h>
 #include <mach/msm_iomap.h>
@@ -159,25 +160,23 @@
 	return cesynr;
 }
 
-static int proc_read_status(char *page, char **start, off_t off, int count,
-			    int *eof, void *data)
+static int cache_erp_show(struct seq_file *m, void *v)
 {
 	struct msm_l1_err_stats *l1_stats;
-	char *p = page;
-	int len, cpu, ret, bytes_left = PAGE_SIZE;
+	int cpu;
 
 	for_each_present_cpu(cpu) {
 		l1_stats = &per_cpu(msm_l1_erp_stats, cpu);
 
-		ret = snprintf(p, bytes_left,
-			"CPU %d:\n"	\
-			"\tD-cache tag parity errors:\t%u\n"	\
-			"\tD-cache data parity errors:\t%u\n"	\
-			"\tI-cache tag parity errors:\t%u\n"	\
-			"\tI-cache data parity errors:\t%u\n"	\
-			"\tD-cache timing errors:\t\t%u\n"	\
-			"\tI-cache timing errors:\t\t%u\n"	\
-			"\tTLB multi-hit errors:\t\t%u\n\n",	\
+		seq_printf(m,
+			"CPU %d:\n"
+			"\tD-cache tag parity errors:\t%u\n"
+			"\tD-cache data parity errors:\t%u\n"
+			"\tI-cache tag parity errors:\t%u\n"
+			"\tI-cache data parity errors:\t%u\n"
+			"\tD-cache timing errors:\t\t%u\n"
+			"\tI-cache timing errors:\t\t%u\n"
+			"\tTLB multi-hit errors:\t\t%u\n\n",
 			cpu,
 			l1_stats->dctpe,
 			l1_stats->dcdpe,
@@ -186,18 +185,16 @@
 			l1_stats->dcte,
 			l1_stats->icte,
 			l1_stats->tlbmh);
-		p += ret;
-		bytes_left -= ret;
 	}
 
-	p += snprintf(p, bytes_left,
-			"L2 master port decode errors:\t\t%u\n"	\
-			"L2 master port slave errors:\t\t%u\n"		\
-			"L2 tag soft errors, single-bit:\t\t%u\n"	\
-			"L2 tag soft errors, double-bit:\t\t%u\n"	\
-			"L2 data soft errors, single-bit:\t%u\n"	\
-			"L2 data soft errors, double-bit:\t%u\n"	\
-			"L2 modified soft errors:\t\t%u\n"		\
+	seq_printf(m,
+			"L2 master port decode errors:\t\t%u\n"
+			"L2 master port slave errors:\t\t%u\n"
+			"L2 tag soft errors, single-bit:\t\t%u\n"
+			"L2 tag soft errors, double-bit:\t\t%u\n"
+			"L2 data soft errors, single-bit:\t%u\n"
+			"L2 data soft errors, double-bit:\t%u\n"
+			"L2 modified soft errors:\t\t%u\n"
 			"L2 master port LDREX NOK errors:\t%u\n",
 			msm_l2_erp_stats.mpdcd,
 			msm_l2_erp_stats.mpslv,
@@ -208,16 +205,21 @@
 			msm_l2_erp_stats.mse,
 			msm_l2_erp_stats.mplxrexnok);
 
-	len = (p - page) - off;
-	if (len < 0)
-		len = 0;
-
-	*eof = (len <= count) ? 1 : 0;
-	*start = page + off;
-
-	return len;
+	return 0;
 }
 
+static int cache_erp_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, cache_erp_show, NULL);
+}
+
+static const struct file_operations cache_erp_fops = {
+	.open		= cache_erp_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static int msm_erp_dump_regions(void)
 {
 	int i = 0;
@@ -235,26 +237,30 @@
 }
 
 #ifdef CONFIG_MSM_L1_ERR_LOG
-static int proc_read_log(char *page, char **start, off_t off, int count,
-	int *eof, void *data)
+static int cache_erp_log_show(struct seq_file *m, void *v)
 {
-	char *p = page;
-	int len, log_value;
+	int log_value;
+
 	log_value = __raw_readl(MSM_IMEM_BASE + ERP_LOG_MAGIC_ADDR) ==
 			ERP_LOG_MAGIC ? 1 : 0;
 
-	p += snprintf(p, PAGE_SIZE, "%d\n", log_value);
+	seq_printf(m, "%d\n", log_value);
 
-	len = (p - page) - off;
-	if (len < 0)
-		len = 0;
-
-	*eof = (len <= count) ? 1 : 0;
-	*start = page + off;
-
-	return len;
+	return 0;
 }
 
+static int cache_erp_log_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, cache_erp_log_show, NULL);
+}
+
+static const struct file_operations cache_erp_log_fops = {
+	.open		= cache_erp_log_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static void log_cpu_event(void)
 {
 	__raw_writel(ERP_LOG_MAGIC, MSM_IMEM_BASE + ERP_LOG_MAGIC_ADDR);
@@ -263,11 +269,10 @@
 
 static int procfs_event_log_init(void)
 {
-	procfs_log_entry = create_proc_entry("cpu/msm_erp_log", S_IRUGO, NULL);
-
+	procfs_log_entry = proc_create("cpu/msm_erp_log", S_IRUGO, NULL,
+			&cache_erp_log_fops);
 	if (!procfs_log_entry)
 		return -ENODEV;
-	procfs_log_entry->read_proc = proc_read_log;
 	return 0;
 }
 
@@ -561,7 +566,8 @@
 		goto fail_l1;
 	}
 
-	procfs_entry = create_proc_entry("cpu/msm_cache_erp", S_IRUGO, NULL);
+	procfs_entry = proc_create("cpu/msm_cache_erp", S_IRUGO, NULL,
+			&cache_erp_fops);
 
 	if (!procfs_entry) {
 		pr_err("Failed to create procfs node for cache error reporting\n");
@@ -580,8 +586,6 @@
 		smp_call_function_single(cpu, enable_erp_irq_callback, NULL, 1);
 	put_online_cpus();
 
-	procfs_entry->read_proc = proc_read_status;
-
 	ret = procfs_event_log_init();
 	if (ret)
 		pr_err("Failed to create procfs node for ERP log access\n");
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index 605a7ae..4e47064 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -137,7 +137,8 @@
 	CLK_DUMMY("",	gcc_lpass_mport_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_lpass_q6_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_lpass_sway_clk.c,	"", OFF),
-	CLK_DUMMY("",	gcc_mmss_bimc_gfx_clk.c,	"", OFF),
+	CLK_DUMMY("mem_iface_clk",	gcc_mmss_bimc_gfx_clk.c,
+				     "fdb00000.qcom,kgsl-3d0", OFF),
 	CLK_DUMMY("",	gcc_mmss_vpu_maple_sys_noc_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_ocmem_noc_cfg_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_msg_ram_ahb_clk.c,	"", OFF),
@@ -167,7 +168,8 @@
 	CLK_DUMMY("",	gcc_sdcc4_inactivity_timers_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_spss_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_sys_noc_ufs_axi_clk.c,	"", OFF),
-	CLK_DUMMY("",	gcc_sys_noc_usb3_axi_clk.c,	"", OFF),
+	CLK_DUMMY("mem_iface_clk",	gcc_sys_noc_usb3_axi_clk.c,
+			"f9304000.qcom,usbbam", OFF),
 	CLK_DUMMY("",	gcc_sys_noc_usb3_sec_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_tsif_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_tsif_inactivity_timers_clk.c,	"", OFF),
@@ -182,7 +184,8 @@
 	CLK_DUMMY("",	gcc_ufs_tx_symbol_1_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_usb2a_phy_sleep_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_usb2b_phy_sleep_clk.c,	"", OFF),
-	CLK_DUMMY("",	gcc_usb30_master_clk.c,	"", OFF),
+	CLK_DUMMY("mem_clk",	gcc_usb30_master_clk.c,	"f9304000.qcom,usbbam",
+			OFF),
 	CLK_DUMMY("",	gcc_usb30_mock_utmi_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_usb30_sleep_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_usb30_sec_master_clk.c,	"", OFF),
@@ -310,20 +313,24 @@
 	CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("core_clk_src", mdp_clk_src.c, "fd900000.qcom,mdss_mdp", OFF),
-	CLK_DUMMY("",	mdss_byte0_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_byte1_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_edpaux_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_edplink_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_edppixel_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_esc0_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_esc1_clk.c,	"", OFF),
+	CLK_DUMMY("byte_clk", mdss_byte0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("byte_clk", mdss_byte1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("core_clk", mdss_esc0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("core_clk", mdss_esc1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("pixel_clk", mdss_pclk0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("pixel_clk", mdss_pclk1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
 	CLK_DUMMY("",	mdss_extpclk_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_hdmi_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_hdmi_clk.c,	"", OFF),
 	CLK_DUMMY("core_clk", mdss_mdp_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("lut_clk", mdss_mdp_lut_clk.c, "fd900000.qcom,mdss_mdp", OFF),
-	CLK_DUMMY("",	mdss_pclk0_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_pclk1_clk.c,	"", OFF),
 	CLK_DUMMY("vsync_clk", mdss_vsync_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("",	mmss_misc_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mmss_mmssnoc_ahb_clk.c,	"", OFF),
@@ -333,9 +340,11 @@
 	CLK_DUMMY("iface_clk",	ocmemcx_ocmemnoc_clk.c,
 						"fdd00000.qcom,ocmem", OFF),
 	CLK_DUMMY("",	oxili_ocmemgx_clk.c,	"", OFF),
-	CLK_DUMMY("",	oxili_gfx3d_clk.c,	"", OFF),
+	CLK_DUMMY("core_clk",	oxili_gfx3d_clk.c,
+				     "fdb00000.qcom,kgsl-3d0", OFF),
 	CLK_DUMMY("",	oxili_rbbmtimer_clk.c,	"", OFF),
-	CLK_DUMMY("",	oxilicx_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("iface_clk",	oxilicx_ahb_clk.c,
+				     "fdb00000.qcom,kgsl-3d0", OFF),
 	CLK_DUMMY("",	venus0_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	venus0_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	venus0_core0_vcodec_clk.c,	"", OFF),
@@ -385,8 +394,23 @@
 	CLK_DUMMY("core_clk", qdss_clk.c, "fc321000.funnel", OFF),
 	CLK_DUMMY("core_clk", qdss_clk.c, "fc322000.funnel", OFF),
 	CLK_DUMMY("core_clk", qdss_clk.c, "fc345000.funnel", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc355000.funnel", OFF),
 	CLK_DUMMY("core_clk", qdss_clk.c, "fc36c000.funnel", OFF),
 	CLK_DUMMY("core_clk", qdss_clk.c, "fc302000.stm", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc310000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc311000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc312000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc313000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc314000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc315000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc316000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc317000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc318000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc340000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc341000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc342000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc343000.cti", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc344000.cti", OFF),
 
 	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc326000.tmc", OFF),
 	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc324000.replicator", OFF),
@@ -395,8 +419,23 @@
 	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc321000.funnel", OFF),
 	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc322000.funnel", OFF),
 	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc345000.funnel", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc355000.funnel", OFF),
 	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc36c000.funnel", OFF),
 	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc302000.stm", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc310000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc311000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc312000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc313000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc314000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc315000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc316000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc317000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc318000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc340000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc341000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc342000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc343000.cti", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc344000.cti", OFF),
 };
 
 struct clock_init_data msm8084_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8092.c b/arch/arm/mach-msm/clock-8092.c
index f8150c4..ec7a4b0 100644
--- a/arch/arm/mach-msm/clock-8092.c
+++ b/arch/arm/mach-msm/clock-8092.c
@@ -44,6 +44,8 @@
 	CLK_DUMMY("iface_clk",	SDC1_P_CLK,	"msm_sdcc.1", OFF),
 	CLK_DUMMY("core_clk",	SDC2_CLK,	"msm_sdcc.2", OFF),
 	CLK_DUMMY("iface_clk",	SDC2_P_CLK,	"msm_sdcc.2", OFF),
+	CLK_DUMMY("dfab_clk",	DFAB_CLK,	"msm_sps", OFF),
+	CLK_DUMMY("dma_bam_pclk",	DMA_BAM_P_CLK,	"msm_sps", OFF),
 	CLK_DUMMY("",	usb30_master_clk_src.c,	"", OFF),
 	CLK_DUMMY("",	tsif_ref_clk_src.c,	"", OFF),
 	CLK_DUMMY("",	ce1_clk_src.c,	"", OFF),
@@ -300,6 +302,8 @@
 	CLK_DUMMY("iface_clk", NULL, "fdc84000.qcom,iommu", OFF),
 	CLK_DUMMY("alt_core_clk", NULL, "fdc84000.qcom,iommu", OFF),
 	CLK_DUMMY("core_clk", NULL, "fdc84000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk", NULL, "fdee4000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk", NULL, "fdee4000.qcom,iommu", OFF),
 	/* BCSS broadcast */
 	CLK_DUMMY("",	bcc_dem_core_b_clk_src.c,	"", OFF),
 	CLK_DUMMY("",	adc_01_clk_src.c,	"", OFF),
@@ -329,6 +333,11 @@
 	CLK_DUMMY("",	nidaq_out_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_bcss_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	bcc_lnb_core_clk.c,	"", OFF),
+
+	/* USB */
+	CLK_DUMMY("core_clk", NULL, "msm_otg", OFF),
+	CLK_DUMMY("iface_clk", NULL, "msm_otg", OFF),
+	CLK_DUMMY("xo", NULL, "msm_otg", OFF),
 };
 
 struct clock_init_data mpq8092_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 452bc28..0cd5d55 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -265,6 +265,7 @@
 #define MMPLL1_PLL_STATUS                                  (0x005C)
 #define MMSS_PLL_VOTE_APCS                                 (0x0100)
 #define VCODEC0_CMD_RCGR                                   (0x1000)
+#define VENUS0_BCR                                         (0x1020)
 #define VENUS0_VCODEC0_CBCR                                (0x1028)
 #define VENUS0_AHB_CBCR                                    (0x1030)
 #define VENUS0_AXI_CBCR                                    (0x1034)
@@ -274,6 +275,7 @@
 #define BYTE0_CMD_RCGR                                     (0x2120)
 #define ESC0_CMD_RCGR                                      (0x2160)
 #define MDSS_AHB_CBCR                                      (0x2308)
+#define MDSS_BCR                                           (0x2300)
 #define MDSS_AXI_CBCR                                      (0x2310)
 #define MDSS_PCLK0_CBCR                                    (0x2314)
 #define MDSS_MDP_CBCR                                      (0x231C)
@@ -312,18 +314,22 @@
 #define CAMSS_TOP_AHB_CBCR                                 (0x3484)
 #define CAMSS_MICRO_AHB_CBCR                               (0x3494)
 #define JPEG0_CMD_RCGR                                     (0x3500)
+#define CAMSS_JPEG_BCR                                     (0x35A0)
 #define CAMSS_JPEG_JPEG0_CBCR                              (0x35A8)
 #define CAMSS_JPEG_JPEG_AHB_CBCR                           (0x35B4)
 #define CAMSS_JPEG_JPEG_AXI_CBCR                           (0x35B8)
 #define VFE0_CMD_RCGR                                      (0x3600)
 #define CPP_CMD_RCGR                                       (0x3640)
+#define CAMSS_VFE_BCR                                      (0x36A0)
 #define CAMSS_VFE_VFE0_CBCR                                (0x36A8)
 #define CAMSS_VFE_CPP_CBCR                                 (0x36B0)
 #define CAMSS_VFE_CPP_AHB_CBCR                             (0x36B4)
 #define CAMSS_VFE_VFE_AHB_CBCR                             (0x36B8)
 #define CAMSS_VFE_VFE_AXI_CBCR                             (0x36BC)
+#define CAMSS_CSI_VFE0_BCR                                 (0x3700)
 #define CAMSS_CSI_VFE0_CBCR                                (0x3704)
 #define OXILI_GFX3D_CBCR                                   (0x4028)
+#define OXILICX_BCR                                        (0x4030)
 #define OXILICX_AXI_CBCR                                   (0x4038)
 #define OXILICX_AHB_CBCR                                   (0x403C)
 #define MMPLL2_PLL_MODE                                    (0x4100)
@@ -2255,6 +2261,7 @@
 
 static struct branch_clk camss_csi_vfe0_clk = {
 	.cbcr_reg = CAMSS_CSI_VFE0_CBCR,
+	.bcr_reg = CAMSS_CSI_VFE0_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2302,6 +2309,7 @@
 
 static struct branch_clk camss_jpeg_jpeg0_clk = {
 	.cbcr_reg = CAMSS_JPEG_JPEG0_CBCR,
+	.bcr_reg = CAMSS_JPEG_BCR,
 	.has_sibling = 0,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2430,6 +2438,7 @@
 
 static struct branch_clk camss_vfe_vfe0_clk = {
 	.cbcr_reg = CAMSS_VFE_VFE0_CBCR,
+	.bcr_reg = CAMSS_VFE_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2512,6 +2521,7 @@
 
 static struct branch_clk mdss_mdp_clk = {
 	.cbcr_reg = MDSS_MDP_CBCR,
+	.bcr_reg = MDSS_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2608,6 +2618,7 @@
 
 static struct branch_clk oxili_gfx3d_clk = {
 	.cbcr_reg = OXILI_GFX3D_CBCR,
+	.bcr_reg = OXILICX_BCR,
 	.has_sibling = 0,
 	.max_div = 0,
 	.base = &virt_bases[MMSS_BASE],
@@ -2667,6 +2678,7 @@
 
 static struct branch_clk venus0_vcodec0_clk = {
 	.cbcr_reg = VENUS0_VCODEC0_CBCR,
+	.bcr_reg = VENUS0_BCR,
 	.has_sibling = 0,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3378,9 +3390,17 @@
 	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6f.qcom,camera"),
 	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "90.qcom,camera"),
 	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6d.qcom,camera"),
+	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6a.qcom,camera"),
+	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6c.qcom,camera"),
 	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6f.qcom,camera"),
 	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "90.qcom,camera"),
 	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6d.qcom,camera"),
+	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6a.qcom,camera"),
+	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6c.qcom,camera"),
+
+	/* eeprom clocks */
+	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6c.qcom,eeprom"),
+	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6c.qcom,eeprom"),
 
 	/* CCI clocks */
 	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 1514bba..0677525 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -1547,7 +1547,7 @@
 	F_END
 };
 
-static CLK_SDC(sdc1_clk, 1, 6,  52000000, 104000000);
+static CLK_SDC(sdc1_clk, 1, 6,  52000000, 208000000);
 static CLK_SDC(sdc2_clk, 2, 5,  52000000, 104000000);
 static CLK_SDC(sdc3_clk, 3, 4, 104000000, 208000000);
 static CLK_SDC(sdc4_clk, 4, 3,  33000000,  67000000);
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 11886a4..a8cb46e 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -3706,6 +3706,7 @@
 
 static struct branch_clk camss_csi_vfe0_clk = {
 	.cbcr_reg = CAMSS_CSI_VFE0_CBCR,
+	.bcr_reg = CAMSS_CSI_VFE0_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3718,6 +3719,7 @@
 
 static struct branch_clk camss_csi_vfe1_clk = {
 	.cbcr_reg = CAMSS_CSI_VFE1_CBCR,
+	.bcr_reg = CAMSS_CSI_VFE1_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3765,6 +3767,7 @@
 
 static struct branch_clk camss_jpeg_jpeg0_clk = {
 	.cbcr_reg = CAMSS_JPEG_JPEG0_CBCR,
+	.bcr_reg = CAMSS_JPEG_BCR,
 	.has_sibling = 0,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -3965,6 +3968,7 @@
 
 static struct branch_clk camss_vfe_vfe0_clk = {
 	.cbcr_reg = CAMSS_VFE_VFE0_CBCR,
+	.bcr_reg = CAMSS_VFE_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -4166,6 +4170,7 @@
 
 static struct branch_clk mdss_mdp_clk = {
 	.cbcr_reg = MDSS_MDP_CBCR,
+	.bcr_reg = MDSS_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -4359,6 +4364,7 @@
 
 static struct branch_clk oxili_gfx3d_clk = {
 	.cbcr_reg = OXILI_GFX3D_CBCR,
+	.bcr_reg = OXILI_BCR,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.parent = &oxili_gfx3d_clk_src.c,
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index c91af54..fc32a59 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -161,25 +161,62 @@
 DEFINE_SIMPLE_ATTRIBUTE(clock_hwcg_fops, clock_debug_hwcg_get,
 			NULL, "%llu\n");
 
+static void clock_print_fmax_by_level(struct seq_file *m, int level)
+{
+	struct clk *clock = m->private;
+	struct clk_vdd_class *vdd_class = clock->vdd_class;
+	int off, i, vdd_level, nregs = vdd_class->num_regulators;
+
+	vdd_level = find_vdd_level(clock, clock->rate);
+
+	seq_printf(m, "%2s%10lu", vdd_level == level ? "[" : "",
+		clock->fmax[level]);
+	for (i = 0; i < nregs; i++) {
+		off = nregs*level + i;
+		if (vdd_class->vdd_uv)
+			seq_printf(m, "%10u", vdd_class->vdd_uv[off]);
+		if (vdd_class->vdd_ua)
+			seq_printf(m, "%10u", vdd_class->vdd_ua[off]);
+	}
+
+	if (vdd_level == level)
+		seq_puts(m, "]");
+	seq_puts(m, "\n");
+}
+
 static int fmax_rates_show(struct seq_file *m, void *unused)
 {
 	struct clk *clock = m->private;
-	int level = 0;
+	struct clk_vdd_class *vdd_class = clock->vdd_class;
+	int level = 0, i, nregs = vdd_class->num_regulators;
+	char reg_name[10];
 
 	int vdd_level = find_vdd_level(clock, clock->rate);
 	if (vdd_level < 0) {
 		seq_printf(m, "could not find_vdd_level for %s, %ld\n",
-			   clock->dbg_name, clock->rate);
+			clock->dbg_name, clock->rate);
 		return 0;
 	}
-	for (level = 0; level < clock->num_fmax; level++) {
-		if (vdd_level == level)
-			seq_printf(m, "[%lu] ", clock->fmax[level]);
-		else
-			seq_printf(m, "%lu ", clock->fmax[level]);
+
+	seq_printf(m, "%12s", "");
+	for (i = 0; i < nregs; i++) {
+		snprintf(reg_name, ARRAY_SIZE(reg_name), "reg %d", i);
+		seq_printf(m, "%10s", reg_name);
+		if (vdd_class->vdd_ua)
+			seq_printf(m, "%10s", "");
+	}
+
+	seq_printf(m, "\n%12s", "freq");
+	for (i = 0; i < nregs; i++) {
+		seq_printf(m, "%10s", "uV");
+		if (vdd_class->vdd_ua)
+			seq_printf(m, "%10s", "uA");
 	}
 	seq_printf(m, "\n");
 
+	for (level = 0; level < clock->num_fmax; level++)
+		clock_print_fmax_by_level(m, level);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/clock-dsi-8610.c b/arch/arm/mach-msm/clock-dsi-8610.c
index 44b332e..73196fe 100644
--- a/arch/arm/mach-msm/clock-dsi-8610.c
+++ b/arch/arm/mach-msm/clock-dsi-8610.c
@@ -192,7 +192,7 @@
 	status = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_0);
 	if (!status & DSI_PLL_RDY_BIT) {
 		pr_err("DSI PLL not ready\n");
-		clk_disable(dsi_ahb_clk);
+		clk_disable_unprepare(dsi_ahb_clk);
 		return HANDOFF_DISABLED_CLK;
 	}
 
@@ -370,35 +370,19 @@
 	return HANDOFF_ENABLED_CLK;
 }
 
-int dsi_prepare(struct clk *clk)
-{
-	return clk_prepare(dsi_ahb_clk);
-}
-
-void dsi_unprepare(struct clk *clk)
-{
-	clk_unprepare(dsi_ahb_clk);
-}
-
 struct clk_ops clk_ops_dsi_dsiclk = {
-	.prepare = dsi_prepare,
-	.unprepare = dsi_unprepare,
 	.set_rate = dsi_dsiclk_set_rate,
 	.round_rate = dsi_dsiclk_round_rate,
 	.handoff = dsi_dsiclk_handoff,
 };
 
 struct clk_ops clk_ops_dsi_byteclk = {
-	.prepare = dsi_prepare,
-	.unprepare = dsi_unprepare,
 	.set_rate = dsi_byteclk_set_rate,
 	.round_rate = dsi_byteclk_round_rate,
 	.handoff = dsi_byteclk_handoff,
 };
 
 struct clk_ops clk_ops_dsi_vco = {
-	.prepare = dsi_prepare,
-	.unprepare = dsi_unprepare,
 	.enable = dsi_pll_vco_enable,
 	.disable = dsi_pll_vco_disable,
 	.set_rate = dsi_pll_vco_set_rate,
diff --git a/arch/arm/mach-msm/clock-dummy.c b/arch/arm/mach-msm/clock-dummy.c
index 883a5c2..139c756 100644
--- a/arch/arm/mach-msm/clock-dummy.c
+++ b/arch/arm/mach-msm/clock-dummy.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, 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
@@ -19,6 +19,7 @@
 
 static int dummy_clk_set_rate(struct clk *clk, unsigned long rate)
 {
+	clk->rate = rate;
 	return 0;
 }
 
@@ -34,7 +35,7 @@
 
 static unsigned long dummy_clk_get_rate(struct clk *clk)
 {
-	return 0;
+	return clk->rate;
 }
 
 static long dummy_clk_round_rate(struct clk *clk, unsigned long rate)
@@ -42,7 +43,7 @@
 	return rate;
 }
 
-static struct clk_ops clk_ops_dummy = {
+struct clk_ops clk_ops_dummy = {
 	.reset = dummy_clk_reset,
 	.set_rate = dummy_clk_set_rate,
 	.set_max_rate = dummy_clk_set_max_rate,
diff --git a/arch/arm/mach-msm/clock-krypton.c b/arch/arm/mach-msm/clock-krypton.c
index aaee003..0b615cc 100644
--- a/arch/arm/mach-msm/clock-krypton.c
+++ b/arch/arm/mach-msm/clock-krypton.c
@@ -46,6 +46,8 @@
 	CLK_DUMMY("mem_clk", bimc_msmbus_clk.c, "msm_bimc", OFF),
 	CLK_DUMMY("mem_a_clk", bimc_msmbus_a_clk.c, "msm_bimc", OFF),
 	CLK_DUMMY("mem_clk", bimc_acpu_a_clk.c, "", OFF),
+	CLK_DUMMY("dfab_clk",	DFAB_CLK,	"msm_sps", OFF),
+	CLK_DUMMY("dma_bam_pclk",	DMA_BAM_P_CLK,	"msm_sps", OFF),
 
 	CLK_DUMMY("clktype", gcc_imem_axi_clk         , "drivername", OFF),
 	CLK_DUMMY("clktype", gcc_imem_cfg_ahb_clk     , "drivername", OFF),
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index 70b6bea..aeb4e48 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -870,8 +870,6 @@
 	u32 status;
 	int pll_locked = 0;
 
-	dsi_pll_toggle_lock_detect();
-
 	/* poll for PLL ready status */
 	if (readl_poll_timeout_noirq((mdss_dsi_base +
 			DSI_0_PHY_PLL_UNIPHY_PLL_STATUS),
@@ -888,6 +886,12 @@
 	return pll_locked;
 }
 
+static inline int dsi_pll_toggle_lock_detect_and_check_status(void)
+{
+	dsi_pll_toggle_lock_detect();
+	return dsi_pll_lock_status();
+}
+
 static void dsi_pll_software_reset(void)
 {
 	/*
@@ -919,7 +923,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
 	udelay(1000);
 
-	pll_locked = dsi_pll_lock_status();
+	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	for (i = 0; (i < 4) && !pll_locked; i++) {
 		DSS_REG_W(mdss_dsi_base,
 			DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07);
@@ -930,7 +934,7 @@
 		DSS_REG_W(mdss_dsi_base,
 			DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
 		udelay(1000);
-		pll_locked = dsi_pll_lock_status();
+		pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	}
 
 	if (pll_locked)
@@ -966,7 +970,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
 	udelay(1000);
 
-	pll_locked = dsi_pll_lock_status();
+	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
 		pll_locked ? "Locked" : "Unlocked");
 
@@ -995,7 +999,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
 	udelay(1000);
 
-	pll_locked = dsi_pll_lock_status();
+	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
 		pll_locked ? "Locked" : "Unlocked");
 
@@ -1020,7 +1024,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
 	udelay(1000);
 
-	pll_locked = dsi_pll_lock_status();
+	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
 		pll_locked ? "Locked" : "Unlocked");
 
@@ -1047,7 +1051,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
 	udelay(1000);
 
-	pll_locked = dsi_pll_lock_status();
+	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
 		pll_locked ? "Locked" : "Unlocked");
 
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 8356207..1d7a5e2 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -42,7 +42,7 @@
 	int rc;
 	struct msm_rpm_iv_pair iv = { .id = r->rpm_status_id, };
 	rc = msm_rpm_get_status(&iv, 1);
-	return (rc < 0) ? rc : iv.value * r->factor;
+	return (rc < 0) ? rc : iv.value * 1000;
 }
 
 static int clk_rpmrs_handoff(struct rpm_clk *r)
@@ -54,7 +54,7 @@
 		return rc;
 
 	if (!r->branch)
-		r->c.rate = iv.value * r->factor;
+		r->c.rate = iv.value * 1000;
 
 	return 0;
 }
@@ -122,7 +122,7 @@
 			unsigned long *active_khz, unsigned long *sleep_khz)
 {
 	/* Convert the rate (hz) to khz */
-	*active_khz = DIV_ROUND_UP(rate, r->factor);
+	*active_khz = DIV_ROUND_UP(rate, 1000);
 
 	/*
 	 * Active-only clocks don't care what the rate is during sleep. So,
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index b20c3d6..d283861 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -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
@@ -39,9 +39,7 @@
 	const bool active_only;
 	bool enabled;
 	bool branch; /* true: RPM only accepts 1 for ON and 0 for OFF */
-	unsigned factor;
 	struct clk_rpmrs_data *rpmrs_data;
-
 	struct rpm_clk *peer;
 	struct clk c;
 };
@@ -69,7 +67,6 @@
 		.rpm_status_id = (stat_id), \
 		.rpm_key = (key), \
 		.peer = &active, \
-		.factor = 1000, \
 		.rpmrs_data = (rpmrsdata),\
 		.c = { \
 			.ops = &clk_ops_rpm, \
@@ -85,7 +82,6 @@
 		.rpm_key = (key), \
 		.peer = &name, \
 		.active_only = true, \
-		.factor = 1000, \
 		.rpmrs_data = (rpmrsdata),\
 		.c = { \
 			.ops = &clk_ops_rpm, \
@@ -104,7 +100,6 @@
 		.rpm_status_id = (stat_id), \
 		.rpm_key = (key), \
 		.peer = &active, \
-		.factor = 1000, \
 		.branch = true, \
 		.rpmrs_data = (rpmrsdata),\
 		.c = { \
@@ -121,7 +116,6 @@
 		.rpm_key = (key), \
 		.peer = &name, \
 		.active_only = true, \
-		.factor = 1000, \
 		.branch = true, \
 		.rpmrs_data = (rpmrsdata),\
 		.c = { \
@@ -132,46 +126,13 @@
 		}, \
 	};
 
-#define __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, stat_id, \
-				key, rpmrsdata) \
-	static struct rpm_clk active; \
-	static struct rpm_clk name = { \
-		.rpm_res_type = (type), \
-		.rpm_clk_id = (r_id), \
-		.rpm_status_id = (stat_id), \
-		.rpm_key = (key), \
-		.peer = &active, \
-		.factor = 1, \
-		.rpmrs_data = (rpmrsdata),\
-		.c = { \
-			.ops = &clk_ops_rpm, \
-			.dbg_name = #name, \
-			CLK_INIT(name.c), \
-		}, \
-	}; \
-	static struct rpm_clk active = { \
-		.rpm_res_type = (type), \
-		.rpm_clk_id = (r_id), \
-		.rpm_status_id = (stat_id), \
-		.rpm_key = (key), \
-		.peer = &name, \
-		.active_only = true, \
-		.factor = 1, \
-		.rpmrs_data = (rpmrsdata),\
-		.c = { \
-			.ops = &clk_ops_rpm, \
-			.dbg_name = #active, \
-			CLK_INIT(active.c), \
-		}, \
-	};
-
 #define DEFINE_CLK_RPM(name, active, r_id, dep) \
 	__DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
 		MSM_RPM_STATUS_ID_##r_id##_CLK, dep, 0, &clk_rpmrs_data)
 
 #define DEFINE_CLK_RPM_QDSS(name, active) \
-	__DEFINE_CLK_RPM_QDSS(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
-		MSM_RPM_STATUS_ID_QDSS_CLK, 0, &clk_rpmrs_data)
+	__DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
+		MSM_RPM_STATUS_ID_QDSS_CLK, 0, 0, &clk_rpmrs_data)
 
 #define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
 	__DEFINE_CLK_RPM_BRANCH(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
@@ -186,8 +147,8 @@
 				RPM_SMD_KEY_ENABLE, &clk_rpmrs_data_smd)
 
 #define DEFINE_CLK_RPM_SMD_QDSS(name, active, type, r_id) \
-	__DEFINE_CLK_RPM_QDSS(name, active, type, r_id, \
-		0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
+	__DEFINE_CLK_RPM(name, active, type, r_id, \
+		0, 0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
 /*
  * The RPM XO buffer clock management code aggregates votes for pin-control mode
  * and software mode separately. Software-enable has higher priority over pin-
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index 5550282..60a62ec 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -125,21 +125,9 @@
 #define CPR_FUSE_RO_SEL_BITS		3
 #define CPR_FUSE_RO_SEL_BITS_MASK	((1<<CPR_FUSE_RO_SEL_BITS)-1)
 
-#define CPR_FUSE_TARGET_QUOT_TURBO_SHIFT	0
-#define CPR_FUSE_TARGET_QUOT_NOMINAL_SHIFT	12
-#define CPR_FUSE_TARGET_QUOT_SVS_SHIFT		24
+#define CPR_FUSE_MIN_QUOT_DIFF		100
 
-#define CPR_FUSE_DISABLE_CPR_SHIFT		36
-#define CPR_FUSE_LOCAL_APPROACH_SHIFT		37
-#define CPR_FUSE_REDUNDANT_SHIFT		57
-
-/* PVS eFuse parameters */
-#define PVS_FUSE_REDUNDANT_SHIFT	24
-#define PVS_FUSE_REDUNDANT_BITS		3
-#define PVS_FUSE_REDUNDANT_MASK		((1<<PVS_FUSE_REDUNDANT_BITS)-1)
-
-#define PVS_FUSE_BINS_SHIFT		6
-#define PVS_FUSE_BINS_REDUNDANT_SHIFT	27
+#define BYTES_PER_FUSE_ROW		8
 
 enum voltage_change_dir {
 	NO_CHANGE,
@@ -154,9 +142,11 @@
 	int				corner;
 	int				ceiling_max;
 
+	/* eFuse parameters */
+	phys_addr_t	efuse_addr;
+	void __iomem	*efuse_base;
+
 	/* Process voltage parameters */
-	phys_addr_t	pvs_efuse;
-	u32		num_efuse_bits;
 	u32		pvs_bin_process[CPR_PVS_EFUSE_BINS_MAX];
 	u32		pvs_corner_v[NUM_APC_PVS][CPR_CORNER_MAX];
 	/* Process voltage variables */
@@ -173,12 +163,9 @@
 	int			vdd_mx_vmin;
 
 	/* CPR parameters */
-	phys_addr_t	cpr_fuse_addr;
 	u64		cpr_fuse_bits;
-	u64		cpr_fuse_bits_2;
 	bool		cpr_fuse_disable;
 	bool		cpr_fuse_local;
-	bool		cpr_fuse_redundancy;
 	int		cpr_fuse_target_quot[CPR_CORNER_MAX];
 	int		cpr_fuse_ro_sel[CPR_CORNER_MAX];
 	int		gcnt;
@@ -215,16 +202,26 @@
 	u32		vdd_apc_step_down_limit;
 };
 
-static int cpr_debug_enable;
+#define CPR_DEBUG_MASK_IRQ	BIT(0)
+#define CPR_DEBUG_MASK_API	BIT(1)
+
+static int cpr_debug_enable = CPR_DEBUG_MASK_IRQ;
 static int cpr_enable;
 static struct cpr_regulator *the_cpr;
 
 module_param_named(debug_enable, cpr_debug_enable, int, S_IRUGO | S_IWUSR);
 #define cpr_debug(message, ...) \
 	do { \
-		if (cpr_debug_enable) \
+		if (cpr_debug_enable & CPR_DEBUG_MASK_API) \
 			pr_info(message, ##__VA_ARGS__); \
 	} while (0)
+#define cpr_debug_irq(message, ...) \
+	do { \
+		if (cpr_debug_enable & CPR_DEBUG_MASK_IRQ) \
+			pr_info(message, ##__VA_ARGS__); \
+		else \
+			pr_debug(message, ##__VA_ARGS__); \
+	} while (0)
 
 static bool cpr_is_allowed(struct cpr_regulator *cpr_vreg)
 {
@@ -282,11 +279,12 @@
 	cpr_masked_write(cpr_vreg, REG_RBCPR_CTL, mask, value);
 }
 
-static void cpr_ctl_enable(struct cpr_regulator *cpr_vreg)
+static void cpr_ctl_enable(struct cpr_regulator *cpr_vreg, int corner)
 {
 	u32 val;
 
-	if (cpr_is_allowed(cpr_vreg))
+	if (cpr_is_allowed(cpr_vreg) &&
+	    (cpr_vreg->ceiling_volt[corner] > cpr_vreg->floor_volt[corner]))
 		val = RBCPR_CTL_LOOP_EN;
 	else
 		val = 0;
@@ -384,7 +382,7 @@
 			cpr_ctl_disable(the_cpr);
 			cpr_irq_clr(the_cpr);
 			cpr_corner_restore(the_cpr, the_cpr->corner);
-			cpr_ctl_enable(the_cpr);
+			cpr_ctl_enable(the_cpr, the_cpr->corner);
 		} else {
 			cpr_ctl_disable(the_cpr);
 			cpr_irq_set(the_cpr, 0);
@@ -500,16 +498,16 @@
 				& RBCPR_RESULT0_ERROR_STEPS_MASK;
 	last_volt = cpr_vreg->last_volt[corner];
 
-	cpr_debug("last_volt[corner:%d] = %d uV\n", corner, last_volt);
+	cpr_debug_irq("last_volt[corner:%d] = %d uV\n", corner, last_volt);
 
 	if (dir == UP) {
-		cpr_debug("Up: cpr status = 0x%08x (error_steps=%d)\n",
-			  reg_val, error_steps);
+		cpr_debug_irq("Up: cpr status = 0x%08x (error_steps=%d)\n",
+			      reg_val, error_steps);
 
 		if (last_volt >= cpr_vreg->ceiling_volt[corner]) {
-			cpr_debug("[corn:%d] @ ceiling: %d >= %d: NACK\n",
-				  corner, last_volt,
-				  cpr_vreg->ceiling_volt[corner]);
+			cpr_debug_irq("[corn:%d] @ ceiling: %d >= %d: NACK\n",
+				      corner, last_volt,
+				      cpr_vreg->ceiling_volt[corner]);
 			cpr_irq_clr_nack(cpr_vreg);
 
 			/* Maximize the UP threshold */
@@ -521,17 +519,18 @@
 		}
 
 		if (error_steps > cpr_vreg->vdd_apc_step_up_limit) {
-			cpr_debug("%d is over up-limit(%d): Clamp\n",
-				  error_steps,
-				  cpr_vreg->vdd_apc_step_up_limit);
+			cpr_debug_irq("%d is over up-limit(%d): Clamp\n",
+				      error_steps,
+				      cpr_vreg->vdd_apc_step_up_limit);
 			error_steps = cpr_vreg->vdd_apc_step_up_limit;
 		}
 
 		/* Calculate new voltage */
 		new_volt = last_volt + (error_steps * cpr_vreg->step_volt);
 		if (new_volt > cpr_vreg->ceiling_volt[corner]) {
-			cpr_debug("new_volt(%d) >= ceiling_volt(%d): Clamp\n",
-				  new_volt, cpr_vreg->ceiling_volt[corner]);
+			cpr_debug_irq("new_volt(%d) >= ceiling(%d): Clamp\n",
+				      new_volt,
+				      cpr_vreg->ceiling_volt[corner]);
 			new_volt = cpr_vreg->ceiling_volt[corner];
 		}
 
@@ -557,15 +556,16 @@
 		/* Ack */
 		cpr_irq_clr_ack(cpr_vreg);
 
-		cpr_debug("UP: -> new_volt = %d uV\n", new_volt);
+		cpr_debug_irq("UP: -> new_volt[corner:%d] = %d uV\n",
+			      corner, new_volt);
 	} else if (dir == DOWN) {
-		cpr_debug("Down: cpr status = 0x%08x (error_steps=%d)\n",
-			  reg_val, error_steps);
+		cpr_debug_irq("Down: cpr status = 0x%08x (error_steps=%d)\n",
+			      reg_val, error_steps);
 
 		if (last_volt <= cpr_vreg->floor_volt[corner]) {
-			cpr_debug("[corn:%d] @ floor: %d <= %d: NACK\n",
-				  corner, last_volt,
-				  cpr_vreg->floor_volt[corner]);
+			cpr_debug_irq("[corn:%d] @ floor: %d <= %d: NACK\n",
+				      corner, last_volt,
+				      cpr_vreg->floor_volt[corner]);
 			cpr_irq_clr_nack(cpr_vreg);
 
 			/* Maximize the DOWN threshold */
@@ -586,17 +586,18 @@
 		}
 
 		if (error_steps > cpr_vreg->vdd_apc_step_down_limit) {
-			cpr_debug("%d is over down-limit(%d): Clamp\n",
-				  error_steps,
-				  cpr_vreg->vdd_apc_step_down_limit);
+			cpr_debug_irq("%d is over down-limit(%d): Clamp\n",
+				      error_steps,
+				      cpr_vreg->vdd_apc_step_down_limit);
 			error_steps = cpr_vreg->vdd_apc_step_down_limit;
 		}
 
 		/* Calculte new voltage */
 		new_volt = last_volt - (error_steps * cpr_vreg->step_volt);
 		if (new_volt < cpr_vreg->floor_volt[corner]) {
-			cpr_debug("new_volt(%d) < floor_volt(%d): Clamp\n",
-				  new_volt, cpr_vreg->floor_volt[corner]);
+			cpr_debug_irq("new_volt(%d) < floor(%d): Clamp\n",
+				      new_volt,
+				      cpr_vreg->floor_volt[corner]);
 			new_volt = cpr_vreg->floor_volt[corner];
 		}
 
@@ -616,7 +617,8 @@
 		/* Ack */
 		cpr_irq_clr_ack(cpr_vreg);
 
-		cpr_debug("DOWN: -> new_volt = %d uV\n", new_volt);
+		cpr_debug_irq("DOWN: -> new_volt[corner:%d] = %d uV\n",
+			      corner, new_volt);
 	}
 }
 
@@ -628,7 +630,7 @@
 	mutex_lock(&cpr_vreg->cpr_mutex);
 
 	reg_val = cpr_read(cpr_vreg, REG_RBIF_IRQ_STATUS);
-	cpr_debug("IRQ_STATUS = 0x%02X\n", reg_val);
+	cpr_debug_irq("IRQ_STATUS = 0x%02X\n", reg_val);
 
 	if (!cpr_is_allowed(cpr_vreg)) {
 		reg_val = cpr_read(cpr_vreg, REG_RBCPR_CTL);
@@ -647,7 +649,7 @@
 		cpr_irq_clr_nack(cpr_vreg);
 	} else if (reg_val & CPR_INT_MID) {
 		/* RBCPR_CTL_SW_AUTO_CONT_ACK_EN is enabled */
-		cpr_debug("IRQ occured for Mid Flag\n");
+		cpr_debug_irq("IRQ occured for Mid Flag\n");
 	} else {
 		pr_err("IRQ occured for unknown flag (0x%08x)\n", reg_val);
 	}
@@ -693,7 +695,7 @@
 	if (cpr_is_allowed(cpr_vreg) && cpr_vreg->corner) {
 		cpr_irq_clr(cpr_vreg);
 		cpr_corner_switch(cpr_vreg, cpr_vreg->corner);
-		cpr_ctl_enable(cpr_vreg);
+		cpr_ctl_enable(cpr_vreg, cpr_vreg->corner);
 	}
 	mutex_unlock(&cpr_vreg->cpr_mutex);
 
@@ -759,7 +761,7 @@
 	if (cpr_is_allowed(cpr_vreg) && cpr_vreg->vreg_enabled) {
 		cpr_irq_clr(cpr_vreg);
 		cpr_corner_switch(cpr_vreg, corner);
-		cpr_ctl_enable(cpr_vreg);
+		cpr_ctl_enable(cpr_vreg, corner);
 	}
 
 	cpr_vreg->corner = corner;
@@ -808,7 +810,7 @@
 	cpr_irq_clr(cpr_vreg);
 
 	enable_irq(cpr_vreg->cpr_irq);
-	cpr_ctl_enable(cpr_vreg);
+	cpr_ctl_enable(cpr_vreg, cpr_vreg->corner);
 
 	return 0;
 }
@@ -838,7 +840,7 @@
 #define cpr_regulator_resume NULL
 #endif
 
-static int cpr_config(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_config(struct cpr_regulator *cpr_vreg)
 {
 	int i;
 	u32 val, gcnt, reg;
@@ -928,47 +930,80 @@
 	return 0;
 }
 
-static int __init cpr_pvs_init(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_is_fuse_redundant(struct cpr_regulator *cpr_vreg,
+					 u32 redun_sel[4])
 {
-	void __iomem *efuse_base;
-	u32 efuse_bits, redundant, shift, mask;
-	int i, process;
+	u32 fuse_bits;
+	int redundant;
 
-	efuse_base = ioremap(cpr_vreg->pvs_efuse, 4);
-	if (!efuse_base) {
-		pr_err("Unable to map pvs_efuse 0x%08x\n",
-				cpr_vreg->pvs_efuse);
-		return -EINVAL;
+	fuse_bits = readl_relaxed(cpr_vreg->efuse_base
+				  + redun_sel[0] * BYTES_PER_FUSE_ROW);
+	fuse_bits = (fuse_bits >> redun_sel[1]) & ((1 << redun_sel[2]) - 1);
+	if (fuse_bits == redun_sel[3])
+		redundant = 1;
+	else
+		redundant = 0;
+
+	pr_info("[row:%d] = 0x%x @%d:%d = %d?: redundant=%d\n",
+		redun_sel[0], fuse_bits,
+		redun_sel[1], redun_sel[2], redun_sel[3], redundant);
+	return redundant;
+}
+
+static int __devinit cpr_pvs_init(struct platform_device *pdev,
+			       struct cpr_regulator *cpr_vreg)
+{
+	struct device_node *of_node = pdev->dev.of_node;
+	u32 efuse_bits;
+	int rc, process;
+	u32 pvs_fuse[3], pvs_fuse_redun_sel[4];
+	bool redundant;
+	size_t pvs_bins;
+
+	rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse-redun-sel",
+					pvs_fuse_redun_sel, 4);
+	if (rc < 0) {
+		pr_err("pvs-fuse-redun-sel missing: rc=%d\n", rc);
+		return rc;
 	}
 
-	efuse_bits = readl_relaxed(efuse_base);
+	redundant = cpr_is_fuse_redundant(cpr_vreg, pvs_fuse_redun_sel);
+
+	if (redundant) {
+		rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse-redun",
+						pvs_fuse, 3);
+		if (rc < 0) {
+			pr_err("pvs-fuse-redun missing: rc=%d\n", rc);
+			return rc;
+		}
+	} else {
+		rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse",
+						pvs_fuse, 3);
+		if (rc < 0) {
+			pr_err("pvs-fuse missing: rc=%d\n", rc);
+			return rc;
+		}
+	}
 
 	/* Construct PVS process # from the efuse bits */
-	redundant = (efuse_bits >> PVS_FUSE_REDUNDANT_SHIFT)
-			& PVS_FUSE_REDUNDANT_MASK;
-	if (redundant == 2)
-		shift = PVS_FUSE_BINS_REDUNDANT_SHIFT;
-	else
-		shift = PVS_FUSE_BINS_SHIFT;
-	mask = (1 << cpr_vreg->num_efuse_bits) - 1;
-	cpr_vreg->pvs_bin = (efuse_bits >> shift) & mask;
+	efuse_bits = readl_relaxed(cpr_vreg->efuse_base +
+				   pvs_fuse[0] * BYTES_PER_FUSE_ROW);
+	cpr_vreg->pvs_bin = (efuse_bits >> pvs_fuse[1]) &
+				   ((1 << pvs_fuse[2]) - 1);
 
-	/* Set ceiling max and use it for APC_PVS_NO */
-	cpr_vreg->ceiling_max =
-		cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_CORNER_TURBO];
-
-	iounmap(efuse_base);
+	pvs_bins = 1 << pvs_fuse[2];
+	rc = of_property_read_u32_array(of_node, "qcom,pvs-bin-process",
+					cpr_vreg->pvs_bin_process,
+					pvs_bins);
+	if (rc < 0) {
+		pr_err("pvs-bin-process missing: rc=%d\n", rc);
+		return rc;
+	}
 
 	process = cpr_vreg->pvs_bin_process[cpr_vreg->pvs_bin];
-	pr_info("[0x%08X] = 0x%08X, n_bits=%d, bin=%d (%d) [redundant=%d]\n",
-		cpr_vreg->pvs_efuse, efuse_bits, cpr_vreg->num_efuse_bits,
-		cpr_vreg->pvs_bin, process, redundant);
-	for (i = APC_PVS_SLOW; i < NUM_APC_PVS; i++) {
-		pr_info("[%d] [%d %d %d] uV\n", i,
-			cpr_vreg->pvs_corner_v[i][CPR_CORNER_SVS],
-			cpr_vreg->pvs_corner_v[i][CPR_CORNER_NORMAL],
-			cpr_vreg->pvs_corner_v[i][CPR_CORNER_TURBO]);
-	}
+	pr_info("[row:%d] = 0x%08X, n_bits=%d, bin=%d (%d)\n",
+		pvs_fuse[0], efuse_bits, pvs_fuse[2],
+		cpr_vreg->pvs_bin, process);
 
 	if (process == APC_PVS_NO || process >= NUM_APC_PVS) {
 		pr_err("Bin=%d (%d) is out of spec. Assume SLOW.\n",
@@ -994,7 +1029,7 @@
 	}								\
 } while (0)
 
-static int __init cpr_apc_init(struct platform_device *pdev,
+static int __devinit cpr_apc_init(struct platform_device *pdev,
 			       struct cpr_regulator *cpr_vreg)
 {
 	struct device_node *of_node = pdev->dev.of_node;
@@ -1055,90 +1090,156 @@
 	}
 }
 
-static int __init cpr_init_cpr_efuse(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_init_cpr_efuse(struct platform_device *pdev,
+				     struct cpr_regulator *cpr_vreg)
 {
-	void __iomem *efuse_base;
+	struct device_node *of_node = pdev->dev.of_node;
+	int i, rc = 0;
+	bool redundant;
+	u32 cpr_fuse_redun_sel[4];
+	char *targ_quot_str, *ro_sel_str;
+	u32 cpr_fuse_row;
+	u32 bp_cpr_disable, bp_scheme;
+	int bp_target_quot[CPR_CORNER_MAX];
+	int bp_ro_sel[CPR_CORNER_MAX];
 	u32 ro_sel, val;
-	u64 fuse_bits;
-	int ro_sel_shift[CPR_CORNER_MAX];
+	u64 fuse_bits, fuse_bits_2;
 
-	efuse_base = ioremap(cpr_vreg->cpr_fuse_addr, 16);
-	if (!efuse_base) {
-		pr_err("Unable to map cpr_fuse_addr 0x%08x\n",
-				cpr_vreg->cpr_fuse_addr);
-		return -EINVAL;
+	rc = of_property_read_u32_array(of_node, "qcom,cpr-fuse-redun-sel",
+					cpr_fuse_redun_sel, 4);
+	if (rc < 0) {
+		pr_err("cpr-fuse-redun-sel missing: rc=%d\n", rc);
+		return rc;
 	}
 
-	cpr_vreg->cpr_fuse_bits = readll_relaxed(efuse_base);
-	cpr_vreg->cpr_fuse_bits_2 = readll_relaxed(efuse_base + 8);
+	redundant = cpr_is_fuse_redundant(cpr_vreg, cpr_fuse_redun_sel);
 
-	iounmap(efuse_base);
+	if (redundant) {
+		CPR_PROP_READ_U32(of_node, "cpr-fuse-redun-row",
+				  &cpr_fuse_row, rc);
+		targ_quot_str = "qcom,cpr-fuse-redun-target-quot";
+		ro_sel_str = "qcom,cpr-fuse-redun-ro-sel";
+	} else {
+		CPR_PROP_READ_U32(of_node, "cpr-fuse-row",
+				  &cpr_fuse_row, rc);
+		targ_quot_str = "qcom,cpr-fuse-target-quot";
+		ro_sel_str = "qcom,cpr-fuse-ro-sel";
+	}
+	if (rc)
+		return rc;
+
+	rc = of_property_read_u32_array(of_node,
+		targ_quot_str,
+		&bp_target_quot[CPR_CORNER_SVS],
+		CPR_CORNER_MAX - CPR_CORNER_SVS);
+	if (rc < 0) {
+		pr_err("missing %s: rc=%d\n", targ_quot_str, rc);
+		return rc;
+	}
+
+	rc = of_property_read_u32_array(of_node,
+		ro_sel_str,
+		&bp_ro_sel[CPR_CORNER_SVS],
+		CPR_CORNER_MAX - CPR_CORNER_SVS);
+	if (rc < 0) {
+		pr_err("missing %s: rc=%d\n", ro_sel_str, rc);
+		return rc;
+	}
 
 	/* Read the control bits of eFuse */
-	cpr_vreg->cpr_fuse_disable = (cpr_vreg->cpr_fuse_bits >>
-				      CPR_FUSE_DISABLE_CPR_SHIFT) & 0x01;
-	cpr_vreg->cpr_fuse_local = (cpr_vreg->cpr_fuse_bits >>
-				    CPR_FUSE_LOCAL_APPROACH_SHIFT) & 0x01;
-	cpr_vreg->cpr_fuse_redundancy = (cpr_vreg->cpr_fuse_bits >>
-					 CPR_FUSE_REDUNDANT_SHIFT) & 0x01;
+	fuse_bits = readll_relaxed(cpr_vreg->efuse_base
+				   + cpr_fuse_row * BYTES_PER_FUSE_ROW);
+	pr_info("[row:%d] = 0x%llx\n", cpr_fuse_row, fuse_bits);
 
-	pr_info("[0x%08X] = 0x%llx\n", cpr_vreg->cpr_fuse_addr,
-		cpr_vreg->cpr_fuse_bits);
-	pr_info("disable = %d, local = %d, redundancy = %d\n",
-			cpr_vreg->cpr_fuse_disable,
-			cpr_vreg->cpr_fuse_local,
-			cpr_vreg->cpr_fuse_redundancy);
-	pr_info("[0x%08X] = 0x%llx\n", cpr_vreg->cpr_fuse_addr + 8,
-		cpr_vreg->cpr_fuse_bits_2);
+	if (redundant) {
+		if (of_property_read_bool(of_node,
+				"qcom,cpr-fuse-redun-bp-cpr-disable")) {
+			CPR_PROP_READ_U32(of_node,
+					  "cpr-fuse-redun-bp-cpr-disable",
+					  &bp_cpr_disable, rc);
+			CPR_PROP_READ_U32(of_node,
+					  "cpr-fuse-redun-bp-scheme",
+					  &bp_scheme, rc);
+			if (rc)
+				return rc;
+			fuse_bits_2 = fuse_bits;
+		} else {
+			u32 temp_row;
 
-	if (cpr_vreg->cpr_fuse_redundancy == 0) {
-		fuse_bits = cpr_vreg->cpr_fuse_bits;
-		ro_sel_shift[CPR_CORNER_SVS] = 54;
-		ro_sel_shift[CPR_CORNER_NORMAL] = 38;
-		ro_sel_shift[CPR_CORNER_TURBO] = 41;
+			/* Use original fuse if no optional property */
+			CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-cpr-disable",
+					  &bp_cpr_disable, rc);
+			CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-scheme",
+					  &bp_scheme, rc);
+			CPR_PROP_READ_U32(of_node, "cpr-fuse-row",
+					  &temp_row, rc);
+			if (rc)
+				return rc;
+			fuse_bits_2 = readll_relaxed(cpr_vreg->efuse_base
+					+ temp_row * BYTES_PER_FUSE_ROW);
+			pr_info("[original row:%d] = 0x%llx\n",
+				temp_row, fuse_bits_2);
+		}
 	} else {
-		fuse_bits = cpr_vreg->cpr_fuse_bits_2;
-		ro_sel_shift[CPR_CORNER_SVS] = 46;
-		ro_sel_shift[CPR_CORNER_NORMAL] = 36;
-		ro_sel_shift[CPR_CORNER_TURBO] = 39;
+		CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-cpr-disable",
+				  &bp_cpr_disable, rc);
+		CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-scheme",
+				  &bp_scheme, rc);
+		if (rc)
+			return rc;
+		fuse_bits_2 = fuse_bits;
 	}
 
-	/* SVS */
-	ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_SVS])
-				& CPR_FUSE_RO_SEL_BITS_MASK;
-	val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_SVS_SHIFT)
-				& CPR_FUSE_TARGET_QUOT_BITS_MASK;
-	cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_SVS] = val;
-	cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_SVS] = ro_sel;
-	pr_info("SVS: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+	cpr_vreg->cpr_fuse_disable = (fuse_bits_2 >> bp_cpr_disable) & 0x01;
+	cpr_vreg->cpr_fuse_local = (fuse_bits_2 >> bp_scheme) & 0x01;
 
-	/* Nominal */
-	ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_NORMAL])
-				& CPR_FUSE_RO_SEL_BITS_MASK;
-	val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_NOMINAL_SHIFT)
-				& CPR_FUSE_TARGET_QUOT_BITS_MASK;
-	cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_NORMAL] = val;
-	cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_NORMAL] = ro_sel;
-	pr_info("Nominal: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+	pr_info("disable = %d, local = %d\n",
+		cpr_vreg->cpr_fuse_disable, cpr_vreg->cpr_fuse_local);
 
-	/* Turbo */
-	ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_TURBO])
+	for (i = CPR_CORNER_SVS; i < CPR_CORNER_MAX; i++) {
+		ro_sel = (fuse_bits >> bp_ro_sel[i])
 				& CPR_FUSE_RO_SEL_BITS_MASK;
-	val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_TURBO_SHIFT)
+		val = (fuse_bits >> bp_target_quot[i])
 				& CPR_FUSE_TARGET_QUOT_BITS_MASK;
-	cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_TURBO] = val;
-	cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_TURBO] = ro_sel;
-	pr_info("Turbo: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+		cpr_vreg->cpr_fuse_target_quot[i] = val;
+		cpr_vreg->cpr_fuse_ro_sel[i] = ro_sel;
+		pr_info("Corner[%d]: ro_sel = %d, target quot = %d\n",
+			i, ro_sel, val);
+	}
 
+	cpr_vreg->cpr_fuse_bits = fuse_bits;
 	if (!cpr_vreg->cpr_fuse_bits) {
 		cpr_vreg->cpr_fuse_disable = 1;
 		pr_err("cpr_fuse_bits = 0: set cpr_fuse_disable = 1\n");
+	} else {
+		/* Check if the target quotients are too close together */
+		int *quot = cpr_vreg->cpr_fuse_target_quot;
+		bool valid_fuse = true;
+
+		if ((quot[CPR_CORNER_TURBO] > quot[CPR_CORNER_NORMAL]) &&
+		    (quot[CPR_CORNER_NORMAL] > quot[CPR_CORNER_SVS])) {
+			if ((quot[CPR_CORNER_TURBO] -
+			     quot[CPR_CORNER_NORMAL])
+					<= CPR_FUSE_MIN_QUOT_DIFF)
+				valid_fuse = false;
+			else if ((quot[CPR_CORNER_NORMAL] -
+				  quot[CPR_CORNER_SVS])
+					<= CPR_FUSE_MIN_QUOT_DIFF)
+				valid_fuse = false;
+		} else {
+			valid_fuse = false;
+		}
+
+		if (!valid_fuse) {
+			cpr_vreg->cpr_fuse_disable = 1;
+			pr_err("invalid quotient values\n");
+		}
 	}
 
 	return 0;
 }
 
-static int __init cpr_init_cpr_voltages(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_init_cpr_voltages(struct cpr_regulator *cpr_vreg)
 {
 	int i;
 
@@ -1155,7 +1256,7 @@
 	return 0;
 }
 
-static int __init cpr_init_cpr_parameters(struct platform_device *pdev,
+static int __devinit cpr_init_cpr_parameters(struct platform_device *pdev,
 					  struct cpr_regulator *cpr_vreg)
 {
 	struct device_node *of_node = pdev->dev.of_node;
@@ -1223,20 +1324,12 @@
 	return rc;
 }
 
-static int __init cpr_init_cpr(struct platform_device *pdev,
+static int __devinit cpr_init_cpr(struct platform_device *pdev,
 			       struct cpr_regulator *cpr_vreg)
 {
 	struct resource *res;
 	int rc = 0;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-					   "cpr_efuse");
-	if (!res || !res->start) {
-		pr_err("cpr_efuse missing: res=%p\n", res);
-		return -EINVAL;
-	}
-	cpr_vreg->cpr_fuse_addr = res->start;
-
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rbcpr_clk");
 	if (!res || !res->start) {
 		pr_err("missing rbcpr_clk address: res=%p\n", res);
@@ -1244,7 +1337,7 @@
 	}
 	cpr_vreg->rbcpr_clk_addr = res->start;
 
-	rc = cpr_init_cpr_efuse(cpr_vreg);
+	rc = cpr_init_cpr_efuse(pdev, cpr_vreg);
 	if (rc)
 		return rc;
 
@@ -1287,44 +1380,41 @@
 	return 0;
 }
 
-static int __init cpr_pvs_parse_dt(struct platform_device *pdev,
-				   struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_efuse_init(struct platform_device *pdev,
+				 struct cpr_regulator *cpr_vreg)
+{
+	struct resource *res;
+	int len;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "efuse_addr");
+	if (!res || !res->start) {
+		pr_err("efuse_addr missing: res=%p\n", res);
+		return -EINVAL;
+	}
+	cpr_vreg->efuse_addr = res->start;
+	len = res->end - res->start + 1;
+
+	pr_info("efuse_addr = 0x%x (len=0x%x)\n", res->start, len);
+
+	cpr_vreg->efuse_base = ioremap(cpr_vreg->efuse_addr, len);
+	if (!cpr_vreg->efuse_base) {
+		pr_err("Unable to map efuse_addr 0x%08x\n",
+				cpr_vreg->efuse_addr);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void cpr_efuse_free(struct cpr_regulator *cpr_vreg)
+{
+	iounmap(cpr_vreg->efuse_base);
+}
+
+static int __devinit cpr_voltage_plan_init(struct platform_device *pdev,
+					struct cpr_regulator *cpr_vreg)
 {
 	struct device_node *of_node = pdev->dev.of_node;
-	struct resource *res;
-	int rc;
-	size_t pvs_bins;
-
-	/* Parse process voltage parameters */
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pvs_efuse");
-	if (!res || !res->start) {
-		pr_err("pvs_efuse missing: res=%p\n", res);
-		return -EINVAL;
-	}
-	cpr_vreg->pvs_efuse = res->start;
-
-	rc = of_property_read_u32(of_node, "qcom,num-efuse-bits",
-				&cpr_vreg->num_efuse_bits);
-	if (rc < 0) {
-		pr_err("num-efuse-bits missing: rc=%d\n", rc);
-		return rc;
-	}
-
-	if (cpr_vreg->num_efuse_bits == 0 ||
-	    cpr_vreg->num_efuse_bits > CPR_PVS_EFUSE_BITS_MAX) {
-		pr_err("invalid num-efuse-bits : %d\n",
-		       cpr_vreg->num_efuse_bits);
-		return -EINVAL;
-	}
-
-	pvs_bins = 1 << cpr_vreg->num_efuse_bits;
-	rc = of_property_read_u32_array(of_node, "qcom,pvs-bin-process",
-					cpr_vreg->pvs_bin_process,
-					pvs_bins);
-	if (rc < 0) {
-		pr_err("pvs-bin-process missing: rc=%d\n", rc);
-		return rc;
-	}
+	int rc, i;
 
 	rc = of_property_read_u32_array(of_node,
 		"qcom,pvs-corner-ceiling-slow",
@@ -1353,6 +1443,17 @@
 		return rc;
 	}
 
+	/* Set ceiling max and use it for APC_PVS_NO */
+	cpr_vreg->ceiling_max =
+		cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_CORNER_TURBO];
+
+	for (i = APC_PVS_SLOW; i < NUM_APC_PVS; i++) {
+		pr_info("[%d] [%d %d %d] uV\n", i,
+			cpr_vreg->pvs_corner_v[i][CPR_CORNER_SVS],
+			cpr_vreg->pvs_corner_v[i][CPR_CORNER_NORMAL],
+			cpr_vreg->pvs_corner_v[i][CPR_CORNER_TURBO]);
+	}
+
 	return 0;
 }
 
@@ -1386,31 +1487,39 @@
 		return -ENOMEM;
 	}
 
-	rc = cpr_pvs_parse_dt(pdev, cpr_vreg);
+	rc = cpr_efuse_init(pdev, cpr_vreg);
 	if (rc) {
-		pr_err("Wrong DT parameter specified: rc=%d\n", rc);
+		pr_err("Wrong eFuse address specified: rc=%d\n", rc);
 		return rc;
 	}
 
-	rc = cpr_pvs_init(cpr_vreg);
+	rc = cpr_voltage_plan_init(pdev, cpr_vreg);
+	if (rc) {
+		pr_err("Wrong DT parameter specified: rc=%d\n", rc);
+		goto err_out;
+	}
+
+	rc = cpr_pvs_init(pdev, cpr_vreg);
 	if (rc) {
 		pr_err("Initialize PVS wrong: rc=%d\n", rc);
-		return rc;
+		goto err_out;
 	}
 
 	rc = cpr_apc_init(pdev, cpr_vreg);
 	if (rc) {
 		if (rc != -EPROBE_DEFER)
 			pr_err("Initialize APC wrong: rc=%d\n", rc);
-		return rc;
+		goto err_out;
 	}
 
 	rc = cpr_init_cpr(pdev, cpr_vreg);
 	if (rc) {
 		pr_err("Initialize CPR failed: rc=%d\n", rc);
-		return rc;
+		goto err_out;
 	}
 
+	cpr_efuse_free(cpr_vreg);
+
 	mutex_init(&cpr_vreg->cpr_mutex);
 
 	rdesc			= &cpr_vreg->rdesc;
@@ -1433,6 +1542,10 @@
 	the_cpr = cpr_vreg;
 
 	return 0;
+
+err_out:
+	cpr_efuse_free(cpr_vreg);
+	return rc;
 }
 
 static int __devexit cpr_regulator_remove(struct platform_device *pdev)
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 231a7e0..e02df3e 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -128,15 +128,6 @@
 	struct cpufreq_frequency_table *table;
 
 	struct cpufreq_work_struct *cpu_work = NULL;
-	cpumask_var_t mask;
-
-	if (!cpu_active(policy->cpu)) {
-		pr_info("cpufreq: cpu %d is not active.\n", policy->cpu);
-		return -ENODEV;
-	}
-
-	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
-		return -ENOMEM;
 
 	mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
 
@@ -164,22 +155,14 @@
 	cpu_work->frequency = table[index].frequency;
 	cpu_work->status = -ENODEV;
 
-	cpumask_clear(mask);
-	cpumask_set_cpu(policy->cpu, mask);
-	if (cpumask_equal(mask, &current->cpus_allowed)) {
-		ret = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
-		goto done;
-	} else {
-		cancel_work_sync(&cpu_work->work);
-		INIT_COMPLETION(cpu_work->complete);
-		queue_work_on(policy->cpu, msm_cpufreq_wq, &cpu_work->work);
-		wait_for_completion(&cpu_work->complete);
-	}
+	cancel_work_sync(&cpu_work->work);
+	INIT_COMPLETION(cpu_work->complete);
+	queue_work_on(policy->cpu, msm_cpufreq_wq, &cpu_work->work);
+	wait_for_completion(&cpu_work->complete);
 
 	ret = cpu_work->status;
 
 done:
-	free_cpumask_var(mask);
 	mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
 	return ret;
 }
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 5d25134..f8a32b4 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -25,6 +25,7 @@
 #ifdef CONFIG_MSM_SCM
 #define SCM_SVC_BOOT 0x1
 #define SCM_CMD_TERMINATE_PC 0x2
+#define SCM_CMD_CORE_HOTPLUGGED 0x10
 #endif
 
 ENTRY(msm_arch_idle)
@@ -99,7 +100,7 @@
 #ifdef CONFIG_MSM_SCM
 	ldr	r0, =SCM_SVC_BOOT
 	ldr	r1, =SCM_CMD_TERMINATE_PC
-	mov	r2, #0
+	ldr	r2, =SCM_CMD_CORE_HOTPLUGGED
 	bl	scm_call_atomic1
 #else
 	mrc     p15, 0, r3, c1, c0, 0    /* read current CR    */
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 7b26bd6..6370bd4 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -183,7 +183,7 @@
 };
 
 struct msm_camera_gpio_num_info {
-	uint16_t gpio_num[2];
+	uint16_t gpio_num[7];
 };
 
 struct msm_camera_gpio_conf {
diff --git a/arch/arm/mach-msm/include/mach/camera2.h b/arch/arm/mach-msm/include/mach/camera2.h
index 3e7e5fd..887c594 100644
--- a/arch/arm/mach-msm/include/mach/camera2.h
+++ b/arch/arm/mach-msm/include/mach/camera2.h
@@ -40,6 +40,7 @@
 enum cci_i2c_master_t {
 	MASTER_0,
 	MASTER_1,
+	MASTER_MAX,
 };
 
 struct msm_camera_slave_info {
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 72b5cc1..75dc240 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -168,6 +168,7 @@
 int msm_clock_register(struct clk_lookup *table, size_t size);
 
 extern struct clk dummy_clk;
+extern struct clk_ops clk_ops_dummy;
 
 #define CLK_DUMMY(clk_name, clk_id, clk_dev, flags) { \
 	.con_id = clk_name, \
@@ -175,6 +176,16 @@
 	.clk = &dummy_clk, \
 	}
 
+#define DEFINE_CLK_DUMMY(name, _rate) \
+	static struct fixed_clk name = { \
+		.c = { \
+			.dbg_name = #name, \
+			.rate = _rate, \
+			.ops = &clk_ops_dummy, \
+			CLK_INIT(name.c), \
+		}, \
+	};
+
 #define CLK_LOOKUP(con, c, dev) { .con_id = con, .clk = &c, .dev_id = dev }
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index c979e0c..7cfbd93 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -327,30 +327,43 @@
 
 static inline int msm_soc_version_supports_iommu_v0(void)
 {
+	static int soc_supports_v0 = -1;
 #ifdef CONFIG_OF
 	struct device_node *node;
+#endif
 
+	if (soc_supports_v0 != -1)
+		return soc_supports_v0;
+
+#ifdef CONFIG_OF
 	node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v1");
 	if (node) {
+		soc_supports_v0 = 0;
 		of_node_put(node);
 		return 0;
 	}
 
 	node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v0");
 	if (node) {
+		soc_supports_v0 = 1;
 		of_node_put(node);
 		return 1;
 	}
 #endif
 	if (cpu_is_msm8960() &&
-	    SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 2)
+	    SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 2) {
+		soc_supports_v0 = 0;
 		return 0;
+	}
 
 	if (cpu_is_msm8x60() &&
 	    (SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 2 ||
 	    SOCINFO_VERSION_MINOR(socinfo_get_version()) < 1))	{
+		soc_supports_v0 = 0;
 		return 0;
 	}
+
+	soc_supports_v0 = 1;
 	return 1;
 }
 #endif
diff --git a/arch/arm/mach-msm/include/mach/ipa.h b/arch/arm/mach-msm/include/mach/ipa.h
index b6acef2..f79afee 100644
--- a/arch/arm/mach-msm/include/mach/ipa.h
+++ b/arch/arm/mach-msm/include/mach/ipa.h
@@ -670,6 +670,7 @@
 int teth_bridge_set_aggr_params(struct teth_aggr_params *aggr_params);
 
 void ipa_bam_reg_dump(void);
+bool ipa_emb_ul_pipes_empty(void);
 
 #else /* CONFIG_IPA */
 
@@ -1113,6 +1114,11 @@
 	return;
 }
 
+static inline bool ipa_emb_ul_pipes_empty(void)
+{
+	return false;
+}
+
 #endif /* CONFIG_IPA*/
 
 #endif /* _IPA_H_ */
diff --git a/arch/arm/mach-msm/include/mach/mpm.h b/arch/arm/mach-msm/include/mach/mpm.h
index b92c039..e76a6a9 100644
--- a/arch/arm/mach-msm/include/mach/mpm.h
+++ b/arch/arm/mach-msm/include/mach/mpm.h
@@ -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
@@ -163,4 +163,23 @@
 static inline void msm_mpm_exit_sleep(bool from_idle) {}
 static inline void __init of_mpm_init(struct device_node *node) {}
 #endif
+#ifdef CONFIG_MSM_MPM_OF
+/** msm_mpm_suspend_prepare() - Called at prepare_late() op during suspend
+ *
+ *
+ *  When called the MPM driver checks if the wakeup interrupts can be monitored
+ *  by MPM hardware and program them accordingly. If wake up interrupts cannot
+ *  be monitored then it disallows system low power modes.
+ */
+void msm_mpm_suspend_prepare(void);
+/** msm_mpm_suspend_wake - Called during wake() op in suspend.
+ *
+ *  When called MPM drivers sets the vote for system low power modes depending
+ *  on the active interrupts.
+ */
+void msm_mpm_suspend_wake(void);
+#else
+static inline void msm_mpm_suspend_prepare(void){}
+static inline void msm_mpm_suspend_wake(void) {}
+#endif
 #endif /* __ARCH_ARM_MACH_MSM_MPM_H */
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
index 95f33d5..ff3da11 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.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
@@ -25,7 +25,8 @@
 
 struct msm_hdmi_audio_codec_ops {
 	int (*audio_info_setup)(struct platform_device *pdev,
-		u32 num_of_channels, u32 channel_allocation, u32 level_shift,
+		u32 sample_rate, u32 num_of_channels,
+		u32 channel_allocation, u32 level_shift,
 		bool down_mix);
 	int (*get_audio_edid_blk) (struct platform_device *pdev,
 		struct msm_hdmi_audio_edid_blk *blk);
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h b/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
index a8b9da5..1861b48 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
@@ -23,7 +23,7 @@
  *
  */
 
-#define MSMKRYPTON_SHARED_RAM_PHYS		0x00000000
+#define MSMKRYPTON_SHARED_RAM_PHYS		0x02200000
 
 #define MSMKRYPTON_TLMM_PHYS			0xFD510000
 #define MSMKRYPTON_TLMM_SIZE			SZ_16K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 7b73333..67cf442 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -115,7 +115,8 @@
 
 #if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27) \
 	|| defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM9625) \
-	|| defined(CONFIG_ARCH_MSM8610) || defined(CONFIG_ARCH_MSM8226)
+	|| defined(CONFIG_ARCH_MSM8610) || defined(CONFIG_ARCH_MSM8226) \
+	|| defined(CONFIG_ARCH_MSMKRYPTON)
 #define MSM_SHARED_RAM_SIZE	SZ_1M
 #else
 #define MSM_SHARED_RAM_SIZE	SZ_2M
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index 62fada1..2653ae4 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -46,6 +46,7 @@
 	SMD_MODEM = SMEM_MODEM,
 	SMD_Q6 = SMEM_Q6,
 	SMD_DSPS = SMEM_DSPS,
+	SMD_TZ = SMEM_DSPS,
 	SMD_WCNSS = SMEM_WCNSS,
 	SMD_MODEM_Q6_FW = SMEM_MODEM_Q6_FW,
 	SMD_RPM = SMEM_RPM,
@@ -72,6 +73,7 @@
 	SMD_MODEM_RPM,
 	SMD_QDSP_RPM,
 	SMD_WCNSS_RPM,
+	SMD_TZ_RPM,
 	SMD_NUM_TYPE,
 	SMD_LOOPBACK_TYPE = 100,
 
diff --git a/arch/arm/mach-msm/include/mach/msm_tspp.h b/arch/arm/mach-msm/include/mach/msm_tspp.h
index ddc99f3..2c40d83 100644
--- a/arch/arm/mach-msm/include/mach/msm_tspp.h
+++ b/arch/arm/mach-msm/include/mach/msm_tspp.h
@@ -25,7 +25,7 @@
 
 struct tspp_data_descriptor {
 	void *virt_base;   /* logical address of the actual data */
-	u32 phys_base;     /* physical address of the actual data */
+	phys_addr_t phys_base; /* physical address of the actual data */
 	u32 size;          /* size of buffer in bytes */
 	int id;            /* unique identifier */
 	void *user;        /* user-defined data */
@@ -33,9 +33,9 @@
 
 typedef void (tspp_notifier)(int channel_id, void *user);
 typedef void* (tspp_allocator)(int channel_id, u32 size,
-	u32 *phys_base, void *user);
+	phys_addr_t *phys_base, void *user);
 typedef void (tspp_memfree)(int channel_id, u32 size,
-	void *virt_base, u32 phys_base, void *user);
+	void *virt_base, phys_addr_t phys_base, void *user);
 
 /* Kernel API functions */
 int tspp_open_stream(u32 dev, u32 channel_id,
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 6f83c53..32d58d4 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -174,8 +174,8 @@
 	/* Request Power State */
 	unsigned power_state;
 	struct ocmem_eviction_data *edata;
-	/* Request that triggered eviction */
-	struct ocmem_req *e_handle;
+	/* Eviction data of the request being evicted */
+	struct ocmem_eviction_data *eviction_info;
 };
 
 struct ocmem_handle {
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index 3332701..6cd4a2e 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -17,6 +17,34 @@
 
 #include <linux/types.h>	/* u32 */
 
+#ifdef CONFIG_ARM_LPAE
+
+/* Returns upper 4bits of 36bits physical address */
+#define SPS_GET_UPPER_ADDR(addr) ((addr & 0xF00000000ULL) >> 32)
+
+/* Returns 36bits physical address from 32bit address &
+ * flags word */
+#define DESC_FULL_ADDR(flags, addr) (((flags & 0xF) << 32) | addr)
+
+/* Returns flags word with flags and 4bit upper address
+ * from flags and 36bit physical address */
+#define DESC_FLAG_WORD(flags, addr) (((addr & 0xF00000000ULL) >> 32) | flags)
+
+#else
+
+#define SPS_GET_UPPER_ADDR(addr) (0)
+#define DESC_FULL_ADDR(flags, addr) (addr)
+#define DESC_FLAG_WORD(flags, addr) (flags)
+
+#endif
+
+/* Returns upper 4bits of 36bits physical address from
+ * flags word */
+#define DESC_UPPER_ADDR(flags) ((flags & 0xF))
+
+/* Returns lower 32bits of 36bits physical address */
+#define SPS_GET_LOWER_ADDR(addr) ((u32)(addr & 0xFFFFFFFF))
+
 /* SPS device handle indicating use of system memory */
 #define SPS_DEV_HANDLE_MEM       ((u32)0x7ffffffful)
 
@@ -56,8 +84,8 @@
 #define SPS_IOVEC_FLAG_LOCK  0x0400  /* pipe lock */
 #define SPS_IOVEC_FLAG_UNLOCK  0x0200  /* pipe unlock */
 #define SPS_IOVEC_FLAG_IMME 0x0100  /* immediate command descriptor */
-#define SPS_IOVEC_FLAG_NO_SUBMIT 0x0002  /* Do not submit descriptor to HW */
-#define SPS_IOVEC_FLAG_DEFAULT   0x0001  /* Use driver default */
+#define SPS_IOVEC_FLAG_NO_SUBMIT 0x0020  /* Do not submit descriptor to HW */
+#define SPS_IOVEC_FLAG_DEFAULT   0x0010  /* Use driver default */
 
 /* Maximum descriptor/iovec size */
 #define SPS_IOVEC_MAX_SIZE   (32 * 1024 - 1)  /* 32K-1 bytes due to HW limit */
@@ -79,6 +107,9 @@
 #define SPS_BAM_NO_EXT_P_RST        (1UL << 4)
 /* Don't enable local clock gating */
 #define SPS_BAM_NO_LOCAL_CLK_GATING (1UL << 5)
+/* Don't enable writeback cancel*/
+#define SPS_BAM_CANCEL_WB           (1UL << 6)
+
 
 /* BAM device management flags */
 
@@ -137,6 +168,8 @@
 	SPS_O_OUT_OF_DESC = 0x00000008,/* Out of descriptors */
 	SPS_O_ERROR     = 0x00000010,  /* Error */
 	SPS_O_EOT       = 0x00000020,  /* End-of-transfer */
+	SPS_O_RST_ERROR = 0x00000040,  /* Pipe reset unsucessful error */
+	SPS_O_HRESP_ERROR = 0x00000080,/* Errorneous Hresponse by AHB MASTER */
 
 	/* Options to enable hardware features */
 	SPS_O_STREAMING = 0x00010000,  /* Enable streaming mode (no EOT) */
@@ -200,6 +233,8 @@
 	SPS_EVENT_FLOWOFF,	/* Graceful halt (idle) */
 	SPS_EVENT_INACTIVE,	/* Inactivity timeout */
 	SPS_EVENT_ERROR,	/* Error */
+	SPS_EVENT_RST_ERROR,    /* Pipe Reset unsuccessful */
+	SPS_EVENT_HRESP_ERROR,  /* Errorneous Hresponse by AHB Master*/
 	SPS_EVENT_MAX,
 };
 
@@ -429,7 +464,7 @@
  */
 struct sps_mem_buffer {
 	void *base;
-	u32 phys_base;
+	phys_addr_t phys_base;
 	u32 size;
 	u32 min_size;
 };
@@ -646,7 +681,7 @@
  *
  */
 struct sps_transfer {
-	u32 iovec_phys;
+	phys_addr_t iovec_phys;
 	struct sps_iovec *iovec;
 	u32 iovec_count;
 	void *user;
@@ -938,7 +973,7 @@
  * @return 0 on success, negative value on error
  *
  */
-int sps_transfer_one(struct sps_pipe *h, u32 addr, u32 size,
+int sps_transfer_one(struct sps_pipe *h, phys_addr_t addr, u32 size,
 		     void *user, u32 flags);
 
 /**
@@ -1335,8 +1370,8 @@
 	return -EPERM;
 }
 
-static inline int sps_transfer_one(struct sps_pipe *h, u32 addr, u32 size,
-		     void *user, u32 flags)
+static inline int sps_transfer_one(struct sps_pipe *h, phys_addr_t addr,
+					u32 size, void *user, u32 flags)
 {
 	return -EPERM;
 }
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index 962429e..c232cc9 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -15,6 +15,7 @@
 #define __SUBSYS_RESTART_H
 
 #include <linux/spinlock.h>
+#include <linux/interrupt.h>
 
 #define SUBSYS_NAME_MAX_LENGTH 40
 
@@ -57,8 +58,15 @@
 	int (*powerup)(const struct subsys_desc *desc);
 	void (*crash_shutdown)(const struct subsys_desc *desc);
 	int (*ramdump)(int, const struct subsys_desc *desc);
-	unsigned int err_ready_irq;
+	irqreturn_t (*err_fatal_handler) (int irq, void *dev_id);
+	irqreturn_t (*stop_ack_handler) (int irq, void *dev_id);
+	irqreturn_t (*wdog_bite_handler) (int irq, void *dev_id);
 	int is_not_loadable;
+	unsigned int err_fatal_irq;
+	unsigned int err_ready_irq;
+	unsigned int stop_ack_irq;
+	unsigned int wdog_bite_irq;
+	int force_stop_gpio;
 };
 
 #if defined(CONFIG_MSM_SUBSYSTEM_RESTART)
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index aba5fee..c0cca1d 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -2266,6 +2266,48 @@
 }
 
 /**
+ * msm_ipc_router_rx_data_wait() - Wait for new message destined to a local port.
+ * @port_ptr: Pointer to the local port
+ * @timeout: < 0 timeout indicates infinite wait till a message arrives.
+ *	     > 0 timeout indicates the wait time.
+ *	     0 indicates that we do not wait.
+ * @return: 0 if there are pending messages to read,
+ *	    standard Linux error code otherwise.
+ *
+ * Checks for the availability of messages that are destined to a local port.
+ * If no messages are present then waits as per @timeout.
+ */
+int msm_ipc_router_rx_data_wait(struct msm_ipc_port *port_ptr, long timeout)
+{
+	int ret = 0;
+
+	mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
+	while (list_empty(&port_ptr->port_rx_q)) {
+		mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
+		if (timeout < 0) {
+			ret = wait_event_interruptible(
+					port_ptr->port_rx_wait_q,
+					!list_empty(&port_ptr->port_rx_q));
+			if (ret)
+				return ret;
+		} else if (timeout > 0) {
+			timeout = wait_event_interruptible_timeout(
+					port_ptr->port_rx_wait_q,
+					!list_empty(&port_ptr->port_rx_q),
+					timeout);
+			if (timeout < 0)
+				return -EFAULT;
+		}
+		if (timeout == 0)
+			return -ENOMSG;
+		mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
+	}
+	mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
+
+	return ret;
+}
+
+/**
  * msm_ipc_router_recv_from() - Recieve messages destined to a local port.
  * @port_ptr: Pointer to the local port
  * @data : Pointer to the socket buffer head
@@ -2274,7 +2316,7 @@
  *	     > 0 timeout indicates the wait time.
  *	     0 indicates that we do not wait.
  * @return: = Number of bytes read(On successful read operation).
- *	    = 0 (If there are no pending messages and timeout is 0).
+ *	    = -ENOMSG (If there are no pending messages and timeout is 0).
  *	    = -EINVAL (If either of the arguments, port_ptr or data is invalid)
  *	    = -EFAULT (If there are no pending messages when timeout is > 0
  *	      and the wait_event_interruptible_timeout has returned value > 0)
@@ -2303,28 +2345,10 @@
 	}
 
 	*data = NULL;
-	mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
-	while (list_empty(&port_ptr->port_rx_q)) {
-		mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
-		if (timeout < 0) {
-			ret = wait_event_interruptible(
-					port_ptr->port_rx_wait_q,
-					!list_empty(&port_ptr->port_rx_q));
-			if (ret)
-				return ret;
-		} else if (timeout > 0) {
-			timeout = wait_event_interruptible_timeout(
-					port_ptr->port_rx_wait_q,
-					!list_empty(&port_ptr->port_rx_q),
-					timeout);
-			if (timeout < 0)
-				return -EFAULT;
-		}
-		if (timeout == 0)
-			return 0;
-		mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
-	}
-	mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
+
+	ret = msm_ipc_router_rx_data_wait(port_ptr, timeout);
+	if (ret)
+		return ret;
 
 	ret = msm_ipc_router_read(port_ptr, data, 0);
 	if (ret <= 0 || !(*data))
@@ -2358,12 +2382,10 @@
 
 	ret = msm_ipc_router_recv_from(port_ptr, &in_skb_head, src, 0);
 
-	if (ret == 0)
-		return -ENOMSG;
-
 	if (ret < 0) {
-		pr_err("%s: msm_ipc_router_recv_from failed - ret: %d\n",
-			__func__, ret);
+		if (ret != -ENOMSG)
+			pr_err("%s: msm_ipc_router_recv_from failed - ret: %d\n",
+				__func__, ret);
 		return ret;
 	}
 
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index 55aeade..7bfc52b 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -160,6 +160,8 @@
 
 void msm_ipc_sync_default_sec_rule(void *rule);
 
+int msm_ipc_router_rx_data_wait(struct msm_ipc_port *port_ptr, long timeout);
+
 #if defined CONFIG_MSM_IPC_ROUTER_SMD_XPRT
 extern void *msm_ipc_load_default_node(void);
 
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 515dc92..ea27c71 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -411,33 +411,14 @@
 
 	lock_sock(sk);
 	timeout = sk->sk_rcvtimeo;
-	mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
-	while (list_empty(&port_ptr->port_rx_q)) {
-		mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
-		release_sock(sk);
-		if (timeout < 0) {
-			ret = wait_event_interruptible(
-					port_ptr->port_rx_wait_q,
-					!list_empty(&port_ptr->port_rx_q));
-			if (ret)
-				return ret;
-		} else if (timeout > 0) {
-			timeout = wait_event_interruptible_timeout(
-					port_ptr->port_rx_wait_q,
-					!list_empty(&port_ptr->port_rx_q),
-					timeout);
-			if (timeout < 0)
-				return -EFAULT;
-		}
 
-		if (timeout == 0) {
+	ret = msm_ipc_router_rx_data_wait(port_ptr, timeout);
+	if (ret) {
+		release_sock(sk);
+		if (ret == -ENOMSG)
 			m->msg_namelen = 0;
-			return 0;
-		}
-		lock_sock(sk);
-		mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
+		return ret;
 	}
-	mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
 
 	ret = msm_ipc_router_read(port_ptr, &msg, buf_len);
 	if (ret <= 0 || !msg) {
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index b30cba4..9c5f197 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -781,13 +781,13 @@
 	return rc;
 }
 
-#define SLEW_RATE 2994
+#define SLEW_RATE 2395
 static int krait_voltage_increase(struct krait_power_vreg *from,
 							int vmax)
 {
 	struct pmic_gang_vreg *pvreg = from->pvreg;
 	int rc = 0;
-	int settling_us;
+	int settling_us = DIV_ROUND_UP(vmax - pvreg->pmic_vmax_uV, SLEW_RATE);
 
 	/*
 	 * since krait voltage is increasing set the gang voltage
@@ -800,12 +800,10 @@
 		return rc;
 	}
 
-
 	/* complete the above writes before the delay */
 	mb();
 
 	/* delay until the voltage is settled when it is raised */
-	settling_us = DIV_ROUND_UP(vmax - pvreg->pmic_vmax_uV, SLEW_RATE);
 	udelay(settling_us);
 
 	rc = configure_ldo_or_hs_all(from, vmax);
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index aa33f2c..4d7c3d4 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -16,19 +16,60 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/cpu.h>
 #include <linux/of.h>
 #include <mach/mpm.h>
-#include "lpm_resources.h"
 #include "pm.h"
 #include "rpm-notifier.h"
-
+#include "spm.h"
+#include "idle.h"
 
 enum {
 	MSM_LPM_LVL_DBG_SUSPEND_LIMITS = BIT(0),
 	MSM_LPM_LVL_DBG_IDLE_LIMITS = BIT(1),
 };
 
-#define MAX_STR_LEN 30
+enum {
+	MSM_SCM_L2_ON = 0,
+	MSM_SCM_L2_OFF = 1,
+	MSM_SCM_L2_GDHS = 3,
+};
+
+struct msm_rpmrs_level {
+	enum msm_pm_sleep_mode sleep_mode;
+	uint32_t l2_cache;
+	bool available;
+	uint32_t latency_us;
+	uint32_t steady_state_power;
+	uint32_t energy_overhead;
+	uint32_t time_overhead_us;
+};
+
+struct lpm_lookup_table {
+	uint32_t modes;
+	const char *mode_name;
+};
+
+static void msm_lpm_level_update(void);
+
+static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
+				unsigned long action, void *hcpu);
+
+static struct notifier_block __refdata msm_lpm_cpu_nblk = {
+	.notifier_call = msm_lpm_cpu_callback,
+};
+
+static uint32_t allowed_l2_mode;
+static uint32_t sysfs_dbg_l2_mode = MSM_SPM_L2_MODE_POWER_COLLAPSE;
+static uint32_t default_l2_mode;
+
+static bool no_l2_saw;
+
+static ssize_t msm_lpm_levels_attr_show(
+	struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+static ssize_t msm_lpm_levels_attr_store(struct kobject *kobj,
+	struct kobj_attribute *attr, const char *buf, size_t count);
 
 static int msm_lpm_lvl_dbg_msk;
 
@@ -39,9 +80,54 @@
 static struct msm_rpmrs_level *msm_lpm_levels;
 static int msm_lpm_level_count;
 
-static DEFINE_PER_CPU(uint32_t , msm_lpm_sleep_time);
-static DEFINE_PER_CPU(int , lpm_permitted_level);
-static DEFINE_PER_CPU(struct atomic_notifier_head, lpm_notify_head);
+static struct kobj_attribute lpm_l2_kattr = __ATTR(l2,  S_IRUGO|S_IWUSR,\
+		msm_lpm_levels_attr_show, msm_lpm_levels_attr_store);
+
+static struct attribute *lpm_levels_attr[] = {
+	&lpm_l2_kattr.attr,
+	NULL,
+};
+
+static struct attribute_group lpm_levels_attr_grp = {
+	.attrs = lpm_levels_attr,
+};
+
+/* SYSFS */
+static ssize_t msm_lpm_levels_attr_show(
+	struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	struct kernel_param kp;
+	int rc;
+
+	kp.arg = &sysfs_dbg_l2_mode;
+
+	rc = param_get_uint(buf, &kp);
+
+	if (rc > 0) {
+		strlcat(buf, "\n", PAGE_SIZE);
+		rc++;
+	}
+
+	return rc;
+}
+
+static ssize_t msm_lpm_levels_attr_store(struct kobject *kobj,
+	struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	struct kernel_param kp;
+	unsigned int temp;
+	int rc;
+
+	kp.arg = &temp;
+	rc = param_set_uint(buf, &kp);
+	if (rc)
+		return rc;
+
+	sysfs_dbg_l2_mode = temp;
+	msm_lpm_level_update();
+
+	return count;
+}
 
 static int msm_pm_get_sleep_mode_value(struct device_node *node,
 			const char *key, uint32_t *sleep_mode_val)
@@ -74,8 +160,7 @@
 	if (!ret) {
 		ret = -EINVAL;
 		for (i = 0; i < ARRAY_SIZE(pm_sm_lookup); i++) {
-			if (!strncmp(mode_name, pm_sm_lookup[i].mode_name,
-				MAX_STR_LEN)) {
+			if (!strcmp(mode_name, pm_sm_lookup[i].mode_name)) {
 				*sleep_mode_val = pm_sm_lookup[i].modes;
 				ret = 0;
 				break;
@@ -85,16 +170,61 @@
 	return ret;
 }
 
+static int msm_lpm_set_l2_mode(int sleep_mode)
+{
+	int lpm = sleep_mode;
+	int rc = 0;
+
+	if (no_l2_saw)
+		goto bail_set_l2_mode;
+
+	msm_pm_set_l2_flush_flag(MSM_SCM_L2_ON);
+
+	switch (sleep_mode) {
+	case MSM_SPM_L2_MODE_POWER_COLLAPSE:
+		msm_pm_set_l2_flush_flag(MSM_SCM_L2_OFF);
+		break;
+	case MSM_SPM_L2_MODE_GDHS:
+		msm_pm_set_l2_flush_flag(MSM_SCM_L2_GDHS);
+		break;
+	case MSM_SPM_L2_MODE_RETENTION:
+	case MSM_SPM_L2_MODE_DISABLED:
+		break;
+	default:
+		lpm = MSM_SPM_L2_MODE_DISABLED;
+		break;
+	}
+
+	rc = msm_spm_l2_set_low_power_mode(lpm, true);
+
+	if (rc) {
+		if (rc == -ENXIO)
+			WARN_ON_ONCE(1);
+		else
+			pr_err("%s: Failed to set L2 low power mode %d, ERR %d",
+			__func__, lpm, rc);
+	}
+
+bail_set_l2_mode:
+	return rc;
+}
+
 static void msm_lpm_level_update(void)
 {
-	unsigned int lpm_level;
+	int lpm_level;
 	struct msm_rpmrs_level *level = NULL;
+	uint32_t max_l2_mode;
+	static DEFINE_MUTEX(lpm_lock);
+
+	mutex_lock(&lpm_lock);
+
+	max_l2_mode = min(allowed_l2_mode, sysfs_dbg_l2_mode);
 
 	for (lpm_level = 0; lpm_level < msm_lpm_level_count; lpm_level++) {
 		level = &msm_lpm_levels[lpm_level];
-		level->available =
-			!msm_lpm_level_beyond_limit(&level->rs_limits);
+		level->available = !(level->l2_cache > max_l2_mode);
 	}
+	mutex_unlock(&lpm_lock);
 }
 
 int msm_lpm_enter_sleep(uint32_t sclk_count, void *limits,
@@ -102,13 +232,7 @@
 {
 	int ret = 0;
 	int debug_mask;
-	struct msm_rpmrs_limits *l = (struct msm_rpmrs_limits *)limits;
-	struct msm_lpm_sleep_data sleep_data;
-
-	sleep_data.limits = limits;
-	sleep_data.kernel_sleep = __get_cpu_var(msm_lpm_sleep_time);
-	atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
-		MSM_LPM_STATE_ENTER, &sleep_data);
+	uint32_t l2 = *(uint32_t *)limits;
 
 	if (from_idle)
 		debug_mask = msm_lpm_lvl_dbg_msk &
@@ -118,19 +242,20 @@
 			MSM_LPM_LVL_DBG_SUSPEND_LIMITS;
 
 	if (debug_mask)
-		pr_info("%s(): pxo:%d l2:%d mem:0x%x(0x%x) dig:0x%x(0x%x)\n",
-				__func__, l->pxo, l->l2_cache,
-				l->vdd_mem_lower_bound,
-				l->vdd_mem_upper_bound,
-				l->vdd_dig_lower_bound,
-				l->vdd_dig_upper_bound);
+		pr_info("%s(): l2:%d", __func__, l2);
 
-	ret = msm_lpmrs_enter_sleep(sclk_count, l, from_idle, notify_rpm);
+	ret = msm_lpm_set_l2_mode(l2);
+
 	if (ret) {
-		pr_warn("%s() LPM resources failed to enter sleep\n",
-				__func__);
-		goto bail;
+		if (ret == -ENXIO)
+			ret = 0;
+		else {
+			pr_warn("%s(): Failed to set L2 SPM Mode %d",
+					__func__, l2);
+			goto bail;
+		}
 	}
+
 	if (notify_rpm) {
 		ret = msm_rpm_enter_sleep(debug_mask);
 		if (ret) {
@@ -138,6 +263,8 @@
 					__func__, ret);
 			goto bail;
 		}
+
+		msm_mpm_enter_sleep(sclk_count, from_idle);
 	}
 bail:
 	return ret;
@@ -147,12 +274,12 @@
 		bool notify_rpm, bool collapsed)
 {
 
-	msm_lpmrs_exit_sleep((struct msm_rpmrs_limits *)limits,
-				from_idle, notify_rpm, collapsed);
-	if (notify_rpm)
+	msm_lpm_set_l2_mode(default_l2_mode);
+
+	if (notify_rpm) {
+		msm_mpm_exit_sleep(from_idle);
 		msm_rpm_exit_sleep();
-	atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
-			MSM_LPM_STATE_EXIT, NULL);
+	}
 }
 
 void msm_lpm_show_resources(void)
@@ -161,48 +288,6 @@
 	return;
 }
 
-uint32_t msm_pm_get_pxo(struct msm_rpmrs_limits *limits)
-{
-	return limits->pxo;
-}
-
-uint32_t msm_pm_get_l2_cache(struct msm_rpmrs_limits *limits)
-{
-	return limits->l2_cache;
-}
-
-uint32_t msm_pm_get_vdd_mem(struct msm_rpmrs_limits *limits)
-{
-	return limits->vdd_mem_upper_bound;
-}
-
-uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits)
-{
-	return limits->vdd_dig_upper_bound;
-}
-
-static bool lpm_level_permitted(int cur_level_count)
-{
-	if (__get_cpu_var(lpm_permitted_level) == msm_lpm_level_count + 1)
-		return true;
-	return (__get_cpu_var(lpm_permitted_level) == cur_level_count);
-}
-
-int msm_lpm_register_notifier(int cpu, int level_iter,
-			struct notifier_block *nb, bool is_latency_measure)
-{
-	per_cpu(lpm_permitted_level, cpu) = level_iter;
-	return atomic_notifier_chain_register(&per_cpu(lpm_notify_head,
-			cpu), nb);
-}
-
-int msm_lpm_unregister_notifier(int cpu, struct notifier_block *nb)
-{
-	per_cpu(lpm_permitted_level, cpu) = msm_lpm_level_count + 1;
-	return atomic_notifier_chain_unregister(&per_cpu(lpm_notify_head, cpu),
-				nb);
-}
-
 s32 msm_cpuidle_get_deep_idle_latency(void)
 {
 	int i;
@@ -225,17 +310,26 @@
 	}
 	return best->latency_us - 1;
 }
-static bool msm_lpm_irqs_detectable(struct msm_rpmrs_limits *limits,
-		bool irqs_detectable, bool gpio_detectable)
+
+static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
+	unsigned long action, void *hcpu)
 {
-	if (!limits->irqs_detectable)
-		return irqs_detectable;
-
-	if (!limits->gpio_detectable)
-		return gpio_detectable;
-
-	return true;
-
+	switch (action) {
+	case CPU_UP_PREPARE:
+	case CPU_UP_PREPARE_FROZEN:
+		allowed_l2_mode = default_l2_mode;
+		msm_lpm_level_update();
+		break;
+	case CPU_DEAD_FROZEN:
+	case CPU_DEAD:
+	case CPU_UP_CANCELED:
+	case CPU_UP_CANCELED_FROZEN:
+		if (num_online_cpus() == 1)
+			allowed_l2_mode = MSM_SPM_L2_MODE_POWER_COLLAPSE;
+		msm_lpm_level_update();
+		break;
+	}
+	return NOTIFY_OK;
 }
 
 static void *msm_lpm_lowest_limits(bool from_idle,
@@ -244,24 +338,15 @@
 {
 	unsigned int cpu = smp_processor_id();
 	struct msm_rpmrs_level *best_level = NULL;
+	uint32_t best_level_pwr = 0;
 	uint32_t pwr;
 	int i;
-	int best_level_iter = msm_lpm_level_count + 1;
-	bool irqs_detect = false;
-	bool gpio_detect = false;
 	bool modify_event_timer;
 	uint32_t next_wakeup_us = time_param->sleep_us;
 
 	if (!msm_lpm_levels)
 		return NULL;
 
-	msm_lpm_level_update();
-
-	if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
-		irqs_detect = msm_mpm_irqs_detectable(from_idle);
-		gpio_detect = msm_mpm_gpio_irqs_detectable(from_idle);
-	}
-
 	for (i = 0; i < msm_lpm_level_count; i++) {
 		struct msm_rpmrs_level *level = &msm_lpm_levels[i];
 
@@ -293,11 +378,6 @@
 		if (next_wakeup_us <= level->time_overhead_us)
 			continue;
 
-		if ((sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) &&
-			!msm_lpm_irqs_detectable(&level->rs_limits,
-				irqs_detect, gpio_detect))
-				continue;
-
 		if ((MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE == sleep_mode)
 			|| (MSM_PM_SLEEP_MODE_POWER_COLLAPSE == sleep_mode))
 			if (!cpu && msm_rpm_waiting_for_ack())
@@ -318,12 +398,10 @@
 			pwr += level->energy_overhead / next_wakeup_us;
 		}
 
-		if (!best_level || best_level->rs_limits.power[cpu] >= pwr) {
+		if (!best_level || (best_level_pwr >= pwr)) {
 
-			level->rs_limits.latency_us[cpu] = level->latency_us;
-			level->rs_limits.power[cpu] = pwr;
 			best_level = level;
-			best_level_iter = i;
+			best_level_pwr = pwr;
 			if (power)
 				*power = pwr;
 			if (modify_event_timer &&
@@ -336,32 +414,78 @@
 				time_param->modified_time_us = 0;
 		}
 	}
-	if (best_level && !lpm_level_permitted(best_level_iter))
-		best_level = NULL;
-	else
-		per_cpu(msm_lpm_sleep_time, cpu) =
-			time_param->modified_time_us ?
-			time_param->modified_time_us : time_param->sleep_us;
 
-	return best_level ? &best_level->rs_limits : NULL;
+	return best_level ? &best_level->l2_cache : NULL;
 }
 
-static struct lpm_test_platform_data lpm_test_pdata;
-
-static struct platform_device msm_lpm_test_device = {
-	.name		= "lpm_test",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &lpm_test_pdata,
-	},
-};
-
 static struct msm_pm_sleep_ops msm_lpm_ops = {
 	.lowest_limits = msm_lpm_lowest_limits,
 	.enter_sleep = msm_lpm_enter_sleep,
 	.exit_sleep = msm_lpm_exit_sleep,
 };
 
+static int msm_lpm_get_l2_cache_value(struct device_node *node,
+			char *key, uint32_t *l2_val)
+{
+	int i;
+	struct lpm_lookup_table l2_mode_lookup[] = {
+		{MSM_SPM_L2_MODE_POWER_COLLAPSE, "l2_cache_pc"},
+		{MSM_SPM_L2_MODE_GDHS, "l2_cache_gdhs"},
+		{MSM_SPM_L2_MODE_RETENTION, "l2_cache_retention"},
+		{MSM_SPM_L2_MODE_DISABLED, "l2_cache_active"}
+	};
+	const char *l2_str;
+	int ret;
+
+	ret = of_property_read_string(node, key, &l2_str);
+	if (!ret) {
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(l2_mode_lookup); i++) {
+			if (!strcmp(l2_str, l2_mode_lookup[i].mode_name)) {
+				*l2_val = l2_mode_lookup[i].modes;
+				ret = 0;
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
+static int __devinit msm_lpm_levels_sysfs_add(void)
+{
+	struct kobject *module_kobj = NULL;
+	struct kobject *low_power_kobj = NULL;
+	int rc = 0;
+
+	module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+	if (!module_kobj) {
+		pr_err("%s: cannot find kobject for module %s\n",
+			__func__, KBUILD_MODNAME);
+		rc = -ENOENT;
+		goto resource_sysfs_add_exit;
+	}
+
+	low_power_kobj = kobject_create_and_add(
+				"enable_low_power", module_kobj);
+	if (!low_power_kobj) {
+		pr_err("%s: cannot create kobject\n", __func__);
+		rc = -ENOMEM;
+		goto resource_sysfs_add_exit;
+	}
+
+	rc = sysfs_create_group(low_power_kobj, &lpm_levels_attr_grp);
+resource_sysfs_add_exit:
+	if (rc) {
+		if (low_power_kobj) {
+			sysfs_remove_group(low_power_kobj,
+						&lpm_levels_attr_grp);
+			kobject_del(low_power_kobj);
+		}
+	}
+
+	return rc;
+}
+
 static int __devinit msm_lpm_levels_probe(struct platform_device *pdev)
 {
 	struct msm_rpmrs_level *levels = NULL;
@@ -372,7 +496,6 @@
 	int ret = 0;
 	uint32_t num_levels = 0;
 	int idx = 0;
-	unsigned int m_cpu = 0;
 
 	for_each_child_of_node(pdev->dev.of_node, node)
 		num_levels++;
@@ -392,49 +515,11 @@
 			goto fail;
 		level->sleep_mode = val;
 
-		key = "qcom,xo";
-		ret = msm_lpm_get_xo_value(node, key, &val);
-		if (ret)
-			goto fail;
-		level->rs_limits.pxo = val;
-
 		key = "qcom,l2";
 		ret = msm_lpm_get_l2_cache_value(node, key, &val);
 		if (ret)
 			goto fail;
-		level->rs_limits.l2_cache = val;
-
-		key = "qcom,vdd-dig-upper-bound";
-		ret = of_property_read_u32(node, key, &val);
-		if (ret)
-			goto fail;
-		level->rs_limits.vdd_dig_upper_bound = val;
-
-		key = "qcom,vdd-dig-lower-bound";
-		ret = of_property_read_u32(node, key, &val);
-		if (ret)
-			goto fail;
-		level->rs_limits.vdd_dig_lower_bound = val;
-
-		key = "qcom,vdd-mem-upper-bound";
-		ret = of_property_read_u32(node, key, &val);
-		if (ret)
-			goto fail;
-		level->rs_limits.vdd_mem_upper_bound = val;
-
-		key = "qcom,vdd-mem-lower-bound";
-		ret = of_property_read_u32(node, key, &val);
-		if (ret)
-			goto fail;
-		level->rs_limits.vdd_mem_lower_bound = val;
-
-		key = "qcom,gpio-detectable";
-		level->rs_limits.gpio_detectable =
-				of_property_read_bool(node, key);
-
-		key = "qcom,irqs-detectable";
-		level->rs_limits.irqs_detectable =
-				of_property_read_bool(node, key);
+		level->l2_cache = val;
 
 		key = "qcom,latency-us";
 		ret = of_property_read_u32(node, key, &val);
@@ -463,22 +548,33 @@
 		level->available = true;
 	}
 
+	node = pdev->dev.of_node;
+	key = "qcom,no-l2-saw";
+	no_l2_saw = of_property_read_bool(node, key);
+
 	msm_lpm_levels = levels;
 	msm_lpm_level_count = idx;
 
-	lpm_test_pdata.msm_lpm_test_levels = msm_lpm_levels;
-	lpm_test_pdata.msm_lpm_test_level_count = msm_lpm_level_count;
-	key = "qcom,use-qtimer";
-	lpm_test_pdata.use_qtimer =
-			of_property_read_bool(pdev->dev.of_node, key);
+	if (num_online_cpus() == 1)
+		allowed_l2_mode = MSM_SPM_L2_MODE_POWER_COLLAPSE;
 
-	for_each_possible_cpu(m_cpu)
-		per_cpu(lpm_permitted_level, m_cpu) =
-					msm_lpm_level_count + 1;
+	/* Do the following two steps only if L2 SAW is present */
+	if (!no_l2_saw) {
+		key = "qcom,default-l2-state";
+		if (msm_lpm_get_l2_cache_value(node, key, &default_l2_mode))
+			goto fail;
 
-	platform_device_register(&msm_lpm_test_device);
+		if (msm_lpm_levels_sysfs_add())
+			goto fail;
+		register_hotcpu_notifier(&msm_lpm_cpu_nblk);
+		msm_pm_set_l2_flush_flag(0);
+	} else {
+		msm_pm_set_l2_flush_flag(1);
+		default_l2_mode = MSM_SPM_L2_MODE_POWER_COLLAPSE;
+	}
+
+	msm_lpm_level_update();
 	msm_pm_set_sleep_ops(&msm_lpm_ops);
-
 	return 0;
 fail:
 	pr_err("%s: Error in name %s key %s\n", __func__, node->full_name, key);
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
deleted file mode 100644
index 1d9c539..0000000
--- a/arch/arm/mach-msm/lpm_resources.c
+++ /dev/null
@@ -1,1009 +0,0 @@
-/* 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
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/cpu.h>
-#include <linux/notifier.h>
-#include <linux/hrtimer.h>
-#include <linux/tick.h>
-#include <mach/mpm.h>
-#include <mach/rpm-smd.h>
-#include <mach/trace_msm_low_power.h>
-#include "spm.h"
-#include "lpm_resources.h"
-#include "rpm-notifier.h"
-#include "idle.h"
-
-
-/*Debug Definitions*/
-enum {
-	MSM_LPMRS_DEBUG_RPM = BIT(0),
-	MSM_LPMRS_DEBUG_PXO = BIT(1),
-	MSM_LPMRS_DEBUG_VDD_DIG = BIT(2),
-	MSM_LPMRS_DEBUG_VDD_MEM = BIT(3),
-	MSM_LPMRS_DEBUG_L2 = BIT(4),
-	MSM_LPMRS_DEBUG_LVLS = BIT(5),
-};
-
-static int msm_lpm_debug_mask;
-module_param_named(
-	debug_mask, msm_lpm_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP
-);
-
-static bool msm_lpm_get_rpm_notif = true;
-
-/*Macros*/
-#define MAX_RS_NAME		(16)
-#define MAX_RS_SIZE		(4)
-#define IS_RPM_CTL(rs) \
-	(!strncmp(rs->name, "rpm_ctl", MAX_RS_NAME))
-#define MAX_STR_LEN		30
-
-static bool msm_lpm_beyond_limits_vdd_dig(struct msm_rpmrs_limits *limits);
-static void msm_lpm_aggregate_vdd_dig(struct msm_rpmrs_limits *limits);
-static void msm_lpm_flush_vdd_dig(int notify_rpm);
-static void msm_lpm_notify_vdd_dig(struct msm_rpm_notifier_data
-					*rpm_notifier_cb);
-static int msm_lpm_init_value_vdd_dig(struct device_node *node,
-					char *key, uint32_t *default_value);
-
-static bool msm_lpm_beyond_limits_vdd_mem(struct msm_rpmrs_limits *limits);
-static void msm_lpm_aggregate_vdd_mem(struct msm_rpmrs_limits *limits);
-static void msm_lpm_flush_vdd_mem(int notify_rpm);
-static void msm_lpm_notify_vdd_mem(struct msm_rpm_notifier_data
-					*rpm_notifier_cb);
-static int msm_lpm_init_value_vdd_mem(struct device_node *node,
-					char *key, uint32_t *default_value);
-
-
-static bool msm_lpm_beyond_limits_pxo(struct msm_rpmrs_limits *limits);
-static void msm_lpm_aggregate_pxo(struct msm_rpmrs_limits *limits);
-static void msm_lpm_flush_pxo(int notify_rpm);
-static void msm_lpm_notify_pxo(struct msm_rpm_notifier_data
-					*rpm_notifier_cb);
-static int msm_lpm_init_value_pxo(struct device_node *node,
-				char *key, uint32_t *default_value);
-
-
-static bool msm_lpm_beyond_limits_l2(struct msm_rpmrs_limits *limits);
-static void msm_lpm_flush_l2(int notify_rpm);
-static void msm_lpm_aggregate_l2(struct msm_rpmrs_limits *limits);
-static int msm_lpm_init_value_l2(struct device_node *node,
-				char *key, uint32_t *default_value);
-
-static void msm_lpm_flush_rpm_ctl(int notify_rpm);
-
-static int msm_lpm_rpm_callback(struct notifier_block *rpm_nb,
-				unsigned long action, void *rpm_notif);
-
-static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
-				unsigned long action, void *hcpu);
-
-static ssize_t msm_lpm_resource_attr_show(
-	struct kobject *kobj, struct kobj_attribute *attr, char *buf);
-static ssize_t msm_lpm_resource_attr_store(struct kobject *kobj,
-	struct kobj_attribute *attr, const char *buf, size_t count);
-
-
-#define RPMRS_ATTR(_name) \
-	__ATTR(_name, S_IRUGO|S_IWUSR, \
-		msm_lpm_resource_attr_show, msm_lpm_resource_attr_store)
-
-/*Data structures*/
-struct msm_lpm_rs_data {
-	uint32_t type;
-	uint32_t id;
-	uint32_t key;
-	uint32_t value;
-	uint32_t default_value;
-	struct msm_rpm_request *handle;
-};
-
-enum {
-	MSM_LPM_RPM_RS_TYPE = 0,
-	MSM_LPM_LOCAL_RS_TYPE = 1,
-};
-
-enum {
-	MSM_SCM_L2_ON = 0,
-	MSM_SCM_L2_OFF = 1,
-	MSM_SCM_L2_GDHS = 3,
-};
-
-struct msm_lpm_resource {
-	struct msm_lpm_rs_data rs_data;
-	uint32_t sleep_value;
-	char name[MAX_RS_NAME];
-
-	uint32_t  enable_low_power;
-	bool valid;
-
-	bool (*beyond_limits)(struct msm_rpmrs_limits *limits);
-	void (*aggregate)(struct msm_rpmrs_limits *limits);
-	void (*flush)(int notify_rpm);
-	void (*notify)(struct msm_rpm_notifier_data *rpm_notifier_cb);
-	struct kobj_attribute ko_attr;
-	int (*init_value)(struct device_node *node,
-			char *key, uint32_t *default_value);
-};
-
-struct lpm_lookup_table {
-	uint32_t modes;
-	const char *mode_name;
-};
-
-static struct msm_lpm_resource msm_lpm_l2 = {
-	.name = "l2",
-	.beyond_limits = msm_lpm_beyond_limits_l2,
-	.aggregate = msm_lpm_aggregate_l2,
-	.flush = msm_lpm_flush_l2,
-	.notify = NULL,
-	.valid = false,
-	.ko_attr = RPMRS_ATTR(l2),
-	.init_value = msm_lpm_init_value_l2,
-};
-
-static struct msm_lpm_resource msm_lpm_vdd_dig = {
-	.name = "vdd-dig",
-	.beyond_limits = msm_lpm_beyond_limits_vdd_dig,
-	.aggregate = msm_lpm_aggregate_vdd_dig,
-	.flush = msm_lpm_flush_vdd_dig,
-	.notify = msm_lpm_notify_vdd_dig,
-	.valid = false,
-	.ko_attr = RPMRS_ATTR(vdd_dig),
-	.init_value = msm_lpm_init_value_vdd_dig,
-};
-
-static struct msm_lpm_resource msm_lpm_vdd_mem = {
-	.name = "vdd-mem",
-	.beyond_limits = msm_lpm_beyond_limits_vdd_mem,
-	.aggregate = msm_lpm_aggregate_vdd_mem,
-	.flush = msm_lpm_flush_vdd_mem,
-	.notify = msm_lpm_notify_vdd_mem,
-	.valid = false,
-	.ko_attr = RPMRS_ATTR(vdd_mem),
-	.init_value = msm_lpm_init_value_vdd_mem,
-};
-
-static struct msm_lpm_resource msm_lpm_pxo = {
-	.name = "pxo",
-	.beyond_limits = msm_lpm_beyond_limits_pxo,
-	.aggregate = msm_lpm_aggregate_pxo,
-	.flush = msm_lpm_flush_pxo,
-	.notify = msm_lpm_notify_pxo,
-	.valid = false,
-	.ko_attr = RPMRS_ATTR(pxo),
-	.init_value = msm_lpm_init_value_pxo,
-};
-
-static struct msm_lpm_resource *msm_lpm_resources[] = {
-	&msm_lpm_vdd_dig,
-	&msm_lpm_vdd_mem,
-	&msm_lpm_pxo,
-	&msm_lpm_l2,
-};
-
-static struct msm_lpm_resource msm_lpm_rpm_ctl = {
-	.name = "rpm_ctl",
-	.beyond_limits = NULL,
-	.aggregate = NULL,
-	.flush = msm_lpm_flush_rpm_ctl,
-	.valid = true,
-	.ko_attr = RPMRS_ATTR(rpm_ctl),
-};
-
-static struct notifier_block msm_lpm_rpm_nblk = {
-	.notifier_call = msm_lpm_rpm_callback,
-};
-
-static struct notifier_block __refdata msm_lpm_cpu_nblk = {
-	.notifier_call = msm_lpm_cpu_callback,
-};
-
-static DEFINE_SPINLOCK(msm_lpm_sysfs_lock);
-
-/* Attribute Definitions */
-static struct attribute *msm_lpm_attributes[] = {
-	&msm_lpm_vdd_dig.ko_attr.attr,
-	&msm_lpm_vdd_mem.ko_attr.attr,
-	&msm_lpm_pxo.ko_attr.attr,
-	&msm_lpm_l2.ko_attr.attr,
-	NULL,
-};
-
-static struct attribute_group msm_lpm_attribute_group = {
-	.attrs = msm_lpm_attributes,
-};
-
-static struct attribute *msm_lpm_rpm_ctl_attribute[] = {
-	&msm_lpm_rpm_ctl.ko_attr.attr,
-	NULL,
-};
-
-static struct attribute_group msm_lpm_rpm_ctl_attr_group = {
-	.attrs = msm_lpm_rpm_ctl_attribute,
-};
-
-#define GET_RS_FROM_ATTR(attr) \
-	(container_of(attr, struct msm_lpm_resource, ko_attr))
-
-/* RPM */
-static struct msm_rpm_request *msm_lpm_create_rpm_request
-				(uint32_t rsc_type, uint32_t rsc_id)
-{
-	struct msm_rpm_request *handle = NULL;
-
-	handle = msm_rpm_create_request(MSM_RPM_CTX_SLEEP_SET,
-						rsc_type,
-						rsc_id, 1);
-	return handle;
-}
-
-static int msm_lpm_send_sleep_data(struct msm_rpm_request *handle,
-					uint32_t key, uint8_t *value)
-{
-	int ret = 0;
-	int msg_id;
-
-	if (!handle)
-		return ret;
-
-	ret = msm_rpm_add_kvp_data_noirq(handle, key, value, MAX_RS_SIZE);
-
-	if (ret < 0) {
-		pr_err("%s: Error adding kvp data key %u, size %d\n",
-				__func__, key, MAX_RS_SIZE);
-		return ret;
-	}
-
-	msg_id = msm_rpm_send_request_noirq(handle);
-	if (!msg_id) {
-		pr_err("%s: Error sending RPM request key %u, handle 0x%x\n",
-				__func__, key, (unsigned int)handle);
-		ret = -EIO;
-		return ret;
-	}
-
-	ret = msm_rpm_wait_for_ack_noirq(msg_id);
-	if (ret < 0) {
-		pr_err("%s: Couldn't get ACK from RPM for Msg %d Error %d",
-				__func__, msg_id, ret);
-		return ret;
-	}
-	if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_RPM)
-		pr_info("Rs key %u, value %u, size %d\n", key,
-				*(unsigned int *)value, MAX_RS_SIZE);
-	return ret;
-}
-
-/* RPM Notifier */
-static int msm_lpm_rpm_callback(struct notifier_block *rpm_nb,
-					unsigned long action,
-					void *rpm_notif)
-{
-	int i;
-	struct msm_lpm_resource *rs = NULL;
-	struct msm_rpm_notifier_data *rpm_notifier_cb =
-			(struct msm_rpm_notifier_data *)rpm_notif;
-
-	if (!msm_lpm_get_rpm_notif)
-		return NOTIFY_DONE;
-
-	if (!(rpm_nb && rpm_notif))
-		return NOTIFY_BAD;
-
-	for (i = 0; i < ARRAY_SIZE(msm_lpm_resources); i++) {
-		rs = msm_lpm_resources[i];
-		if (rs && rs->valid && rs->notify)
-			rs->notify(rpm_notifier_cb);
-	}
-
-	return NOTIFY_OK;
-}
-
-/* SYSFS */
-static ssize_t msm_lpm_resource_attr_show(
-	struct kobject *kobj, struct kobj_attribute *attr, char *buf)
-{
-	struct kernel_param kp;
-	unsigned long flags;
-	unsigned int temp;
-	int rc;
-
-	spin_lock_irqsave(&msm_lpm_sysfs_lock, flags);
-	temp = GET_RS_FROM_ATTR(attr)->enable_low_power;
-	spin_unlock_irqrestore(&msm_lpm_sysfs_lock, flags);
-
-	kp.arg = &temp;
-	rc = param_get_uint(buf, &kp);
-
-	if (rc > 0) {
-		strlcat(buf, "\n", PAGE_SIZE);
-		rc++;
-	}
-
-	return rc;
-}
-
-static ssize_t msm_lpm_resource_attr_store(struct kobject *kobj,
-	struct kobj_attribute *attr, const char *buf, size_t count)
-{
-	struct kernel_param kp;
-	unsigned long flags;
-	unsigned int temp;
-	int rc;
-
-	kp.arg = &temp;
-	rc = param_set_uint(buf, &kp);
-	if (rc)
-		return rc;
-
-	spin_lock_irqsave(&msm_lpm_sysfs_lock, flags);
-	GET_RS_FROM_ATTR(attr)->enable_low_power = temp;
-
-	if (IS_RPM_CTL(GET_RS_FROM_ATTR(attr))) {
-		struct msm_lpm_resource *rs = GET_RS_FROM_ATTR(attr);
-		rs->flush(false);
-	}
-
-	spin_unlock_irqrestore(&msm_lpm_sysfs_lock, flags);
-
-	return count;
-}
-
-/* lpm resource handling functions */
-/* Common */
-static void msm_lpm_notify_common(struct msm_rpm_notifier_data *cb,
-				struct msm_lpm_resource *rs)
-{
-	if ((cb->rsc_type == rs->rs_data.type) &&
-		(cb->rsc_id == rs->rs_data.id) &&
-		(cb->key == rs->rs_data.key)) {
-
-		BUG_ON(cb->size > MAX_RS_SIZE);
-
-		if (rs->valid) {
-			if (cb->value) {
-				memcpy(&rs->rs_data.value, cb->value, cb->size);
-				msm_rpm_add_kvp_data_noirq(rs->rs_data.handle,
-						cb->key, cb->value, cb->size);
-			}
-			else
-				rs->rs_data.value = rs->rs_data.default_value;
-
-			if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_RPM)
-				pr_info("Notification received Rs %s value %u\n",
-						rs->name, rs->rs_data.value);
-		}
-	}
-}
-
-/* L2 */
-static bool msm_lpm_beyond_limits_l2(struct msm_rpmrs_limits *limits)
-{
-	uint32_t l2;
-	bool ret = false;
-	struct msm_lpm_resource *rs = &msm_lpm_l2;
-
-	if (rs->valid) {
-		uint32_t l2_buf = rs->rs_data.value;
-
-		if (rs->enable_low_power == 1)
-			l2 = MSM_LPM_L2_CACHE_GDHS;
-		else if (rs->enable_low_power == 2)
-			l2 = MSM_LPM_L2_CACHE_HSFS_OPEN;
-		else
-			l2 = MSM_LPM_L2_CACHE_ACTIVE ;
-
-		if (l2_buf > l2)
-			l2 = l2_buf;
-		ret = (l2 > limits->l2_cache);
-
-		if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_L2)
-			pr_info("%s: l2 buf %u, l2 %u, limits %u\n",
-				__func__, l2_buf, l2, limits->l2_cache);
-	}
-	return ret;
-}
-
-static void msm_lpm_aggregate_l2(struct msm_rpmrs_limits *limits)
-{
-	struct msm_lpm_resource *rs = &msm_lpm_l2;
-
-	if (rs->valid)
-		rs->sleep_value = limits->l2_cache;
-	trace_lpm_resources(rs->sleep_value, rs->name);
-}
-
-static void msm_lpm_set_l2_mode(int sleep_mode)
-{
-	int lpm, rc;
-
-	msm_pm_set_l2_flush_flag(MSM_SCM_L2_ON);
-
-	switch (sleep_mode) {
-	case MSM_LPM_L2_CACHE_HSFS_OPEN:
-		lpm = MSM_SPM_L2_MODE_POWER_COLLAPSE;
-		msm_pm_set_l2_flush_flag(MSM_SCM_L2_OFF);
-		break;
-	case MSM_LPM_L2_CACHE_GDHS:
-		lpm = MSM_SPM_L2_MODE_GDHS;
-		msm_pm_set_l2_flush_flag(MSM_SCM_L2_GDHS);
-		break;
-	case MSM_LPM_L2_CACHE_RETENTION:
-		lpm = MSM_SPM_L2_MODE_RETENTION;
-		break;
-	default:
-	case MSM_LPM_L2_CACHE_ACTIVE:
-		lpm = MSM_SPM_L2_MODE_DISABLED;
-		break;
-	}
-
-	rc = msm_spm_l2_set_low_power_mode(lpm, true);
-
-	if (rc < 0)
-		pr_err("%s: Failed to set L2 low power mode %d",
-			__func__, lpm);
-
-	if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_L2)
-		pr_info("%s: Requesting low power mode %d\n",
-				__func__, lpm);
-}
-
-static int msm_lpm_init_value_l2(struct device_node *node,
-					char *key, uint32_t *default_value)
-{
-	return msm_lpm_get_l2_cache_value(node, key, default_value);
-}
-
-static void msm_lpm_flush_l2(int notify_rpm)
-{
-	struct msm_lpm_resource *rs = &msm_lpm_l2;
-
-	msm_lpm_set_l2_mode(rs->sleep_value);
-}
-
-int msm_lpm_get_l2_cache_value(struct device_node *node,
-			char *key, uint32_t *l2_val)
-{
-	int i;
-	struct lpm_lookup_table l2_mode_lookup[] = {
-		{MSM_LPM_L2_CACHE_HSFS_OPEN, "l2_cache_pc"},
-		{MSM_LPM_L2_CACHE_GDHS, "l2_cache_gdhs"},
-		{MSM_LPM_L2_CACHE_RETENTION, "l2_cache_retention"},
-		{MSM_LPM_L2_CACHE_ACTIVE, "l2_cache_active"}
-	};
-	const char *l2_str;
-	int ret;
-
-	ret = of_property_read_string(node, key, &l2_str);
-	if (!ret) {
-		ret = -EINVAL;
-		for (i = 0; i < ARRAY_SIZE(l2_mode_lookup); i++) {
-			if (!strncmp(l2_str, l2_mode_lookup[i].mode_name,
-				MAX_STR_LEN)) {
-				*l2_val = l2_mode_lookup[i].modes;
-				ret = 0;
-				break;
-			}
-		}
-	}
-	return ret;
-}
-
-/* RPM CTL */
-static void msm_lpm_flush_rpm_ctl(int notify_rpm)
-{
-	struct msm_lpm_resource *rs = &msm_lpm_rpm_ctl;
-	msm_lpm_send_sleep_data(rs->rs_data.handle,
-				rs->rs_data.key,
-				(uint8_t *)&rs->sleep_value);
-}
-
-/*VDD Dig*/
-static bool msm_lpm_beyond_limits_vdd_dig(struct msm_rpmrs_limits *limits)
-{
-	bool ret = true;
-	struct msm_lpm_resource *rs = &msm_lpm_vdd_dig;
-
-	if (rs->valid) {
-		uint32_t vdd_buf = rs->rs_data.value;
-		uint32_t vdd_dig = rs->enable_low_power ? rs->enable_low_power :
-					rs->rs_data.default_value;
-
-		if (vdd_buf > vdd_dig)
-			vdd_dig = vdd_buf;
-
-		ret = (vdd_dig > limits->vdd_dig_upper_bound);
-
-		if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_VDD_DIG)
-			pr_info("%s:buf %d vdd dig %d limits%d\n",
-				__func__, vdd_buf, vdd_dig,
-				limits->vdd_dig_upper_bound);
-	}
-	return ret;
-}
-
-static int msm_lpm_init_value_vdd_dig(struct device_node *node,
-					char *key, uint32_t *default_value)
-{
-	return of_property_read_u32(node, key, default_value);
-}
-
-static void msm_lpm_aggregate_vdd_dig(struct msm_rpmrs_limits *limits)
-{
-	struct msm_lpm_resource *rs = &msm_lpm_vdd_dig;
-
-	if (rs->valid) {
-		uint32_t vdd_buf = rs->rs_data.value;
-		if (limits->vdd_dig_lower_bound > vdd_buf)
-			rs->sleep_value = limits->vdd_dig_lower_bound;
-		else
-			rs->sleep_value = vdd_buf;
-	}
-	trace_lpm_resources(rs->sleep_value, rs->name);
-}
-
-static void msm_lpm_flush_vdd_dig(int notify_rpm)
-{
-	if (notify_rpm) {
-		struct msm_lpm_resource *rs = &msm_lpm_vdd_dig;
-		msm_lpm_send_sleep_data(rs->rs_data.handle,
-					rs->rs_data.key,
-					(uint8_t *)&rs->sleep_value);
-	}
-}
-
-static void msm_lpm_notify_vdd_dig(struct msm_rpm_notifier_data
-					*rpm_notifier_cb)
-{
-	struct msm_lpm_resource *rs = &msm_lpm_vdd_dig;
-	msm_lpm_notify_common(rpm_notifier_cb, rs);
-}
-
-/*VDD Mem*/
-static bool msm_lpm_beyond_limits_vdd_mem(struct msm_rpmrs_limits *limits)
-{
-	bool ret = true;
-	struct msm_lpm_resource *rs = &msm_lpm_vdd_mem;
-
-	if (rs->valid) {
-		uint32_t vdd_buf = rs->rs_data.value;
-		uint32_t vdd_mem = rs->enable_low_power ? rs->enable_low_power :
-					rs->rs_data.default_value;
-
-		if (vdd_buf > vdd_mem)
-			vdd_mem = vdd_buf;
-
-		ret = (vdd_mem > limits->vdd_mem_upper_bound);
-
-		if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_VDD_MEM)
-			pr_info("%s:buf %d vdd mem %d limits%d\n",
-				__func__, vdd_buf, vdd_mem,
-				limits->vdd_mem_upper_bound);
-	}
-	return ret;
-}
-
-static void msm_lpm_aggregate_vdd_mem(struct msm_rpmrs_limits *limits)
-{
-	struct msm_lpm_resource *rs = &msm_lpm_vdd_mem;
-
-	if (rs->valid) {
-		uint32_t vdd_buf = rs->rs_data.value;
-		if (limits->vdd_mem_lower_bound > vdd_buf)
-			rs->sleep_value = limits->vdd_mem_lower_bound;
-		else
-			rs->sleep_value = vdd_buf;
-	}
-	trace_lpm_resources(rs->sleep_value, rs->name);
-}
-
-static void msm_lpm_flush_vdd_mem(int notify_rpm)
-{
-	if (notify_rpm) {
-		struct msm_lpm_resource *rs = &msm_lpm_vdd_mem;
-		msm_lpm_send_sleep_data(rs->rs_data.handle,
-					rs->rs_data.key,
-					(uint8_t *)&rs->sleep_value);
-	}
-}
-
-static void msm_lpm_notify_vdd_mem(struct msm_rpm_notifier_data
-					*rpm_notifier_cb)
-{
-	struct msm_lpm_resource *rs = &msm_lpm_vdd_mem;
-	msm_lpm_notify_common(rpm_notifier_cb, rs);
-}
-
-static int msm_lpm_init_value_vdd_mem(struct device_node *node,
-					char *key, uint32_t *default_value)
-{
-	return of_property_read_u32(node, key, default_value);
-}
-
-/*PXO*/
-static bool msm_lpm_beyond_limits_pxo(struct msm_rpmrs_limits *limits)
-{
-	bool ret = true;
-	struct msm_lpm_resource *rs = &msm_lpm_pxo;
-
-	if (rs->valid) {
-		uint32_t pxo_buf = rs->rs_data.value;
-		uint32_t pxo = rs->enable_low_power ? MSM_LPM_PXO_OFF :
-					rs->rs_data.default_value;
-
-		if (pxo_buf > pxo)
-			pxo = pxo_buf;
-
-		ret = (pxo > limits->pxo);
-
-		if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_PXO)
-			pr_info("%s:pxo buf %d pxo %d limits pxo %d\n",
-					__func__, pxo_buf, pxo, limits->pxo);
-	}
-	return ret;
-}
-
-static void msm_lpm_aggregate_pxo(struct msm_rpmrs_limits *limits)
-{
-	struct msm_lpm_resource *rs = &msm_lpm_pxo;
-
-	if (rs->valid) {
-		uint32_t pxo_buf = rs->rs_data.value;
-		if (limits->pxo > pxo_buf)
-			rs->sleep_value = limits->pxo;
-		else
-			rs->sleep_value = pxo_buf;
-
-		if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_PXO)
-			pr_info("%s: pxo buf %d sleep value %d\n",
-					__func__, pxo_buf, rs->sleep_value);
-	}
-	trace_lpm_resources(rs->sleep_value, rs->name);
-}
-
-static void msm_lpm_flush_pxo(int notify_rpm)
-{
-	if (notify_rpm) {
-		struct msm_lpm_resource *rs = &msm_lpm_pxo;
-		msm_lpm_send_sleep_data(rs->rs_data.handle,
-					rs->rs_data.key,
-					(uint8_t *)&rs->sleep_value);
-	}
-}
-
-static void msm_lpm_notify_pxo(struct msm_rpm_notifier_data
-					*rpm_notifier_cb)
-{
-	struct msm_lpm_resource *rs = &msm_lpm_pxo;
-	msm_lpm_notify_common(rpm_notifier_cb, rs);
-}
-
-static int msm_lpm_init_value_pxo(struct device_node *node,
-				char *key, uint32_t *default_value)
-{
-	return msm_lpm_get_xo_value(node, key, default_value);
-}
-
-static inline bool msm_lpm_use_mpm(struct msm_rpmrs_limits *limits)
-{
-	return (limits->pxo == MSM_LPM_PXO_OFF);
-}
-
-int msm_lpm_get_xo_value(struct device_node *node,
-			char *key, uint32_t *xo_val)
-{
-	int  i;
-	struct lpm_lookup_table pxo_mode_lookup[] = {
-		{MSM_LPM_PXO_OFF, "xo_off"},
-		{MSM_LPM_PXO_ON, "xo_on"}
-	};
-	const char *xo_str;
-	int ret;
-
-	ret = of_property_read_string(node, key, &xo_str);
-	if (!ret) {
-		ret = -EINVAL;
-		for (i = 0; i < ARRAY_SIZE(pxo_mode_lookup); i++) {
-			if (!strncmp(xo_str, pxo_mode_lookup[i].mode_name,
-				MAX_STR_LEN)) {
-				*xo_val = pxo_mode_lookup[i].modes;
-				ret = 0;
-				break;
-			}
-		}
-	}
-	return ret;
-}
-
-/* LPM levels interface */
-bool msm_lpm_level_beyond_limit(struct msm_rpmrs_limits *limits)
-{
-	int i;
-	struct msm_lpm_resource *rs;
-	bool beyond_limit = false;
-
-	for (i = 0; i < ARRAY_SIZE(msm_lpm_resources); i++) {
-		rs = msm_lpm_resources[i];
-		if (rs->beyond_limits && rs->beyond_limits(limits)) {
-			beyond_limit = true;
-			if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_LVLS)
-				pr_info("%s: %s beyond limit", __func__,
-						rs->name);
-			break;
-		}
-	}
-
-	return beyond_limit;
-}
-
-int msm_lpmrs_enter_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
-				bool from_idle, bool notify_rpm)
-{
-	int ret = 0;
-	int i;
-	struct msm_lpm_resource *rs = NULL;
-
-	for (i = 0; i < ARRAY_SIZE(msm_lpm_resources); i++) {
-		rs = msm_lpm_resources[i];
-		if (rs->aggregate)
-			rs->aggregate(limits);
-	}
-
-	msm_lpm_get_rpm_notif = false;
-	for (i = 0; i < ARRAY_SIZE(msm_lpm_resources); i++) {
-		rs = msm_lpm_resources[i];
-		if (rs->valid && rs->flush)
-			rs->flush(notify_rpm);
-	}
-	msm_lpm_get_rpm_notif = true;
-
-	if (notify_rpm)
-		msm_mpm_enter_sleep(sclk_count, from_idle);
-
-	return ret;
-}
-
-void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
-		bool from_idle, bool notify_rpm, bool collapsed)
-{
-	if (msm_lpm_use_mpm(limits))
-		msm_mpm_exit_sleep(from_idle);
-
-	if (msm_lpm_l2.valid)
-		msm_lpm_set_l2_mode(msm_lpm_l2.rs_data.default_value);
-}
-
-static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
-		unsigned long action, void *hcpu)
-{
-	struct msm_lpm_resource *rs = &msm_lpm_l2;
-	switch (action) {
-	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
-		rs->rs_data.value = rs->rs_data.default_value;
-		break;
-	case CPU_ONLINE_FROZEN:
-	case CPU_ONLINE:
-		if (num_online_cpus() > 1)
-			rs->rs_data.value = rs->rs_data.default_value;
-		break;
-	case CPU_DEAD_FROZEN:
-	case CPU_DEAD:
-		if (num_online_cpus() == 1)
-			rs->rs_data.value = MSM_LPM_L2_CACHE_HSFS_OPEN;
-		break;
-	}
-	return NOTIFY_OK;
-}
-
-/* RPM CTL */
-static int __devinit msm_lpm_init_rpm_ctl(void)
-{
-	struct msm_lpm_resource *rs = &msm_lpm_rpm_ctl;
-
-	rs->rs_data.handle = msm_rpm_create_request(
-				MSM_RPM_CTX_ACTIVE_SET,
-				rs->rs_data.type,
-				rs->rs_data.id, 1);
-	if (!rs->rs_data.handle)
-		return -EIO;
-
-	rs->valid = true;
-	return 0;
-}
-
-static int __devinit msm_lpm_resource_sysfs_add(void)
-{
-	struct kobject *module_kobj = NULL;
-	struct kobject *low_power_kobj = NULL;
-	struct kobject *mode_kobj = NULL;
-	int rc = 0;
-
-	module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
-	if (!module_kobj) {
-		pr_err("%s: cannot find kobject for module %s\n",
-			__func__, KBUILD_MODNAME);
-		rc = -ENOENT;
-		goto resource_sysfs_add_exit;
-	}
-
-	low_power_kobj = kobject_create_and_add(
-				"enable_low_power", module_kobj);
-	if (!low_power_kobj) {
-		pr_err("%s: cannot create kobject\n", __func__);
-		rc = -ENOMEM;
-		goto resource_sysfs_add_exit;
-	}
-
-	mode_kobj = kobject_create_and_add(
-				"mode", module_kobj);
-	if (!mode_kobj) {
-		pr_err("%s: cannot create kobject\n", __func__);
-		rc = -ENOMEM;
-		goto resource_sysfs_add_exit;
-	}
-
-	rc = sysfs_create_group(low_power_kobj, &msm_lpm_attribute_group);
-	if (rc) {
-		pr_err("%s: cannot create kobject attribute group\n", __func__);
-		goto resource_sysfs_add_exit;
-	}
-
-	rc = sysfs_create_group(mode_kobj, &msm_lpm_rpm_ctl_attr_group);
-	if (rc) {
-		pr_err("%s: cannot create kobject attribute group\n", __func__);
-		goto resource_sysfs_add_exit;
-	}
-
-resource_sysfs_add_exit:
-	if (rc) {
-		if (low_power_kobj)
-			sysfs_remove_group(low_power_kobj,
-					&msm_lpm_attribute_group);
-		kobject_del(low_power_kobj);
-		kobject_del(mode_kobj);
-	}
-
-	return rc;
-}
-
-late_initcall(msm_lpm_resource_sysfs_add);
-
-static int __devinit msm_lpmrs_probe(struct platform_device *pdev)
-{
-	struct device_node *node = NULL;
-	char *key = NULL;
-	int ret = 0;
-
-	for_each_child_of_node(pdev->dev.of_node, node) {
-		struct msm_lpm_resource *rs = NULL;
-		const char *val;
-		int i;
-		bool local_resource;
-
-		key = "qcom,name";
-		ret = of_property_read_string(node, key, &val);
-		if (ret) {
-			pr_err("Cannot read string\n");
-			goto fail;
-		}
-
-		for (i = 0; i < ARRAY_SIZE(msm_lpm_resources); i++) {
-			char *lpmrs_name = msm_lpm_resources[i]->name;
-			if (!msm_lpm_resources[i]->valid &&
-				!strncmp(val, lpmrs_name, strnlen(lpmrs_name,
-							MAX_RS_NAME))) {
-				rs = msm_lpm_resources[i];
-				break;
-			}
-		}
-
-		if (!rs) {
-			pr_err("LPM resource not found\n");
-			continue;
-		}
-
-		key = "qcom,init-value";
-		ret = rs->init_value(node, key, &rs->rs_data.default_value);
-		if (ret) {
-			pr_err("%s():Failed to read %s\n", __func__, key);
-			goto fail;
-		}
-
-		rs->rs_data.value = rs->rs_data.default_value;
-
-		key = "qcom,local-resource-type";
-		local_resource = of_property_read_bool(node, key);
-
-		if (!local_resource) {
-			key = "qcom,type";
-			ret = of_property_read_u32(node, key,
-					&rs->rs_data.type);
-			if (ret) {
-				pr_err("Failed to read type\n");
-				goto fail;
-			}
-
-			key = "qcom,id";
-			ret = of_property_read_u32(node, key, &rs->rs_data.id);
-			if (ret) {
-				pr_err("Failed to read id\n");
-				goto fail;
-			}
-
-			key = "qcom,key";
-			ret = of_property_read_u32(node, key, &rs->rs_data.key);
-			if (ret) {
-				pr_err("Failed to read key\n");
-				goto fail;
-			}
-
-			rs->rs_data.handle = msm_lpm_create_rpm_request(
-						rs->rs_data.type,
-						rs->rs_data.id);
-
-			if (!rs->rs_data.handle) {
-				pr_err("%s: Failed to allocate handle for %s\n",
-						__func__, rs->name);
-				ret = -1;
-				goto fail;
-			}
-			/* fall through */
-		}
-
-		rs->valid = true;
-	}
-	msm_rpm_register_notifier(&msm_lpm_rpm_nblk);
-	msm_lpm_init_rpm_ctl();
-
-	if (msm_lpm_l2.valid) {
-		register_hotcpu_notifier(&msm_lpm_cpu_nblk);
-		/* For UP mode, set the default to HSFS OPEN*/
-		if (num_possible_cpus() == 1) {
-			msm_lpm_l2.rs_data.default_value =
-					MSM_LPM_L2_CACHE_HSFS_OPEN;
-			msm_lpm_l2.rs_data.value = MSM_LPM_L2_CACHE_HSFS_OPEN;
-		}
-		msm_pm_set_l2_flush_flag(0);
-	} else
-		msm_pm_set_l2_flush_flag(1);
-
-fail:
-	return ret;
-}
-
-static struct of_device_id msm_lpmrs_match_table[] = {
-	{.compatible = "qcom,lpm-resources"},
-	{},
-};
-
-static struct platform_driver msm_lpmrs_driver = {
-	.probe = msm_lpmrs_probe,
-	.driver = {
-		.name = "lpm-resources",
-		.owner = THIS_MODULE,
-		.of_match_table = msm_lpmrs_match_table,
-	},
-};
-
-int __init msm_lpmrs_module_init(void)
-{
-	return platform_driver_register(&msm_lpmrs_driver);
-}
diff --git a/arch/arm/mach-msm/lpm_resources.h b/arch/arm/mach-msm/lpm_resources.h
deleted file mode 100644
index 105cfe6..0000000
--- a/arch/arm/mach-msm/lpm_resources.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/* 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
- * 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.
- */
-
-#ifndef __ARCH_ARM_MACH_MSM_LPM_RESOURCES_H
-#define __ARCH_ARM_MACH_MSM_LPM_RESOURCES_H
-
-#include "pm.h"
-#include "test-lpm.h"
-
-enum {
-	MSM_LPM_PXO_OFF,
-	MSM_LPM_PXO_ON
-};
-
-enum {
-	MSM_LPM_L2_CACHE_HSFS_OPEN,
-	MSM_LPM_L2_CACHE_GDHS,
-	MSM_LPM_L2_CACHE_RETENTION,
-	MSM_LPM_L2_CACHE_ACTIVE,
-};
-
-struct msm_rpmrs_limits {
-	uint32_t pxo;
-	uint32_t l2_cache;
-	uint32_t vdd_mem_upper_bound;
-	uint32_t vdd_mem_lower_bound;
-	uint32_t vdd_dig_upper_bound;
-	uint32_t vdd_dig_lower_bound;
-	bool irqs_detectable;
-	bool gpio_detectable;
-
-	uint32_t latency_us[NR_CPUS];
-	uint32_t power[NR_CPUS];
-};
-
-struct msm_rpmrs_level {
-	enum msm_pm_sleep_mode sleep_mode;
-	struct msm_rpmrs_limits rs_limits;
-	bool available;
-	uint32_t latency_us;
-	uint32_t steady_state_power;
-	uint32_t energy_overhead;
-	uint32_t time_overhead_us;
-};
-
-enum {
-	MSM_LPM_STATE_ENTER = 0,
-	MSM_LPM_STATE_EXIT = 1,
-};
-
-#define MSM_PM(field) MSM_LPM_##field
-
-/**
- * msm_pm_get_pxo() -  get the limits for pxo
- * @limits:            pointer to the msm_rpmrs_limits structure
- *
- * This function gets the limits to the resource pxo on
- * 8974
- */
-
-uint32_t msm_pm_get_pxo(struct msm_rpmrs_limits *limits);
-
-/**
- * msm_pm_get_l2_cache() -  get the limits for l2 cache
- * @limits:            pointer to the msm_rpmrs_limits structure
- *
- * This function gets the limits to the resource l2 cache
- * on 8974
- */
-
-uint32_t msm_pm_get_l2_cache(struct msm_rpmrs_limits *limits);
-
-/**
- * msm_pm_get_vdd_mem() -  get the limits for pxo
- * @limits:            pointer to the msm_rpmrs_limits structure
- *
- * This function gets the limits to the resource vdd mem
- * on 8974
- */
-
-uint32_t msm_pm_get_vdd_mem(struct msm_rpmrs_limits *limits);
-
-/**
- * msm_pm_get_vdd_dig() -  get the limits for vdd dig
- * @limits:            pointer to the msm_rpmrs_limits structure
- *
- * This function gets the limits to the resource on 8974
- */
-
-uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits);
-
-/**
- * msm_lpm_get_xo_value() - get the enum value for xo
- * @node		pointer to the device node
- * @key			pxo property key
- * @xo_val		xo enum value
- */
-int msm_lpm_get_xo_value(struct device_node *node,
-			char *key, uint32_t *xo_val);
-
-/**
- * msm_lpm_get_l2_cache_value() - get the enum value for l2 cache
- * @node                pointer to the device node
- * @key                 l2 cache property key
- * @l2_val              l2 mode enum value
- */
-int msm_lpm_get_l2_cache_value(struct device_node *node,
-				char *key, uint32_t *l2_val);
-
-/**
- * struct msm_lpm_sleep_data - abstraction to get sleep data
- * @limits:	pointer to the msm_rpmrs_limits structure
- * @kernel_sleep:	kernel sleep time as decided by the power calculation
- *			algorithm
- *
- * This structure is an abstraction to get the limits and kernel sleep time
- * during enter sleep.
- */
-
-struct msm_lpm_sleep_data {
-	struct msm_rpmrs_limits *limits;
-	uint32_t kernel_sleep;
-};
-
-/**
- * msm_lpm_register_notifier() - register for notifications
- * @cpu:               cpu to debug
- * @level_iter:        low power level index to debug
- * @nb:       notifier block to callback on notifications
- * @is_latency_measure: is it latency measure
- *
- * This function sets the permitted level to the index of the
- * level under test and registers notifier for callback.
- */
-
-int msm_lpm_register_notifier(int cpu, int level_iter,
-		struct notifier_block *nb, bool is_latency_measure);
-
-/**
- * msm_lpm_unregister_notifier() - unregister from notifications
- * @cpu:               cpu to debug
- * @nb:       notifier block to callback on notifications
- *
- * This function sets the permitted level to a value one more than
- * available levels count which indicates that all levels are
- * permitted and it also unregisters notifier for callback.
- */
-
-int msm_lpm_unregister_notifier(int cpu, struct notifier_block *nb);
-
-#ifdef CONFIG_MSM_RPM_SMD
-
-/**
- * msm_lpm_level_beyond_limit() - Check if the resources in a low power level
- * is beyond the limits of the driver votes received for those resources.This
- * function is used by lpm_levels to eliminate any low power level that cannot
- * be entered.
- *
- * @limits: pointer to the resource limits of a low power level.
- *
- * returns true if the resource limits are beyond driver resource votes.
- * false otherwise.
- */
-bool msm_lpm_level_beyond_limit(struct msm_rpmrs_limits *limits);
-
-/**
- * msm_lpmrs_enter_sleep() - Enter sleep flushes the sleep votes of low power
- * resources to the RPM driver, also configure the MPM if needed depending
- * on the low power mode being entered. L2 low power mode is also set in
- * this function.
-
- * @sclk_count: wakeup counter for RPM.
- * @limits: pointer to the resource limits of the low power mode being entered.
- * @from_idle: bool to determine if this call being made as a part of
- *             idle power collapse.
- * @notify_rpm: bool that informs if this is an RPM notified power collapse.
- *
- * returns 0 on success.
- */
-int msm_lpmrs_enter_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
-	bool from_idle, bool notify_rpm);
-
-/**
- * msm_lpmrs_exit_sleep() - Exit sleep, reset the MPM and L2 mode.
- * @ limits: pointer to resource limits of the most recent low power mode.
- * @from_idle: bool to determine if this call being made as a part of
- *             idle power collapse.
- * @notify_rpm: bool that informs if this is an RPM notified power collapse.
- * @collapsed: bool that informs if the Krait was power collapsed.
- */
-void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
-	bool from_idle, bool notify_rpm, bool collapsed);
-/**
- * msm_lpmrs_module_init() - Init function that parses the device tree to
- * get the low power resource attributes and registers with RPM driver for
- * callback notification.
- *
- * returns 0 on success.
- */
-int __init msm_lpmrs_module_init(void);
-
-#else
-static inline bool msm_lpm_level_beyond_limit(struct msm_rpmrs_limits *limits)
-{
-	return true;
-}
-
-static inline int msm_lpmrs_enter_sleep(uint32_t sclk_count,
-	struct msm_rpmrs_limits *limits, bool from_idle, bool notify_rpm)
-{
-	return 0;
-}
-
-static inline void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
-	bool from_idle, bool notify_rpm, bool collapsed)
-{
-	return;
-}
-
-static inline int __init msm_lpmrs_module_init(void)
-{
-	return 0;
-}
-#endif /* CONFIG_MSM_RPM_SMD */
-
-#endif
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 2ce4fa0..a974018 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -308,6 +308,8 @@
 	unsigned long memory_reserve_prop_length;
 	unsigned int memory_size;
 	unsigned int memory_start;
+	unsigned int num_holes = 0;
+	int i;
 	int ret;
 
 	memory_name_prop = of_get_flat_dt_prop(node,
@@ -358,21 +360,27 @@
 mem_remove:
 
 	if (memory_remove_prop) {
-		if (memory_remove_prop_length != (2*sizeof(unsigned int))) {
+		if (!memory_remove_prop_length || (memory_remove_prop_length %
+				(2 * sizeof(unsigned int)) != 0)) {
 			WARN(1, "Memory remove malformed\n");
 			goto mem_reserve;
 		}
 
-		memory_start = be32_to_cpu(memory_remove_prop[0]);
-		memory_size = be32_to_cpu(memory_remove_prop[1]);
+		num_holes = memory_remove_prop_length /
+					(2 * sizeof(unsigned int));
 
-		ret = memblock_remove(memory_start, memory_size);
-		if (ret)
-			WARN(1, "Failed to remove memory %x-%x\n",
+		for (i = 0; i < (num_holes * 2); i += 2) {
+			memory_start = be32_to_cpu(memory_remove_prop[i]);
+			memory_size = be32_to_cpu(memory_remove_prop[i+1]);
+
+			ret = memblock_remove(memory_start, memory_size);
+			if (ret)
+				WARN(1, "Failed to remove memory %x-%x\n",
 				memory_start, memory_start+memory_size);
-		else
-			pr_info("Node %s removed memory %x-%x\n", uname,
+			else
+				pr_info("Node %s removed memory %x-%x\n", uname,
 				memory_start, memory_start+memory_size);
+		}
 	}
 
 mem_reserve:
@@ -428,6 +436,8 @@
 	unsigned long memory_remove_prop_length;
 	unsigned long hole_start;
 	unsigned long hole_size;
+	unsigned int num_holes = 0;
+	int i = 0;
 
 	memory_remove_prop = of_get_flat_dt_prop(node,
 						"qcom,memblock-remove",
@@ -441,15 +451,21 @@
 	}
 
 	if (memory_remove_prop) {
-		if (memory_remove_prop_length != (2*sizeof(unsigned int))) {
+		if (!memory_remove_prop_length || (memory_remove_prop_length %
+			(2 * sizeof(unsigned int)) != 0)) {
 			WARN(1, "Memory remove malformed\n");
 			goto out;
 		}
 
-		hole_start = be32_to_cpu(memory_remove_prop[0]);
-		hole_size = be32_to_cpu(memory_remove_prop[1]);
+		num_holes = memory_remove_prop_length /
+					(2 * sizeof(unsigned int));
 
-		adjust_meminfo(hole_start, hole_size);
+		for (i = 0; i < (num_holes * 2); i += 2) {
+			hole_start = be32_to_cpu(memory_remove_prop[i]);
+			hole_size = be32_to_cpu(memory_remove_prop[i+1]);
+
+			adjust_meminfo(hole_start, hole_size);
+		}
 	}
 
 out:
diff --git a/arch/arm/mach-msm/mpm-of.c b/arch/arm/mach-msm/mpm-of.c
index 5c654b0..a0746f9 100644
--- a/arch/arm/mach-msm/mpm-of.c
+++ b/arch/arm/mach-msm/mpm-of.c
@@ -27,10 +27,17 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/regulator/consumer.h>
+#include <linux/workqueue.h>
 #include <asm/hardware/gic.h>
 #include <asm/arch_timer.h>
 #include <mach/gpio.h>
 #include <mach/mpm.h>
+#include <mach/clk.h>
+#include <mach/rpm-regulator-smd.h>
 
 enum {
 	MSM_MPM_GIC_IRQ_DOMAIN,
@@ -75,6 +82,12 @@
 #define ARCH_TIMER_HZ (19200000)
 static struct msm_mpm_device_data msm_mpm_dev_data;
 
+static struct clk *xo_clk;
+static bool xo_enabled;
+static struct workqueue_struct *msm_mpm_wq;
+static struct work_struct msm_mpm_work;
+static struct completion wake_wq;
+
 enum mpm_reg_offsets {
 	MSM_MPM_REG_WAKEUP,
 	MSM_MPM_REG_ENABLE,
@@ -257,6 +270,8 @@
 		else
 			__clear_bit(d->hwirq, irq_apps);
 
+		if (!wakeset && (msm_mpm_initialized & MSM_MPM_DEVICE_PROBED))
+			complete(&wake_wq);
 	}
 
 	return 0;
@@ -543,6 +558,54 @@
 		}
 	}
 }
+static void msm_mpm_sys_low_power_modes(bool allow)
+{
+	if (allow) {
+		if (xo_enabled) {
+			clk_disable_unprepare(xo_clk);
+			xo_enabled = false;
+		}
+	} else {
+		if (!xo_enabled) {
+			/* If we cannot enable XO clock then we want to flag it,
+			 * than having to deal with not being able to wakeup
+			 * from a non-monitorable interrupt
+			 */
+			BUG_ON(clk_prepare_enable(xo_clk));
+			xo_enabled = true;
+		}
+	}
+}
+
+void msm_mpm_suspend_prepare(void)
+{
+	bool allow = msm_mpm_irqs_detectable(false) &&
+		msm_mpm_gpio_irqs_detectable(false);
+	msm_mpm_sys_low_power_modes(allow);
+}
+EXPORT_SYMBOL(msm_mpm_suspend_prepare);
+
+void msm_mpm_suspend_wake(void)
+{
+	bool allow = msm_mpm_irqs_detectable(true) &&
+		msm_mpm_gpio_irqs_detectable(true);
+	msm_mpm_sys_low_power_modes(allow);
+}
+EXPORT_SYMBOL(msm_mpm_suspend_wake);
+
+static void msm_mpm_work_fn(struct work_struct *work)
+{
+	unsigned long flags;
+	while (1) {
+		bool allow;
+		wait_for_completion(&wake_wq);
+		spin_lock_irqsave(&msm_mpm_lock, flags);
+		allow = msm_mpm_irqs_detectable(true) &&
+				msm_mpm_gpio_irqs_detectable(true);
+		spin_unlock_irqrestore(&msm_mpm_lock, flags);
+		msm_mpm_sys_low_power_modes(allow);
+	}
+}
 
 static int __devinit msm_mpm_dev_probe(struct platform_device *pdev)
 {
@@ -555,73 +618,89 @@
 		return 0;
 	}
 
+	xo_clk = devm_clk_get(&pdev->dev, "xo");
+
+	if (IS_ERR(xo_clk)) {
+		pr_err("%s(): Cannot get clk resource for XO\n", __func__);
+		return PTR_ERR(xo_clk);
+	}
+
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vmpm");
 	if (!res) {
 		pr_err("%s(): Missing RPM memory resource\n", __func__);
-		goto fail;
+		return -EINVAL;
 	}
 
 	dev->mpm_request_reg_base = devm_request_and_ioremap(&pdev->dev, res);
 
 	if (!dev->mpm_request_reg_base) {
 		pr_err("%s(): Unable to iomap\n", __func__);
-		goto fail;
+		return -EADDRNOTAVAIL;
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ipc");
 	if (!res) {
 		pr_err("%s(): Missing GCC memory resource\n", __func__);
-		goto failed_irq_get;
+		return -EINVAL;
 	}
 
 	dev->mpm_apps_ipc_reg = devm_ioremap(&pdev->dev, res->start,
 					resource_size(res));
+	if (!dev->mpm_apps_ipc_reg) {
+		pr_err("%s(): Unable to iomap IPC register\n", __func__);
+		return -EADDRNOTAVAIL;
+	}
 
 	if (of_property_read_u32(pdev->dev.of_node,
 				"qcom,ipc-bit-offset", &offset)) {
 		pr_info("%s(): Cannot read ipc bit offset\n", __func__);
-		goto failed_free_irq;
+		return -EINVAL ;
 	}
 
 	dev->mpm_apps_ipc_val = (1 << offset);
 
-	if (!dev->mpm_apps_ipc_reg)
-		goto failed_irq_get;
-
 	dev->mpm_ipc_irq = platform_get_irq(pdev, 0);
 
 	if (dev->mpm_ipc_irq == -ENXIO) {
 		pr_info("%s(): Cannot find IRQ resource\n", __func__);
-		goto failed_irq_get;
+		return -ENXIO;
 	}
-	ret = request_irq(dev->mpm_ipc_irq, msm_mpm_irq,
+	ret = devm_request_irq(&pdev->dev, dev->mpm_ipc_irq, msm_mpm_irq,
 			IRQF_TRIGGER_RISING, pdev->name, msm_mpm_irq);
 
 	if (ret) {
 		pr_info("%s(): request_irq failed errno: %d\n", __func__, ret);
-		goto failed_irq_get;
+		return ret;
 	}
 	ret = irq_set_irq_wake(dev->mpm_ipc_irq, 1);
 
 	if (ret) {
 		pr_err("%s: failed to set wakeup irq %u: %d\n",
 			__func__, dev->mpm_ipc_irq, ret);
-		goto failed_irq_get;
+		return ret;
 
 	}
+
+	init_completion(&wake_wq);
+
+	INIT_WORK(&msm_mpm_work, msm_mpm_work_fn);
+	msm_mpm_wq = create_singlethread_workqueue("mpm");
+
+	if (msm_mpm_wq)
+		queue_work(msm_mpm_wq, &msm_mpm_work);
+	else  {
+		pr_warn("%s(): Failed to create wq. So voting against XO off",
+				__func__);
+		/* Throw a BUG. Otherwise, its possible that system allows
+		 * XO shutdown when there are non-monitored interrupts are
+		 * pending and cause errors at a later point in time.
+		 */
+		BUG_ON(clk_prepare_enable(xo_clk));
+		xo_enabled = true;
+	}
+
 	msm_mpm_initialized |= MSM_MPM_DEVICE_PROBED;
-
 	return 0;
-
-failed_free_irq:
-	free_irq(dev->mpm_ipc_irq, msm_mpm_irq);
-failed_irq_get:
-	if (dev->mpm_apps_ipc_reg)
-		devm_iounmap(&pdev->dev, dev->mpm_apps_ipc_reg);
-	if (dev->mpm_request_reg_base)
-		devm_iounmap(&pdev->dev, dev->mpm_request_reg_base);
-fail:
-	return -EINVAL;
 }
 
 static inline int __init mpm_irq_domain_linear_size(struct irq_domain *d)
diff --git a/arch/arm/mach-msm/msm_watchdog_v2.c b/arch/arm/mach-msm/msm_watchdog_v2.c
index 4778d5b..52e94e6 100644
--- a/arch/arm/mach-msm/msm_watchdog_v2.c
+++ b/arch/arm/mach-msm/msm_watchdog_v2.c
@@ -340,6 +340,11 @@
 	mb();
 	/* Delay to make sure bite occurs */
 	mdelay(1);
+	pr_err("Wdog - STS: 0x%x, CTL: 0x%x, BARK TIME: 0x%x, BITE TIME: 0x%x",
+		__raw_readl(wdog_dd->base + WDT0_STS),
+		__raw_readl(wdog_dd->base + WDT0_EN),
+		__raw_readl(wdog_dd->base + WDT0_BARK_TIME),
+		__raw_readl(wdog_dd->base + WDT0_BITE_TIME));
 	panic("Failed to cause a watchdog bite! - Falling back to kernel panic!");
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index a3fd6b2..cbf7933 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -1192,19 +1192,23 @@
 }
 
 /* Remove the request from eviction lists */
-static void cancel_restore(struct ocmem_req *e_handle,
-				struct ocmem_req *req)
+static void cancel_restore(struct ocmem_req *req)
 {
-	struct ocmem_eviction_data *edata = e_handle->edata;
+	struct ocmem_eviction_data *edata;
 
-	if (!edata || !req)
+	if (!req)
+		return;
+
+	edata = req->eviction_info;
+
+	if (!edata)
 		return;
 
 	if (list_empty(&edata->req_list))
 		return;
 
 	list_del_init(&req->eviction_list);
-	req->e_handle = NULL;
+	req->eviction_info = NULL;
 
 	return;
 }
@@ -1499,8 +1503,8 @@
 	}
 
 	/* Remove the request from any restore lists */
-	if (req->e_handle)
-		cancel_restore(req->e_handle, req);
+	if (req->eviction_info)
+		cancel_restore(req);
 
 	/* Remove the request from any pending opreations */
 	if (TEST_STATE(req, R_ENQUEUED)) {
@@ -1747,12 +1751,7 @@
 		goto shrink_fail;
 	}
 
-	if (!req->e_handle) {
-		pr_err("Unable to find evicting request\n");
-		goto shrink_fail;
-	}
-
-	edata = req->e_handle->edata;
+	edata = req->eviction_info;
 
 	if (!edata) {
 		pr_err("Unable to find eviction data\n");
@@ -1905,7 +1904,7 @@
 						&e_req->eviction_list,
 						&edata->req_list);
 					atomic_inc(&edata->pending);
-					e_req->e_handle = req;
+					e_req->eviction_info = edata;
 				}
 			}
 		} else {
@@ -2037,7 +2036,7 @@
 		pr_debug("ocmem: restoring evicted request %p\n",
 							req);
 		req->edata = NULL;
-		req->e_handle = NULL;
+		req->eviction_info = NULL;
 		req->op = SCHED_ALLOCATE;
 		inc_ocmem_stat(zone_of(req), NR_RESTORES);
 		sched_enqueue(req);
@@ -2076,8 +2075,11 @@
 	struct ocmem_eviction_data *edata = evictions[id];
 	int rc = 0;
 
-	if (!edata)
+	if (!edata) {
+		pr_err("Client %s invoked restore without any eviction\n",
+					get_name(id));
 		return -EINVAL;
+	}
 
 	mutex_lock(&free_mutex);
 	rc = __restore_common(edata);
diff --git a/arch/arm/mach-msm/pcie.c b/arch/arm/mach-msm/pcie.c
index c09b759..7695b2d 100644
--- a/arch/arm/mach-msm/pcie.c
+++ b/arch/arm/mach-msm/pcie.c
@@ -484,22 +484,19 @@
 static void msm_pcie_adjust_tlp_size(struct msm_pcie_dev_t *dev)
 {
 	/*
-	 * Apply this fix only for device such as APQ8064 version 1.
 	 * Set the Max TLP size to 2K, instead of using default of 4K
 	 * to avoid a RAM problem in PCIE20 core of that version.
 	 */
-	if (readl_relaxed(dev->elbi + PCIE20_ELBI_VERSION) == 0x01002107) {
 
-		/*
-		 * CFG_REMOTE_RD_REQ_BRIDGE_SIZE:
-		 *   5=4KB/4=2KB/3=1KB/2=512B/1=256B/0=128B
-		 */
-		writel_relaxed(4, dev->pcie20 +
-					 PCIE20_PLR_AXI_MSTR_RESP_COMP_CTRL0);
+	/*
+	 * CFG_REMOTE_RD_REQ_BRIDGE_SIZE:
+	 *   5=4KB/4=2KB/3=1KB/2=512B/1=256B/0=128B
+	 */
+	writel_relaxed(4, dev->pcie20 +
+				 PCIE20_PLR_AXI_MSTR_RESP_COMP_CTRL0);
 
-		writel_relaxed(1, dev->pcie20 +
-					 PCIE20_PLR_AXI_MSTR_RESP_COMP_CTRL1);
-	}
+	writel_relaxed(1, dev->pcie20 +
+				 PCIE20_PLR_AXI_MSTR_RESP_COMP_CTRL1);
 };
 
 static int __init msm_pcie_setup(int nr, struct pci_sys_data *sys)
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 643d945..28d8e42 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -33,6 +33,8 @@
 	"8  Perf: Add cortex A7 perf support\n"
 	"9  ARM: dts: msm: add perf-events support for msm8226\n"
 	"10 Perf: Fix counts across power collapse\n"
+	"11 ARM: dts: msm: add perf-events support for msm8x10, msm8x12\n"
+	"12 Perf: Make per-process counters configurable\n"
 ;
 
 static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/perf_trace_counters.c b/arch/arm/mach-msm/perf_trace_counters.c
index d961994..65b0d28 100644
--- a/arch/arm/mach-msm/perf_trace_counters.c
+++ b/arch/arm/mach-msm/perf_trace_counters.c
@@ -10,9 +10,13 @@
  * GNU General Public License for more details.
  */
 #include <asm/thread_notify.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
 #define CREATE_TRACE_POINTS
 #include "perf_trace_counters.h"
 
+static unsigned int tp_pid_state;
+
 static int tracectr_notifier(struct notifier_block *self, unsigned long cmd,
 		void *v)
 {
@@ -34,9 +38,80 @@
 	.notifier_call  = tracectr_notifier,
 };
 
+static void enable_tp_pid(void)
+{
+	if (tp_pid_state == 0) {
+		tp_pid_state = 1;
+		thread_register_notifier(&tracectr_notifier_block);
+	}
+}
+
+static void disable_tp_pid(void)
+{
+	if (tp_pid_state == 1) {
+		tp_pid_state = 0;
+		thread_unregister_notifier(&tracectr_notifier_block);
+	}
+}
+
+static ssize_t read_enabled_perftp_file_bool(struct file *file,
+		char __user *user_buf, size_t count, loff_t *ppos)
+{
+	char buf[2];
+	buf[1] = '\n';
+	if (tp_pid_state == 0)
+		buf[0] = '0';
+	else
+		buf[0] = '1';
+	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t write_enabled_perftp_file_bool(struct file *file,
+		const char __user *user_buf, size_t count, loff_t *ppos)
+{
+	char buf[32];
+	size_t buf_size;
+
+	buf_size = min(count, (sizeof(buf)-1));
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	switch (buf[0]) {
+	case 'y':
+	case 'Y':
+	case '1':
+		enable_tp_pid();
+		break;
+	case 'n':
+	case 'N':
+	case '0':
+		disable_tp_pid();
+		break;
+	}
+
+	return count;
+}
+
+static const struct file_operations fops_perftp = {
+	.read =		read_enabled_perftp_file_bool,
+	.write =	write_enabled_perftp_file_bool,
+	.llseek =	default_llseek,
+};
+
 int __init init_tracecounters(void)
 {
-	thread_register_notifier(&tracectr_notifier_block);
+	struct dentry *dir;
+	struct dentry *file;
+	unsigned int value = 1;
+
+	dir = debugfs_create_dir("perf_debug_tp", NULL);
+	if (!dir)
+		return -ENOMEM;
+	file = debugfs_create_file("enabled", 0777, dir,
+		&value, &fops_perftp);
+	if (!file) {
+		debugfs_remove(dir);
+		return -ENOMEM;
+	}
 	return 0;
 }
 late_initcall(init_tracecounters);
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index ff1fd4f..4adbdc0 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -30,6 +30,7 @@
 #include <linux/list_sort.h>
 #include <linux/idr.h>
 #include <linux/interrupt.h>
+#include <linux/of_gpio.h>
 
 #include <asm/uaccess.h>
 #include <asm/setup.h>
@@ -251,6 +252,7 @@
 	struct pil_desc *desc = dev_id;
 	struct pil_priv *priv = desc->priv;
 
+	pil_info(desc, "Power/Clock ready interrupt received\n");
 	if (!desc->priv->unvoted_flag) {
 		desc->priv->unvoted_flag = 1;
 		__pil_proxy_unvote(priv);
@@ -586,6 +588,34 @@
 	return ret;
 }
 
+static void pil_parse_devicetree(struct pil_desc *desc)
+{
+	int clk_ready = 0;
+
+	if (of_find_property(desc->dev->of_node,
+				"qcom,gpio-proxy-unvote",
+				NULL)) {
+		clk_ready = of_get_named_gpio(desc->dev->of_node,
+				"qcom,gpio-proxy-unvote", 0);
+
+		if (clk_ready < 0) {
+			dev_err(desc->dev,
+				"[%s]: Error getting proxy unvoting gpio\n",
+				desc->name);
+			return;
+		}
+
+		clk_ready = gpio_to_irq(clk_ready);
+		if (clk_ready < 0) {
+			dev_err(desc->dev,
+				"[%s]: Error getting proxy unvote IRQ\n",
+				desc->name);
+			return;
+		}
+	}
+	desc->proxy_unvote_irq = clk_ready;
+}
+
 /* Synchronize request_firmware() with suspend */
 static DECLARE_RWSEM(pil_pm_rwsem);
 
@@ -741,12 +771,6 @@
 	void __iomem *addr;
 	char buf[sizeof(priv->info->name)];
 
-	/* Ignore users who don't make any sense */
-	WARN(desc->ops->proxy_unvote && desc->proxy_unvote_irq == 0
-		 && !desc->proxy_timeout,
-		 "Invalid proxy unvote callback or a proxy timeout of 0"
-		 " was specified or no proxy unvote IRQ was specified.\n");
-
 	if (WARN(desc->ops->proxy_unvote && !desc->ops->proxy_vote,
 				"Invalid proxy voting. Ignoring\n"))
 		((struct pil_reset_ops *)desc->ops)->proxy_unvote = NULL;
@@ -767,7 +791,15 @@
 	strncpy(buf, desc->name, sizeof(buf));
 	__iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4);
 
-	if (desc->proxy_unvote_irq > 0) {
+	pil_parse_devicetree(desc);
+
+	/* Ignore users who don't make any sense */
+	WARN(desc->ops->proxy_unvote && desc->proxy_unvote_irq == 0
+		 && !desc->proxy_timeout,
+		 "Invalid proxy unvote callback or a proxy timeout of 0"
+		 " was specified or no proxy unvote IRQ was specified.\n");
+
+	if (desc->proxy_unvote_irq > 0 && desc->ops->proxy_unvote) {
 		ret = request_threaded_irq(desc->proxy_unvote_irq,
 				  NULL,
 				  proxy_unvote_intr_handler,
diff --git a/arch/arm/mach-msm/pil-dsps.c b/arch/arm/mach-msm/pil-dsps.c
index 73b58ab..f0a5ebf 100644
--- a/arch/arm/mach-msm/pil-dsps.c
+++ b/arch/arm/mach-msm/pil-dsps.c
@@ -23,6 +23,7 @@
 #include <mach/msm_smsm.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -317,6 +318,8 @@
 		goto err_subsys;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = smsm_state_cb_register(SMSM_DSPS_STATE, SMSM_RESET,
 				     dsps_smsm_state_cb, drv);
 	if (ret)
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 840c90f..b209a25 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -571,6 +571,8 @@
 		goto err_smem;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = devm_request_irq(&pdev->dev, drv->irq, gss_wdog_bite_irq,
 			IRQF_TRIGGER_RISING, "gss_a5_wdog", drv);
 	if (ret < 0)
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index 8398206..f6a853e 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -25,6 +25,7 @@
 #include <mach/subsystem_restart.h>
 #include <mach/msm_smsm.h>
 #include <mach/ramdump.h>
+#include <mach/msm_bus_board.h>
 
 #include "modem_notifier.h"
 #include "peripheral-loader.h"
@@ -490,6 +491,8 @@
 		goto err_ramdump;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = devm_request_irq(&pdev->dev, drv->irq, modem_wdog_bite_irq,
 			IRQF_TRIGGER_RISING, "modem_watchdog", drv);
 	if (ret)
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 80c0862..620ab5c 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -31,6 +31,7 @@
 #include <mach/msm_smsm.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -83,9 +84,6 @@
 	bool restart_inprogress;
 	bool crash;
 	struct delayed_work cancel_vote_work;
-	int irq;
-	unsigned int err_fatal_irq;
-	int force_stop_gpio;
 	struct ramdump_device *ramdump_dev;
 };
 
@@ -308,7 +306,7 @@
 
 static irqreturn_t wcnss_err_fatal_intr_handler(int irq, void *dev_id)
 {
-	struct pronto_data *drv = dev_id;
+	struct pronto_data *drv = subsys_to_drv(dev_id);
 
 	pr_err("Fatal error on the wcnss.\n");
 
@@ -326,11 +324,11 @@
 
 static irqreturn_t wcnss_wdog_bite_irq_hdlr(int irq, void *dev_id)
 {
-	struct pronto_data *drv = dev_id;
+	struct pronto_data *drv = subsys_to_drv(dev_id);
 
 	drv->crash = true;
 
-	disable_irq_nosync(drv->irq);
+	disable_irq_nosync(drv->subsys_desc.wdog_bite_irq);
 
 	if (drv->restart_inprogress) {
 		pr_err("Ignoring wcnss bite irq, restart in progress\n");
@@ -380,7 +378,7 @@
 			return ret;
 	}
 	drv->restart_inprogress = false;
-	enable_irq(drv->irq);
+	enable_irq(drv->subsys_desc.wdog_bite_irq);
 	schedule_delayed_work(&drv->cancel_vote_work, msecs_to_jiffies(5000));
 
 	return 0;
@@ -392,7 +390,7 @@
 
 	pr_err("wcnss crash shutdown %d\n", drv->crash);
 	if (!drv->crash)
-		gpio_set_value(drv->force_stop_gpio, 1);
+		gpio_set_value(subsys->force_stop_gpio, 1);
 }
 
 static int wcnss_ramdump(int enable, const struct subsys_desc *subsys)
@@ -410,27 +408,14 @@
 	struct pronto_data *drv;
 	struct resource *res;
 	struct pil_desc *desc;
-	int ret, err_fatal_gpio, irq;
+	int ret;
 	uint32_t regval;
 
-	int clk_ready = of_get_named_gpio(pdev->dev.of_node,
-			"qcom,gpio-proxy-unvote", 0);
-	if (clk_ready < 0)
-		return clk_ready;
-
-	clk_ready = gpio_to_irq(clk_ready);
-	if (clk_ready < 0)
-		return clk_ready;
-
 	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
 	if (!drv)
 		return -ENOMEM;
 	platform_set_drvdata(pdev, drv);
 
-	drv->irq = platform_get_irq(pdev, 0);
-	if (drv->irq < 0)
-		return drv->irq;
-
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pmu_base");
 	drv->base = devm_request_and_ioremap(&pdev->dev, res);
 	if (!drv->base)
@@ -452,27 +437,9 @@
 	if (ret)
 		return ret;
 
-	err_fatal_gpio = of_get_named_gpio(pdev->dev.of_node,
-			"qcom,gpio-err-fatal", 0);
-	if (err_fatal_gpio < 0)
-		return err_fatal_gpio;
-
-	irq = gpio_to_irq(err_fatal_gpio);
-	if (irq < 0)
-		return irq;
-
-	drv->err_fatal_irq = irq;
-
-	drv->force_stop_gpio = of_get_named_gpio(pdev->dev.of_node,
-			"qcom,gpio-force-stop", 0);
-	if (drv->force_stop_gpio < 0)
-		return drv->force_stop_gpio;
-
-
 	desc->dev = &pdev->dev;
 	desc->owner = THIS_MODULE;
 	desc->proxy_timeout = 10000;
-	desc->proxy_unvote_irq = clk_ready;
 
 	if (pas_supported(PAS_WCNSS) > 0) {
 		desc->ops = &pil_pronto_ops_trusted;
@@ -504,6 +471,8 @@
 	if (IS_ERR(drv->cxo))
 		return PTR_ERR(drv->cxo);
 
+	scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
 	ret = pil_desc_init(desc);
 	if (ret)
 		return ret;
@@ -517,17 +486,8 @@
 	drv->subsys_desc.crash_shutdown = crash_shutdown;
 	drv->subsys_desc.start = pronto_start;
 	drv->subsys_desc.stop = pronto_stop;
-
-	ret = of_get_named_gpio(pdev->dev.of_node,
-			"qcom,gpio-err-ready", 0);
-	if (ret < 0)
-		return ret;
-
-	ret = gpio_to_irq(ret);
-	if (ret < 0)
-		return ret;
-
-	drv->subsys_desc.err_ready_irq = ret;
+	drv->subsys_desc.err_fatal_handler = wcnss_err_fatal_intr_handler;
+	drv->subsys_desc.wdog_bite_handler = wcnss_wdog_bite_irq_hdlr;
 
 	INIT_DELAYED_WORK(&drv->cancel_vote_work, wcnss_post_bootup);
 
@@ -537,19 +497,6 @@
 		goto err_subsys;
 	}
 
-	ret = devm_request_irq(&pdev->dev, drv->irq, wcnss_wdog_bite_irq_hdlr,
-			IRQF_TRIGGER_HIGH, "wcnss_wdog", drv);
-	if (ret < 0)
-		goto err_irq;
-
-	ret = devm_request_irq(&pdev->dev, drv->err_fatal_irq,
-			wcnss_err_fatal_intr_handler,
-			IRQF_TRIGGER_RISING, "pil-pronto", drv);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to register SMP2P err fatal handler!\n");
-		goto err_irq;
-	}
-
 	drv->ramdump_dev = create_ramdump_device("pronto", &pdev->dev);
 	if (!drv->ramdump_dev) {
 		ret = -ENOMEM;
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index a369878..58d4301 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -24,6 +24,7 @@
 #include <mach/subsystem_restart.h>
 #include <mach/scm.h>
 #include <mach/ramdump.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -393,6 +394,8 @@
 		goto err_subsys;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = devm_request_irq(&pdev->dev, drv->irq, lpass_wdog_bite_irq,
 			       IRQF_TRIGGER_RISING, "lpass_wdog", drv);
 	if (ret) {
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
index 7acb599..6ec8430 100644
--- a/arch/arm/mach-msm/pil-q6v4-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.c
@@ -26,6 +26,7 @@
 #include <mach/subsystem_notif.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "smd_private.h"
 #include "sysmon.h"
@@ -356,6 +357,8 @@
 		goto err_notif_riva;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	drv->modem_notif_hdle = subsys_notif_register_notifier("modem", &mnb);
 	if (IS_ERR(drv->modem_notif_hdle)) {
 		ret = PTR_ERR(drv->modem_notif_hdle);
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index c4b6038..6ee5965 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -24,6 +24,7 @@
 #include <mach/msm_smsm.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "smd_private.h"
 #include "peripheral-loader.h"
@@ -462,6 +463,8 @@
 	if (ret)
 		goto err_irq;
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
 			smsm_state_cb, drv);
 	if (ret)
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 6cd6ffe..a9a6942 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -30,6 +30,7 @@
 #include <mach/scm.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "pil-q6v5.h"
@@ -47,13 +48,10 @@
 	struct subsys_device *subsys;
 	struct subsys_desc subsys_desc;
 	void *ramdump_dev;
-	int wdog_irq;
 	struct work_struct work;
 	void *wcnss_notif_hdle;
 	void *modem_notif_hdle;
 	int crash_shutdown;
-	unsigned int err_fatal_irq;
-	int force_stop_gpio;
 };
 
 #define subsys_to_drv(d) container_of(d, struct lpass_data, subsys_desc)
@@ -278,7 +276,7 @@
 
 static irqreturn_t adsp_err_fatal_intr_handler (int irq, void *dev_id)
 {
-	struct lpass_data *drv = dev_id;
+	struct lpass_data *drv = subsys_to_drv(dev_id);
 
 	/* Ignore if we're the one that set the force stop bit in the outbound
 	 * entry
@@ -338,7 +336,7 @@
 	/* The write needs to go through before the q6 is shutdown. */
 	mb();
 	pil_shutdown(&drv->q6->desc);
-	disable_irq_nosync(drv->wdog_irq);
+	disable_irq_nosync(drv->subsys_desc.wdog_bite_irq);
 
 	pr_debug("ADSP is Down\n");
 	adsp_set_state("OFFLINE");
@@ -350,7 +348,7 @@
 	struct lpass_data *drv = subsys_to_lpass(subsys);
 	int ret = 0;
 	ret = pil_boot(&drv->q6->desc);
-	enable_irq(drv->wdog_irq);
+	enable_irq(drv->subsys_desc.wdog_bite_irq);
 
 	pr_debug("ADSP is back online\n");
 	adsp_set_state("ONLINE");
@@ -372,15 +370,15 @@
 	struct lpass_data *drv = subsys_to_lpass(subsys);
 
 	drv->crash_shutdown = 1;
-	gpio_set_value(drv->force_stop_gpio, 1);
+	gpio_set_value(subsys->force_stop_gpio, 1);
 	send_q6_nmi();
 }
 
 static irqreturn_t adsp_wdog_bite_irq(int irq, void *dev_id)
 {
-	struct lpass_data *drv = dev_id;
+	struct lpass_data *drv = subsys_to_drv(dev_id);
 
-	disable_irq_nosync(drv->wdog_irq);
+	disable_irq_nosync(drv->subsys_desc.wdog_bite_irq);
 	schedule_work(&drv->work);
 
 	return IRQ_HANDLED;
@@ -405,34 +403,13 @@
 	struct q6v5_data *q6;
 	struct pil_desc *desc;
 	struct resource *res;
-	int ret, gpio_clk_ready;
+	int ret;
 
 	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
 	if (!drv)
 		return -ENOMEM;
 	platform_set_drvdata(pdev, drv);
 
-	drv->wdog_irq = platform_get_irq(pdev, 0);
-	if (drv->wdog_irq < 0)
-		return drv->wdog_irq;
-
-	ret = gpio_to_irq(of_get_named_gpio(pdev->dev.of_node,
-					    "qcom,gpio-err-fatal", 0));
-	if (ret < 0)
-		return ret;
-	drv->err_fatal_irq = ret;
-
-	ret = gpio_to_irq(of_get_named_gpio(pdev->dev.of_node,
-					    "qcom,gpio-proxy-unvote", 0));
-	if (ret < 0)
-		return ret;
-	gpio_clk_ready = ret;
-
-	drv->force_stop_gpio = of_get_named_gpio(pdev->dev.of_node,
-						"qcom,gpio-force-stop", 0);
-	if (drv->force_stop_gpio < 0)
-		return drv->force_stop_gpio;
-
 	q6 = pil_q6v5_init(pdev);
 	if (IS_ERR(q6))
 		return PTR_ERR(q6);
@@ -441,7 +418,6 @@
 	desc = &q6->desc;
 	desc->owner = THIS_MODULE;
 	desc->proxy_timeout = PROXY_TIMEOUT_MS;
-	desc->proxy_unvote_irq = gpio_clk_ready;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "restart_reg");
 	q6->restart_reg = devm_request_and_ioremap(&pdev->dev, res);
@@ -472,6 +448,8 @@
 		dev_info(&pdev->dev, "using non-secure boot\n");
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
 	ret = pil_desc_init(desc);
 	if (ret)
 		return ret;
@@ -485,6 +463,8 @@
 	drv->subsys_desc.crash_shutdown = adsp_crash_shutdown;
 	drv->subsys_desc.start = lpass_start;
 	drv->subsys_desc.stop = lpass_stop;
+	drv->subsys_desc.err_fatal_handler = adsp_err_fatal_intr_handler;
+	drv->subsys_desc.wdog_bite_handler = adsp_wdog_bite_irq;
 
 	INIT_WORK(&drv->work, adsp_fatal_fn);
 
@@ -500,18 +480,6 @@
 		goto err_subsys;
 	}
 
-	ret = devm_request_irq(&pdev->dev, drv->wdog_irq, adsp_wdog_bite_irq,
-			IRQF_TRIGGER_RISING, dev_name(&pdev->dev), drv);
-	if (ret)
-		goto err_irq;
-
-	ret = devm_request_irq(&pdev->dev, drv->err_fatal_irq,
-				adsp_err_fatal_intr_handler,
-				IRQF_TRIGGER_RISING,
-				dev_name(&pdev->dev), drv);
-	if (ret)
-		goto err_irq;
-
 	drv->wcnss_notif_hdle = subsys_notif_register_notifier("wcnss", &wnb);
 	if (IS_ERR(drv->wcnss_notif_hdle)) {
 		ret = PTR_ERR(drv->wcnss_notif_hdle);
@@ -544,7 +512,6 @@
 err_notif_modem:
 	subsys_notif_unregister_notifier(drv->wcnss_notif_hdle, &wnb);
 err_notif_wcnss:
-err_irq:
 	subsys_unregister(drv->subsys);
 err_subsys:
 	destroy_ramdump_device(drv->ramdump_dev);
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 1f03fd32..c267541 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -24,8 +24,8 @@
 #include <linux/of.h>
 #include <linux/regulator/consumer.h>
 #include <linux/interrupt.h>
-#include <linux/of_gpio.h>
 #include <linux/dma-mapping.h>
+#include <linux/of_gpio.h>
 
 #include <mach/subsystem_restart.h>
 #include <mach/clk.h>
@@ -52,9 +52,6 @@
 	void *ramdump_dev;
 	bool crash_shutdown;
 	bool ignore_errors;
-	int err_fatal_irq;
-	unsigned int stop_ack_irq;
-	int force_stop_gpio;
 	struct completion stop_ack;
 };
 
@@ -91,7 +88,7 @@
 
 static irqreturn_t modem_err_fatal_intr_handler(int irq, void *dev_id)
 {
-	struct modem_data *drv = dev_id;
+	struct modem_data *drv = subsys_to_drv(dev_id);
 
 	/* Ignore if we're the one that set the force stop GPIO */
 	if (drv->crash_shutdown)
@@ -105,7 +102,7 @@
 
 static irqreturn_t modem_stop_ack_intr_handler(int irq, void *dev_id)
 {
-	struct modem_data *drv = dev_id;
+	struct modem_data *drv = subsys_to_drv(dev_id);
 	pr_info("Received stop ack interrupt from modem\n");
 	complete(&drv->stop_ack);
 	return IRQ_HANDLED;
@@ -120,12 +117,12 @@
 		return 0;
 
 	if (!subsys_get_crash_status(drv->subsys)) {
-		gpio_set_value(drv->force_stop_gpio, 1);
+		gpio_set_value(subsys->force_stop_gpio, 1);
 		ret = wait_for_completion_timeout(&drv->stop_ack,
 				msecs_to_jiffies(STOP_ACK_TIMEOUT_MS));
 		if (!ret)
 			pr_warn("Timed out on stop ack from modem.\n");
-		gpio_set_value(drv->force_stop_gpio, 0);
+		gpio_set_value(subsys->force_stop_gpio, 0);
 	}
 
 	pil_shutdown(&drv->mba->desc);
@@ -161,7 +158,7 @@
 	struct modem_data *drv = subsys_to_drv(subsys);
 	drv->crash_shutdown = true;
 	if (!subsys_get_crash_status(drv->subsys)) {
-		gpio_set_value(drv->force_stop_gpio, 1);
+		gpio_set_value(subsys->force_stop_gpio, 1);
 		mdelay(STOP_ACK_TIMEOUT_MS);
 	}
 }
@@ -200,9 +197,9 @@
 	.notifier_call = adsp_state_notifier_fn,
 };
 
-static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
+static irqreturn_t modem_wdog_bite_intr_handler(int irq, void *dev_id)
 {
-	struct modem_data *drv = dev_id;
+	struct modem_data *drv = subsys_to_drv(dev_id);
 	if (drv->ignore_errors)
 		return IRQ_HANDLED;
 	pr_err("Watchdog bite received from modem software!\n");
@@ -243,11 +240,7 @@
 static int __devinit pil_subsys_init(struct modem_data *drv,
 					struct platform_device *pdev)
 {
-	int irq, ret;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
+	int ret;
 
 	drv->subsys_desc.name = "modem";
 	drv->subsys_desc.dev = &pdev->dev;
@@ -258,17 +251,9 @@
 	drv->subsys_desc.crash_shutdown = modem_crash_shutdown;
 	drv->subsys_desc.start = mss_start;
 	drv->subsys_desc.stop = mss_stop;
-
-	ret = of_get_named_gpio(pdev->dev.of_node,
-			"qcom,gpio-err-ready", 0);
-	if (ret < 0)
-		return ret;
-
-	ret = gpio_to_irq(ret);
-	if (ret < 0)
-		return ret;
-
-	drv->subsys_desc.err_ready_irq = ret;
+	drv->subsys_desc.err_fatal_handler = modem_err_fatal_intr_handler;
+	drv->subsys_desc.stop_ack_handler = modem_stop_ack_intr_handler;
+	drv->subsys_desc.wdog_bite_handler = modem_wdog_bite_intr_handler;
 
 	drv->subsys = subsys_register(&drv->subsys_desc);
 	if (IS_ERR(drv->subsys)) {
@@ -284,29 +269,6 @@
 		goto err_ramdump;
 	}
 
-	ret = devm_request_irq(&pdev->dev, irq, modem_wdog_bite_irq,
-				IRQF_TRIGGER_RISING, "modem_wdog", drv);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to request watchdog IRQ.\n");
-		goto err_irq;
-	}
-
-	ret = devm_request_irq(&pdev->dev, drv->err_fatal_irq,
-			modem_err_fatal_intr_handler,
-			IRQF_TRIGGER_RISING, "pil-mss", drv);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to register SMP2P err fatal handler!\n");
-		goto err_irq;
-	}
-
-	ret = devm_request_irq(&pdev->dev, drv->stop_ack_irq,
-			modem_stop_ack_intr_handler,
-			IRQF_TRIGGER_RISING, "pil-mss", drv);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to register SMP2P stop ack handler!\n");
-		goto err_irq;
-	}
-
 	drv->adsp_state_notifier = subsys_notif_register_notifier("adsp",
 						&adsp_state_notifier_block);
 	if (IS_ERR(drv->adsp_state_notifier)) {
@@ -336,18 +298,9 @@
 	struct property *prop;
 	int ret;
 
-	int clk_ready = of_get_named_gpio(pdev->dev.of_node,
-			"qcom,gpio-proxy-unvote", 0);
-	if (clk_ready < 0)
-		return clk_ready;
-
-	clk_ready = gpio_to_irq(clk_ready);
-	if (clk_ready < 0)
-		return clk_ready;
-
 	mba = devm_kzalloc(&pdev->dev, sizeof(*mba), GFP_KERNEL);
-	if (IS_ERR(mba))
-		return PTR_ERR(mba);
+	if (!mba)
+		return -ENOMEM;
 	drv->mba = mba;
 
 	q6 = pil_q6v5_init(pdev);
@@ -360,7 +313,6 @@
 	q6_desc->ops = &pil_msa_pbl_ops;
 	q6_desc->owner = THIS_MODULE;
 	q6_desc->proxy_timeout = PROXY_TIMEOUT_MS;
-	q6_desc->proxy_unvote_irq = clk_ready;
 
 	q6->self_auth = of_property_read_bool(pdev->dev.of_node,
 							"qcom,pil-self-auth");
@@ -445,7 +397,7 @@
 static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
 {
 	struct modem_data *drv;
-	int ret, err_fatal_gpio, is_not_loadable, stop_ack_gpio;
+	int ret, is_not_loadable;
 
 	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
 	if (!drv)
@@ -461,35 +413,8 @@
 		if (ret)
 			return ret;
 	}
-
 	init_completion(&drv->stop_ack);
 
-	/* Get the IRQ from the GPIO for registering inbound handler */
-	err_fatal_gpio = of_get_named_gpio(pdev->dev.of_node,
-			"qcom,gpio-err-fatal", 0);
-	if (err_fatal_gpio < 0)
-		return err_fatal_gpio;
-
-	drv->err_fatal_irq = gpio_to_irq(err_fatal_gpio);
-	if (drv->err_fatal_irq < 0)
-		return drv->err_fatal_irq;
-
-	stop_ack_gpio = of_get_named_gpio(pdev->dev.of_node,
-			"qcom,gpio-stop-ack", 0);
-	if (stop_ack_gpio < 0)
-		return stop_ack_gpio;
-
-	ret = gpio_to_irq(stop_ack_gpio);
-	if (ret < 0)
-		return ret;
-	drv->stop_ack_irq = ret;
-
-	/* Get the GPIO pin for writing the outbound bits: add more as needed */
-	drv->force_stop_gpio = of_get_named_gpio(pdev->dev.of_node,
-			"qcom,gpio-force-stop", 0);
-	if (drv->force_stop_gpio < 0)
-		return drv->force_stop_gpio;
-
 	return pil_subsys_init(drv, pdev);
 }
 
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index bf7438b..9a364b7 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -25,6 +25,7 @@
 #include <mach/subsystem_restart.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -534,6 +535,8 @@
 		goto err_subsys;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = devm_request_irq(&pdev->dev, drv->irq, riva_wdog_bite_irq_hdlr,
 			IRQF_TRIGGER_RISING, "riva_wdog", drv);
 	if (ret < 0)
diff --git a/arch/arm/mach-msm/pil-tzapps.c b/arch/arm/mach-msm/pil-tzapps.c
index 1410117..d9f5700 100644
--- a/arch/arm/mach-msm/pil-tzapps.c
+++ b/arch/arm/mach-msm/pil-tzapps.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
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 
 #include <mach/subsystem_restart.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -97,6 +98,9 @@
 		pil_desc_release(desc);
 		return PTR_ERR(drv->subsys);
 	}
+
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index 4e9e54b..a7ebbf7 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -605,6 +605,8 @@
 	if (!drv->ramdump_dev)
 		return -ENOMEM;
 
+	scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
 	rc = pil_desc_init(desc);
 	if (rc)
 		goto err_ramdump;
diff --git a/arch/arm/mach-msm/pil-vidc.c b/arch/arm/mach-msm/pil-vidc.c
index 629907f..3dbddae 100644
--- a/arch/arm/mach-msm/pil-vidc.c
+++ b/arch/arm/mach-msm/pil-vidc.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
@@ -17,6 +17,7 @@
 #include <linux/clk.h>
 
 #include <mach/subsystem_restart.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -122,6 +123,9 @@
 		pil_desc_release(desc);
 		return PTR_ERR(drv->subsys);
 	}
+
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index dd0599b..da5e67a 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -40,6 +40,7 @@
 #include <mach/trace_msm_low_power.h>
 #include <mach/msm-krait-l2-accessors.h>
 #include <mach/msm_bus.h>
+#include <mach/mpm.h>
 #include <asm/cacheflush.h>
 #include <asm/hardware/gic.h>
 #include <asm/pgtable.h>
@@ -1132,9 +1133,22 @@
 		pm_sleep_ops = *ops;
 }
 
+static int msm_suspend_prepare(void)
+{
+	msm_mpm_suspend_prepare();
+	return 0;
+}
+
+static void msm_suspend_wake(void)
+{
+	msm_mpm_suspend_wake();
+}
+
 static const struct platform_suspend_ops msm_pm_ops = {
 	.enter = msm_pm_enter,
 	.valid = suspend_valid_only_mem,
+	.prepare_late = msm_suspend_prepare,
+	.wake = msm_suspend_wake,
 };
 
 static int __devinit msm_pm_snoc_client_probe(struct platform_device *pdev)
@@ -1367,7 +1381,7 @@
 	end = exit_phys + SECTION_SIZE;
 
 	ret = msm_pm_add_idmap(pc_pgd, exit_phys, end,
-					PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
+			PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF);
 
 	if (ret)
 		return ret;
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index 64ee880..8baac01 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -250,7 +250,11 @@
 		return;
 
 	spin_lock_irqsave(&audio->dsp_lock, flags);
-	BUG_ON(list_empty(&audio->out_queue));
+	if (list_empty(&audio->out_queue)) {
+		pr_warning("%s: ingore unexpected event from dsp\n", __func__);
+		spin_unlock_irqrestore(&audio->dsp_lock, flags);
+		return;
+	}
 	used_buf = list_first_entry(&audio->out_queue,
 					struct audio_aio_buffer_node, list);
 	if (token == used_buf->token) {
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index d95f979..c85f7a1 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -47,6 +47,10 @@
 
 #define RESTART_REASON_ADDR 0x65C
 #define DLOAD_MODE_ADDR     0x0
+#define EMERGENCY_DLOAD_MODE_ADDR    0xFE0
+#define EMERGENCY_DLOAD_MAGIC1    0x322A4F99
+#define EMERGENCY_DLOAD_MAGIC2    0xC67E4350
+#define EMERGENCY_DLOAD_MAGIC3    0x77777777
 
 #define SCM_IO_DISABLE_PMIC_ARBITER	1
 
@@ -65,13 +69,14 @@
 #ifdef CONFIG_MSM_DLOAD_MODE
 static int in_panic;
 static void *dload_mode_addr;
+static bool dload_mode_enabled;
+static void *emergency_dload_mode_addr;
 
 /* Download mode master kill-switch */
 static int dload_set(const char *val, struct kernel_param *kp);
 static int download_mode = 1;
 module_param_call(download_mode, dload_set, param_get_int,
 			&download_mode, 0644);
-
 static int panic_prep_restart(struct notifier_block *this,
 			      unsigned long event, void *ptr)
 {
@@ -90,6 +95,27 @@
 		__raw_writel(on ? 0xCE14091A : 0,
 		       dload_mode_addr + sizeof(unsigned int));
 		mb();
+		dload_mode_enabled = on;
+	}
+}
+
+static bool get_dload_mode(void)
+{
+	return dload_mode_enabled;
+}
+
+static void enable_emergency_dload_mode(void)
+{
+	if (emergency_dload_mode_addr) {
+		__raw_writel(EMERGENCY_DLOAD_MAGIC1,
+				emergency_dload_mode_addr);
+		__raw_writel(EMERGENCY_DLOAD_MAGIC2,
+				emergency_dload_mode_addr +
+				sizeof(unsigned int));
+		__raw_writel(EMERGENCY_DLOAD_MAGIC3,
+				emergency_dload_mode_addr +
+				(2 * sizeof(unsigned int)));
+		mb();
 	}
 }
 
@@ -115,6 +141,16 @@
 }
 #else
 #define set_dload_mode(x) do {} while (0)
+
+static void enable_emergency_dload_mode(void)
+{
+	printk(KERN_ERR "dload mode is not enabled on target\n");
+}
+
+static bool get_dload_mode(void)
+{
+	return false;
+}
 #endif
 
 void msm_set_restart_mode(int mode)
@@ -130,7 +166,7 @@
 	set_dload_mode(0);
 #endif
 	pm8xxx_reset_pwr_off(0);
-	qpnp_pon_system_pwr_off(0);
+	qpnp_pon_system_pwr_off(PON_POWER_OFF_SHUTDOWN);
 
 	if (lower_pshold) {
 		if (!use_restart_v2())
@@ -211,7 +247,12 @@
 #endif
 
 	pm8xxx_reset_pwr_off(1);
-	qpnp_pon_system_pwr_off(1);
+
+	/* Hard reset the PMIC unless memory contents must be maintained. */
+	if (get_dload_mode() || (cmd != NULL && cmd[0] != '\0'))
+		qpnp_pon_system_pwr_off(PON_POWER_OFF_WARM_RESET);
+	else
+		qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET);
 
 	if (cmd != NULL) {
 		if (!strncmp(cmd, "bootloader", 10)) {
@@ -222,6 +263,8 @@
 			unsigned long code;
 			code = simple_strtoul(cmd + 4, NULL, 16) & 0xff;
 			__raw_writel(0x6f656d00 | code, restart_reason);
+		} else if (!strncmp(cmd, "edl", 3)) {
+			enable_emergency_dload_mode();
 		} else {
 			__raw_writel(0x77665501, restart_reason);
 		}
@@ -289,6 +332,8 @@
 #ifdef CONFIG_MSM_DLOAD_MODE
 	atomic_notifier_chain_register(&panic_notifier_list, &panic_blk);
 	dload_mode_addr = MSM_IMEM_BASE + DLOAD_MODE_ADDR;
+	emergency_dload_mode_addr = MSM_IMEM_BASE +
+		EMERGENCY_DLOAD_MODE_ADDR;
 	set_dload_mode(download_mode);
 #endif
 	msm_tmr0_base = msm_timer_get_timer0_base();
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index b244c6f..57acdc4 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -255,9 +255,14 @@
 }
 EXPORT_SYMBOL(pas_supported);
 
-static int __init scm_pas_init(void)
+void scm_pas_init(enum msm_bus_fabric_master_type id)
 {
 	int i, rate;
+	static int is_inited;
+
+	if (is_inited)
+		return;
+
 	for (i = 0; i < NUM_CLKS; i++) {
 		scm_clocks[i] = clk_get_sys("scm", scm_clock_names[i]);
 		if (IS_ERR(scm_clocks[i]))
@@ -268,20 +273,14 @@
 	rate = clk_round_rate(scm_clocks[CORE_CLK_SRC], 1);
 	clk_set_rate(scm_clocks[CORE_CLK_SRC], rate);
 
-	if (soc_class_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
-		scm_pas_bw_tbl[0].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
-		scm_pas_bw_tbl[1].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
-	} else {
-		if (!IS_ERR(scm_clocks[BUS_CLK]))
-			clk_set_rate(scm_clocks[BUS_CLK], 64000000);
-		else
-			pr_warn("unable to get bus clock\n");
-	}
+	scm_pas_bw_tbl[0].vectors[0].src = id;
+	scm_pas_bw_tbl[1].vectors[0].src = id;
+
+	clk_set_rate(scm_clocks[BUS_CLK], 64000000);
 
 	scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
 	if (!scm_perf_client)
 		pr_warn("unable to register bus client\n");
 
-	return 0;
+	is_inited = 1;
 }
-module_init(scm_pas_init);
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index f13757c..48bc558 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -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
@@ -9,6 +9,9 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+
+#include <mach/msm_bus_board.h>
+
 #ifndef __MSM_SCM_PAS_H
 #define __MSM_SCM_PAS_H
 
@@ -31,6 +34,7 @@
 extern int pas_auth_and_reset(enum pas_id id);
 extern int pas_shutdown(enum pas_id id);
 extern int pas_supported(enum pas_id id);
+extern void scm_pas_init(enum msm_bus_fabric_master_type id);
 #else
 static inline int pas_init_image(enum pas_id id, const u8 *metadata,
 		size_t size)
@@ -53,6 +57,9 @@
 {
 	return 0;
 }
+static inline void scm_pas_init(enum msm_bus_fabric_master_type id)
+{
+}
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/smcmod.c b/arch/arm/mach-msm/smcmod.c
index 221a522..683fb32 100644
--- a/arch/arm/mach-msm/smcmod.c
+++ b/arch/arm/mach-msm/smcmod.c
@@ -29,6 +29,7 @@
 #include <linux/msm_ion.h>
 #include <asm/smcmod.h>
 #include <mach/scm.h>
+#include <mach/socinfo.h>
 
 static DEFINE_MUTEX(ioctl_lock);
 
@@ -513,6 +514,110 @@
 	return ret;
 }
 
+static int smcmod_send_dec_cmd(struct smcmod_decrypt_req *reqp)
+{
+	struct ion_client *ion_clientp;
+	struct ion_handle *ion_handlep = NULL;
+	int ion_fd;
+	int ret;
+	u32 pa;
+	size_t size;
+	struct {
+		u32 args[4];
+	} req;
+	struct {
+		u32 args[3];
+	} rsp;
+
+	ion_clientp = msm_ion_client_create(UINT_MAX, "smcmod");
+	if (IS_ERR_OR_NULL(ion_clientp))
+		return PTR_ERR(ion_clientp);
+
+	switch (reqp->operation) {
+	case SMCMOD_DECRYPT_REQ_OP_METADATA: {
+		ion_fd = reqp->request.metadata.ion_fd;
+		ret = smcmod_ion_fd_to_phys(ion_fd, ion_clientp,
+					    &ion_handlep, &pa, &size);
+		if (ret)
+			goto error;
+
+		req.args[0] = reqp->request.metadata.len;
+		req.args[1] = pa;
+		break;
+	}
+	case SMCMOD_DECRYPT_REQ_OP_IMG_FRAG: {
+		ion_fd = reqp->request.img_frag.ion_fd;
+		ret = smcmod_ion_fd_to_phys(ion_fd, ion_clientp,
+					    &ion_handlep, &pa, &size);
+		if (ret)
+			goto error;
+
+		req.args[0] = reqp->request.img_frag.ctx_id;
+		req.args[1] = reqp->request.img_frag.last_frag;
+		req.args[2] = reqp->request.img_frag.frag_len;
+		req.args[3] = pa + reqp->request.img_frag.offset;
+		break;
+	}
+	default:
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/*
+	 * scm_call does cache maintenance over request and response buffers.
+	 * The userspace must flush/invalidate ion input/output buffers itself.
+	 */
+
+	ret = scm_call(reqp->service_id, reqp->command_id,
+		       &req, sizeof(req), &rsp, sizeof(rsp));
+	if (ret)
+		goto error;
+
+	switch (reqp->operation) {
+	case SMCMOD_DECRYPT_REQ_OP_METADATA:
+		reqp->response.metadata.status = rsp.args[0];
+		reqp->response.metadata.ctx_id = rsp.args[1];
+		reqp->response.metadata.end_offset = rsp.args[2] - pa;
+		break;
+	case SMCMOD_DECRYPT_REQ_OP_IMG_FRAG: {
+		reqp->response.img_frag.status = rsp.args[0];
+		break;
+	}
+	default:
+		break;
+	}
+
+error:
+	if (!IS_ERR_OR_NULL(ion_clientp)) {
+		if (!IS_ERR_OR_NULL(ion_handlep))
+			ion_free(ion_clientp, ion_handlep);
+		ion_client_destroy(ion_clientp);
+	}
+	return ret;
+}
+
+static int smcmod_ioctl_check(unsigned cmd)
+{
+	switch (cmd) {
+	case SMCMOD_IOCTL_SEND_REG_CMD:
+	case SMCMOD_IOCTL_SEND_BUF_CMD:
+	case SMCMOD_IOCTL_SEND_CIPHER_CMD:
+	case SMCMOD_IOCTL_SEND_MSG_DIGEST_CMD:
+	case SMCMOD_IOCTL_GET_VERSION:
+		if (!cpu_is_fsm9xxx())
+			return -EINVAL;
+		break;
+	case SMCMOD_IOCTL_SEND_DECRYPT_CMD:
+		if (!cpu_is_msm8226())
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static long smcmod_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 {
 	void __user *argp = (void __user *)arg;
@@ -531,6 +636,10 @@
 	 */
 	mutex_lock(&ioctl_lock);
 
+	ret = smcmod_ioctl_check(cmd);
+	if (ret)
+		goto cleanup;
+
 	switch (cmd) {
 	case SMCMOD_IOCTL_SEND_REG_CMD:
 		{
@@ -652,6 +761,26 @@
 		}
 		break;
 
+	case SMCMOD_IOCTL_SEND_DECRYPT_CMD:
+		{
+			struct smcmod_decrypt_req req;
+
+			if (copy_from_user((void *)&req, argp, sizeof(req))) {
+				ret = -EFAULT;
+				goto cleanup;
+			}
+
+			ret = smcmod_send_dec_cmd(&req);
+			if (ret < 0)
+				goto cleanup;
+
+			if (copy_to_user(argp, (void *)&req, sizeof(req))) {
+				ret = -EFAULT;
+				goto cleanup;
+			}
+		}
+		break;
+
 	default:
 		ret = -EINVAL;
 	}
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index a6e3497..e148868 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -724,6 +724,7 @@
 	[SMD_MODEM_RPM] = {SMD_MODEM, SMD_RPM},
 	[SMD_QDSP_RPM] = {SMD_Q6, SMD_RPM},
 	[SMD_WCNSS_RPM] = {SMD_WCNSS, SMD_RPM},
+	[SMD_TZ_RPM] = {SMD_TZ, SMD_RPM},
 };
 
 struct restart_notifier_block {
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 20a6165..1c44f9a 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -41,7 +41,7 @@
 #ifdef CONFIG_ARCH_FSM9XXX
 #define NUM_SMD_PKT_PORTS 4
 #else
-#define NUM_SMD_PKT_PORTS 28
+#define NUM_SMD_PKT_PORTS 31
 #endif
 
 #define PDRIVER_NAME_MAX_SIZE 32
@@ -711,6 +711,9 @@
 	"smdcntl5",
 	"smdcntl6",
 	"smdcntl7",
+	"smdcntl9",
+	"smdcntl10",
+	"smdcntl11",
 	"smd22",
 	"smdcnt_rev0",
 	"smdcnt_rev1",
@@ -742,6 +745,9 @@
 	"DATA12_CNTL",
 	"DATA13_CNTL",
 	"DATA14_CNTL",
+	"DATA15_CNTL",
+	"DATA16_CNTL",
+	"DATA17_CNTL",
 	"DATA22",
 	"DATA23_CNTL",
 	"DATA24_CNTL",
@@ -783,6 +789,9 @@
 	SMD_APPS_MODEM,
 	SMD_APPS_MODEM,
 	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
 	SMD_APPS_DSPS,
 	SMD_APPS_QDSP,
 	SMD_APPS_MODEM,
@@ -1028,6 +1037,13 @@
 	int i;
 	int r;
 
+	if (ARRAY_SIZE(smd_ch_name) != NUM_SMD_PKT_PORTS ||
+			ARRAY_SIZE(smd_ch_edge) != NUM_SMD_PKT_PORTS ||
+			ARRAY_SIZE(smd_pkt_dev_name) != NUM_SMD_PKT_PORTS) {
+		pr_err("%s: mismatch in number of ports\n", __func__);
+		BUG();
+	}
+
 	r = alloc_chrdev_region(&smd_pkt_number,
 			       0,
 			       NUM_SMD_PKT_PORTS,
diff --git a/arch/arm/mach-msm/smd_private.c b/arch/arm/mach-msm/smd_private.c
index 94192d3..a7ef87f 100644
--- a/arch/arm/mach-msm/smd_private.c
+++ b/arch/arm/mach-msm/smd_private.c
@@ -267,7 +267,8 @@
 int is_word_access_ch(unsigned ch_type)
 {
 	if (ch_type == SMD_APPS_RPM || ch_type == SMD_MODEM_RPM ||
-		ch_type == SMD_QDSP_RPM || ch_type == SMD_WCNSS_RPM)
+		ch_type == SMD_QDSP_RPM || ch_type == SMD_WCNSS_RPM ||
+		ch_type == SMD_TZ_RPM)
 		return 1;
 	else
 		return 0;
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 7b1a4c3..01e0985 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -32,6 +32,7 @@
 #include <linux/debugfs.h>
 #include <linux/miscdevice.h>
 #include <linux/interrupt.h>
+#include <linux/of_gpio.h>
 
 #include <asm/current.h>
 
@@ -502,8 +503,10 @@
 	if (ret)
 		return ret;
 
-	if (subsys->desc->is_not_loadable)
+	if (subsys->desc->is_not_loadable) {
+		subsys_set_state(subsys, SUBSYS_ONLINE);
 		return 0;
+	}
 
 	ret = wait_for_err_ready(subsys);
 	if (ret)
@@ -989,6 +992,129 @@
 	misc_deregister(&subsys_dev->misc_dev);
 }
 
+static int __get_gpio(struct subsys_desc *desc, const char *prop,
+		int *gpio)
+{
+	struct device_node *dnode = desc->dev->of_node;
+	int ret = -ENOENT;
+
+	if (of_find_property(dnode, prop, NULL)) {
+		*gpio = of_get_named_gpio(dnode, prop, 0);
+		ret = *gpio < 0 ? *gpio : 0;
+	}
+
+	return ret;
+}
+
+static int __get_irq(struct subsys_desc *desc, const char *prop,
+		unsigned int *irq)
+{
+	int ret, gpio, irql;
+
+	ret = __get_gpio(desc, prop, &gpio);
+	if (ret)
+		return ret;
+
+	irql = gpio_to_irq(gpio);
+
+	if (irql == -ENOENT)
+		irql = -ENXIO;
+
+	if (irql < 0) {
+		pr_err("[%s]: Error getting IRQ \"%s\"\n", desc->name,
+				prop);
+		return irql;
+	} else {
+		*irq = irql;
+	}
+
+	return 0;
+}
+
+static int subsys_parse_devicetree(struct subsys_desc *desc)
+{
+	int ret;
+	struct platform_device *pdev = container_of(desc->dev,
+					struct platform_device, dev);
+
+	ret = __get_irq(desc, "qcom,gpio-err-fatal", &desc->err_fatal_irq);
+	if (ret && ret != -ENOENT)
+		return ret;
+
+	ret = __get_irq(desc, "qcom,gpio-err-ready", &desc->err_ready_irq);
+	if (ret && ret != -ENOENT)
+		return ret;
+
+	ret = __get_irq(desc, "qcom,gpio-stop-ack", &desc->stop_ack_irq);
+	if (ret && ret != -ENOENT)
+		return ret;
+
+	ret = __get_gpio(desc, "qcom,gpio-force-stop", &desc->force_stop_gpio);
+	if (ret && ret != -ENOENT)
+		return ret;
+
+	desc->wdog_bite_irq = platform_get_irq(pdev, 0);
+	if (desc->wdog_bite_irq < 0)
+		return desc->wdog_bite_irq;
+
+	return 0;
+}
+
+static int subsys_setup_irqs(struct subsys_device *subsys)
+{
+	struct subsys_desc *desc = subsys->desc;
+	int ret;
+
+	if (desc->err_fatal_irq && desc->err_fatal_handler) {
+		ret = devm_request_irq(desc->dev, desc->err_fatal_irq,
+				desc->err_fatal_handler,
+				IRQF_TRIGGER_RISING, desc->name, desc);
+		if (ret < 0) {
+			dev_err(desc->dev, "[%s]: Unable to register error fatal IRQ handler!: %d\n",
+				desc->name, ret);
+			return ret;
+		}
+	}
+
+	if (desc->stop_ack_irq && desc->stop_ack_handler) {
+		ret = devm_request_irq(desc->dev, desc->stop_ack_irq,
+			desc->stop_ack_handler,
+			IRQF_TRIGGER_RISING, desc->name, desc);
+		if (ret < 0) {
+			dev_err(desc->dev, "[%s]: Unable to register stop ack handler!: %d\n",
+				desc->name, ret);
+			return ret;
+		}
+	}
+
+	if (desc->wdog_bite_irq && desc->wdog_bite_handler) {
+		ret = devm_request_irq(desc->dev, desc->wdog_bite_irq,
+			desc->wdog_bite_handler,
+			IRQF_TRIGGER_RISING, desc->name, desc);
+		if (ret < 0) {
+			dev_err(desc->dev, "[%s]: Unable to register wdog bite handler!: %d\n",
+				desc->name, ret);
+			return ret;
+		}
+	}
+
+	if (desc->err_ready_irq) {
+		ret = devm_request_irq(desc->dev,
+					desc->err_ready_irq,
+					subsys_err_ready_intr_handler,
+					IRQF_TRIGGER_RISING,
+					"error_ready_interrupt", subsys);
+		if (ret < 0) {
+			dev_err(desc->dev,
+				"[%s]: Unable to register err ready handler\n",
+				desc->name);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 struct subsys_device *subsys_register(struct subsys_desc *desc)
 {
 	struct subsys_device *subsys;
@@ -1006,6 +1132,9 @@
 
 	subsys->notify = subsys_notif_add_subsys(desc->name);
 	subsys->restart_order = update_restart_order(subsys);
+	ret = subsys_parse_devicetree(desc);
+	if (ret)
+		goto err_dtree;
 
 	snprintf(subsys->wlname, sizeof(subsys->wlname), "ssr(%s)", desc->name);
 	wake_lock_init(&subsys->wake_lock, WAKE_LOCK_SUSPEND, subsys->wlname);
@@ -1037,19 +1166,9 @@
 		goto err_register;
 	}
 
-	if (subsys->desc->err_ready_irq) {
-		ret = devm_request_irq(&subsys->dev,
-					subsys->desc->err_ready_irq,
-					subsys_err_ready_intr_handler,
-					IRQF_TRIGGER_RISING,
-					"error_ready_interrupt", subsys);
-		if (ret < 0) {
-			dev_err(&subsys->dev,
-				"[%s]: Unable to register err ready handler\n",
-				subsys->desc->name);
-			goto err_misc_device;
-		}
-	}
+	ret = subsys_setup_irqs(subsys);
+	if (ret < 0)
+		goto err_misc_device;
 
 	return subsys;
 
@@ -1062,6 +1181,7 @@
 	ida_simple_remove(&subsys_ida, subsys->id);
 err_ida:
 	wake_lock_destroy(&subsys->wake_lock);
+err_dtree:
 	kfree(subsys);
 	return ERR_PTR(ret);
 }
diff --git a/arch/arm/mach-msm/test_qmi_client.c b/arch/arm/mach-msm/test_qmi_client.c
index d070e37..b701be8 100644
--- a/arch/arm/mach-msm/test_qmi_client.c
+++ b/arch/arm/mach-msm/test_qmi_client.c
@@ -61,6 +61,25 @@
 /* Variable to hold the test result */
 static int test_res;
 
+static unsigned int callback_count;
+static void test_async_resp_cb(struct qmi_handle *handle,
+			   unsigned int msg_id, void *msg,
+			   void *resp_cb_data, int stat)
+{
+	callback_count++;
+	if (stat == 0)
+		D("%s invoked %d time(s): [RESP_LEN] = %d, [RESP_VALID] = %d",
+			__func__, callback_count,
+			((struct test_data_resp_msg_v01 *)msg)->data_len,
+			((struct test_data_resp_msg_v01 *)msg)->data_valid);
+	else if (stat < 0)
+		pr_err("%s: Request Failed [MSG_ID]: %d, [ERR_ID]: %d, [Callback_count]: %d",
+			__func__, msg_id, stat,	callback_count);
+
+	kfree(msg);
+	kfree(resp_cb_data);
+}
+
 static int test_qmi_ping_pong_send_sync_msg(void)
 {
 	struct test_ping_req_msg_v01 req;
@@ -138,12 +157,68 @@
 	return rc;
 }
 
+static int test_qmi_data_send_async_msg(unsigned int data_len)
+{
+	struct test_data_req_msg_v01 *req;
+	struct test_data_resp_msg_v01 *resp;
+	struct msg_desc req_desc, *resp_desc;
+	int rc, i;
+
+	req = kzalloc(sizeof(struct test_data_req_msg_v01), GFP_KERNEL);
+	if (!req) {
+		pr_err("%s: Data req msg alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	resp = kzalloc(sizeof(struct test_data_resp_msg_v01), GFP_KERNEL);
+	if (!resp) {
+		pr_err("%s: Data resp msg alloc failed\n", __func__);
+		kfree(req);
+		return -ENOMEM;
+	}
+
+	resp_desc = kzalloc(sizeof(struct msg_desc), GFP_KERNEL);
+	if (!resp_desc) {
+		pr_err("%s: Resp_desc msg alloc failed\n", __func__);
+		kfree(req);
+		kfree(resp);
+		return -ENOMEM;
+	}
+
+	req->data_len = data_len;
+	for (i = 0; i < data_len; i = i + sizeof(int))
+		memcpy(req->data + i, (uint8_t *)&i, sizeof(int));
+	req->client_name_valid = 0;
+
+	req_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+	req_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+	req_desc.ei_array = test_data_req_msg_v01_ei;
+
+	resp_desc->max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+	resp_desc->msg_id = TEST_DATA_REQ_MSG_ID_V01;
+	resp_desc->ei_array = test_data_resp_msg_v01_ei;
+
+	rc = qmi_send_req_nowait(test_clnt, &req_desc, req, sizeof(*req),
+			       resp_desc, resp, sizeof(*resp),
+			       test_async_resp_cb, (void *)resp_desc);
+	if (rc < 0) {
+		pr_err("%s: send req failed\n", __func__);
+		kfree(resp);
+		kfree(resp_desc);
+	}
+	kfree(req);
+	return rc;
+}
+
 static void test_clnt_recv_msg(struct work_struct *work)
 {
 	int rc;
 
-	rc = qmi_recv_msg(test_clnt);
-	if (rc < 0)
+	do {
+		D("%s: Notified about a Receive Event", __func__);
+	} while ((rc = qmi_recv_msg(test_clnt)) == 0);
+
+	if (rc != -ENOMSG)
 		pr_err("%s: Error receiving message\n", __func__);
 }
 
@@ -280,6 +355,32 @@
 				} while (test_clnt_reset);
 			}
 		}
+	} else if (!strncmp(cmd, "data_async", sizeof(cmd))) {
+		int i;
+		callback_count = 0;
+		for (i = 0; i < test_rep_cnt; i++) {
+			test_res = test_qmi_data_send_async_msg(test_data_sz);
+			if (test_res == -ENETRESET || test_clnt_reset) {
+				--i;
+				do {
+					msleep(50);
+				} while (test_clnt_reset);
+			} else if (test_res < 0) {
+				--i;
+				pr_err("%s: Error sending txn, aborting now",
+					__func__);
+				break;
+			}
+		}
+		while (callback_count < i) {
+			if (test_clnt_reset) {
+				pr_err("%s: Service Exited", __func__);
+				break;
+			}
+			msleep(50);
+		}
+		D("%s complete\n", __func__);
+		callback_count = 0;
 	} else {
 		test_res = -EINVAL;
 	}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e65b5ba..c2efc34 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -360,9 +360,13 @@
 PTE_SET_FN(nx, pte_mknexec)
 
 SET_MEMORY_FN(ro, pte_set_ro)
+EXPORT_SYMBOL(set_memory_ro);
 SET_MEMORY_FN(rw, pte_set_rw)
+EXPORT_SYMBOL(set_memory_rw);
 SET_MEMORY_FN(x, pte_set_x)
+EXPORT_SYMBOL(set_memory_x);
 SET_MEMORY_FN(nx, pte_set_nx)
+EXPORT_SYMBOL(set_memory_nx);
 
 /*
  * Adjust the PMD section entries according to the CPU in use.
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index e62af21..1d12b07 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -21,6 +21,7 @@
 #include <linux/uaccess.h>
 #include <linux/user.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <asm/cp15.h>
 #include <asm/cputype.h>
@@ -656,23 +657,23 @@
 }
 
 #ifdef CONFIG_PROC_FS
-static int proc_read_status(char *page, char **start, off_t off, int count,
-			    int *eof, void *data)
+static int vfp_bounce_show(struct seq_file *m, void *v)
 {
-	char *p = page;
-	int len;
-
-	p += snprintf(p, PAGE_SIZE, "%llu\n", atomic64_read(&vfp_bounce_count));
-
-	len = (p - page) - off;
-	if (len < 0)
-		len = 0;
-
-	*eof = (len <= count) ? 1 : 0;
-	*start = page + off;
-
-	return len;
+	seq_printf(m, "%llu\n", atomic64_read(&vfp_bounce_count));
+	return 0;
 }
+
+static int vfp_bounce_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, vfp_bounce_show, NULL);
+}
+
+static const struct file_operations vfp_bounce_fops = {
+	.open		= vfp_bounce_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 #endif
 
 /*
@@ -755,11 +756,9 @@
 	}
 
 #ifdef CONFIG_PROC_FS
-	procfs_entry = create_proc_entry("cpu/vfp_bounce", S_IRUGO, NULL);
-
-	if (procfs_entry)
-		procfs_entry->read_proc = proc_read_status;
-	else
+	procfs_entry = proc_create("cpu/vfp_bounce", S_IRUGO, NULL,
+			&vfp_bounce_fops);
+	if (!procfs_entry)
 		pr_err("Failed to create procfs node for VFP bounce reporting\n");
 #endif
 
diff --git a/block/blk-core.c b/block/blk-core.c
index 123f79a..40d9b35 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -2058,10 +2058,8 @@
 			 * not be passed by new incoming requests
 			 */
 			rq->cmd_flags |= REQ_STARTED;
-			if (rq->cmd_flags & REQ_URGENT) {
-				WARN_ON(q->dispatched_urgent);
+			if (rq->cmd_flags & REQ_URGENT)
 				q->dispatched_urgent = true;
-			}
 			trace_block_rq_issue(q, rq);
 		}
 
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 32629e2..b4711cb 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -239,6 +239,9 @@
 	unsigned long workload_expires;
 	struct cfq_group *serving_group;
 
+	unsigned int nr_urgent_pending;
+	unsigned int nr_urgent_in_flight;
+
 	/*
 	 * Each priority tree is sorted by next_request position.  These
 	 * trees are used when determining if two or more queues are
@@ -2091,6 +2094,14 @@
 	(RQ_CFQG(rq))->dispatched++;
 	elv_dispatch_sort(q, rq);
 
+	if (rq->cmd_flags & REQ_URGENT) {
+		if (!cfqd->nr_urgent_pending)
+			WARN_ON(1);
+		else
+			cfqd->nr_urgent_pending--;
+		cfqd->nr_urgent_in_flight++;
+	}
+
 	cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++;
 	cfqq->nr_sectors += blk_rq_sectors(rq);
 	cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq),
@@ -3194,6 +3205,69 @@
 	}
 }
 
+/*
+ * Called when a request (rq) is reinserted (to cfqq). Check if there's
+ * something we should do about it
+ */
+static void
+cfq_rq_requeued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+		struct request *rq)
+{
+	struct cfq_io_cq *cic = RQ_CIC(rq);
+
+	cfqd->rq_queued++;
+	if (rq->cmd_flags & REQ_PRIO)
+		cfqq->prio_pending++;
+
+	cfqq->dispatched--;
+	(RQ_CFQG(rq))->dispatched--;
+
+	cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
+
+	cfq_update_io_thinktime(cfqd, cfqq, cic);
+	cfq_update_io_seektime(cfqd, cfqq, rq);
+	cfq_update_idle_window(cfqd, cfqq, cic);
+
+	cfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq);
+
+	if (cfqq == cfqd->active_queue) {
+		if (cfq_cfqq_wait_request(cfqq)) {
+			if (blk_rq_bytes(rq) > PAGE_CACHE_SIZE ||
+			    cfqd->busy_queues > 1) {
+				cfq_del_timer(cfqd, cfqq);
+				cfq_clear_cfqq_wait_request(cfqq);
+			} else {
+				cfq_blkiocg_update_idle_time_stats(
+						&cfqq->cfqg->blkg);
+				cfq_mark_cfqq_must_dispatch(cfqq);
+			}
+		}
+	} else if (cfq_should_preempt(cfqd, cfqq, rq)) {
+		cfq_preempt_queue(cfqd, cfqq);
+	}
+}
+
+static int cfq_reinsert_request(struct request_queue *q, struct request *rq)
+{
+	struct cfq_data *cfqd = q->elevator->elevator_data;
+	struct cfq_queue *cfqq = RQ_CFQQ(rq);
+
+	if (!cfqq || cfqq->cfqd != cfqd)
+		return -EIO;
+
+	cfq_log_cfqq(cfqd, cfqq, "re-insert_request");
+	list_add(&rq->queuelist, &cfqq->fifo);
+	cfq_add_rq_rb(rq);
+
+	cfq_rq_requeued(cfqd, cfqq, rq);
+	if (rq->cmd_flags & REQ_URGENT) {
+			if (cfqd->nr_urgent_in_flight)
+				cfqd->nr_urgent_in_flight--;
+			cfqd->nr_urgent_pending++;
+	}
+	return 0;
+}
+
 static void cfq_insert_request(struct request_queue *q, struct request *rq)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
@@ -3208,7 +3282,45 @@
 	cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
 			&cfqd->serving_group->blkg, rq_data_dir(rq),
 			rq_is_sync(rq));
+
 	cfq_rq_enqueued(cfqd, cfqq, rq);
+
+	if (rq->cmd_flags & REQ_URGENT) {
+		WARN_ON(1);
+		blk_dump_rq_flags(rq, "");
+		rq->cmd_flags &= ~REQ_URGENT;
+	}
+
+	/* Request is considered URGENT if:
+	 * 1. The queue being served is of a lower IO priority then the new
+	 *    request
+	 * OR:
+	 * 2. The workload being performed is ASYNC
+	 * Only READ requests may be considered as URGENT
+	 */
+	if ((cfqd->active_queue &&
+		 cfqq->ioprio_class < cfqd->active_queue->ioprio_class) ||
+		(cfqd->serving_type == ASYNC_WORKLOAD &&
+		 rq_data_dir(rq) == READ)) {
+		rq->cmd_flags |= REQ_URGENT;
+		cfqd->nr_urgent_pending++;
+	}
+}
+
+
+/**
+ * cfq_urgent_pending() - Return TRUE if there is an urgent
+ *			  request on scheduler
+ * @q:	requests queue
+ */
+static bool cfq_urgent_pending(struct request_queue *q)
+{
+	struct cfq_data *cfqd = q->elevator->elevator_data;
+
+	if (cfqd->nr_urgent_pending && !cfqd->nr_urgent_in_flight)
+		return true;
+
+	return false;
 }
 
 /*
@@ -3292,6 +3404,14 @@
 	const int sync = rq_is_sync(rq);
 	unsigned long now;
 
+	if (rq->cmd_flags & REQ_URGENT) {
+		if (!cfqd->nr_urgent_in_flight)
+			WARN_ON(1);
+		else
+			cfqd->nr_urgent_in_flight--;
+		rq->cmd_flags &= ~REQ_URGENT;
+	}
+
 	now = jiffies;
 	cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d",
 		     !!(rq->cmd_flags & REQ_NOIDLE));
@@ -3859,6 +3979,8 @@
 		.elevator_bio_merged_fn =	cfq_bio_merged,
 		.elevator_dispatch_fn =		cfq_dispatch_requests,
 		.elevator_add_req_fn =		cfq_insert_request,
+		.elevator_reinsert_req_fn	= cfq_reinsert_request,
+		.elevator_is_urgent_fn		= cfq_urgent_pending,
 		.elevator_activate_req_fn =	cfq_activate_request,
 		.elevator_deactivate_req_fn =	cfq_deactivate_request,
 		.elevator_completed_req_fn =	cfq_completed_request,
diff --git a/block/elevator.c b/block/elevator.c
index 44193a8..55f1f1e 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -842,7 +842,6 @@
 
 	if (rq->cmd_flags & REQ_URGENT) {
 		q->notified_urgent = false;
-		WARN_ON(!q->dispatched_urgent);
 		q->dispatched_urgent = false;
 	}
 	/*
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 5401814..7f159f0 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -21,6 +21,7 @@
 #include <linux/firmware.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/io.h>
 
 #define to_dev(obj) container_of(obj, struct device, kobj)
 
@@ -98,6 +99,8 @@
 	struct page **pages;
 	int nr_pages;
 	int page_array_size;
+	phys_addr_t dest_addr;
+	size_t dest_size;
 	struct timer_list timeout;
 	struct device dev;
 	bool nowait;
@@ -239,6 +242,10 @@
 
 	switch (loading) {
 	case 1:
+		if (fw_priv->dest_addr) {
+			set_bit(FW_STATUS_LOADING, &fw_priv->status);
+			break;
+		}
 		firmware_free_data(fw_priv->fw);
 		memset(fw_priv->fw, 0, sizeof(struct firmware));
 		/* If the pages are not owned by 'struct firmware' */
@@ -252,6 +259,11 @@
 		break;
 	case 0:
 		if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
+			if (fw_priv->dest_addr) {
+				complete(&fw_priv->completion);
+				clear_bit(FW_STATUS_LOADING, &fw_priv->status);
+				break;
+			}
 			vunmap(fw_priv->fw->data);
 			fw_priv->fw->data = vmap(fw_priv->pages,
 						 fw_priv->nr_pages,
@@ -286,6 +298,67 @@
 
 static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
 
+static int __firmware_data_rw(struct firmware_priv *fw_priv, char *buffer,
+				loff_t *offset, size_t count, int read)
+{
+	u8 __iomem *fw_buf;
+	int retval = count;
+
+	if ((*offset + count) > fw_priv->dest_size) {
+		pr_debug("%s: Failed size check.\n", __func__);
+		retval = -EINVAL;
+		goto out;
+	}
+
+	fw_buf = ioremap(fw_priv->dest_addr + *offset, count);
+	if (!fw_buf) {
+		pr_debug("%s: Failed ioremap.\n", __func__);
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	if (read)
+		memcpy(buffer, fw_buf, count);
+	else
+		memcpy(fw_buf, buffer, count);
+
+	*offset += count;
+	iounmap(fw_buf);
+
+out:
+	return retval;
+}
+
+static ssize_t firmware_direct_read(struct file *filp, struct kobject *kobj,
+				  struct bin_attribute *bin_attr,
+				  char *buffer, loff_t offset, size_t count)
+{
+	struct device *dev = to_dev(kobj);
+	struct firmware_priv *fw_priv = to_firmware_priv(dev);
+	struct firmware *fw;
+	ssize_t ret_count;
+
+	mutex_lock(&fw_lock);
+	fw = fw_priv->fw;
+
+	if (offset > fw->size) {
+		ret_count = 0;
+		goto out;
+	}
+	if (count > fw->size - offset)
+		count = fw->size - offset;
+
+	if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
+		ret_count = -ENODEV;
+		goto out;
+	}
+
+	ret_count = __firmware_data_rw(fw_priv, buffer, &offset, count, 1);
+out:
+	mutex_unlock(&fw_lock);
+	return ret_count;
+}
+
 static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj,
 				  struct bin_attribute *bin_attr,
 				  char *buffer, loff_t offset, size_t count)
@@ -368,6 +441,35 @@
 	return 0;
 }
 
+static ssize_t firmware_direct_write(struct file *filp, struct kobject *kobj,
+				   struct bin_attribute *bin_attr,
+				   char *buffer, loff_t offset, size_t count)
+{
+	struct device *dev = to_dev(kobj);
+	struct firmware_priv *fw_priv = to_firmware_priv(dev);
+	struct firmware *fw;
+	ssize_t retval;
+
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	mutex_lock(&fw_lock);
+	fw = fw_priv->fw;
+	if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	retval = __firmware_data_rw(fw_priv, buffer, &offset, count, 0);
+	if (retval < 0)
+		goto out;
+
+	fw->size = max_t(size_t, offset, fw->size);
+out:
+	mutex_unlock(&fw_lock);
+	return retval;
+}
+
 /**
  * firmware_data_write - write method for firmware
  * @filp: open sysfs file
@@ -433,6 +535,13 @@
 	.write = firmware_data_write,
 };
 
+static struct bin_attribute firmware_direct_attr_data = {
+	.attr = { .name = "data", .mode = 0644 },
+	.size = 0,
+	.read = firmware_direct_read,
+	.write = firmware_direct_write,
+};
+
 static void firmware_class_timeout(u_long data)
 {
 	struct firmware_priv *fw_priv = (struct firmware_priv *) data;
@@ -511,6 +620,8 @@
 {
 	int retval = 0;
 	struct device *f_dev = &fw_priv->dev;
+	struct bin_attribute *fw_attr_data = fw_priv->dest_addr ?
+			&firmware_direct_attr_data : &firmware_attr_data;
 
 	dev_set_uevent_suppress(f_dev, true);
 
@@ -523,7 +634,7 @@
 		goto err_put_dev;
 	}
 
-	retval = device_create_bin_file(f_dev, &firmware_attr_data);
+	retval = device_create_bin_file(f_dev, fw_attr_data);
 	if (retval) {
 		dev_err(f_dev, "%s: sysfs_create_bin_file failed\n", __func__);
 		goto err_del_dev;
@@ -558,7 +669,7 @@
 
 	device_remove_file(f_dev, &dev_attr_loading);
 err_del_bin_attr:
-	device_remove_bin_file(f_dev, &firmware_attr_data);
+	device_remove_bin_file(f_dev, fw_attr_data);
 err_del_dev:
 	device_del(f_dev);
 err_put_dev:
@@ -566,6 +677,35 @@
 	return retval;
 }
 
+static int
+__request_firmware(const struct firmware **firmware_p, const char *name,
+		   struct device *device, phys_addr_t dest_addr, size_t size)
+{
+	struct firmware_priv *fw_priv;
+	int ret;
+
+	fw_priv = _request_firmware_prepare(firmware_p, name, device, true,
+					    false);
+	if (IS_ERR_OR_NULL(fw_priv))
+		return PTR_RET(fw_priv);
+
+	fw_priv->dest_addr = dest_addr;
+	fw_priv->dest_size = size;
+
+	ret = usermodehelper_read_trylock();
+	if (WARN_ON(ret)) {
+		dev_err(device, "firmware: %s will not be loaded\n", name);
+	} else {
+		ret = _request_firmware_load(fw_priv, true,
+					firmware_loading_timeout());
+		usermodehelper_read_unlock();
+	}
+	if (ret)
+		_request_firmware_cleanup(firmware_p);
+
+	return ret;
+}
+
 /**
  * request_firmware: - send firmware request and wait for it
  * @firmware_p: pointer to firmware image
@@ -583,27 +723,33 @@
  **/
 int
 request_firmware(const struct firmware **firmware_p, const char *name,
-                 struct device *device)
+		 struct device *device)
 {
-	struct firmware_priv *fw_priv;
+	return __request_firmware(firmware_p, name, device, 0, 0);
+}
+
+/**
+ * request_firmware_direct: - send firmware request and wait for it
+ * @name: name of firmware file
+ * @device: device for which firmware is being loaded
+ * @dest_addr: Destination address for the firmware
+ * @dest_size:
+ *
+ *      Similar to request_firmware, except takes in a buffer address and
+ *      copies firmware data directly to that buffer. Returns the size of
+ *      the firmware that was loaded at dest_addr.
+*/
+int request_firmware_direct(const char *name, struct device *device,
+			phys_addr_t dest_addr, size_t dest_size)
+{
+	const struct firmware *fp = NULL;
 	int ret;
 
-	fw_priv = _request_firmware_prepare(firmware_p, name, device, true,
-					    false);
-	if (IS_ERR_OR_NULL(fw_priv))
-		return PTR_RET(fw_priv);
-
-	ret = usermodehelper_read_trylock();
-	if (WARN_ON(ret)) {
-		dev_err(device, "firmware: %s will not be loaded\n", name);
-	} else {
-		ret = _request_firmware_load(fw_priv, true,
-					firmware_loading_timeout());
-		usermodehelper_read_unlock();
-	}
+	ret = __request_firmware(&fp, name, device, dest_addr, dest_size);
 	if (ret)
-		_request_firmware_cleanup(firmware_p);
-
+		return ret;
+	ret = fp->size;
+	release_firmware(fp);
 	return ret;
 }
 
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c
index 0de37c9..58b0513 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.c
@@ -742,6 +742,16 @@
 
 	fd_install(ret, lock->file);
 
+	/*
+	 * Taking a reference for lock file.
+	 * This is required as now we have two file descriptor
+	 * pointing to same file. If one FD is closed, lock file
+	 * will be closed. Taking this reference will make sure
+	 * that file doesn't get close. This refrence will go
+	 * when client will call close on this FD.
+	 */
+	fget(ret);
+
 	return ret;
 }
 EXPORT_SYMBOL(genlock_get_fd_handle);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 83d94f1..a740be6 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -395,21 +395,26 @@
 static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra,
 			remote_arg_t *rpra, remote_arg_t *upra,
 			struct fastrpc_buf *ibuf, struct fastrpc_buf **abufs,
-			int *nbufs)
+			int *nbufs, int *fds)
 {
+	struct fastrpc_apps *me = &gfa;
 	struct smq_invoke_buf *list;
 	struct fastrpc_buf *pbuf = ibuf, *obufs = 0;
 	struct smq_phy_page *pages;
+	struct ion_handle **handles = NULL;
 	void *args;
 	int i, rlen, size, used, inh, bufs = 0, err = 0;
 	int inbufs = REMOTE_SCALARS_INBUFS(sc);
 	int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+	unsigned long iova, len;
 
 	list = smq_invoke_buf_start(rpra, sc);
 	pages = smq_phy_page_start(sc, list);
 	used = ALIGN(pbuf->used, BALIGN);
 	args = (void *)((char *)pbuf->virt + used);
 	rlen = pbuf->size - used;
+	if (fds)
+		handles = (struct ion_handle **)(fds + inbufs + outbufs);
 	for (i = 0; i < inbufs + outbufs; ++i) {
 
 		rpra[i].buf.len = pra[i].buf.len;
@@ -418,6 +423,22 @@
 		if (list[i].num) {
 			rpra[i].buf.pv = pra[i].buf.pv;
 			continue;
+		} else if (me->smmu.enabled && fds && (fds[i] >= 0)) {
+			len = buf_page_size(pra[i].buf.len);
+			handles[i] = ion_import_dma_buf(me->iclient, fds[i]);
+			VERIFY(err, 0 == IS_ERR_OR_NULL(handles[i]));
+			if (err)
+				goto bail;
+			VERIFY(err, 0 == ion_map_iommu(me->iclient, handles[i],
+						me->smmu.domain_id, 0, SZ_4K, 0,
+						&iova, &len, 0, 0));
+			if (err)
+				goto bail;
+			rpra[i].buf.pv = pra[i].buf.pv;
+			list[i].num = 1;
+			pages[list[i].pgidx].addr = iova;
+			pages[list[i].pgidx].size = len;
+			continue;
 		}
 		if (rlen < pra[i].buf.len) {
 			struct fastrpc_buf *b;
@@ -770,15 +791,17 @@
 static int fastrpc_release_current_dsp_process(void);
 
 static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t kernel,
-			struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra)
+			struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra,
+			int *fds)
 {
 	remote_arg_t *rpra = 0;
 	struct fastrpc_device *dev = 0;
 	struct smq_invoke_ctx *ctx = 0;
 	struct fastrpc_buf obuf, *abufs = 0, *b;
+	struct ion_handle **handles = NULL;
 	int interrupted = 0;
 	uint32_t sc;
-	int i, nbufs = 0, err = 0;
+	int i, bufs, nbufs = 0, err = 0;
 
 	sc = invoke->sc;
 	obuf.handle = 0;
@@ -798,7 +821,7 @@
 			goto bail;
 		rpra = (remote_arg_t *)obuf.virt;
 		VERIFY(err, 0 == get_args(kernel, sc, pra, rpra, invoke->pra,
-					&obuf, &abufs, &nbufs));
+					&obuf, &abufs, &nbufs, fds));
 		if (err)
 			goto bail;
 	}
@@ -828,8 +851,19 @@
 	}
 	context_free(ctx);
 
-	if (me->smmu.enabled)
+	if (me->smmu.enabled) {
+		bufs = REMOTE_SCALARS_LENGTH(sc);
+		if (fds) {
+			handles = (struct ion_handle **)(fds + bufs);
+			for (i = 0; i < bufs; i++)
+				if (!IS_ERR_OR_NULL(handles[i])) {
+					ion_unmap_iommu(me->iclient, handles[i],
+							me->smmu.domain_id, 0);
+					ion_free(me->iclient, handles[i]);
+				}
+		}
 		iommu_detach_group(me->smmu.domain, me->smmu.group);
+	}
 	for (i = 0, b = abufs; i < nbufs; ++i, ++b)
 		free_mem(b);
 
@@ -856,7 +890,7 @@
 	ioctl.handle = 1;
 	ioctl.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
 	ioctl.pra = ra;
-	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
 	return err;
 }
 
@@ -874,7 +908,7 @@
 	ioctl.handle = 1;
 	ioctl.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
 	ioctl.pra = ra;
-	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
 	return err;
 }
 
@@ -912,7 +946,7 @@
 	ioctl.handle = 1;
 	ioctl.sc = REMOTE_SCALARS_MAKE(2, 2, 1);
 	ioctl.pra = ra;
-	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
 	mmap->vaddrout = routargs.vaddrout;
 	if (err)
 		goto bail;
@@ -941,7 +975,7 @@
 	ioctl.handle = 1;
 	ioctl.sc = REMOTE_SCALARS_MAKE(3, 1, 0);
 	ioctl.pra = ra;
-	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
 	return err;
 }
 
@@ -1107,33 +1141,49 @@
 				 unsigned long ioctl_param)
 {
 	struct fastrpc_apps *me = &gfa;
-	struct fastrpc_ioctl_invoke invoke;
+	struct fastrpc_ioctl_invoke_fd invokefd;
+	struct fastrpc_ioctl_invoke *invoke = &invokefd.inv;
 	struct fastrpc_ioctl_mmap mmap;
 	struct fastrpc_ioctl_munmap munmap;
 	remote_arg_t *pra = 0;
 	void *param = (char *)ioctl_param;
 	struct file_data *fdata = (struct file_data *)file->private_data;
-	int bufs, err = 0;
+	int *fds = 0;
+	int bufs, size = 0, err = 0;
 
 	switch (ioctl_num) {
+	case FASTRPC_IOCTL_INVOKE_FD:
 	case FASTRPC_IOCTL_INVOKE:
-		VERIFY(err, 0 == copy_from_user(&invoke, param,
-						sizeof(invoke)));
+		invokefd.fds = 0;
+		size = (ioctl_num == FASTRPC_IOCTL_INVOKE) ?
+				sizeof(*invoke) : sizeof(invokefd);
+		VERIFY(err, 0 == copy_from_user(&invokefd, param, size));
 		if (err)
 			goto bail;
-		bufs = REMOTE_SCALARS_INBUFS(invoke.sc) +
-			REMOTE_SCALARS_OUTBUFS(invoke.sc);
+		bufs = REMOTE_SCALARS_INBUFS(invoke->sc) +
+			REMOTE_SCALARS_OUTBUFS(invoke->sc);
 		if (bufs) {
-			bufs = bufs * sizeof(*pra);
-			VERIFY(err, 0 != (pra = kmalloc(bufs, GFP_KERNEL)));
+			size = bufs * sizeof(*pra);
+			if (invokefd.fds)
+				size = size + bufs * sizeof(*fds) +
+					bufs * sizeof(struct ion_handle *);
+			VERIFY(err, 0 != (pra = kzalloc(size, GFP_KERNEL)));
 			if (err)
 				goto bail;
 		}
-		VERIFY(err, 0 == copy_from_user(pra, invoke.pra, bufs));
+		VERIFY(err, 0 == copy_from_user(pra, invoke->pra,
+						bufs * sizeof(*pra)));
 		if (err)
 			goto bail;
-		VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 0, &invoke,
-								pra)));
+		if (invokefd.fds) {
+			fds = (int *)(pra + bufs);
+			VERIFY(err, 0 == copy_from_user(fds, invokefd.fds,
+							bufs * sizeof(*fds)));
+		if (err)
+			goto bail;
+		}
+		VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 0, invoke,
+								pra, fds)));
 		if (err)
 			goto bail;
 		break;
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index f2804ad..da70eb5 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -19,6 +19,7 @@
 #define FASTRPC_IOCTL_INVOKE  _IOWR('R', 1, struct fastrpc_ioctl_invoke)
 #define FASTRPC_IOCTL_MMAP    _IOWR('R', 2, struct fastrpc_ioctl_mmap)
 #define FASTRPC_IOCTL_MUNMAP  _IOWR('R', 3, struct fastrpc_ioctl_munmap)
+#define FASTRPC_IOCTL_INVOKE_FD  _IOWR('R', 4, struct fastrpc_ioctl_invoke_fd)
 #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
 #define DEVICE_NAME      "adsprpc-smd"
 
@@ -94,6 +95,11 @@
 	remote_arg_t *pra;	/* remote arguments list */
 };
 
+struct fastrpc_ioctl_invoke_fd {
+	struct fastrpc_ioctl_invoke inv;
+	int *fds;		/* fd list */
+};
+
 struct fastrpc_ioctl_munmap {
 	uint32_t vaddrout;	/* address to unmap */
 	int  size;		/* size */
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index d01496e..0c67ed8 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -20,6 +20,8 @@
 #include <linux/workqueue.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_device.h>
+#include <linux/pm_wakeup.h>
+#include <linux/spinlock.h>
 #include <asm/current.h>
 #ifdef CONFIG_DIAG_OVER_USB
 #include <mach/usbdiag.h>
@@ -39,6 +41,12 @@
 struct mutex dci_event_mask_mutex;
 struct mutex dci_health_mutex;
 
+spinlock_t ws_lock;
+unsigned long ws_lock_flags;
+
+/* Number of milliseconds anticipated to process the DCI data */
+#define DCI_WAKEUP_TIMEOUT 1
+
 #define DCI_CHK_CAPACITY(entry, new_data_len)				\
 ((entry->data_len + new_data_len > entry->total_capacity) ? 1 : 0)	\
 
@@ -96,6 +104,11 @@
 		read_bytes += 5 + dci_pkt_len;
 		buf += 5 + dci_pkt_len; /* advance to next DCI pkt */
 	}
+	/* Release wakeup source when there are no more clients to
+	   process DCI data */
+	if (driver->num_dci_client == 0)
+		diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
 	/* wake up all sleeping DCI clients which have some data */
 	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
 		if (driver->dci_client_tbl[i].client &&
@@ -1101,6 +1114,9 @@
 			diag_smd_notify);
 		driver->smd_dci[index].ch_save =
 			driver->smd_dci[index].ch;
+		driver->dci_device = &pdev->dev;
+		driver->dci_device->power.wakeup = wakeup_source_register
+							("DIAG_DCI_WS");
 		if (err)
 			pr_err("diag: In %s, cannot open DCI port, Id = %d, err: %d\n",
 				__func__, pdev->id, err);
@@ -1123,6 +1139,9 @@
 			diag_smd_notify);
 		driver->smd_dci_cmd[index].ch_save =
 			driver->smd_dci_cmd[index].ch;
+		driver->dci_cmd_device = &pdev->dev;
+		driver->dci_cmd_device->power.wakeup = wakeup_source_register
+							("DIAG_DCI_CMD_WS");
 		if (err)
 			pr_err("diag: In %s, cannot open DCI port, Id = %d, err: %d\n",
 				__func__, pdev->id, err);
@@ -1174,10 +1193,13 @@
 	driver->dci_tag = 0;
 	driver->dci_client_id = 0;
 	driver->num_dci_client = 0;
+	driver->dci_device = NULL;
+	driver->dci_cmd_device = NULL;
 	mutex_init(&driver->dci_mutex);
 	mutex_init(&dci_log_mask_mutex);
 	mutex_init(&dci_event_mask_mutex);
 	mutex_init(&dci_health_mutex);
+	spin_lock_init(&ws_lock);
 
 	for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
 		success = diag_smd_constructor(&driver->smd_dci[i], i,
@@ -1408,3 +1430,26 @@
 		driver->dci_client_tbl[i].real_time = real_time;
 	return i;
 }
+
+void diag_dci_try_activate_wakeup_source(smd_channel_t *channel)
+{
+	spin_lock_irqsave(&ws_lock, ws_lock_flags);
+	if (channel == driver->smd_dci[MODEM_DATA].ch) {
+		pm_wakeup_event(driver->dci_device, DCI_WAKEUP_TIMEOUT);
+		pm_stay_awake(driver->dci_device);
+	} else if (channel == driver->smd_dci_cmd[MODEM_DATA].ch) {
+		pm_wakeup_event(driver->dci_cmd_device, DCI_WAKEUP_TIMEOUT);
+		pm_stay_awake(driver->dci_cmd_device);
+	}
+	spin_unlock_irqrestore(&ws_lock, ws_lock_flags);
+}
+
+void diag_dci_try_deactivate_wakeup_source(smd_channel_t *channel)
+{
+	spin_lock_irqsave(&ws_lock, ws_lock_flags);
+	if (channel == driver->smd_dci[MODEM_DATA].ch)
+		pm_relax(driver->dci_device);
+	else if (channel == driver->smd_dci_cmd[MODEM_DATA].ch)
+		pm_relax(driver->dci_cmd_device);
+	spin_unlock_irqrestore(&ws_lock, ws_lock_flags);
+}
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 2335d37..520995b 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -138,4 +138,7 @@
 void diag_dci_smd_record_info(int read_bytes);
 uint8_t diag_dci_get_cumulative_real_time(void);
 int diag_dci_set_real_time(int client_id, uint8_t real_time);
+/* Functions related to DCI wakeup sources */
+void diag_dci_try_activate_wakeup_source(smd_channel_t *channel);
+void diag_dci_try_deactivate_wakeup_source(smd_channel_t *channel);
 #endif
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index 0badda6..3d1a6cd 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -176,6 +176,26 @@
 		bytes_in_buf += bytes_written;
 		bytes_remaining -= bytes_written;
 #endif
+		if (driver->dci_device) {
+			bytes_written = scnprintf(buf+bytes_in_buf,
+						  bytes_remaining,
+				"dci power active, relax: %lu, %lu\n",
+				driver->dci_device->power.wakeup->active_count,
+				driver->dci_device->power.wakeup->relax_count);
+			bytes_in_buf += bytes_written;
+			bytes_remaining -= bytes_written;
+		}
+		if (driver->dci_cmd_device) {
+			bytes_written = scnprintf(buf+bytes_in_buf,
+						  bytes_remaining,
+				"dci cmd power active, relax: %lu, %lu\n",
+				driver->dci_cmd_device->power.wakeup->
+						  active_count,
+				driver->dci_cmd_device->power.wakeup->
+						  relax_count);
+			bytes_in_buf += bytes_written;
+			bytes_remaining -= bytes_written;
+		}
 	}
 	temp_data += diag_dbgfs_dci_data_index;
 	for (i = diag_dbgfs_dci_data_index; i < DIAG_DCI_DEBUG_CNT; i++) {
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index b7784b5..7154942 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -27,7 +27,7 @@
 
 /* Size of the USB buffers used for read and write*/
 #define USB_MAX_OUT_BUF 4096
-#define APPS_BUF_SIZE	2000
+#define APPS_BUF_SIZE	4096
 #define IN_BUF_SIZE		16384
 #define MAX_IN_BUF_SIZE	32768
 #define MAX_SYNC_OBJ_NAME_SIZE	32
@@ -333,6 +333,8 @@
 	unsigned hdlc_count;
 	unsigned hdlc_escape;
 	int in_busy_pktdata;
+	struct device *dci_device;
+	struct device *dci_cmd_device;
 	/* Variables for non real time mode */
 	int real_time_mode;
 	int real_time_update_busy;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 7513c7b..6e70062 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -306,9 +306,10 @@
 
 	mutex_lock(&driver->diagchar_mutex);
 	driver->ref_count--;
-	/* On Client exit, try to destroy all 3 pools */
+	/* On Client exit, try to destroy all 4 pools */
 	diagmem_exit(driver, POOL_TYPE_COPY);
 	diagmem_exit(driver, POOL_TYPE_HDLC);
+	diagmem_exit(driver, POOL_TYPE_USER);
 	diagmem_exit(driver, POOL_TYPE_WRITE_STRUCT);
 	for (i = 0; i < driver->num_clients; i++) {
 		if (NULL != diagpriv_data && diagpriv_data->pid ==
@@ -1452,19 +1453,25 @@
 		driver->data_ready[index] ^= DCI_DATA_TYPE;
 		for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
 			driver->smd_dci[i].in_busy_1 = 0;
-			if (driver->smd_dci[i].ch)
+			if (driver->smd_dci[i].ch) {
+				diag_dci_try_deactivate_wakeup_source(
+						driver->smd_dci[i].ch);
 				queue_work(driver->diag_dci_wq,
 				&(driver->smd_dci[i].diag_read_smd_work));
+			}
 		}
 		if (driver->supports_separate_cmdrsp) {
 			for (i = 0; i < NUM_SMD_DCI_CMD_CHANNELS; i++) {
 				if (!driver->separate_cmdrsp[i])
 					continue;
 				driver->smd_dci_cmd[i].in_busy_1 = 0;
-				if (driver->smd_dci_cmd[i].ch)
+				if (driver->smd_dci_cmd[i].ch) {
+					diag_dci_try_deactivate_wakeup_source(
+						driver->smd_dci_cmd[i].ch);
 					queue_work(driver->diag_dci_wq,
 						&(driver->smd_dci_cmd[i].
 							diag_read_smd_work));
+				}
 			}
 		}
 		goto exit;
@@ -1527,11 +1534,14 @@
 		err = copy_from_user(user_space_data, buf + 4, payload_size);
 		if (err) {
 			pr_alert("diag: copy failed for DCI data\n");
+			diagmem_free(driver, user_space_data, POOL_TYPE_USER);
+			user_space_data = NULL;
 			return DIAG_DCI_SEND_DATA_FAIL;
 		}
 		err = diag_process_dci_transaction(user_space_data,
 							payload_size);
 		diagmem_free(driver, user_space_data, POOL_TYPE_USER);
+		user_space_data = NULL;
 		return err;
 	}
 	if (pkt_type == CALLBACK_DATA_TYPE) {
@@ -1542,16 +1552,19 @@
 			return -EBADMSG;
 		}
 
+		mutex_lock(&driver->diagchar_mutex);
 		buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
 		if (!buf_copy) {
 			driver->dropped_count++;
+			mutex_unlock(&driver->diagchar_mutex);
 			return -ENOMEM;
 		}
 
 		err = copy_from_user(buf_copy, buf + 4, payload_size);
 		if (err) {
 			pr_err("diag: copy failed for user space data\n");
-			return -EIO;
+			ret = -EIO;
+			goto fail_free_copy;
 		}
 		/* Check for proc_type */
 		remote_proc = diag_get_remote(*(int *)buf_copy);
@@ -1560,8 +1573,7 @@
 			wait_event_interruptible(driver->wait_q,
 				 (driver->in_busy_pktdata == 0));
 			ret = diag_process_apps_pkt(buf_copy, payload_size);
-			diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
-			return ret;
+			goto fail_free_copy;
 		}
 		/* The packet is for the remote processor */
 		token_offset = 4;
@@ -1574,20 +1586,20 @@
 							1 + payload_size);
 		send.terminate = 1;
 
-		mutex_lock(&driver->diagchar_mutex);
+
 		if (!buf_hdlc)
 			buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
 							POOL_TYPE_HDLC);
 		if (!buf_hdlc) {
 			ret = -ENOMEM;
-			goto fail_free_hdlc;
+			driver->used = 0;
+			goto fail_free_copy;
 		}
 		if (HDLC_OUT_BUF_SIZE < (2 * payload_size) + 3) {
 			pr_err("diag: Dropping packet, HDLC encoded packet payload size crosses buffer limit. Current payload size %d\n",
 					((2*payload_size) + 3));
 			driver->dropped_count++;
 			ret = -EBADMSG;
-			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
 			goto fail_free_hdlc;
 		}
 		enc.dest = buf_hdlc + driver->used;
@@ -1614,10 +1626,11 @@
 			if (diag_hsic[index].hsic_ch && (payload_size > 0)) {
 				/* wait sending mask updates
 				 * if HSIC ch not ready */
-				if (diag_hsic[index].in_busy_hsic_write)
+				while (diag_hsic[index].in_busy_hsic_write) {
 					wait_event_interruptible(driver->wait_q,
 						(diag_hsic[index].
 						 in_busy_hsic_write != 1));
+				}
 				diag_hsic[index].in_busy_hsic_write = 1;
 				diag_hsic[index].in_busy_hsic_read_on_device =
 									0;
@@ -1652,13 +1665,7 @@
 			}
 		}
 #endif
-		diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
-		diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
-		buf_copy = NULL;
-		buf_hdlc = NULL;
-		driver->used = 0;
-		mutex_unlock(&driver->diagchar_mutex);
-		return ret;
+		goto fail_free_hdlc;
 	}
 	if (pkt_type == USER_SPACE_DATA_TYPE) {
 		user_space_data = diagmem_alloc(driver, payload_size,
@@ -1672,6 +1679,7 @@
 		if (err) {
 			pr_err("diag: copy failed for user space data\n");
 			diagmem_free(driver, user_space_data, POOL_TYPE_USER);
+			user_space_data = NULL;
 			return -EIO;
 		}
 		/* Check for proc_type */
@@ -1690,6 +1698,7 @@
 				pr_alert("diag: mask request Invalid\n");
 				diagmem_free(driver, user_space_data,
 							POOL_TYPE_USER);
+				user_space_data = NULL;
 				return -EFAULT;
 			}
 		}
@@ -1730,10 +1739,11 @@
 			if (diag_hsic[index].hsic_ch) {
 				/* wait sending mask updates
 				 * if HSIC ch not ready */
-				if (diag_hsic[index].in_busy_hsic_write)
+				while (diag_hsic[index].in_busy_hsic_write) {
 					wait_event_interruptible(driver->wait_q,
 						(diag_hsic[index].
 						 in_busy_hsic_write != 1));
+				}
 				diag_hsic[index].in_busy_hsic_write = 1;
 				diag_hsic[index].in_busy_hsic_read_on_device =
 									0;
@@ -1767,6 +1777,7 @@
 							err);
 					diagmem_free(driver, user_space_data,
 								POOL_TYPE_USER);
+					user_space_data = NULL;
 					return err;
 				}
 			}
@@ -1777,6 +1788,7 @@
 			diag_process_hdlc((void *)
 				(user_space_data + token_offset), payload_size);
 		diagmem_free(driver, user_space_data, POOL_TYPE_USER);
+		user_space_data = NULL;
 		return 0;
 	}
 
@@ -1788,9 +1800,11 @@
 		return -EBADMSG;
 	}
 
+	mutex_lock(&driver->diagchar_mutex);
 	buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
 	if (!buf_copy) {
 		driver->dropped_count++;
+		mutex_unlock(&driver->diagchar_mutex);
 		return -ENOMEM;
 	}
 
@@ -1834,13 +1848,13 @@
 			length++;
 	}
 #endif
-	mutex_lock(&driver->diagchar_mutex);
 	if (!buf_hdlc)
 		buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
 						 POOL_TYPE_HDLC);
 	if (!buf_hdlc) {
 		ret = -ENOMEM;
-		goto fail_free_hdlc;
+		driver->used = 0;
+		goto fail_free_copy;
 	}
 	if (HDLC_OUT_BUF_SIZE < (2*payload_size) + 3) {
 		pr_err("diag: Dropping packet, HDLC encoded packet payload size crosses buffer limit. Current payload size %d\n",
@@ -1853,7 +1867,6 @@
 		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
 		if (err) {
 			/*Free the buffer right away if write failed */
-			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
 			if (driver->logging_mode == USB_MODE)
 				diagmem_free(driver, (unsigned char *)driver->
 					write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
@@ -1866,7 +1879,7 @@
 							 POOL_TYPE_HDLC);
 		if (!buf_hdlc) {
 			ret = -ENOMEM;
-			goto fail_free_hdlc;
+			goto fail_free_copy;
 		}
 	}
 
@@ -1882,7 +1895,6 @@
 		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
 		if (err) {
 			/*Free the buffer right away if write failed */
-			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
 			if (driver->logging_mode == USB_MODE)
 				diagmem_free(driver, (unsigned char *)driver->
 					write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
@@ -1895,7 +1907,7 @@
 							 POOL_TYPE_HDLC);
 		if (!buf_hdlc) {
 			ret = -ENOMEM;
-			goto fail_free_hdlc;
+			goto fail_free_copy;
 		}
 		enc.dest = buf_hdlc + driver->used;
 		enc.dest_last = (void *)(buf_hdlc + driver->used +
@@ -1908,7 +1920,6 @@
 		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
 		if (err) {
 			/*Free the buffer right away if write failed */
-			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
 			if (driver->logging_mode == USB_MODE)
 				diagmem_free(driver, (unsigned char *)driver->
 					write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
@@ -1920,6 +1931,7 @@
 	}
 
 	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+	buf_copy = NULL;
 	mutex_unlock(&driver->diagchar_mutex);
 	if (!timer_in_progress)	{
 		timer_in_progress = 1;
@@ -1928,14 +1940,18 @@
 	return 0;
 
 fail_free_hdlc:
+	diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
 	buf_hdlc = NULL;
 	driver->used = 0;
 	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+	buf_copy = NULL;
 	mutex_unlock(&driver->diagchar_mutex);
 	return ret;
 
 fail_free_copy:
 	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+	buf_copy = NULL;
+	mutex_unlock(&driver->diagchar_mutex);
 	return ret;
 }
 
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6e7080e..379dc4d 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -69,6 +69,13 @@
 void encode_rsp_and_send(int buf_length)
 {
 	struct diag_smd_info *data = &(driver->smd_data[MODEM_DATA]);
+
+	if (buf_length > APPS_BUF_SIZE) {
+		pr_err("diag: In %s, invalid len %d, permissible len %d\n",
+					__func__, buf_length, APPS_BUF_SIZE);
+		return;
+	}
+
 	send.state = DIAG_STATE_START;
 	send.pkt = driver->apps_rsp_buf;
 	send.last = (void *)(driver->apps_rsp_buf + buf_length);
@@ -390,10 +397,18 @@
 			(smd_info->type == SMD_DATA_TYPE))
 		buf = smd_info->buf_in_2;
 
+	if (!buf && (smd_info->type == SMD_DCI_TYPE ||
+					smd_info->type == SMD_DCI_CMD_TYPE))
+		diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
 	if (smd_info->ch && buf) {
 		temp_buf = buf;
 		pkt_len = smd_cur_packet_size(smd_info->ch);
 
+		if (pkt_len == 0 && (smd_info->type == SMD_DCI_TYPE ||
+					smd_info->type == SMD_DCI_CMD_TYPE))
+			diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
 		while (pkt_len && (pkt_len != total_recd)) {
 			loop_count++;
 			r = smd_read_avail(smd_info->ch);
@@ -412,7 +427,7 @@
 				} else {
 					pr_debug("diag: In %s, return from wait_event ch closed\n",
 						__func__);
-					return;
+					goto fail_return;
 				}
 			}
 			total_recd += r;
@@ -425,13 +440,13 @@
 				} else {
 					pr_err("diag: In %s, SMD sending in packets more than %d bytes\n",
 						__func__, MAX_IN_BUF_SIZE);
-					return;
+					goto fail_return;
 				}
 			}
 			if (pkt_len < r) {
 				pr_err("diag: In %s, SMD sending incorrect pkt\n",
 					__func__);
-				return;
+				goto fail_return;
 			}
 			if (pkt_len > r) {
 				pr_debug("diag: In %s, SMD sending partial pkt %d %d %d %d %d %d\n",
@@ -462,6 +477,13 @@
 		(driver->logging_mode == MEMORY_DEVICE_MODE)) {
 			chk_logging_wakeup();
 	}
+	return;
+
+fail_return:
+	if (smd_info->type == SMD_DCI_TYPE ||
+					smd_info->type == SMD_DCI_CMD_TYPE)
+		diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+	return;
 }
 
 void diag_read_smd_work_fn(struct work_struct *work)
@@ -1300,10 +1322,12 @@
 {
 	int i;
 
-	if (index > 490) {
-		pr_err("diag: error response too huge, aborting\n");
+	/* -1 to accomodate the first byte 0x13 */
+	if (index > APPS_BUF_SIZE-1) {
+		pr_err("diag: cannot send err rsp, huge length: %d\n", index);
 		return;
 	}
+
 	driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
 	for (i = 0; i < index; i++)
 		driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
@@ -1705,10 +1729,12 @@
 	wake_up(&driver->smd_wait_q);
 
 	if (smd_info->type == SMD_DCI_TYPE ||
-		smd_info->type == SMD_DCI_CMD_TYPE)
+					smd_info->type == SMD_DCI_CMD_TYPE) {
+		if (event == SMD_EVENT_DATA)
+			diag_dci_try_activate_wakeup_source(smd_info->ch);
 		queue_work(driver->diag_dci_wq,
 				&(smd_info->diag_read_smd_work));
-	else
+	} else
 		queue_work(driver->diag_wq, &(smd_info->diag_read_smd_work));
 }
 
diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c
index e5a6734..143959b 100644
--- a/drivers/char/diag/diagfwd_bridge.c
+++ b/drivers/char/diag/diagfwd_bridge.c
@@ -61,9 +61,11 @@
 		diag_bridge[index].usb_connected = 1;
 	}
 
-	if (index == SMUX && driver->diag_smux_enabled) {
-		driver->in_busy_smux = 0;
-		diagfwd_connect_smux();
+	if (index == SMUX) {
+		if (driver->diag_smux_enabled) {
+			driver->in_busy_smux = 0;
+			diagfwd_connect_smux();
+		}
 	} else {
 		if (index >= MAX_HSIC_CH) {
 			pr_err("diag: Invalid hsic channel index %d in %s\n",
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index fa46aab..d1f72a8 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -203,6 +203,7 @@
 
 	/* The write of the data to the HSIC bridge is complete */
 	diag_hsic[index].in_busy_hsic_write = 0;
+	wake_up_interruptible(&driver->wait_q);
 
 	if (!diag_hsic[index].hsic_ch) {
 		pr_err("DIAG in %s: hsic_ch == 0, ch = %d\n", __func__, index);
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index 132df90..6efab5b 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -65,6 +65,7 @@
 #define CSR_QDSSPWRREQIGNORE	(0x060)
 #define CSR_QDSSSPARE		(0x064)
 #define CSR_IPCAT		(0x068)
+#define CSR_BYTECNTVAL		(0x06C)
 
 #define BLKSIZE_256		0
 #define BLKSIZE_512		1
@@ -159,6 +160,19 @@
 }
 EXPORT_SYMBOL(coresight_csr_hwctrl_set);
 
+void coresight_csr_set_byte_cntr(uint32_t count)
+{
+	struct csr_drvdata *drvdata = csrdrvdata;
+
+	CSR_UNLOCK(drvdata);
+
+	csr_writel(drvdata, count, CSR_BYTECNTVAL);
+	mb();
+
+	CSR_LOCK(drvdata);
+}
+EXPORT_SYMBOL(coresight_csr_set_byte_cntr);
+
 static int __devinit csr_probe(struct platform_device *pdev)
 {
 	int ret;
diff --git a/drivers/coresight/coresight-cti.c b/drivers/coresight/coresight-cti.c
index d0900d1..d139583 100644
--- a/drivers/coresight/coresight-cti.c
+++ b/drivers/coresight/coresight-cti.c
@@ -107,22 +107,37 @@
 	return 0;
 }
 
-static void __cti_map_trigin(struct cti_drvdata *drvdata, int trig, int ch)
+static int __cti_map_trigin(struct cti_drvdata *drvdata, int trig, int ch)
 {
 	uint32_t ctien;
+	int ret;
+
+	if (drvdata->refcnt == 0) {
+		ret = cti_enable(drvdata);
+		if (ret)
+			return ret;
+	}
 
 	CTI_UNLOCK(drvdata);
 
 	ctien = cti_readl(drvdata, CTIINEN(trig));
+	if (ctien & (0x1 << ch))
+		goto out;
 	cti_writel(drvdata, (ctien | 0x1 << ch), CTIINEN(trig));
 
 	CTI_LOCK(drvdata);
+
+	drvdata->refcnt++;
+	return 0;
+out:
+	CTI_LOCK(drvdata);
+	return 0;
 }
 
 int coresight_cti_map_trigin(struct coresight_cti *cti, int trig, int ch)
 {
 	struct cti_drvdata *drvdata;
-	int ret = 0;
+	int ret;
 
 	if (IS_ERR_OR_NULL(cti))
 		return -EINVAL;
@@ -134,36 +149,43 @@
 	drvdata = to_cti_drvdata(cti);
 
 	mutex_lock(&drvdata->mutex);
-	if (drvdata->refcnt == 0) {
-		ret = cti_enable(drvdata);
-		if (ret)
-			goto err;
-	}
-	drvdata->refcnt++;
-
-	__cti_map_trigin(drvdata, trig, ch);
-err:
+	ret = __cti_map_trigin(drvdata, trig, ch);
 	mutex_unlock(&drvdata->mutex);
 	return ret;
 }
 EXPORT_SYMBOL(coresight_cti_map_trigin);
 
-static void __cti_map_trigout(struct cti_drvdata *drvdata, int trig, int ch)
+static int __cti_map_trigout(struct cti_drvdata *drvdata, int trig, int ch)
 {
 	uint32_t ctien;
+	int ret;
+
+	if (drvdata->refcnt == 0) {
+		ret = cti_enable(drvdata);
+		if (ret)
+			return ret;
+	}
 
 	CTI_UNLOCK(drvdata);
 
 	ctien = cti_readl(drvdata, CTIOUTEN(trig));
+	if (ctien & (0x1 << ch))
+		goto out;
 	cti_writel(drvdata, (ctien | 0x1 << ch), CTIOUTEN(trig));
 
 	CTI_LOCK(drvdata);
+
+	drvdata->refcnt++;
+	return 0;
+out:
+	CTI_LOCK(drvdata);
+	return 0;
 }
 
 int coresight_cti_map_trigout(struct coresight_cti *cti, int trig, int ch)
 {
 	struct cti_drvdata *drvdata;
-	int ret = 0;
+	int ret;
 
 	if (IS_ERR_OR_NULL(cti))
 		return -EINVAL;
@@ -175,15 +197,7 @@
 	drvdata = to_cti_drvdata(cti);
 
 	mutex_lock(&drvdata->mutex);
-	if (drvdata->refcnt == 0) {
-		ret = cti_enable(drvdata);
-		if (ret)
-			goto err;
-	}
-	drvdata->refcnt++;
-
-	__cti_map_trigout(drvdata, trig, ch);
-err:
+	ret = __cti_map_trigout(drvdata, trig, ch);
 	mutex_unlock(&drvdata->mutex);
 	return ret;
 }
@@ -193,9 +207,11 @@
 {
 	CTI_UNLOCK(drvdata);
 
-	cti_writel(drvdata, 0x1, CTICONTROL);
+	cti_writel(drvdata, 0x0, CTICONTROL);
 
 	CTI_LOCK(drvdata);
+
+	clk_disable_unprepare(drvdata->clk);
 }
 
 static void __cti_unmap_trigin(struct cti_drvdata *drvdata, int trig, int ch)
@@ -205,9 +221,19 @@
 	CTI_UNLOCK(drvdata);
 
 	ctien = cti_readl(drvdata, CTIINEN(trig));
+	if (!(ctien & (0x1 << ch)))
+		goto out;
 	cti_writel(drvdata, (ctien & ~(0x1 << ch)), CTIINEN(trig));
 
 	CTI_LOCK(drvdata);
+
+	if (drvdata->refcnt == 1)
+		cti_disable(drvdata);
+	drvdata->refcnt--;
+	return;
+out:
+	CTI_LOCK(drvdata);
+	return;
 }
 
 void coresight_cti_unmap_trigin(struct coresight_cti *cti, int trig, int ch)
@@ -224,13 +250,8 @@
 
 	mutex_lock(&drvdata->mutex);
 	__cti_unmap_trigin(drvdata, trig, ch);
-
-	if (drvdata->refcnt == 1)
-		cti_disable(drvdata);
-	drvdata->refcnt--;
 	mutex_unlock(&drvdata->mutex);
 
-	clk_disable_unprepare(drvdata->clk);
 }
 EXPORT_SYMBOL(coresight_cti_unmap_trigin);
 
@@ -241,9 +262,19 @@
 	CTI_UNLOCK(drvdata);
 
 	ctien = cti_readl(drvdata, CTIOUTEN(trig));
+	if (!(ctien & (0x1 << ch)))
+		goto out;
 	cti_writel(drvdata, (ctien & ~(0x1 << ch)), CTIOUTEN(trig));
 
 	CTI_LOCK(drvdata);
+
+	if (drvdata->refcnt == 1)
+		cti_disable(drvdata);
+	drvdata->refcnt--;
+	return;
+out:
+	CTI_LOCK(drvdata);
+	return;
 }
 
 void coresight_cti_unmap_trigout(struct coresight_cti *cti, int trig, int ch)
@@ -260,13 +291,7 @@
 
 	mutex_lock(&drvdata->mutex);
 	__cti_unmap_trigout(drvdata, trig, ch);
-
-	if (drvdata->refcnt == 1)
-		cti_disable(drvdata);
-	drvdata->refcnt--;
 	mutex_unlock(&drvdata->mutex);
-
-	clk_disable_unprepare(drvdata->clk);
 }
 EXPORT_SYMBOL(coresight_cti_unmap_trigout);
 
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
index b570252..3ad1f34 100644
--- a/drivers/coresight/coresight-priv.h
+++ b/drivers/coresight/coresight-priv.h
@@ -48,12 +48,14 @@
 extern void msm_qdss_csr_disable_bam_to_usb(void);
 extern void msm_qdss_csr_disable_flush(void);
 extern int coresight_csr_hwctrl_set(phys_addr_t addr, uint32_t val);
+extern void coresight_csr_set_byte_cntr(uint32_t);
 #else
 static inline void msm_qdss_csr_enable_bam_to_usb(void) {}
 static inline void msm_qdss_csr_disable_bam_to_usb(void) {}
 static inline void msm_qdss_csr_disable_flush(void) {}
 static inline int coresight_csr_hwctrl_set(phys_addr_t addr,
 					   uint32_t val) { return -ENOSYS; }
+static inline void coresight_csr_set_byte_cntr(uint32_t val) {}
 #endif
 #ifdef CONFIG_CORESIGHT_ETM
 extern unsigned int etm_readl_cp14(uint32_t off);
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index 4186abe..c501700 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -30,6 +30,10 @@
 #include <linux/of_coresight.h>
 #include <linux/coresight.h>
 #include <linux/coresight-cti.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
 #include <linux/usb/usb_qdss.h>
 #include <mach/memory.h>
 #include <mach/sps.h>
@@ -135,6 +139,8 @@
 	struct device		*dev;
 	struct coresight_device	*csdev;
 	struct miscdevice	miscdev;
+	struct cdev		byte_cntr_dev;
+	struct class		*byte_cntr_class;
 	struct clk		*clk;
 	spinlock_t		spinlock;
 	bool			reset_flush_race;
@@ -157,6 +163,19 @@
 	bool			enable;
 	enum tmc_config_type	config_type;
 	uint32_t		trigger_cntr;
+	int			byte_cntr_irq;
+	atomic_t		byte_cntr_irq_cnt;
+	uint32_t		byte_cntr_value;
+	struct mutex		byte_cntr_read_lock;
+	struct mutex		byte_cntr_lock;
+	uint32_t		byte_cntr_block_size;
+	bool			byte_cntr_overflow;
+	bool			byte_cntr_present;
+	bool			byte_cntr_enable;
+	uint32_t		byte_cntr_overflow_cnt;
+	bool			byte_cntr_read_active;
+	wait_queue_head_t	wq;
+	char			*byte_cntr_node;
 };
 
 static void tmc_wait_for_flush(struct tmc_drvdata *drvdata)
@@ -368,6 +387,52 @@
 	mutex_unlock(&drvdata->usb_lock);
 }
 
+static uint32_t tmc_etr_get_write_ptr(struct tmc_drvdata *drvdata)
+{
+	uint32_t rwp = 0;
+
+	TMC_UNLOCK(drvdata);
+
+	rwp = tmc_readl(drvdata, TMC_RWP);
+
+	TMC_LOCK(drvdata);
+
+	return rwp;
+}
+
+static void tmc_etr_byte_cntr_start(struct tmc_drvdata *drvdata)
+{
+	if (!drvdata->byte_cntr_present)
+		return;
+
+	mutex_lock(&drvdata->byte_cntr_lock);
+	atomic_set(&drvdata->byte_cntr_irq_cnt, 0);
+	drvdata->byte_cntr_overflow = false;
+	drvdata->byte_cntr_read_active = false;
+	drvdata->byte_cntr_enable = true;
+	if (drvdata->byte_cntr_value != 0)
+		drvdata->byte_cntr_overflow_cnt = drvdata->size /
+						 (drvdata->byte_cntr_value * 8);
+	else
+		drvdata->byte_cntr_overflow_cnt = 0;
+	coresight_csr_set_byte_cntr(drvdata->byte_cntr_value);
+	mutex_unlock(&drvdata->byte_cntr_lock);
+}
+
+static void tmc_etr_byte_cntr_stop(struct tmc_drvdata *drvdata)
+{
+	if (!drvdata->byte_cntr_present)
+		return;
+
+	mutex_lock(&drvdata->byte_cntr_lock);
+	coresight_csr_set_byte_cntr(0);
+	drvdata->byte_cntr_value = 0;
+	drvdata->byte_cntr_enable = false;
+	mutex_unlock(&drvdata->byte_cntr_lock);
+
+	wake_up(&drvdata->wq);
+}
+
 static void __tmc_etb_enable(struct tmc_drvdata *drvdata)
 {
 	/* Zero out the memory to help with debug */
@@ -438,10 +503,14 @@
 		coresight_cti_map_trigout(drvdata->cti_flush, 1, 0);
 		coresight_cti_map_trigin(drvdata->cti_reset, 0, 0);
 	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM &&
-		    !drvdata->reset_flush_race) {
-			coresight_cti_map_trigout(drvdata->cti_flush, 3, 0);
-			coresight_cti_map_trigin(drvdata->cti_reset, 2, 0);
+		if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) {
+			tmc_etr_byte_cntr_start(drvdata);
+			if (!drvdata->reset_flush_race) {
+				coresight_cti_map_trigout(drvdata->cti_flush,
+							  3, 0);
+				coresight_cti_map_trigin(drvdata->cti_reset,
+							 2, 0);
+			}
 		} else if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) {
 			drvdata->usbch = usb_qdss_open("qdss", drvdata,
 						       usb_notifier);
@@ -674,10 +743,14 @@
 		coresight_cti_unmap_trigin(drvdata->cti_reset, 0, 0);
 		coresight_cti_unmap_trigout(drvdata->cti_flush, 1, 0);
 	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM &&
-		    !drvdata->reset_flush_race) {
-			coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0);
-			coresight_cti_unmap_trigout(drvdata->cti_flush, 3, 0);
+		if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) {
+			tmc_etr_byte_cntr_stop(drvdata);
+			if (!drvdata->reset_flush_race) {
+				coresight_cti_unmap_trigin(drvdata->cti_reset,
+							   2, 0);
+				coresight_cti_unmap_trigout(drvdata->cti_flush,
+							    3, 0);
+			}
 		} else if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) {
 			tmc_etr_bam_disable(drvdata);
 			usb_qdss_close(drvdata->usbch);
@@ -929,6 +1002,161 @@
 	.llseek		= no_llseek,
 };
 
+static int tmc_etr_byte_cntr_open(struct inode *inode, struct file *file)
+{
+	struct tmc_drvdata *drvdata = container_of(inode->i_cdev,
+						   struct tmc_drvdata,
+						   byte_cntr_dev);
+
+	if (drvdata->out_mode != TMC_ETR_OUT_MODE_MEM ||
+	    !drvdata->byte_cntr_enable)
+		return -EPERM;
+
+	if (!mutex_trylock(&drvdata->byte_cntr_read_lock))
+		return -EPERM;
+
+	file->private_data = drvdata;
+	nonseekable_open(inode, file);
+	drvdata->byte_cntr_block_size = drvdata->byte_cntr_value * 8;
+	drvdata->byte_cntr_read_active = true;
+	dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
+	return 0;
+}
+
+static void tmc_etr_read_bytes(struct tmc_drvdata *drvdata, loff_t *ppos,
+			       size_t bytes, size_t *len)
+{
+	if (*len >= bytes) {
+		atomic_dec(&drvdata->byte_cntr_irq_cnt);
+		*len = bytes;
+	} else {
+		if (((uint32_t)*ppos % bytes) + *len > bytes)
+				*len = bytes - ((uint32_t)*ppos % bytes);
+		if ((*len + (uint32_t)*ppos) % bytes == 0)
+			atomic_dec(&drvdata->byte_cntr_irq_cnt);
+	}
+}
+
+static size_t tmc_etr_flush_bytes(struct tmc_drvdata *drvdata, loff_t *ppos,
+				  size_t bytes)
+{
+	uint32_t rwp = 0;
+	size_t len = bytes;
+
+	rwp = tmc_etr_get_write_ptr(drvdata);
+	if (rwp >= (drvdata->paddr + *ppos)) {
+		if (len > (rwp - drvdata->paddr - *ppos))
+			len = rwp - drvdata->paddr - *ppos;
+	}
+	return len;
+}
+
+static ssize_t tmc_etr_byte_cntr_read(struct file *file, char __user *data,
+				  size_t len, loff_t *ppos)
+{
+	struct tmc_drvdata *drvdata = file->private_data;
+	char *bufp = drvdata->vaddr + *ppos;
+	size_t bytes = drvdata->byte_cntr_block_size;
+	int ret = 0;
+
+	if (!data)
+		return -EINVAL;
+	if (drvdata->byte_cntr_overflow)
+		return -EIO;
+
+	mutex_lock(&drvdata->byte_cntr_lock);
+	/* In case the byte counter is enabled and disabled multiple times
+	 * prevent unexpected data from being given to the user
+	 */
+	if (!drvdata->byte_cntr_read_active)
+		goto read_err0;
+
+	if (!drvdata->byte_cntr_enable) {
+		if (!atomic_read(&drvdata->byte_cntr_irq_cnt)) {
+			/* Read the last 'block' of data which might be needed
+			 * to be read partially. If already read, return 0
+			 */
+			len = tmc_etr_flush_bytes(drvdata, ppos, bytes);
+			if (!len)
+				goto read_err0;
+		} else {
+			/* Keep reading until you reach the last block of data
+			 */
+			tmc_etr_read_bytes(drvdata, ppos, bytes, &len);
+		}
+	} else {
+		if (!atomic_read(&drvdata->byte_cntr_irq_cnt)) {
+			mutex_unlock(&drvdata->byte_cntr_lock);
+			if (wait_event_interruptible(drvdata->wq,
+			    (atomic_read(&drvdata->byte_cntr_irq_cnt) > 0) ||
+			    !drvdata->byte_cntr_enable)) {
+				ret = -ERESTARTSYS;
+				goto read_err1;
+			}
+			mutex_lock(&drvdata->byte_cntr_lock);
+			if (!drvdata->byte_cntr_read_active) {
+				ret = 0;
+				goto read_err0;
+			}
+		}
+		if (drvdata->byte_cntr_overflow) {
+			ret = -EIO;
+			goto read_err0;
+		}
+		if (!drvdata->byte_cntr_enable &&
+		    !atomic_read(&drvdata->byte_cntr_irq_cnt)) {
+			len = tmc_etr_flush_bytes(drvdata, ppos, bytes);
+			if (!len) {
+				ret = 0;
+				goto read_err0;
+			}
+		} else {
+			tmc_etr_read_bytes(drvdata, ppos, bytes, &len);
+		}
+	}
+	if (copy_to_user(data, bufp, len)) {
+		mutex_unlock(&drvdata->byte_cntr_lock);
+		dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
+		ret = -EFAULT;
+		goto read_err1;
+	}
+	mutex_unlock(&drvdata->byte_cntr_lock);
+
+	if (*ppos + len >= drvdata->size)
+		*ppos = 0;
+	else
+		*ppos += len;
+
+	dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
+		__func__, len, (int) (drvdata->size - *ppos));
+	return len;
+
+read_err0:
+	mutex_unlock(&drvdata->byte_cntr_lock);
+read_err1:
+	return ret;
+}
+
+static int tmc_etr_byte_cntr_release(struct inode *inode, struct file *file)
+{
+	struct tmc_drvdata *drvdata = file->private_data;
+
+	mutex_lock(&drvdata->byte_cntr_lock);
+	drvdata->byte_cntr_read_active = false;
+	mutex_unlock(&drvdata->byte_cntr_lock);
+	mutex_unlock(&drvdata->byte_cntr_read_lock);
+	dev_dbg(drvdata->dev, "%s: released\n", __func__);
+	return 0;
+}
+
+static const struct file_operations byte_cntr_fops = {
+	.owner		= THIS_MODULE,
+	.open		= tmc_etr_byte_cntr_open,
+	.read		= tmc_etr_byte_cntr_read,
+	.release	= tmc_etr_byte_cntr_release,
+	.llseek		= no_llseek,
+};
+
 static ssize_t tmc_show_trigger_cntr(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -1044,6 +1272,41 @@
 static DEVICE_ATTR(out_mode, S_IRUGO | S_IWUSR, tmc_etr_show_out_mode,
 		   tmc_etr_store_out_mode);
 
+static ssize_t tmc_etr_show_byte_cntr_value(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val = drvdata->byte_cntr_value;
+
+	if (!drvdata->byte_cntr_present)
+		return -EPERM;
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t tmc_etr_store_byte_cntr_value(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t size)
+{
+	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+
+	if (!drvdata->byte_cntr_present || drvdata->byte_cntr_enable)
+		return -EPERM;
+	if (sscanf(buf, "%lx", &val) != 1)
+		return -EINVAL;
+	if ((drvdata->size / 8) < val)
+		return -EINVAL;
+	if (drvdata->size % (val * 8) != 0)
+		return -EINVAL;
+
+	drvdata->byte_cntr_value = val;
+	return size;
+}
+static DEVICE_ATTR(byte_cntr_value, S_IRUGO | S_IWUSR,
+		   tmc_etr_show_byte_cntr_value, tmc_etr_store_byte_cntr_value);
+
 static struct attribute *tmc_attrs[] = {
 	&dev_attr_trigger_cntr.attr,
 	NULL,
@@ -1055,6 +1318,7 @@
 
 static struct attribute *tmc_etr_attrs[] = {
 	&dev_attr_out_mode.attr,
+	&dev_attr_byte_cntr_value.attr,
 	NULL,
 };
 
@@ -1118,6 +1382,113 @@
 	sps_deregister_bam_device(bamdata->handle);
 }
 
+static irqreturn_t tmc_etr_byte_cntr_irq(int irq, void *data)
+{
+	struct tmc_drvdata *drvdata = data;
+
+	atomic_inc(&drvdata->byte_cntr_irq_cnt);
+	if (atomic_read(&drvdata->byte_cntr_irq_cnt) >
+			drvdata->byte_cntr_overflow_cnt) {
+		dev_err(drvdata->dev, "Byte counter overflow\n");
+		drvdata->byte_cntr_overflow = true;
+	}
+	wake_up(&drvdata->wq);
+	return IRQ_HANDLED;
+}
+
+static int tmc_etr_byte_cntr_dev_register(struct tmc_drvdata *drvdata)
+{
+	int ret;
+	struct device *device;
+	dev_t dev;
+
+	ret = alloc_chrdev_region(&dev, 0, 1, drvdata->byte_cntr_node);
+	if (ret)
+		goto dev_err0;
+	cdev_init(&drvdata->byte_cntr_dev, &byte_cntr_fops);
+	drvdata->byte_cntr_dev.owner = THIS_MODULE;
+	drvdata->byte_cntr_dev.ops = &byte_cntr_fops;
+	ret = cdev_add(&drvdata->byte_cntr_dev, dev, 1);
+	if (ret)
+		goto dev_err1;
+	drvdata->byte_cntr_class = class_create(THIS_MODULE,
+						drvdata->byte_cntr_node);
+	if (!drvdata->byte_cntr_class)
+		goto dev_err2;
+	device = device_create(drvdata->byte_cntr_class, NULL,
+			       drvdata->byte_cntr_dev.dev, drvdata,
+			       drvdata->byte_cntr_node);
+	if (IS_ERR(device)) {
+		ret = PTR_ERR(device);
+		goto dev_err3;
+	}
+	return 0;
+dev_err3:
+	class_destroy(drvdata->byte_cntr_class);
+dev_err2:
+	cdev_del(&drvdata->byte_cntr_dev);
+dev_err1:
+	unregister_chrdev_region(drvdata->byte_cntr_dev.dev, 1);
+dev_err0:
+	return ret;
+}
+
+static void tmc_etr_byte_cntr_dev_deregister(struct tmc_drvdata *drvdata)
+{
+	device_destroy(drvdata->byte_cntr_class, drvdata->byte_cntr_dev.dev);
+	class_destroy(drvdata->byte_cntr_class);
+	cdev_del(&drvdata->byte_cntr_dev);
+	unregister_chrdev_region(drvdata->byte_cntr_dev.dev, 1);
+}
+
+static int tmc_etr_byte_cntr_init(struct platform_device *pdev,
+				  struct tmc_drvdata *drvdata)
+{
+	int ret = 0;
+	size_t node_size = strlen("-stream") + 1;
+	char *node_name = (char *)((struct coresight_platform_data *)
+			(pdev->dev.platform_data))->name;
+
+	if (!drvdata->byte_cntr_present) {
+		dev_info(&pdev->dev, "Byte Counter feature absent\n");
+		return 0;
+	}
+
+	drvdata->byte_cntr_irq = platform_get_irq_byname(pdev,
+							"byte-cntr-irq");
+	if (drvdata->byte_cntr_irq < 0) {
+		dev_err(&pdev->dev, "Byte-cntr-irq not specified\n");
+		return 0;
+	}
+	ret = devm_request_irq(&pdev->dev, drvdata->byte_cntr_irq,
+			tmc_etr_byte_cntr_irq,
+			IRQF_TRIGGER_RISING | IRQF_SHARED,
+			node_name, drvdata);
+	if (ret) {
+		dev_err(&pdev->dev, "Request irq failed\n");
+		return ret;
+	}
+	init_waitqueue_head(&drvdata->wq);
+	node_size += strlen(node_name);
+	drvdata->byte_cntr_node = devm_kzalloc(&pdev->dev,
+				node_size, GFP_KERNEL);
+	strlcpy(drvdata->byte_cntr_node, node_name, node_size);
+	strlcat(drvdata->byte_cntr_node, "-stream", node_size);
+	ret = tmc_etr_byte_cntr_dev_register(drvdata);
+	if (ret) {
+		dev_err(&pdev->dev, "Byte cntr node not registered\n");
+		return ret;
+	}
+	dev_info(&pdev->dev, "Byte Counter feature enabled\n");
+	return 0;
+}
+
+static void tmc_etr_byte_cntr_exit(struct tmc_drvdata *drvdata)
+{
+	if (drvdata->byte_cntr_present)
+		tmc_etr_byte_cntr_dev_deregister(drvdata);
+}
+
 static int __devinit tmc_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -1162,6 +1533,9 @@
 	spin_lock_init(&drvdata->spinlock);
 	mutex_init(&drvdata->read_lock);
 	mutex_init(&drvdata->usb_lock);
+	mutex_init(&drvdata->byte_cntr_lock);
+	mutex_init(&drvdata->byte_cntr_read_lock);
+	atomic_set(&drvdata->byte_cntr_irq_cnt, 0);
 
 	drvdata->clk = devm_clk_get(dev, "core_clk");
 	if (IS_ERR(drvdata->clk))
@@ -1207,10 +1581,16 @@
 		memset(drvdata->vaddr, 0, drvdata->size);
 		drvdata->buf = drvdata->vaddr;
 		drvdata->out_mode = TMC_ETR_OUT_MODE_MEM;
-
-		ret = tmc_etr_bam_init(pdev, drvdata);
+		if (pdev->dev.of_node)
+			drvdata->byte_cntr_present = !of_property_read_bool
+						     (pdev->dev.of_node,
+						     "qcom,byte-cntr-absent");
+		ret = tmc_etr_byte_cntr_init(pdev, drvdata);
 		if (ret)
 			goto err0;
+		ret = tmc_etr_bam_init(pdev, drvdata);
+		if (ret)
+			goto err1;
 	} else {
 		baddr = devm_kzalloc(dev, PAGE_SIZE + drvdata->size,
 				     GFP_KERNEL);
@@ -1277,7 +1657,7 @@
 	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
 	if (!desc) {
 		ret = -ENOMEM;
-		goto err1;
+		goto err2;
 	}
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
 		desc->type = CORESIGHT_DEV_TYPE_SINK;
@@ -1290,7 +1670,7 @@
 		drvdata->csdev = coresight_register(desc);
 		if (IS_ERR(drvdata->csdev)) {
 			ret = PTR_ERR(drvdata->csdev);
-			goto err1;
+			goto err2;
 		}
 	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
 		desc->type = CORESIGHT_DEV_TYPE_SINK;
@@ -1303,7 +1683,7 @@
 		drvdata->csdev = coresight_register(desc);
 		if (IS_ERR(drvdata->csdev)) {
 			ret = PTR_ERR(drvdata->csdev);
-			goto err1;
+			goto err2;
 		}
 	} else {
 		desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
@@ -1317,7 +1697,7 @@
 		drvdata->csdev = coresight_register(desc);
 		if (IS_ERR(drvdata->csdev)) {
 			ret = PTR_ERR(drvdata->csdev);
-			goto err1;
+			goto err2;
 		}
 	}
 
@@ -1327,14 +1707,16 @@
 	drvdata->miscdev.fops = &tmc_fops;
 	ret = misc_register(&drvdata->miscdev);
 	if (ret)
-		goto err2;
+		goto err3;
 
 	dev_info(dev, "TMC initialized\n");
 	return 0;
-err2:
+err3:
 	coresight_unregister(drvdata->csdev);
-err1:
+err2:
 	tmc_etr_bam_exit(drvdata);
+err1:
+	tmc_etr_byte_cntr_exit(drvdata);
 err0:
 	free_contiguous_memory_by_paddr(drvdata->paddr);
 	return ret;
@@ -1344,6 +1726,7 @@
 {
 	struct tmc_drvdata *drvdata = platform_get_drvdata(pdev);
 
+	tmc_etr_byte_cntr_exit(drvdata);
 	misc_deregister(&drvdata->miscdev);
 	coresight_unregister(drvdata->csdev);
 	tmc_etr_bam_exit(drvdata);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 3d5614b..374170d 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -435,8 +435,12 @@
 	if (ret != 1)							\
 		return -EINVAL;						\
 									\
+	ret = cpufreq_driver->verify(&new_policy);			\
+	if (ret)							\
+		pr_err("cpufreq: Frequency verification failed\n");	\
+									\
+	policy->user_policy.object = new_policy.object;			\
 	ret = __cpufreq_set_policy(policy, &new_policy);		\
-	policy->user_policy.object = policy->object;			\
 									\
 	return ret ? ret : count;					\
 }
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index eae16fa..4c05978 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -188,12 +188,7 @@
 	min_rev = (rev & CRYPTO_CORE_MINOR_REV_MASK) >> CRYPTO_CORE_MINOR_REV;
 	step_rev = (rev & CRYPTO_CORE_STEP_REV_MASK) >> CRYPTO_CORE_STEP_REV;
 
-	if ((maj_rev != 0x05) || (min_rev > 0x02) || (step_rev > 0x02)) {
-		pr_err("Unknown Qualcomm crypto device at 0x%x, rev %d.%d.%d\n",
-			pce_dev->phy_iobase, maj_rev, min_rev, step_rev);
-		return -EIO;
-	};
-	if ((min_rev > 0)  && (step_rev != 0)) {
+	if (maj_rev != 0x05) {
 		pr_err("Unknown Qualcomm crypto device at 0x%x, rev %d.%d.%d\n",
 			pce_dev->phy_iobase, maj_rev, min_rev, step_rev);
 		return -EIO;
@@ -3725,7 +3720,7 @@
 	qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 							DMA_TO_DEVICE);
-	/* cipher + mac output  for encryption    */
+	/* cipher output  for encryption    */
 	if (areq->src != areq->dst) {
 		if (pce_dev->ce_sps.minor_version == 0)
 			/*
@@ -3806,7 +3801,7 @@
 		if (_qce_sps_add_data((uint32_t)pce_dev->phy_iv_in, ivsize,
 					&pce_dev->ce_sps.in_transfer))
 			goto bad;
-		if (_qce_sps_add_sg_data(pce_dev, areq->src, areq->cryptlen,
+		if (_qce_sps_add_sg_data(pce_dev, areq->src, q_req->cryptlen,
 					&pce_dev->ce_sps.in_transfer))
 			goto bad;
 		_qce_set_flag(&pce_dev->ce_sps.in_transfer,
@@ -3818,7 +3813,7 @@
 				(ivsize + areq->assoclen),
 				&pce_dev->ce_sps.out_transfer))
 			goto bad;
-		if (_qce_sps_add_sg_data(pce_dev, areq->dst, areq->cryptlen,
+		if (_qce_sps_add_sg_data(pce_dev, areq->dst, q_req->cryptlen,
 					&pce_dev->ce_sps.out_transfer))
 			goto bad;
 
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index d069f2e..0e4b309 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1937,7 +1937,7 @@
 	rc = misc_register(&podev->miscdevice);
 	qce_hw_support(podev->qce, &podev->ce_support);
 	if (podev->ce_support.bam) {
-		podev->platform_support.ce_shared = podev->ce_support.is_shared;
+		podev->platform_support.ce_shared = 0;
 		podev->platform_support.shared_ce_resource = 0;
 		podev->platform_support.hw_key_support =
 						podev->ce_support.hw_key;
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index 64341e9..ed001f0 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -589,6 +589,9 @@
 	}
 	mutex_unlock(&qpnp_pin_chips_lock);
 
+	if (!q_spec)
+		return -ENODEV;
+
 	rc = _qpnp_pin_config(q_chip, q_spec, param);
 
 	return rc;
@@ -1225,6 +1228,8 @@
 		if (!res) {
 			dev_err(&spmi->dev, "%s: node %s is missing has no base address definition\n",
 				__func__, d_node->of_node->full_name);
+			rc = -EINVAL;
+			goto err_probe;
 		}
 
 		rc = of_property_read_u32(d_node->of_node,
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index a80b0c6..a4d2c1b 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -31,6 +31,8 @@
 
 struct ion_iommu_heap {
 	struct ion_heap heap;
+	struct ion_page_pool **cached_pools;
+	struct ion_page_pool **uncached_pools;
 };
 
 /*
@@ -48,9 +50,14 @@
 };
 
 #define MAX_VMAP_RETRIES 10
+#define BAD_ORDER	-1
 
 static const unsigned int orders[] = {8, 4, 0};
 static const int num_orders = ARRAY_SIZE(orders);
+static unsigned int low_gfp_flags = __GFP_HIGHMEM | GFP_KERNEL | __GFP_ZERO;
+static unsigned int high_gfp_flags = (__GFP_HIGHMEM | __GFP_NORETRY
+				| __GFP_NO_KSWAPD | __GFP_NOWARN |
+				 __GFP_IO | __GFP_FS | __GFP_ZERO);
 
 struct page_info {
 	struct page *page;
@@ -58,13 +65,25 @@
 	struct list_head list;
 };
 
+static int order_to_index(unsigned int order)
+{
+	int i;
+	for (i = 0; i < num_orders; i++)
+		if (order == orders[i])
+			return i;
+	BUG();
+	return BAD_ORDER;
+}
+
 static unsigned int order_to_size(int order)
 {
 	return PAGE_SIZE << order;
 }
 
-static struct page_info *alloc_largest_available(unsigned long size,
-						unsigned int max_order)
+static struct page_info *alloc_largest_available(struct ion_iommu_heap *heap,
+						unsigned long size,
+						unsigned int max_order,
+						unsigned long flags)
 {
 	struct page *page;
 	struct page_info *info;
@@ -72,21 +91,35 @@
 
 	for (i = 0; i < num_orders; i++) {
 		gfp_t gfp;
+		int idx = order_to_index(orders[i]);
+		struct ion_page_pool *pool;
+
+		if (idx == BAD_ORDER)
+			continue;
+
+		if (ION_IS_CACHED(flags)) {
+			pool = heap->cached_pools[idx];
+			BUG_ON(!pool);
+		} else {
+			pool = heap->uncached_pools[idx];
+			BUG_ON(!pool);
+		}
+
 		if (size < order_to_size(orders[i]))
 			continue;
 		if (max_order < orders[i])
 			continue;
 
-		gfp = __GFP_HIGHMEM;
-
 		if (orders[i]) {
-			gfp |= __GFP_COMP | __GFP_NORETRY |
-			       __GFP_NO_KSWAPD | __GFP_NOWARN;
+			gfp = high_gfp_flags;
 		} else {
-			gfp |= GFP_KERNEL;
+			gfp = low_gfp_flags;
 		}
 		trace_alloc_pages_iommu_start(gfp, orders[i]);
-		page = alloc_pages(gfp, orders[i]);
+		if (flags & ION_FLAG_POOL_FORCE_ALLOC)
+			page = alloc_pages(gfp, orders[i]);
+		else
+			page = ion_page_pool_alloc(pool);
 		trace_alloc_pages_iommu_end(gfp, orders[i]);
 		if (!page) {
 			trace_alloc_pages_iommu_fail(gfp, orders[i]);
@@ -103,6 +136,47 @@
 	return NULL;
 }
 
+static int ion_iommu_buffer_zero(struct ion_iommu_priv_data *data)
+{
+	int i, j;
+	unsigned int npages_to_vmap;
+	unsigned int total_pages;
+	void *ptr = NULL;
+
+	/*
+	 * As an optimization, we manually zero out all of the
+	 * pages in one fell swoop here. To safeguard against
+	 * insufficient vmalloc space, we only vmap
+	 * `npages_to_vmap' at a time, starting with a
+	 * conservative estimate of 1/8 of the total number of
+	 * vmalloc pages available. Note that the `pages'
+	 * array is composed of all 4K pages, irrespective of
+	 * the size of the pages on the sg list.
+	 */
+	npages_to_vmap = ((VMALLOC_END - VMALLOC_START)/8)
+			>> PAGE_SHIFT;
+	total_pages = data->nrpages;
+	for (i = 0; i < total_pages; i += npages_to_vmap) {
+		npages_to_vmap = min(npages_to_vmap, total_pages - i);
+		for (j = 0; j < MAX_VMAP_RETRIES && npages_to_vmap;
+			++j) {
+			ptr = vmap(&data->pages[i], npages_to_vmap,
+					VM_IOREMAP, pgprot_kernel);
+			if (ptr)
+				break;
+			else
+				npages_to_vmap >>= 1;
+		}
+		if (!ptr)
+			return -ENOMEM;
+
+		memset(ptr, 0, npages_to_vmap * PAGE_SIZE);
+		vunmap(ptr);
+	}
+
+	return 0;
+}
+
 static int ion_iommu_heap_allocate(struct ion_heap *heap,
 				      struct ion_buffer *buffer,
 				      unsigned long size, unsigned long align,
@@ -112,13 +186,14 @@
 	struct list_head pages_list;
 	struct page_info *info, *tmp_info;
 	struct ion_iommu_priv_data *data = NULL;
+	struct ion_iommu_heap *iommu_heap =
+		container_of(heap, struct ion_iommu_heap, heap);
 
 	if (msm_use_iommu()) {
 		struct scatterlist *sg;
 		struct sg_table *table;
 		int j;
-		void *ptr = NULL;
-		unsigned int npages_to_vmap, total_pages, num_large_pages = 0;
+		unsigned int num_large_pages = 0;
 		unsigned long size_remaining = PAGE_ALIGN(size);
 		unsigned int max_order = ION_IS_CACHED(flags) ? 0 : orders[0];
 		unsigned int page_tbl_size;
@@ -129,8 +204,10 @@
 
 		INIT_LIST_HEAD(&pages_list);
 		while (size_remaining > 0) {
-			info = alloc_largest_available(size_remaining,
-						max_order);
+			info = alloc_largest_available(iommu_heap,
+						size_remaining,
+						max_order,
+						flags);
 			if (!info) {
 				ret = -ENOMEM;
 				goto err_free_data;
@@ -190,44 +267,21 @@
 			kfree(info);
 		}
 
-		/*
-		 * As an optimization, we omit __GFP_ZERO from
-		 * alloc_page above and manually zero out all of the
-		 * pages in one fell swoop here. To safeguard against
-		 * insufficient vmalloc space, we only vmap
-		 * `npages_to_vmap' at a time, starting with a
-		 * conservative estimate of 1/8 of the total number of
-		 * vmalloc pages available. Note that the `pages'
-		 * array is composed of all 4K pages, irrespective of
-		 * the size of the pages on the sg list.
-		 */
-		npages_to_vmap = ((VMALLOC_END - VMALLOC_START)/8)
-			>> PAGE_SHIFT;
-		total_pages = data->nrpages;
-		for (i = 0; i < total_pages; i += npages_to_vmap) {
-			npages_to_vmap = min(npages_to_vmap, total_pages - i);
-			for (j = 0; j < MAX_VMAP_RETRIES && npages_to_vmap;
-			     ++j) {
-				ptr = vmap(&data->pages[i], npages_to_vmap,
-					VM_IOREMAP, pgprot_kernel);
-				if (ptr)
-					break;
-				else
-					npages_to_vmap >>= 1;
-			}
-			if (!ptr) {
+
+		if (flags & ION_FLAG_POOL_FORCE_ALLOC) {
+			ret = ion_iommu_buffer_zero(data);
+			if (ret) {
 				pr_err("Couldn't vmap the pages for zeroing\n");
-				ret = -ENOMEM;
 				goto err3;
 			}
-			memset(ptr, 0, npages_to_vmap * PAGE_SIZE);
-			vunmap(ptr);
-		}
 
-		if (!ION_IS_CACHED(flags))
-			dma_sync_sg_for_device(NULL, table->sgl, table->nents,
+
+			if (!ION_IS_CACHED(flags))
+				dma_sync_sg_for_device(NULL, table->sgl,
+						table->nents,
 						DMA_BIDIRECTIONAL);
 
+		}
 		buffer->priv_virt = data;
 		return 0;
 
@@ -264,14 +318,38 @@
 	struct scatterlist *sg;
 	struct sg_table *table = buffer->sg_table;
 	struct ion_iommu_priv_data *data = buffer->priv_virt;
+	bool cached = ion_buffer_cached(buffer);
+	struct ion_iommu_heap *iommu_heap =
+	     container_of(buffer->heap, struct	ion_iommu_heap, heap);
 
 	if (!table)
 		return;
 	if (!data)
 		return;
 
-	for_each_sg(table->sgl, sg, table->nents, i)
-		__free_pages(sg_page(sg), get_order(sg_dma_len(sg)));
+	if (!(buffer->flags & ION_FLAG_POOL_FORCE_ALLOC))
+		ion_iommu_buffer_zero(data);
+
+	for_each_sg(table->sgl, sg, table->nents, i) {
+		int order = get_order(sg_dma_len(sg));
+		int idx = order_to_index(order);
+		struct ion_page_pool *pool;
+
+		if (idx == BAD_ORDER) {
+			WARN_ON(1);
+			continue;
+		}
+
+		if (cached)
+			pool = iommu_heap->cached_pools[idx];
+		else
+			pool = iommu_heap->uncached_pools[idx];
+
+		if (buffer->flags & ION_FLAG_POOL_FORCE_ALLOC)
+			__free_pages(sg_page(sg), order);
+		else
+			ion_page_pool_free(pool, sg_page(sg));
+	}
 
 	sg_free_table(table);
 	kfree(table);
@@ -356,6 +434,47 @@
 {
 }
 
+static int ion_iommu_heap_debug_show(struct ion_heap *heap, struct seq_file *s,
+					void *unused)
+{
+
+	struct ion_iommu_heap *iommu_heap = container_of(heap,
+							struct ion_iommu_heap,
+							heap);
+	int i;
+	unsigned long total = 0;
+
+	seq_printf(s, "Cached Pools:\n");
+	for (i = 0; i < num_orders; i++) {
+		struct ion_page_pool *pool = iommu_heap->cached_pools[i];
+		seq_printf(s, "%d order %u highmem pages in pool = %lx total\n",
+			   pool->high_count, pool->order,
+			   (1 << pool->order) * PAGE_SIZE * pool->high_count);
+		seq_printf(s, "%d order %u lowmem pages in pool = %lx total\n",
+			   pool->low_count, pool->order,
+			   (1 << pool->order) * PAGE_SIZE * pool->low_count);
+
+		total += (1 << pool->order) * PAGE_SIZE *
+			  (pool->low_count + pool->high_count);
+	}
+
+	seq_printf(s, "Uncached Pools:\n");
+	for (i = 0; i < num_orders; i++) {
+		struct ion_page_pool *pool = iommu_heap->uncached_pools[i];
+		seq_printf(s, "%d order %u highmem pages in pool = %lx total\n",
+			   pool->high_count, pool->order,
+			   (1 << pool->order) * PAGE_SIZE * pool->high_count);
+		seq_printf(s, "%d order %u lowmem pages in pool = %lx total\n",
+			   pool->low_count, pool->order,
+			   (1 << pool->order) * PAGE_SIZE * pool->low_count);
+
+		total += (1 << pool->order) * PAGE_SIZE *
+			  (pool->low_count + pool->high_count);
+	}
+	seq_printf(s, "Total bytes in pool: %lx\n", total);
+	return 0;
+}
+
 static struct ion_heap_ops iommu_heap_ops = {
 	.allocate = ion_iommu_heap_allocate,
 	.free = ion_iommu_heap_free,
@@ -369,6 +488,7 @@
 struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *heap_data)
 {
 	struct ion_iommu_heap *iommu_heap;
+	int i;
 
 	iommu_heap = kzalloc(sizeof(struct ion_iommu_heap), GFP_KERNEL);
 	if (!iommu_heap)
@@ -376,8 +496,66 @@
 
 	iommu_heap->heap.ops = &iommu_heap_ops;
 	iommu_heap->heap.type = ION_HEAP_TYPE_IOMMU;
+	iommu_heap->uncached_pools = kzalloc(
+			      sizeof(struct ion_page_pool *) * num_orders,
+			      GFP_KERNEL);
+	if (!iommu_heap->uncached_pools)
+		goto err_alloc_uncached_pools;
 
+	iommu_heap->cached_pools = kzalloc(
+			      sizeof(struct ion_page_pool *) * num_orders,
+			      GFP_KERNEL);
+
+	if (!iommu_heap->cached_pools)
+		goto err_alloc_cached_pools;
+
+	for (i = 0; i < num_orders; i++) {
+		struct ion_page_pool *pool;
+		gfp_t gfp_flags;
+
+		if (orders[i])
+			gfp_flags = high_gfp_flags | __GFP_ZERO;
+		else
+			gfp_flags = low_gfp_flags | __GFP_ZERO;
+		pool = ion_page_pool_create(gfp_flags, orders[i]);
+		if (!pool)
+			goto err_create_cached_pool;
+		iommu_heap->cached_pools[i] = pool;
+	}
+
+	for (i = 0; i < num_orders; i++) {
+		struct ion_page_pool *pool;
+		gfp_t gfp_flags;
+
+		if (orders[i])
+			gfp_flags = high_gfp_flags | __GFP_ZERO;
+		else
+			gfp_flags = low_gfp_flags | __GFP_ZERO;
+		pool = ion_page_pool_create(gfp_flags, orders[i]);
+		if (!pool)
+			goto err_create_uncached_pool;
+		iommu_heap->uncached_pools[i] = pool;
+	}
+	iommu_heap->heap.debug_show = ion_iommu_heap_debug_show;
 	return &iommu_heap->heap;
+
+err_create_uncached_pool:
+	for (i = 0; i < num_orders; i++)
+		if (iommu_heap->cached_pools[i])
+			ion_page_pool_destroy(iommu_heap->uncached_pools[i]);
+
+
+err_create_cached_pool:
+	for (i = 0; i < num_orders; i++)
+		if (iommu_heap->uncached_pools[i])
+			ion_page_pool_destroy(iommu_heap->cached_pools[i]);
+
+	kfree(iommu_heap->cached_pools);
+err_alloc_cached_pools:
+	kfree(iommu_heap->uncached_pools);
+err_alloc_uncached_pools:
+	kfree(iommu_heap);
+	return ERR_PTR(-ENOMEM);
 }
 
 void ion_iommu_heap_destroy(struct ion_heap *heap)
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index f990ada..118c39a 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -264,6 +264,9 @@
 		}
 	}
 
+	if (!outer_cache_op)
+		return -EINVAL;
+
 	outer_cache_op(buff_phys_start + offset,
 		       buff_phys_start + offset + length);
 
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index afb11c2..e0af2d4 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -109,6 +109,10 @@
 	.pm4_fw = NULL,
 	.wait_timeout = 0, /* in milliseconds, 0 means disabled */
 	.ib_check_level = 0,
+	.ft_policy = KGSL_FT_DEFAULT_POLICY,
+	.ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY,
+	.fast_hang_detect = 1,
+	.long_ib_detect = 1,
 };
 
 /* This set of registers are used for Hang detection
@@ -211,6 +215,8 @@
 		512, 0, 2, SZ_128K, 0x3FF037, 0x3FF016 },
 };
 
+static unsigned int adreno_isidle(struct kgsl_device *device);
+
 /**
  * adreno_perfcounter_init: Reserve kernel performance counters
  * @device: device to configure
@@ -439,8 +445,11 @@
 	for (i = 0; i < group->reg_count; i++) {
 		if (group->regs[i].countable == countable) {
 			/* Countable already associated with counter */
-			group->regs[i].refcount++;
-			group->regs[i].flags |= flags;
+			if (flags & PERFCOUNTER_FLAG_KERNEL)
+				group->regs[i].kernelcount++;
+			else
+				group->regs[i].usercount++;
+
 			if (offset)
 				*offset = group->regs[i].offset;
 			return 0;
@@ -457,14 +466,20 @@
 
 	/* initialize the new counter */
 	group->regs[empty].countable = countable;
-	group->regs[empty].refcount = 1;
+
+	/* set initial kernel and user count */
+	if (flags & PERFCOUNTER_FLAG_KERNEL) {
+		group->regs[empty].kernelcount = 1;
+		group->regs[empty].usercount = 0;
+	} else {
+		group->regs[empty].kernelcount = 0;
+		group->regs[empty].usercount = 1;
+	}
 
 	/* enable the new counter */
 	adreno_dev->gpudev->perfcounter_enable(adreno_dev, groupid, empty,
 		countable);
 
-	group->regs[empty].flags = flags;
-
 	if (offset)
 		*offset = group->regs[empty].offset;
 
@@ -477,12 +492,13 @@
  * @adreno_dev: Adreno device to configure
  * @groupid: Desired performance counter group
  * @countable: Countable desired to be freed from a  counter
+ * @flags: Flag to determine if kernel or user space request
  *
  * Put a performance counter/countable pair that was previously received.  If
  * noone else is using the countable, free up the counter for others.
  */
 int adreno_perfcounter_put(struct adreno_device *adreno_dev,
-	unsigned int groupid, unsigned int countable)
+	unsigned int groupid, unsigned int countable, unsigned int flags)
 {
 	struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters;
 	struct adreno_perfcount_group *group;
@@ -498,24 +514,27 @@
 
 	group = &(counters->groups[groupid]);
 
+	/*
+	 * Find if the counter/countable pair is used currently.
+	 * Start cycling through registers in the bank.
+	 */
 	for (i = 0; i < group->reg_count; i++) {
+		/* check if countable assigned is what we are looking for */
 		if (group->regs[i].countable == countable) {
-			if (group->regs[i].refcount > 0) {
-				group->regs[i].refcount--;
+			/* found pair, book keep count based on request type */
+			if (flags & PERFCOUNTER_FLAG_KERNEL &&
+					group->regs[i].kernelcount > 0)
+				group->regs[i].kernelcount--;
+			else if (group->regs[i].usercount > 0)
+				group->regs[i].usercount--;
+			else
+				break;
 
-				/*
-				 * book keeping to ensure we never free a
-				 * perf counter used by kernel
-				 */
-				if (group->regs[i].flags &&
-					group->regs[i].refcount == 0)
-					group->regs[i].refcount++;
-
-				/* make available if not used */
-				if (group->regs[i].refcount == 0)
-					group->regs[i].countable =
-						KGSL_PERFCOUNTER_NOT_USED;
-			}
+			/* mark available if not used anymore */
+			if (group->regs[i].kernelcount == 0 &&
+					group->regs[i].usercount == 0)
+				group->regs[i].countable =
+					KGSL_PERFCOUNTER_NOT_USED;
 
 			return 0;
 		}
@@ -818,6 +837,27 @@
 	return cmds - cmds_orig;
 }
 
+/**
+ * adreno_use_default_setstate() - Use CPU instead of the GPU to manage the mmu?
+ * @adreno_dev: the device
+ *
+ * In many cases it is preferable to poke the iommu or gpummu directly rather
+ * than using the GPU command stream. If we are idle or trying to go to a low
+ * power state, using the command stream will be slower and asynchronous, which
+ * needlessly complicates the power state transitions. Additionally,
+ * the hardware simulators do not support command stream MMU operations so
+ * the command stream can never be used if we are capturing CFF data.
+ *
+ */
+static bool adreno_use_default_setstate(struct adreno_device *adreno_dev)
+{
+	return (adreno_isidle(&adreno_dev->dev) ||
+		adreno_dev->drawctxt_active == NULL ||
+		KGSL_STATE_ACTIVE != adreno_dev->dev.state ||
+		atomic_read(&adreno_dev->dev.active_cnt) == 0 ||
+		adreno_dev->dev.cff_dump_enable);
+}
+
 static void adreno_iommu_setstate(struct kgsl_device *device,
 					unsigned int context_id,
 					uint32_t flags)
@@ -832,10 +872,7 @@
 	struct adreno_context *adreno_ctx = NULL;
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-	if (!adreno_dev->drawctxt_active ||
-		KGSL_STATE_ACTIVE != device->state ||
-		!atomic_read(&device->active_cnt) ||
-		device->cff_dump_enable) {
+	if (adreno_use_default_setstate(adreno_dev)) {
 		kgsl_mmu_device_setstate(&device->mmu, flags);
 		return;
 	}
@@ -845,7 +882,7 @@
 	if (context == NULL)
 		return;
 
-	adreno_ctx = context->devctxt;
+	adreno_ctx = ADRENO_CONTEXT(context);
 
 	if (kgsl_mmu_enable_clk(&device->mmu,
 				KGSL_IOMMU_CONTEXT_USER))
@@ -886,8 +923,7 @@
 	adreno_ringbuffer_issuecmds(device, adreno_ctx, KGSL_CMD_FLAGS_PMODE,
 			&link[0], sizedwords);
 
-	kgsl_mmu_disable_clk_on_ts(&device->mmu,
-		rb->timestamp[KGSL_MEMSTORE_GLOBAL], true);
+	kgsl_mmu_disable_clk_on_ts(&device->mmu, rb->global_ts, true);
 	kgsl_context_put(context);
 }
 
@@ -915,11 +951,11 @@
 	 * writes For CFF dump we must idle and use the registers so that it is
 	 * easier to filter out the mmu accesses from the dump
 	 */
-	if (!device->cff_dump_enable && adreno_dev->drawctxt_active) {
+	if (!adreno_use_default_setstate(adreno_dev)) {
 		context = kgsl_context_get(device, context_id);
 		if (context == NULL)
 			return;
-		adreno_ctx = context->devctxt;
+		adreno_ctx = ADRENO_CONTEXT(context);
 
 		if (flags & KGSL_MMUFLAGS_PTUPDATE) {
 			/* wait for graphics pipe to be idle */
@@ -1547,6 +1583,8 @@
 	pdata->bus_scale_table = msm_bus_cl_get_pdata(pdev);
 	if (IS_ERR_OR_NULL(pdata->bus_scale_table)) {
 		ret = PTR_ERR(pdata->bus_scale_table);
+		if (!ret)
+			ret = -EINVAL;
 		goto err;
 	}
 
@@ -1663,6 +1701,8 @@
 
 	adreno_debugfs_init(device);
 
+	adreno_ft_init_sysfs(device);
+
 	kgsl_pwrscale_init(device);
 	kgsl_pwrscale_attach_policy(device, ADRENO_DEFAULT_PWRSCALE_POLICY);
 
@@ -1703,7 +1743,6 @@
 static int adreno_init(struct kgsl_device *device)
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	int i;
 
 	if (KGSL_STATE_DUMP_AND_FT != device->state)
@@ -1744,8 +1783,6 @@
 		adreno_gpulist[adreno_dev->gpulist_index].sync_lock_pfp_ver))
 		device->mmu.flags |= KGSL_MMU_FLAGS_IOMMU_SYNC;
 
-	rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
-
 	/* Initialize ft detection register offsets */
 	ft_detect_regs[0] = adreno_getreg(adreno_dev,
 						ADRENO_REG_RBBM_STATUS);
@@ -1775,12 +1812,17 @@
 	int status = -EINVAL;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	unsigned int state = device->state;
+	unsigned int regulator_left_on = 0;
 
 	kgsl_cffdump_open(device);
 
 	if (KGSL_STATE_DUMP_AND_FT != device->state)
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
 
+	regulator_left_on = (regulator_is_enabled(device->pwrctrl.gpu_reg) ||
+				(device->pwrctrl.gpu_cx &&
+				regulator_is_enabled(device->pwrctrl.gpu_cx)));
+
 	/* Power up the device */
 	kgsl_pwrctrl_enable(device);
 
@@ -1808,6 +1850,14 @@
 		goto error_mmu_off;
 	}
 
+	if (regulator_left_on && adreno_dev->gpudev->soft_reset) {
+		/*
+		 * Reset the GPU for A3xx. A2xx does a soft reset in
+		 * the start function.
+		 */
+		adreno_dev->gpudev->soft_reset(adreno_dev);
+	}
+
 	/* Start the GPU */
 	adreno_dev->gpudev->start(adreno_dev);
 
@@ -1847,6 +1897,9 @@
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
+	if (adreno_dev->drawctxt_active)
+		kgsl_context_put(&adreno_dev->drawctxt_active->base);
+
 	adreno_dev->drawctxt_active = NULL;
 
 	adreno_ringbuffer_stop(&adreno_dev->ringbuffer);
@@ -1879,7 +1932,7 @@
 {
 	unsigned int ft_status = *((unsigned int *) data);
 	struct kgsl_context *context = ptr;
-	struct adreno_context *adreno_context = context->devctxt;
+	struct adreno_context *adreno_context = ADRENO_CONTEXT(context);
 
 	if (ft_status) {
 		context->reset_status =
@@ -1917,20 +1970,16 @@
 static int _set_max_ts(int id, void *ptr, void *data)
 {
 	struct kgsl_device *device = data;
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	struct kgsl_context *context = ptr;
-	struct adreno_context *drawctxt = context->devctxt;
+	struct adreno_context *drawctxt = ADRENO_CONTEXT(context);
 
-	if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
+	if (drawctxt && drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
 		kgsl_sharedmem_writel(device, &device->memstore,
 			KGSL_MEMSTORE_OFFSET(context->id,
-			soptimestamp),
-			rb->timestamp[context->id]);
+			soptimestamp), drawctxt->timestamp);
 		kgsl_sharedmem_writel(device, &device->memstore,
 			KGSL_MEMSTORE_OFFSET(context->id,
-			eoptimestamp),
-			rb->timestamp[context->id]);
+			eoptimestamp), drawctxt->timestamp);
 	}
 
 	return 0;
@@ -2186,7 +2235,7 @@
 	}
 
 	if (context) {
-		adreno_context = context->devctxt;
+		adreno_context = ADRENO_CONTEXT(context);
 		if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
 			if (ft_data->ib1) {
 				ret = _find_hanging_ib_sequence(rb,
@@ -2253,6 +2302,9 @@
 		return -EINVAL;
 	}
 
+	if (adreno_dev->drawctxt_active)
+		kgsl_context_put(&adreno_dev->drawctxt_active->base);
+
 	adreno_dev->drawctxt_active = NULL;
 
 	/* Stop the ringbuffer */
@@ -2315,11 +2367,9 @@
 	}
 
 reset_done:
-	if (context) {
-		struct adreno_context *adreno_context = context->devctxt;
-		kgsl_mmu_setstate(&device->mmu, adreno_context->pagetable,
-			KGSL_MEMSTORE_GLOBAL);
-	}
+	if (context)
+		kgsl_mmu_setstate(&device->mmu, context->pagetable,
+				KGSL_MEMSTORE_GLOBAL);
 
 	/* If iommu is used then we need to make sure that the iommu clocks
 	 * are on since there could be commands in pipeline that touch iommu */
@@ -2438,7 +2488,7 @@
 		}
 	} else {
 		no_context_ft = 0;
-		adreno_context = context->devctxt;
+		adreno_context = ADRENO_CONTEXT(context);
 		adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
 		/*
 		 * set the invalid ts flag to 0 for this context since we have
@@ -2494,16 +2544,16 @@
 		goto play_good_cmds;
 	}
 
-	/* Do not try the reply if hang is due to a pagefault */
-	if (adreno_context && adreno_context->pagefault) {
+	/* Do not try to replay if hang is due to a pagefault */
+	if (context && test_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv)) {
 		/* Resume MMU */
 		mmu->mmu_ops->mmu_pagefault_resume(mmu);
-		if ((ft_data->context_id == adreno_context->id) &&
-			(ft_data->global_eop == adreno_context->pagefault_ts)) {
+		if ((ft_data->context_id == context->id) &&
+			(ft_data->global_eop == context->pagefault_ts)) {
 			ft_data->ft_policy &= ~KGSL_FT_REPLAY;
 			KGSL_FT_ERR(device, "MMU fault skipping replay\n");
 		}
-		adreno_context->pagefault = 0;
+		clear_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv);
 	}
 
 	if (ft_data->ft_policy & KGSL_FT_REPLAY) {
@@ -2591,6 +2641,10 @@
 			adreno_context->flags = (adreno_context->flags &
 				~CTXT_FLAGS_GPU_HANG) | CTXT_FLAGS_GPU_HANG_FT;
 		}
+
+		if (last_active_ctx)
+			_kgsl_context_get(&last_active_ctx->base);
+
 		adreno_dev->drawctxt_active = last_active_ctx;
 	}
 
@@ -2618,10 +2672,7 @@
 		struct kgsl_context *last_ctx = kgsl_context_get(device,
 			ft_data->last_valid_ctx_id);
 
-		if (last_ctx)
-			adreno_dev->drawctxt_active = last_ctx->devctxt;
-
-		kgsl_context_put(last_ctx);
+		adreno_dev->drawctxt_active = ADRENO_CONTEXT(last_ctx);
 	}
 
 done:
@@ -2640,7 +2691,6 @@
 	int ret = 0;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
-	unsigned int timestamp;
 
 	/*
 	 * If GPU FT is turned off do not run FT.
@@ -2657,8 +2707,8 @@
 	"Bad context_id: %u, global_eop: 0x%x\n",
 	ft_data->ib1, ft_data->context_id, ft_data->global_eop);
 
-	timestamp = rb->timestamp[KGSL_MEMSTORE_GLOBAL];
-	KGSL_FT_INFO(device, "Last issued global timestamp: %x\n", timestamp);
+	KGSL_FT_INFO(device, "Last issued global timestamp: %x\n",
+			rb->global_ts);
 
 	/* We may need to replay commands multiple times based on whether
 	 * multiple contexts hang the GPU */
@@ -2687,14 +2737,12 @@
 	/* Restore correct states after fault tolerance */
 	if (adreno_dev->drawctxt_active)
 		device->mmu.hwpagetable =
-			adreno_dev->drawctxt_active->pagetable;
+			adreno_dev->drawctxt_active->base.pagetable;
 	else
 		device->mmu.hwpagetable = device->mmu.defaultpagetable;
-	rb->timestamp[KGSL_MEMSTORE_GLOBAL] = timestamp;
 	kgsl_sharedmem_writel(device, &device->memstore,
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
-			eoptimestamp),
-			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+			eoptimestamp), rb->global_ts);
 
 	/* switch to NULL ctxt */
 	if (adreno_dev->drawctxt_active != NULL)
@@ -2785,6 +2833,264 @@
 }
 EXPORT_SYMBOL(adreno_dump_and_exec_ft);
 
+/**
+ * _ft_sysfs_store() -  Common routine to write to FT sysfs files
+ * @buf: value to write
+ * @count: size of the value to write
+ * @sysfs_cfg: KGSL FT sysfs config to write
+ *
+ * This is a common routine to write to FT sysfs files.
+ */
+static int _ft_sysfs_store(const char *buf, size_t count, unsigned int *ptr)
+{
+	char temp[20];
+	unsigned long val;
+	int rc;
+
+	snprintf(temp, sizeof(temp), "%.*s",
+			 (int)min(count, sizeof(temp) - 1), buf);
+	rc = kstrtoul(temp, 0, &val);
+	if (rc)
+		return rc;
+
+	*ptr = val;
+
+	return count;
+}
+
+/**
+ * _get_adreno_dev() -  Routine to get a pointer to adreno dev
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ */
+struct adreno_device *_get_adreno_dev(struct device *dev)
+{
+	struct kgsl_device *device = kgsl_device_from_dev(dev);
+	return device ? ADRENO_DEVICE(device) : NULL;
+}
+
+/**
+ * _ft_policy_store() -  Routine to configure FT policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * FT policy can be set to any of the options below.
+ * KGSL_FT_DISABLE -> BIT(0) Set to disable FT
+ * KGSL_FT_REPLAY  -> BIT(1) Set to enable replay
+ * KGSL_FT_SKIPIB  -> BIT(2) Set to skip IB
+ * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
+ * by default set FT policy to KGSL_FT_DEFAULT_POLICY
+ */
+static int _ft_policy_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_policy);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+}
+
+/**
+ * _ft_policy_show() -  Routine to read FT policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ *
+ * This is a routine to read current FT policy
+ */
+static int _ft_policy_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_policy);
+}
+
+/**
+ * _ft_pagefault_policy_store() -  Routine to configure FT
+ * pagefault policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * FT pagefault policy can be set to any of the options below.
+ * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
+ * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE  -> BIT(1) Set to enable GPU HALT on
+ * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE  -> BIT(2) Set to log only one
+ * pagefault per page.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
+ * pagefault per INT.
+ */
+static int _ft_pagefault_policy_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_pf_policy);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+}
+
+/**
+ * _ft_pagefault_policy_show() -  Routine to read FT pagefault
+ * policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ *
+ * This is a routine to read current FT pagefault policy
+ */
+static int _ft_pagefault_policy_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_pf_policy);
+}
+
+/**
+ * _ft_fast_hang_detect_store() -  Routine to configure FT fast
+ * hang detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * 0x1 - Enable fast hang detection
+ * 0x0 - Disable fast hang detection
+ */
+static int _ft_fast_hang_detect_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->fast_hang_detect);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+
+}
+
+/**
+ * _ft_fast_hang_detect_show() -  Routine to read FT fast
+ * hang detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ */
+static int _ft_fast_hang_detect_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+				(adreno_dev->fast_hang_detect ? 1 : 0));
+}
+
+/**
+ * _ft_long_ib_detect_store() -  Routine to configure FT long IB
+ * detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * 0x0 - Enable long IB detection
+ * 0x1 - Disable long IB detection
+ */
+static int _ft_long_ib_detect_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->long_ib_detect);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+
+}
+
+/**
+ * _ft_long_ib_detect_show() -  Routine to read FT long IB
+ * detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ */
+static int _ft_long_ib_detect_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+				(adreno_dev->long_ib_detect ? 1 : 0));
+}
+
+
+#define FT_DEVICE_ATTR(name) \
+	DEVICE_ATTR(name, 0644,	_ ## name ## _show, _ ## name ## _store);
+
+FT_DEVICE_ATTR(ft_policy);
+FT_DEVICE_ATTR(ft_pagefault_policy);
+FT_DEVICE_ATTR(ft_fast_hang_detect);
+FT_DEVICE_ATTR(ft_long_ib_detect);
+
+
+const struct device_attribute *ft_attr_list[] = {
+	&dev_attr_ft_policy,
+	&dev_attr_ft_pagefault_policy,
+	&dev_attr_ft_fast_hang_detect,
+	&dev_attr_ft_long_ib_detect,
+	NULL,
+};
+
+int adreno_ft_init_sysfs(struct kgsl_device *device)
+{
+	return kgsl_create_device_sysfs_files(device->dev, ft_attr_list);
+}
+
+void adreno_ft_uninit_sysfs(struct kgsl_device *device)
+{
+	kgsl_remove_device_sysfs_files(device->dev, ft_attr_list);
+}
+
 static int adreno_getproperty(struct kgsl_device *device,
 				enum kgsl_property_type type,
 				void *value,
@@ -2929,20 +3235,15 @@
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
-	unsigned long wait;
+	unsigned long wait = jiffies;
 	unsigned long timeout = jiffies + msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
 	unsigned int rptr;
 
-	/*
-	 * The first time into the loop, wait for 100 msecs and kick wptr again
-	 * to ensure that the hardware has updated correctly.  After that, kick
-	 * it periodically every KGSL_TIMEOUT_PART msecs until the timeout
-	 * expires
-	 */
-
-	wait = jiffies + msecs_to_jiffies(100);
-
 	do {
+		/*
+		 * Wait is "jiffies" first time in the loop to start
+		 * GPU stall detection immediately.
+		 */
 		if (time_after(jiffies, wait)) {
 			/* Check to see if the core is hung */
 			if (adreno_ft_detect(device, regs))
@@ -2964,11 +3265,10 @@
 /* Caller must hold the device mutex. */
 int adreno_idle(struct kgsl_device *device)
 {
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	unsigned int rbbm_status;
 	unsigned long wait_time;
 	unsigned long wait_time_part;
 	unsigned int prev_reg_val[FT_DETECT_REGS_COUNT];
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
 	memset(prev_reg_val, 0, sizeof(prev_reg_val));
 
@@ -2986,23 +3286,15 @@
 	wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
 
 	while (time_before(jiffies, wait_time)) {
-		adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS,
-					&rbbm_status);
-		if (adreno_is_a2xx(adreno_dev)) {
-			if (rbbm_status == 0x110)
-				return 0;
-		} else {
-			if (!(rbbm_status & 0x80000000))
-				return 0;
-		}
+		if (adreno_isidle(device))
+			return 0;
 
-		/* Dont wait for timeout, detect hang faster.
-		 */
+		/* Dont wait for timeout, detect hang faster.  */
 		if (time_after(jiffies, wait_time_part)) {
-				wait_time_part = jiffies +
-					msecs_to_jiffies(KGSL_TIMEOUT_PART);
-				if ((adreno_ft_detect(device, prev_reg_val)))
-					goto err;
+			wait_time_part = jiffies +
+				msecs_to_jiffies(KGSL_TIMEOUT_PART);
+			if ((adreno_ft_detect(device, prev_reg_val)))
+				goto err;
 		}
 
 	}
@@ -3051,9 +3343,8 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-	WARN_ON(device->state == KGSL_STATE_INIT);
 	/* If the device isn't active, don't force it on. */
-	if (device->state == KGSL_STATE_ACTIVE) {
+	if (kgsl_pwrctrl_isenabled(device)) {
 		/* Is the ring buffer is empty? */
 		unsigned int rptr = adreno_get_rptr(rb);
 		if (rptr == rb->wptr) {
@@ -3096,21 +3387,20 @@
 	phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size)
 {
 	struct kgsl_context *context;
-	struct adreno_context *adreno_context = NULL;
 	int next = 0;
 	struct kgsl_memdesc *desc = NULL;
 
-
 	read_lock(&device->context_lock);
 	while (1) {
 		context = idr_get_next(&device->context_idr, &next);
 		if (context == NULL)
 			break;
 
-		adreno_context = (struct adreno_context *)context->devctxt;
-
-		if (kgsl_mmu_pt_equal(&device->mmu, adreno_context->pagetable,
+		if (kgsl_mmu_pt_equal(&device->mmu, context->pagetable,
 					pt_base)) {
+			struct adreno_context *adreno_context;
+
+			adreno_context = ADRENO_CONTEXT(context);
 			desc = &adreno_context->gpustate;
 			if (kgsl_gpuaddr_in_memdesc(desc, gpuaddr, size))
 				break;
@@ -3244,9 +3534,10 @@
 static unsigned int _get_context_id(struct kgsl_context *k_ctxt)
 {
 	unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
+
 	if (k_ctxt != NULL) {
-		struct adreno_context *a_ctxt = k_ctxt->devctxt;
-		if (k_ctxt->id == KGSL_CONTEXT_INVALID || a_ctxt == NULL)
+		struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt);
+		if (kgsl_context_detached(k_ctxt))
 			context_id = KGSL_CONTEXT_INVALID;
 		else if (a_ctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
 			context_id = k_ctxt->id;
@@ -3317,7 +3608,8 @@
 		 */
 
 		if (context && device->state != KGSL_STATE_SLUMBER) {
-			adreno_ringbuffer_issuecmds(device, context->devctxt,
+			adreno_ringbuffer_issuecmds(device,
+					ADRENO_CONTEXT(context),
 					KGSL_CMD_FLAGS_GET_INT, NULL, 0);
 		}
 	}
@@ -3377,6 +3669,7 @@
 	unsigned int curr_context_id = 0;
 	static struct adreno_context *curr_context;
 	static struct kgsl_context *context;
+	static char pid_name[TASK_COMM_LEN] = "unknown";
 
 	if (!adreno_dev->fast_hang_detect)
 		fast_hang_detected = 0;
@@ -3389,7 +3682,7 @@
 
 	if (is_adreno_rbbm_status_idle(device) &&
 		(kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED)
-		== rb->timestamp[KGSL_MEMSTORE_GLOBAL])) {
+		 == rb->global_ts)) {
 
 		/*
 		 * On A2XX if the RPTR != WPTR and the device is idle, then
@@ -3440,8 +3733,13 @@
 
 	if (curr_global_ts == prev_global_ts) {
 
-		/* Get the current context here */
-		if (context == NULL) {
+		/* If we don't already have a good context, get it. */
+		if (kgsl_context_detached(context)) {
+			kgsl_context_put(context);
+			context = NULL;
+			curr_context = NULL;
+			strlcpy(pid_name, "unknown", sizeof(pid_name));
+
 			kgsl_sharedmem_readl(&device->memstore,
 				&curr_context_id,
 				KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
@@ -3451,8 +3749,12 @@
 
 			context = kgsl_context_get(device, curr_context_id);
 			if (context != NULL) {
-				curr_context = context->devctxt;
+				struct task_struct *task;
+				curr_context = ADRENO_CONTEXT(context);
 				curr_context->ib_gpu_time_used = 0;
+				task = find_task_by_vpid(context->pid);
+				if (task)
+					get_task_comm(pid_name, task);
 			} else {
 				KGSL_DRV_ERR(device,
 					"Fault tolerance no context found\n");
@@ -3476,8 +3778,7 @@
 			KGSL_FT_ERR(device,
 				"Proc %s, ctxt_id %d ts %d triggered fault tolerance"
 				" on global ts %d\n",
-				curr_context ? curr_context->pid_name : "",
-				curr_context ? curr_context->id : 0,
+				pid_name, context ? context->id : 0,
 				(kgsl_readtimestamp(device, context,
 				KGSL_TIMESTAMP_RETIRED) + 1),
 				curr_global_ts + 1);
@@ -3489,7 +3790,7 @@
 			curr_context->ib_gpu_time_used += KGSL_TIMEOUT_PART;
 			KGSL_FT_INFO(device,
 			"Proc %s used GPU Time %d ms on timestamp 0x%X\n",
-			curr_context->pid_name, curr_context->ib_gpu_time_used,
+			pid_name, curr_context->ib_gpu_time_used,
 			curr_global_ts+1);
 
 			if ((long_ib_detected) &&
@@ -3505,8 +3806,7 @@
 						"Proc %s, ctxt_id %d ts %d"
 						"used GPU for %d ms long ib "
 						"detected on global ts %d\n",
-						curr_context->pid_name,
-						curr_context->id,
+						pid_name, context->id,
 						(kgsl_readtimestamp(device,
 						context,
 						KGSL_TIMESTAMP_RETIRED)+1),
@@ -3528,6 +3828,7 @@
 		kgsl_context_put(context);
 		context = NULL;
 		curr_context = NULL;
+		strlcpy(pid_name, "unknown", sizeof(pid_name));
 		adreno_dev->long_ib = 0;
 		adreno_dev->long_ib_ts = 0;
 	}
@@ -3550,7 +3851,7 @@
 	if (context_id == KGSL_CONTEXT_INVALID)
 		return -EINVAL;
 
-	ts_issued = adreno_dev->ringbuffer.timestamp[context_id];
+	ts_issued = adreno_context_timestamp(context, &adreno_dev->ringbuffer);
 
 	if (timestamp_cmp(timestamp, ts_issued) <= 0)
 		return 0;
@@ -3585,7 +3886,8 @@
 				unsigned int msecs)
 {
 	static unsigned int io_cnt;
-	struct adreno_context *adreno_ctx = context ? context->devctxt : NULL;
+	struct adreno_context *adreno_ctx = context ? ADRENO_CONTEXT(context) :
+		NULL;
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	unsigned int context_id = _get_context_id(context);
 	unsigned int time_elapsed = 0;
@@ -3593,8 +3895,6 @@
 	int ts_compare = 1;
 	int io, ret = -ETIMEDOUT;
 
-	/* Get out early if the context has already been destroyed */
-
 	if (context_id == KGSL_CONTEXT_INVALID) {
 		KGSL_DRV_WARN(device, "context was detached");
 		return -EINVAL;
@@ -3620,10 +3920,14 @@
 	 * this gives enough time for the engine to start moving and oddly
 	 * provides better hang detection results than just going the full
 	 * KGSL_TIMEOUT_PART right off the bat. The exception to this rule
-	 * is if msecs happens to be < 100ms then just use the full timeout
+	 * is if msecs happens to be < 100ms then just use 20ms or the msecs,
+	 * whichever is larger because anything less than 20 is unreliable
 	 */
 
-	wait = 100;
+	if (msecs == 0 || msecs >= 100)
+		wait = 100;
+	else
+		wait = (msecs > 20) ? msecs : 20;
 
 	do {
 		long status;
@@ -3732,9 +4036,9 @@
 	switch (type) {
 	case KGSL_TIMESTAMP_QUEUED: {
 		struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-		struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-		timestamp = rb->timestamp[context_id];
+		timestamp = adreno_context_timestamp(context,
+				&adreno_dev->ringbuffer);
 		break;
 	}
 	case KGSL_TIMESTAMP_CONSUMED:
@@ -3791,7 +4095,7 @@
 	case IOCTL_KGSL_PERFCOUNTER_PUT: {
 		struct kgsl_perfcounter_put *put = data;
 		result = adreno_perfcounter_put(adreno_dev, put->groupid,
-			put->countable);
+			put->countable, PERFCOUNTER_FLAG_NONE);
 		break;
 	}
 	case IOCTL_KGSL_PERFCOUNTER_QUERY: {
@@ -3906,6 +4210,7 @@
 	/* Optional functions */
 	.setstate = adreno_setstate,
 	.drawctxt_create = adreno_drawctxt_create,
+	.drawctxt_detach = adreno_drawctxt_detach,
 	.drawctxt_destroy = adreno_drawctxt_destroy,
 	.setproperty = adreno_setproperty,
 	.postmortem_dump = adreno_dump,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index b53d16f..c4ead4a 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -25,6 +25,9 @@
 #define ADRENO_DEVICE(device) \
 		KGSL_CONTAINER_OF(device, struct adreno_device, dev)
 
+#define ADRENO_CONTEXT(device) \
+		KGSL_CONTAINER_OF(device, struct adreno_context, base)
+
 #define ADRENO_CHIPID_CORE(_id) (((_id) >> 24) & 0xFF)
 #define ADRENO_CHIPID_MAJOR(_id) (((_id) >> 16) & 0xFF)
 #define ADRENO_CHIPID_MINOR(_id) (((_id) >> 8) & 0xFF)
@@ -138,14 +141,15 @@
 /**
  * struct adreno_perfcount_register: register state
  * @countable: countable the register holds
- * @refcount: number of users of the register
+ * @kernelcount: number of user space users of the register
+ * @usercount: number of kernel users of the register
  * @offset: register hardware offset
  */
 struct adreno_perfcount_register {
 	unsigned int countable;
-	unsigned int refcount;
+	unsigned int kernelcount;
+	unsigned int usercount;
 	unsigned int offset;
-	unsigned int flags;
 };
 
 /**
@@ -337,10 +341,10 @@
 #define  KGSL_FT_DEFAULT_POLICY           (KGSL_FT_REPLAY + KGSL_FT_SKIPIB)
 
 /* Pagefault policy flags */
-#define KGSL_FT_PAGEFAULT_INT_ENABLE         0x00000001
-#define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE     0x00000002
-#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE   0x00000004
-#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT    0x00000008
+#define KGSL_FT_PAGEFAULT_INT_ENABLE         BIT(0)
+#define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE     BIT(1)
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE   BIT(2)
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT    BIT(3)
 #define KGSL_FT_PAGEFAULT_DEFAULT_POLICY     (KGSL_FT_PAGEFAULT_INT_ENABLE + \
 					KGSL_FT_PAGEFAULT_GPUHALT_ENABLE)
 
@@ -407,12 +411,15 @@
 unsigned int adreno_ft_detect(struct kgsl_device *device,
 						unsigned int *prev_reg_val);
 
+int adreno_ft_init_sysfs(struct kgsl_device *device);
+void adreno_ft_uninit_sysfs(struct kgsl_device *device);
+
 int adreno_perfcounter_get(struct adreno_device *adreno_dev,
 	unsigned int groupid, unsigned int countable, unsigned int *offset,
 	unsigned int flags);
 
 int adreno_perfcounter_put(struct adreno_device *adreno_dev,
-	unsigned int groupid, unsigned int countable);
+	unsigned int groupid, unsigned int countable, unsigned int flags);
 
 int adreno_soft_reset(struct kgsl_device *device);
 
@@ -501,6 +508,26 @@
 }
 
 /**
+ * adreno_context_timestamp() - Return the last queued timestamp for the context
+ * @k_ctxt: Pointer to the KGSL context to query
+ * @rb: Pointer to the ringbuffer structure for the GPU
+ *
+ * Return the last queued context for the given context. This is used to verify
+ * that incoming requests are not using an invalid (unsubmitted) timestamp
+ */
+static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt,
+		struct adreno_ringbuffer *rb)
+{
+	if (k_ctxt) {
+		struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt);
+
+		if (a_ctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+			return a_ctxt->timestamp;
+	}
+	return rb->global_ts;
+}
+
+/**
  * adreno_encode_istore_size - encode istore size in CP format
  * @adreno_dev - The 3D device.
  *
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 42137fe..3d72c5c 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1355,7 +1355,7 @@
 	tmp_ctx.gmem_base = adreno_dev->gmem_base;
 
 	result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
-		drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
+		drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size);
 
 	if (result)
 		return result;
@@ -1364,7 +1364,7 @@
 	drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
 
 	/* blank out gmem shadow. */
-	kgsl_sharedmem_set(drawctxt->dev_priv->device,
+	kgsl_sharedmem_set(drawctxt->base.device,
 			&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
 			drawctxt->context_gmem_shadow.size);
 
@@ -1389,7 +1389,7 @@
 	kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
 			    KGSL_CACHE_OP_FLUSH);
 
-	kgsl_cffdump_syncmem(drawctxt->dev_priv,
+	kgsl_cffdump_syncmem(drawctxt->base.device,
 			&drawctxt->context_gmem_shadow.gmemshadow,
 			drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
 			drawctxt->context_gmem_shadow.gmemshadow.size, false);
@@ -1410,13 +1410,13 @@
 	 */
 
 	ret = kgsl_allocate(&drawctxt->gpustate,
-		drawctxt->pagetable, _context_size(adreno_dev));
+		drawctxt->base.pagetable, _context_size(adreno_dev));
 
 	if (ret)
 		return ret;
 
-	kgsl_sharedmem_set(drawctxt->dev_priv->device, &drawctxt->gpustate, 0,
-		0, _context_size(adreno_dev));
+	kgsl_sharedmem_set(drawctxt->base.device, &drawctxt->gpustate,
+		0, 0, _context_size(adreno_dev));
 
 	tmp_ctx.cmd = tmp_ctx.start
 	    = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
@@ -1440,8 +1440,8 @@
 	kgsl_cache_range_op(&drawctxt->gpustate,
 			    KGSL_CACHE_OP_FLUSH);
 
-	kgsl_cffdump_syncmem(drawctxt->dev_priv, &drawctxt->gpustate,
-			drawctxt->gpustate.gpuaddr,
+	kgsl_cffdump_syncmem(drawctxt->base.device,
+			&drawctxt->gpustate, drawctxt->gpustate.gpuaddr,
 			drawctxt->gpustate.size, false);
 
 done:
@@ -1516,7 +1516,7 @@
 			"Current active context has caused gpu hang\n");
 
 	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->reg_save[1],
 			context->reg_save[2] << 2, true);
 		/* save registers and constants. */
@@ -1525,7 +1525,7 @@
 			context->reg_save, 3);
 
 		if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->shader_save[1],
 				context->shader_save[2] << 2, true);
@@ -1534,7 +1534,7 @@
 				KGSL_CMD_FLAGS_PMODE,
 				context->shader_save, 3);
 
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->shader_fixup[1],
 				context->shader_fixup[2] << 2, true);
@@ -1552,7 +1552,7 @@
 
 	if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
 	    (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->context_gmem_shadow.gmem_save[1],
 			context->context_gmem_shadow.gmem_save[2] << 2, true);
 		/* save gmem.
@@ -1562,7 +1562,7 @@
 			KGSL_CMD_FLAGS_PMODE,
 			context->context_gmem_shadow.gmem_save, 3);
 
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->chicken_restore[1],
 			context->chicken_restore[2] << 2, true);
 
@@ -1586,9 +1586,18 @@
 	unsigned int cmds[5];
 
 	if (context == NULL) {
-		/* No context - set the default apgetable and thats it */
+		/* No context - set the default pagetable and thats it */
+		unsigned int id;
+		/*
+		 * If there isn't a current context, the kgsl_mmu_setstate
+		 * will use the CPU path so we don't need to give
+		 * it a valid context id.
+		 */
+		id = (adreno_dev->drawctxt_active != NULL)
+			? adreno_dev->drawctxt_active->base.id
+			: KGSL_CONTEXT_INVALID;
 		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
-				adreno_dev->drawctxt_active->id);
+				  id);
 		return;
 	}
 
@@ -1597,16 +1606,17 @@
 	cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
 	cmds[3] = device->memstore.gpuaddr +
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
-	cmds[4] = context->id;
+	cmds[4] = context->base.id;
 	adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
 					cmds, 5);
-	kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
+	kgsl_mmu_setstate(&device->mmu, context->base.pagetable,
+			context->base.id);
 
 	/* restore gmem.
 	 *  (note: changes shader. shader must not already be restored.)
 	 */
 	if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->context_gmem_shadow.gmem_restore[1],
 			context->context_gmem_shadow.gmem_restore[2] << 2,
 			true);
@@ -1616,7 +1626,7 @@
 			context->context_gmem_shadow.gmem_restore, 3);
 
 		if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->chicken_restore[1],
 				context->chicken_restore[2] << 2, true);
@@ -1631,7 +1641,7 @@
 	}
 
 	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->reg_restore[1],
 			context->reg_restore[2] << 2, true);
 
@@ -1641,7 +1651,7 @@
 
 		/* restore shader instructions & partitioning. */
 		if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->shader_restore[1],
 				context->shader_restore[2] << 2, true);
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 7e5638c..7882dc5 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2321,7 +2321,7 @@
 	tmp_ctx.gmem_base = adreno_dev->gmem_base;
 
 	result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
-		drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
+		drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size);
 
 	if (result)
 		return result;
@@ -2355,7 +2355,7 @@
 	 */
 
 	ret = kgsl_allocate(&drawctxt->gpustate,
-		drawctxt->pagetable, CONTEXT_SIZE);
+		drawctxt->base.pagetable, CONTEXT_SIZE);
 
 	if (ret)
 		return ret;
@@ -2420,7 +2420,7 @@
 		 * already be saved.)
 		 */
 
-		kgsl_cffdump_syncmem(context->dev_priv,
+		kgsl_cffdump_syncmem(context->base.device,
 			&context->gpustate,
 			context->context_gmem_shadow.gmem_save[1],
 			context->context_gmem_shadow.gmem_save[2] << 2, true);
@@ -2441,8 +2441,17 @@
 
 	if (context == NULL) {
 		/* No context - set the default pagetable and thats it */
+		unsigned int id;
+		/*
+		 * If there isn't a current context, the kgsl_mmu_setstate
+		 * will use the CPU path so we don't need to give
+		 * it a valid context id.
+		 */
+		id = (adreno_dev->drawctxt_active != NULL)
+			? adreno_dev->drawctxt_active->base.id
+			: KGSL_CONTEXT_INVALID;
 		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
-				adreno_dev->drawctxt_active->id);
+				  id);
 		return;
 	}
 
@@ -2451,10 +2460,11 @@
 	cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
 	cmds[3] = device->memstore.gpuaddr +
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
-	cmds[4] = context->id;
+	cmds[4] = context->base.id;
 	adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
 					cmds, 5);
-	kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
+	kgsl_mmu_setstate(&device->mmu, context->base.pagetable,
+			context->base.id);
 
 	/*
 	 * Restore GMEM.  (note: changes shader.
@@ -2462,7 +2472,7 @@
 	 */
 
 	if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
-		kgsl_cffdump_syncmem(context->dev_priv,
+		kgsl_cffdump_syncmem(context->base.device,
 			&context->gpustate,
 			context->context_gmem_shadow.gmem_restore[1],
 			context->context_gmem_shadow.gmem_restore[2] << 2,
@@ -3142,97 +3152,97 @@
  */
 
 static struct adreno_perfcount_register a3xx_perfcounters_cp[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_CP_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_CP_0_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_rbbm[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RBBM_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RBBM_1_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_pc[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_1_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_2_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_3_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_1_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_2_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_3_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_vfd[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VFD_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VFD_1_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_hlsq[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_1_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_2_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_3_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_4_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_5_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_1_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_2_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_3_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_4_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_5_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_vpc[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VPC_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VPC_1_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_tse[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TSE_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TSE_1_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_ras[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RAS_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RAS_1_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_uche[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_1_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_2_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_3_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_4_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_5_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_1_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_2_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_3_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_4_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_5_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_tp[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_1_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_2_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_3_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_4_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_5_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_1_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_2_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_3_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_4_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_5_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_sp[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_1_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_2_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_3_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_4_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_5_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_6_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_7_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_1_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_2_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_3_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_4_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_5_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_6_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_7_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_rb[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RB_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RB_1_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_pwr[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PWR_0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PWR_1_LO },
 };
 
 static struct adreno_perfcount_register a3xx_perfcounters_vbif[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT0_LO },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT1_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_CNT0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_CNT1_LO },
 };
 static struct adreno_perfcount_register a3xx_perfcounters_vbif_pwr[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT0_LO },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT1_LO },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT2_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_PWR_CNT0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_PWR_CNT1_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_PWR_CNT2_LO },
 };
 
 static struct adreno_perfcount_group a3xx_perfcounter_groups[] = {
@@ -3296,6 +3306,39 @@
 			NULL, PERFCOUNTER_FLAG_KERNEL);
 }
 
+/**
+ * a3xx_protect_init() - Initializes register protection on a3xx
+ * @device: Pointer to the device structure
+ * Performs register writes to enable protected access to sensitive
+ * registers
+ */
+static void a3xx_protect_init(struct kgsl_device *device)
+{
+	/* enable access protection to privileged registers */
+	kgsl_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);
+
+	/* RBBM registers */
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);
+
+	/* CP registers */
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);
+
+	/* RB registers */
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);
+
+	/* VBIF registers */
+	kgsl_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
+}
+
 static void a3xx_start(struct adreno_device *adreno_dev)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
@@ -3360,6 +3403,8 @@
 		kgsl_regwrite(device, A3XX_RB_GMEM_BASE_ADDR,
 			(unsigned int)(adreno_dev->ocmem_base >> 14));
 	}
+	/* Turn on protection */
+	a3xx_protect_init(device);
 
 	/* Turn on performance counters */
 	kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01);
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 90bd017..fc98d86 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -56,41 +56,6 @@
 		&adreno_dev->wait_timeout);
 	debugfs_create_u32("ib_check", 0644, device->d_debugfs,
 			   &adreno_dev->ib_check_level);
-	/* By Default enable fast hang detection */
-	adreno_dev->fast_hang_detect = 1;
-	debugfs_create_u32("fast_hang_detect", 0644, device->d_debugfs,
-			   &adreno_dev->fast_hang_detect);
-	/*
-	 * FT policy can be set to any of the options below.
-	 * KGSL_FT_OFF -> BIT(0) Set to turn off FT
-	 * KGSL_FT_REPLAY  -> BIT(1) Set to enable replay
-	 * KGSL_FT_SKIPIB  -> BIT(2) Set to skip IB
-	 * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
-	 * KGSL_FT_DISABLE -> BIT(4) Set to disable FT for faulting context
-	 * by default set FT policy to KGSL_FT_DEFAULT_POLICY
-	 */
-	adreno_dev->ft_policy = KGSL_FT_DEFAULT_POLICY;
-	debugfs_create_u32("ft_policy", 0644, device->d_debugfs,
-			   &adreno_dev->ft_policy);
-	/* By default enable long IB detection */
-	adreno_dev->long_ib_detect = 1;
-	debugfs_create_u32("long_ib_detect", 0644, device->d_debugfs,
-			   &adreno_dev->long_ib_detect);
-
-	/*
-	 * FT pagefault policy can be set to any of the options below.
-	 * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
-	 * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE  -> BIT(1) Set to enable GPU HALT on
-	 * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
-	 * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE  -> BIT(2) Set to log only one
-	 * pagefault per page.
-	 * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
-	 * pagefault per INT.
-	 */
-	 adreno_dev->ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY;
-	 debugfs_create_u32("ft_pagefault_policy", 0644, device->d_debugfs,
-			&adreno_dev->ft_pf_policy);
-
 	debugfs_create_file("active_cnt", 0444, device->d_debugfs, device,
 			    &_active_count_fops);
 }
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index b32cdae..bf173a7 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -134,34 +134,32 @@
 
 /**
  * adreno_drawctxt_create - create a new adreno draw context
- * @device - KGSL device to create the context on
- * @pagetable - Pagetable for the context
- * @context- Generic KGSL context structure
- * @flags - flags for the context (passed from user space)
+ * @dev_priv: the owner of the context
+ * @flags: flags for the context (passed from user space)
  *
- * Create a new draw context for the 3D core.  Return 0 on success,
- * or error code on failure.
+ * Create and return a new draw context for the 3D core.
  */
-int adreno_drawctxt_create(struct kgsl_device *device,
-			struct kgsl_pagetable *pagetable,
-			struct kgsl_context *context, uint32_t *flags)
+struct kgsl_context *
+adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
+			uint32_t *flags)
 {
 	struct adreno_context *drawctxt;
+	struct kgsl_device *device = dev_priv->device;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	int ret;
 
 	drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL);
-
 	if (drawctxt == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
-	drawctxt->pid = task_pid_nr(current);
-	strlcpy(drawctxt->pid_name, current->comm, TASK_COMM_LEN);
-	drawctxt->pagetable = pagetable;
+	ret = kgsl_context_init(dev_priv, &drawctxt->base);
+	if (ret != 0) {
+		kfree(drawctxt);
+		return ERR_PTR(ret);
+	}
+
 	drawctxt->bin_base_offset = 0;
-	drawctxt->id = context->id;
-	rb->timestamp[context->id] = 0;
+	drawctxt->timestamp = 0;
 
 	*flags &= (KGSL_CONTEXT_PREAMBLE |
 		KGSL_CONTEXT_NO_GMEM_ALLOC |
@@ -192,50 +190,47 @@
 
 	drawctxt->type =
 		(*flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT;
-	drawctxt->dev_priv = context->dev_priv;
 
 	ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
 	if (ret)
 		goto err;
 
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, ref_wait_ts),
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, ref_wait_ts),
 			KGSL_INIT_REFTIMESTAMP);
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, ts_cmp_enable), 0);
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, ts_cmp_enable),
+			0);
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, soptimestamp), 0);
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp),
+			0);
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, eoptimestamp), 0);
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp),
+			0);
 
-	context->devctxt = drawctxt;
-	return 0;
+	return &drawctxt->base;
 err:
-	kfree(drawctxt);
-	return ret;
+	kgsl_context_put(&drawctxt->base);
+	return ERR_PTR(ret);
 }
 
 /**
- * adreno_drawctxt_destroy - destroy a draw context
- * @device - KGSL device that owns the context
- * @context- Generic KGSL context container for the context
+ * adreno_drawctxt_detach(): detach a context from the GPU
+ * @context: Generic KGSL context container for the context
  *
- * Destroy an existing context.  Return 0 on success or error
- * code on failure.
  */
-
-/* destroy a drawing context */
-
-void adreno_drawctxt_destroy(struct kgsl_device *device,
-			  struct kgsl_context *context)
+void adreno_drawctxt_detach(struct kgsl_context *context)
 {
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct kgsl_device *device;
+	struct adreno_device *adreno_dev;
 	struct adreno_context *drawctxt;
 
-	if (context == NULL || context->devctxt == NULL)
+	if (context == NULL)
 		return;
 
-	drawctxt = context->devctxt;
+	device = context->device;
+	adreno_dev = ADRENO_DEVICE(device);
+	drawctxt = ADRENO_CONTEXT(context);
 	/* deactivate context */
 	if (adreno_dev->drawctxt_active == drawctxt) {
 		/* no need to save GMEM or shader, the context is
@@ -256,9 +251,17 @@
 
 	kgsl_sharedmem_free(&drawctxt->gpustate);
 	kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
+}
 
+
+void adreno_drawctxt_destroy(struct kgsl_context *context)
+{
+	struct adreno_context *drawctxt;
+	if (context == NULL)
+		return;
+
+	drawctxt = ADRENO_CONTEXT(context);
 	kfree(drawctxt);
-	context->devctxt = NULL;
 }
 
 /**
@@ -274,10 +277,12 @@
 				      struct kgsl_context *context,
 				      unsigned int offset)
 {
-	struct adreno_context *drawctxt = context->devctxt;
+	struct adreno_context *drawctxt;
 
-	if (drawctxt)
-		drawctxt->bin_base_offset = offset;
+	if (context == NULL)
+		return;
+	drawctxt = ADRENO_CONTEXT(context);
+	drawctxt->bin_base_offset = offset;
 }
 
 /**
@@ -316,12 +321,22 @@
 
 	KGSL_CTXT_INFO(device, "from %d to %d flags %d\n",
 		adreno_dev->drawctxt_active ?
-		adreno_dev->drawctxt_active->id : 0,
-		drawctxt ? drawctxt->id : 0, flags);
+		adreno_dev->drawctxt_active->base.id : 0,
+		drawctxt ? drawctxt->base.id : 0, flags);
 
 	/* Save the old context */
 	adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
 
+	/* Put the old instance of the active drawctxt */
+	if (adreno_dev->drawctxt_active) {
+		kgsl_context_put(&adreno_dev->drawctxt_active->base);
+		adreno_dev->drawctxt_active = NULL;
+	}
+
+	/* Get a refcount to the new instance */
+	if (drawctxt)
+		_kgsl_context_get(&drawctxt->base);
+
 	/* Set the new context */
 	adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
 	adreno_dev->drawctxt_active = drawctxt;
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index 2b8e600..88d1b8c 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -13,8 +13,6 @@
 #ifndef __ADRENO_DRAWCTXT_H
 #define __ADRENO_DRAWCTXT_H
 
-#include <linux/sched.h>
-
 #include "adreno_pm4types.h"
 #include "a2xx_reg.h"
 
@@ -96,15 +94,11 @@
 };
 
 struct adreno_context {
-	pid_t pid;
-	char pid_name[TASK_COMM_LEN];
-	unsigned int id;
+	struct kgsl_context base;
 	unsigned int ib_gpu_time_used;
+	unsigned int timestamp;
 	uint32_t flags;
-	uint32_t pagefault;
-	unsigned long pagefault_ts;
 	unsigned int type;
-	struct kgsl_pagetable *pagetable;
 	struct kgsl_memdesc gpustate;
 	unsigned int reg_restore[3];
 	unsigned int shader_save[3];
@@ -131,16 +125,15 @@
 	struct kgsl_memdesc constant_load_commands[3];
 	struct kgsl_memdesc cond_execs[4];
 	struct kgsl_memdesc hlsqcontrol_restore_commands[1];
-	struct kgsl_device_private *dev_priv;
 };
 
-int adreno_drawctxt_create(struct kgsl_device *device,
-			struct kgsl_pagetable *pagetable,
-			struct kgsl_context *context,
+
+struct kgsl_context *adreno_drawctxt_create(struct kgsl_device_private *,
 			uint32_t *flags);
 
-void adreno_drawctxt_destroy(struct kgsl_device *device,
-			  struct kgsl_context *context);
+void adreno_drawctxt_detach(struct kgsl_context *context);
+
+void adreno_drawctxt_destroy(struct kgsl_context *context);
 
 void adreno_drawctxt_switch(struct adreno_device *adreno_dev,
 				struct adreno_context *drawctxt,
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index f6c05b5..e03f708 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -138,7 +138,7 @@
 			if (context && context->flags & CTXT_FLAGS_GPU_HANG) {
 				KGSL_CTXT_WARN(rb->device,
 				"Context %p caused a gpu hang. Will not accept commands for context %d\n",
-				context, context->id);
+				context, context->base.id);
 				return -EDEADLK;
 			}
 			wait_time = jiffies + wait_timeout;
@@ -410,32 +410,6 @@
 				rb->memptrs_desc.gpuaddr +
 				GSL_RB_MEMPTRS_RPTR_OFFSET);
 
-	if (adreno_is_a3xx(adreno_dev)) {
-		/* enable access protection to privileged registers */
-		kgsl_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);
-
-		/* RBBM registers */
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);
-
-		/* CP registers */
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);
-
-		/* RB registers */
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);
-
-		/* VBIF registers */
-		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
-	}
-
 	if (adreno_is_a2xx(adreno_dev)) {
 		/* explicitly clear all cp interrupts */
 		kgsl_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
@@ -575,6 +549,8 @@
 	/* overlay structure on memptrs memory */
 	rb->memptrs = (struct kgsl_rbmemptrs *) rb->memptrs_desc.hostptr;
 
+	rb->global_ts = 0;
+
 	return 0;
 }
 
@@ -594,11 +570,11 @@
 	memset(rb, 0, sizeof(struct adreno_ringbuffer));
 }
 
-static uint32_t
+static int
 adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
 				struct adreno_context *context,
 				unsigned int flags, unsigned int *cmds,
-				int sizedwords, uint32_t timestamp)
+				int sizedwords)
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
 	unsigned int *ringcmds;
@@ -607,6 +583,7 @@
 	unsigned int rcmd_gpu;
 	unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
 	unsigned int gpuaddr = rb->device->memstore.gpuaddr;
+	unsigned int timestamp;
 
 	/*
 	 * if the context was not created with per context timestamp
@@ -616,20 +593,7 @@
 	 */
 	if ((context && (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)) &&
 		!(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE))
-		context_id = context->id;
-
-	if ((context && (context->flags & CTXT_FLAGS_USER_GENERATED_TS)) &&
-		!(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) {
-		if (timestamp_cmp(rb->timestamp[context_id],
-						timestamp) >= 0) {
-			KGSL_DRV_ERR(rb->device,
-				"Invalid user generated ts <%d:0x%x>, "
-				"less than last issued ts <%d:0x%x>\n",
-				context_id, timestamp, context_id,
-				rb->timestamp[context_id]);
-			return -ERANGE;
-		}
-	}
+		context_id = context->base.id;
 
 	/* reserve space to temporarily turn off protected mode
 	*  error checking if needed
@@ -669,13 +633,8 @@
 		total_sizedwords += 2;
 
 	ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
-	if (!ringcmds) {
-		/*
-		 * We could not allocate space in ringbuffer, just return the
-		 * last timestamp
-		 */
-		return rb->timestamp[context_id];
-	}
+	if (!ringcmds)
+		return -ENOSPC;
 
 	rcmd_gpu = rb->buffer_desc.gpuaddr
 		+ sizeof(uint)*(rb->wptr-total_sizedwords);
@@ -690,26 +649,19 @@
 	}
 
 	/* always increment the global timestamp. once. */
-	rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
+	rb->global_ts++;
 
-	/*
-	 * If global timestamp then we are not using per context ts for
-	 * this submission
-	 */
-	if (context_id != KGSL_MEMSTORE_GLOBAL) {
-		if (context->flags & CTXT_FLAGS_USER_GENERATED_TS)
-			rb->timestamp[context_id] = timestamp;
-		else
-			rb->timestamp[context_id]++;
-	}
-	timestamp = rb->timestamp[context_id];
+	if (KGSL_MEMSTORE_GLOBAL != context_id)
+		timestamp = context->timestamp;
+	else
+		timestamp = rb->global_ts;
 
 	/* scratchpad ts for fault tolerance */
 	GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
 		cp_type0_packet(adreno_getreg(adreno_dev,
 			ADRENO_REG_CP_TIMESTAMP), 1));
 	GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
-			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+			rb->global_ts);
 
 	/* start-of-pipeline timestamp */
 	GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
@@ -781,7 +733,7 @@
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 				eoptimestamp)));
 		GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
-			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+			rb->global_ts);
 	}
 
 	if (adreno_is_a20x(adreno_dev)) {
@@ -857,7 +809,7 @@
 
 	adreno_ringbuffer_submit(rb);
 
-	return timestamp;
+	return 0;
 }
 
 unsigned int
@@ -877,7 +829,7 @@
 	flags |= KGSL_CMD_FLAGS_INTERNAL_ISSUE;
 
 	return adreno_ringbuffer_addcmds(rb, drawctxt, flags, cmds,
-							sizedwords, 0);
+							sizedwords);
 }
 
 static bool _parse_ibs(struct kgsl_device_private *dev_priv, uint gpuaddr,
@@ -1097,12 +1049,9 @@
 		ret = -EINVAL;
 		goto done;
 	}
-	drawctxt = context->devctxt;
+	drawctxt = ADRENO_CONTEXT(context);
 
 	if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
-		KGSL_CTXT_ERR(device, "proc %s failed fault tolerance"
-			" will not accept commands for context %d\n",
-			drawctxt->pid_name, drawctxt->id);
 		ret = -EDEADLK;
 		goto done;
 	}
@@ -1116,10 +1065,6 @@
 		start_index = 1;
 
 	if (drawctxt->flags & CTXT_FLAGS_SKIP_EOF) {
-		KGSL_CTXT_ERR(device,
-			"proc %s triggered fault tolerance"
-			" skipping commands for context till EOF %d\n",
-			drawctxt->pid_name, drawctxt->id);
 		if (flags & KGSL_CMD_FLAGS_EOF)
 			drawctxt->flags &= ~CTXT_FLAGS_SKIP_EOF;
 		if (start_index)
@@ -1172,10 +1117,30 @@
 
 	adreno_drawctxt_switch(adreno_dev, drawctxt, flags);
 
-	*timestamp = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
+	if (drawctxt->flags & CTXT_FLAGS_USER_GENERATED_TS) {
+		if (timestamp_cmp(drawctxt->timestamp, *timestamp) >= 0) {
+			KGSL_DRV_ERR(device,
+				"Invalid user generated ts <%d:0x%x>, "
+				"less than last issued ts <%d:0x%x>\n",
+				context->id, *timestamp, context->id,
+				drawctxt->timestamp);
+			return -ERANGE;
+		}
+		drawctxt->timestamp = *timestamp;
+	} else
+		drawctxt->timestamp++;
+
+	ret = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
 					drawctxt,
 					(flags & KGSL_CMD_FLAGS_EOF),
-					&link[0], (cmds - link), *timestamp);
+					&link[0], (cmds - link));
+	if (ret)
+		goto done;
+
+	if (drawctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+		*timestamp = drawctxt->timestamp;
+	else
+		*timestamp = adreno_dev->ringbuffer.global_ts;
 
 #ifdef CONFIG_MSM_KGSL_CFF_DUMP
 	/*
@@ -1282,7 +1247,7 @@
 	k_ctxt = kgsl_context_get(device, ft_data->context_id);
 
 	if (k_ctxt) {
-		a_ctxt = k_ctxt->devctxt;
+		a_ctxt = ADRENO_CONTEXT(k_ctxt);
 		if (a_ctxt->flags & CTXT_FLAGS_PREAMBLE)
 			_turn_preamble_on_for_ib_seq(rb, rb_rptr);
 		kgsl_context_put(k_ctxt);
@@ -1319,7 +1284,7 @@
 			k_ctxt = kgsl_context_get(rb->device, val2);
 
 			if (k_ctxt) {
-				a_ctxt = k_ctxt->devctxt;
+				a_ctxt = ADRENO_CONTEXT(k_ctxt);
 
 			/* If we are changing to a good context and were not
 			 * copying commands then copy over commands to the good
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index e9fb050..9634e32 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -55,7 +55,7 @@
 
 	unsigned int wptr; /* write pointer offset in dwords from baseaddr */
 
-	unsigned int timestamp[KGSL_MEMSTORE_MAX];
+	unsigned int global_ts;
 };
 
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 4c1ef54..1ff989c 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -448,20 +448,24 @@
 	entry->priv = NULL;
 }
 
-/* Allocate a new context id */
-
-static struct kgsl_context *
-kgsl_create_context(struct kgsl_device_private *dev_priv)
+/**
+ * kgsl_context_init() - helper to initialize kgsl_context members
+ * @dev_priv: the owner of the context
+ * @context: the newly created context struct, should be allocated by
+ * the device specific drawctxt_create function.
+ *
+ * This is a helper function for the device specific drawctxt_create
+ * function to initialize the common members of its context struct.
+ * If this function succeeds, reference counting is active in the context
+ * struct and the caller should kgsl_context_put() it on error.
+ * If it fails, the caller should just free the context structure
+ * it passed in.
+ */
+int kgsl_context_init(struct kgsl_device_private *dev_priv,
+			struct kgsl_context *context)
 {
+	int ret = 0, id;
 	struct kgsl_device *device = dev_priv->device;
-	struct kgsl_context *context;
-	int ret, id = 0;
-
-	context = kzalloc(sizeof(*context), GFP_KERNEL);
-
-	if (context == NULL)
-		return ERR_PTR(-ENOMEM);
-
 
 	while (1) {
 		if (idr_pre_get(&device->context_idr, GFP_KERNEL) == 0) {
@@ -480,30 +484,26 @@
 	}
 
 	if (ret)
-		goto func_end;
+		goto fail;
 
 	/* MAX - 1, there is one memdesc in memstore for device info */
 	if (id >= KGSL_MEMSTORE_MAX) {
 		KGSL_DRV_INFO(device, "cannot have more than %d "
 				"ctxts due to memstore limitation\n",
 				KGSL_MEMSTORE_MAX);
-		write_lock(&device->context_lock);
-		idr_remove(&device->context_idr, id);
-		write_unlock(&device->context_lock);
 		ret = -ENOSPC;
-		goto func_end;
+		goto fail_free_id;
 	}
 
 	kref_init(&context->refcount);
+	context->device = dev_priv->device;
+	context->pagetable = dev_priv->process_priv->pagetable;
 	context->dev_priv = dev_priv;
+	context->pid = dev_priv->process_priv->pid;
 
 	ret = kgsl_sync_timeline_create(context);
-	if (ret) {
-		write_lock(&device->context_lock);
-		idr_remove(&dev_priv->device->context_idr, id);
-		write_unlock(&device->context_lock);
-		goto func_end;
-	}
+	if (ret)
+		goto fail_free_id;
 
 	/* Initialize the pending event list */
 	INIT_LIST_HEAD(&context->events);
@@ -518,15 +518,15 @@
 	 */
 
 	INIT_LIST_HEAD(&context->events_list);
-
-func_end:
-	if (ret) {
-		kfree(context);
-		return ERR_PTR(ret);
-	}
-
-	return context;
+	return 0;
+fail_free_id:
+	write_lock(&device->context_lock);
+	idr_remove(&dev_priv->device->context_idr, id);
+	write_unlock(&device->context_lock);
+fail:
+	return ret;
 }
+EXPORT_SYMBOL(kgsl_context_init);
 
 /**
  * kgsl_context_detach - Release the "master" context reference
@@ -536,36 +536,35 @@
  * has requested for it to be destroyed. The context itself may
  * exist a bit longer until its reference count goes to zero.
  * Other code referencing the context can detect that it has been
- * detached because the context id will be set to KGSL_CONTEXT_INVALID.
+ * detached by checking the KGSL_CONTEXT_DETACHED bit in
+ * context->priv.
  */
 void
 kgsl_context_detach(struct kgsl_context *context)
 {
-	int id;
 	struct kgsl_device *device;
 	if (context == NULL)
 		return;
-	device = context->dev_priv->device;
-	trace_kgsl_context_detach(device, context);
-	id = context->id;
 
-	if (device->ftbl->drawctxt_destroy)
-		device->ftbl->drawctxt_destroy(device, context);
-	/*device specific drawctxt_destroy MUST clean up devctxt */
-	BUG_ON(context->devctxt);
+	device = context->device;
+
+	/*
+	 * Mark the context as detached to keep others from using
+	 * the context before it gets fully removed, and to make sure
+	 * we don't try to detach twice.
+	 */
+	if (test_and_set_bit(KGSL_CONTEXT_DETACHED, &context->priv))
+		return;
+
+	trace_kgsl_context_detach(device, context);
+
+	device->ftbl->drawctxt_detach(context);
 	/*
 	 * Cancel events after the device-specific context is
-	 * destroyed, to avoid possibly freeing memory while
+	 * detached, to avoid possibly freeing memory while
 	 * it is still in use by the GPU.
 	 */
-	kgsl_cancel_events_ctxt(device, context);
-
-	write_lock(&device->context_lock);
-	context->id = KGSL_CONTEXT_INVALID;
-	idr_remove(&device->context_idr, id);
-	write_unlock(&device->context_lock);
-
-	context->dev_priv = NULL;
+	kgsl_context_cancel_events(device, context);
 
 	kgsl_context_put(context);
 }
@@ -575,8 +574,19 @@
 {
 	struct kgsl_context *context = container_of(kref, struct kgsl_context,
 						    refcount);
+	struct kgsl_device *device = context->device;
+
+	trace_kgsl_context_destroy(device, context);
+
+	write_lock(&device->context_lock);
+	if (context->id != KGSL_CONTEXT_INVALID) {
+		idr_remove(&device->context_idr, context->id);
+		context->id = KGSL_CONTEXT_INVALID;
+	}
+	write_unlock(&device->context_lock);
 	kgsl_sync_timeline_destroy(context);
-	kfree(context);
+
+	device->ftbl->drawctxt_destroy(context);
 }
 
 struct kgsl_device *kgsl_get_device(int dev_idx)
@@ -698,21 +708,22 @@
 	KGSL_PWR_WARN(device, "resume start\n");
 	mutex_lock(&device->mutex);
 	if (device->state == KGSL_STATE_SUSPEND) {
+		kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
 		complete_all(&device->hwaccess_gate);
-	} else {
+	} else if (device->state != KGSL_STATE_INIT) {
 		/*
 		 * This is an error situation,so wait for the device
 		 * to idle and then put the device to SLUMBER state.
 		 * This will put the device to the right state when
 		 * we resume.
 		 */
-		device->ftbl->idle(device);
+		if (device->state == KGSL_STATE_ACTIVE)
+			device->ftbl->idle(device);
 		kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
 		kgsl_pwrctrl_sleep(device);
 		KGSL_PWR_ERR(device,
 			"resume invoked without a suspend\n");
 	}
-	kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
 	kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
 
 	mutex_unlock(&device->mutex);
@@ -807,9 +818,9 @@
 		debugfs_remove_recursive(private->debug_root);
 
 	while (1) {
-		rcu_read_lock();
+		spin_lock(&private->mem_lock);
 		entry = idr_get_next(&private->mem_idr, &next);
-		rcu_read_unlock();
+		spin_unlock(&private->mem_lock);
 		if (entry == NULL)
 			break;
 		kgsl_mem_entry_put(entry);
@@ -820,8 +831,8 @@
 		 */
 		next = 0;
 	}
-	kgsl_mmu_putpagetable(private->pagetable);
 	idr_destroy(&private->mem_idr);
+	kgsl_mmu_putpagetable(private->pagetable);
 
 	kfree(private);
 	return;
@@ -1243,11 +1254,11 @@
 {
 	struct kgsl_mem_entry *entry;
 
-	rcu_read_lock();
+	spin_lock(&process->mem_lock);
 	entry = idr_find(&process->mem_idr, id);
 	if (entry)
 		kgsl_mem_entry_get(entry);
-	rcu_read_unlock();
+	spin_unlock(&process->mem_lock);
 
 	return entry;
 }
@@ -1265,10 +1276,12 @@
 static inline bool kgsl_mem_entry_set_pend(struct kgsl_mem_entry *entry)
 {
 	bool ret = false;
+
+	if (entry == NULL)
+		return false;
+
 	spin_lock(&entry->priv->mem_lock);
-	if (entry && entry->pending_free) {
-		ret = false;
-	} else if (entry) {
+	if (!entry->pending_free) {
 		entry->pending_free = 1;
 		ret = true;
 	}
@@ -1550,9 +1563,11 @@
 }
 
 static void kgsl_freemem_event_cb(struct kgsl_device *device,
-	void *priv, u32 id, u32 timestamp)
+	void *priv, u32 id, u32 timestamp, u32 type)
 {
 	struct kgsl_mem_entry *entry = priv;
+
+	/* Free the memory for all event types */
 	trace_kgsl_mem_timestamp_free(device, entry, id, timestamp, 0);
 	kgsl_mem_entry_put(entry);
 }
@@ -1623,27 +1638,16 @@
 	int result = 0;
 	struct kgsl_drawctxt_create *param = data;
 	struct kgsl_context *context = NULL;
+	struct kgsl_device *device = dev_priv->device;
 
-	context = kgsl_create_context(dev_priv);
-
+	context = device->ftbl->drawctxt_create(dev_priv, &param->flags);
 	if (IS_ERR(context)) {
 		result = PTR_ERR(context);
 		goto done;
 	}
-
-	if (dev_priv->device->ftbl->drawctxt_create) {
-		result = dev_priv->device->ftbl->drawctxt_create(
-			dev_priv->device, dev_priv->process_priv->pagetable,
-			context, &param->flags);
-		if (result)
-			goto done;
-	}
 	trace_kgsl_context_create(dev_priv->device, context, param->flags);
 	param->drawctxt_id = context->id;
 done:
-	if (result && !IS_ERR(context))
-		kgsl_context_detach(context);
-
 	return result;
 }
 
@@ -2600,7 +2604,7 @@
 	if (!entry)
 		return -EINVAL;
 
-	kgsl_cffdump_syncmem(dev_priv, &entry->memdesc, param->gpuaddr,
+	kgsl_cffdump_syncmem(dev_priv->device, &entry->memdesc, param->gpuaddr,
 			     param->len, true);
 
 	kgsl_mem_entry_put(entry);
@@ -2627,21 +2631,23 @@
 };
 
 /**
- * kgsl_genlock_event_cb - Event callback for a genlock timestamp event
- * @device - The KGSL device that expired the timestamp
- * @priv - private data for the event
- * @context_id - the context id that goes with the timestamp
- * @timestamp - the timestamp that triggered the event
+ * kgsl_genlock_event_cb() - Event callback for a genlock timestamp event
+ * @device: The KGSL device that expired the timestamp
+ * @priv: private data for the event
+ * @context_id: the context id that goes with the timestamp
+ * @timestamp: the timestamp that triggered the event
+ * @type: Type of event that signaled the callback
  *
  * Release a genlock lock following the expiration of a timestamp
  */
 
 static void kgsl_genlock_event_cb(struct kgsl_device *device,
-	void *priv, u32 context_id, u32 timestamp)
+	void *priv, u32 context_id, u32 timestamp, u32 type)
 {
 	struct kgsl_genlock_event_priv *ev = priv;
 	int ret;
 
+	/* Signal the lock for every event type */
 	ret = genlock_lock(ev->handle, GENLOCK_UNLOCK, 0, 0);
 	if (ret)
 		KGSL_CORE_ERR("Error while unlocking genlock: %d\n", ret);
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index d05d391..8d390a9 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -218,16 +218,16 @@
 
 void kgsl_get_memory_usage(char *str, size_t len, unsigned int memflags);
 
-int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
-	void (*cb)(struct kgsl_device *, void *, u32, u32), void *priv,
-	void *owner);
+void kgsl_signal_event(struct kgsl_device *device,
+		struct kgsl_context *context, unsigned int timestamp,
+		unsigned int type);
+
+void kgsl_signal_events(struct kgsl_device *device,
+		struct kgsl_context *context, unsigned int type);
 
 void kgsl_cancel_events(struct kgsl_device *device,
 	void *owner);
 
-void kgsl_cancel_events_ctxt(struct kgsl_device *device,
-	struct kgsl_context *context);
-
 extern const struct dev_pm_ops kgsl_pm_ops;
 
 int kgsl_suspend_driver(struct platform_device *pdev, pm_message_t state);
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index b07a1cad..43bcc30 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -410,29 +410,19 @@
 	cffdump_printline(-1, cff_opcode, op1, op2, op3, op4, op5);
 }
 
-void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
-	struct kgsl_memdesc *memdesc, uint gpuaddr, uint sizebytes,
-	bool clean_cache)
+void kgsl_cffdump_syncmem(struct kgsl_device *device,
+			  struct kgsl_memdesc *memdesc, uint gpuaddr,
+			  uint sizebytes, bool clean_cache)
 {
-	struct kgsl_device *device = dev_priv->device;
 	const void *src;
 
 	if (!device->cff_dump_enable)
 		return;
 
+	BUG_ON(memdesc == NULL);
+
 	total_syncmem += sizebytes;
 
-	if (memdesc == NULL) {
-		struct kgsl_mem_entry *entry;
-		entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
-			gpuaddr, sizebytes);
-		if (entry == NULL) {
-			KGSL_CORE_ERR("did not find mapping "
-				"for gpuaddr: 0x%08x\n", gpuaddr);
-			return;
-		}
-		memdesc = &entry->memdesc;
-	}
 	src = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr);
 	if (memdesc->hostptr == NULL) {
 		KGSL_CORE_ERR(
diff --git a/drivers/gpu/msm/kgsl_cffdump.h b/drivers/gpu/msm/kgsl_cffdump.h
index ab5a345..2852e0f 100644
--- a/drivers/gpu/msm/kgsl_cffdump.h
+++ b/drivers/gpu/msm/kgsl_cffdump.h
@@ -28,7 +28,7 @@
 void kgsl_cffdump_destroy(void);
 void kgsl_cffdump_open(struct kgsl_device *device);
 void kgsl_cffdump_close(struct kgsl_device *device);
-void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
+void kgsl_cffdump_syncmem(struct kgsl_device *,
 	struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
 	bool clean_cache);
 void kgsl_cffdump_setmem(struct kgsl_device *device, uint addr,
@@ -74,7 +74,7 @@
 	return;
 }
 
-static inline void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
+static inline void kgsl_cffdump_syncmem(struct kgsl_device *device,
 		struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
 		bool clean_cache)
 {
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index 9dfda32..2a77632 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -296,20 +296,17 @@
 		print_mem_entry(s, entry);
 	}
 
-	spin_unlock(&private->mem_lock);
 
 	/* now print all the unbound entries */
 	while (1) {
-		rcu_read_lock();
 		entry = idr_get_next(&private->mem_idr, &next);
-		rcu_read_unlock();
-
 		if (entry == NULL)
 			break;
 		if (entry->memdesc.gpuaddr == 0)
 			print_mem_entry(s, entry);
 		next++;
 	}
+	spin_unlock(&private->mem_lock);
 
 	return 0;
 }
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index d0e40db..9629d3f 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -15,6 +15,7 @@
 
 #include <linux/idr.h>
 #include <linux/pm_qos.h>
+#include <linux/sched.h>
 
 #include "kgsl.h"
 #include "kgsl_mmu.h"
@@ -53,6 +54,22 @@
 
 #define KGSL_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))
 
+/*
+ * KGSL event types - these are passed to the event callback when the event
+ * expires or is cancelled
+ */
+
+#define KGSL_EVENT_TIMESTAMP_RETIRED 0
+#define KGSL_EVENT_CANCELLED 1
+
+/*
+ * "list" of event types for ftrace symbolic magic
+ */
+
+#define KGSL_EVENT_TYPES \
+	{ KGSL_EVENT_TIMESTAMP_RETIRED, "retired" }, \
+	{ KGSL_EVENT_CANCELLED, "cancelled" }
+
 struct kgsl_device;
 struct platform_device;
 struct kgsl_device_private;
@@ -103,11 +120,10 @@
 	   calling the hook */
 	void (*setstate) (struct kgsl_device *device, unsigned int context_id,
 			uint32_t flags);
-	int (*drawctxt_create) (struct kgsl_device *device,
-		struct kgsl_pagetable *pagetable, struct kgsl_context *context,
-		uint32_t *flags);
-	void (*drawctxt_destroy) (struct kgsl_device *device,
-		struct kgsl_context *context);
+	struct kgsl_context *(*drawctxt_create) (struct kgsl_device_private *,
+						uint32_t *flags);
+	void (*drawctxt_detach) (struct kgsl_context *context);
+	void (*drawctxt_destroy) (struct kgsl_context *context);
 	long (*ioctl) (struct kgsl_device_private *dev_priv,
 		unsigned int cmd, void *data);
 	int (*setproperty) (struct kgsl_device *device,
@@ -127,10 +143,12 @@
 	int              mpu_range;
 };
 
+typedef void (*kgsl_event_func)(struct kgsl_device *, void *, u32, u32, u32);
+
 struct kgsl_event {
 	struct kgsl_context *context;
 	uint32_t timestamp;
-	void (*func)(struct kgsl_device *, void *, u32, u32);
+	kgsl_event_func func;
 	void *priv;
 	struct list_head list;
 	void *owner;
@@ -254,31 +272,45 @@
 	.ver_minor = DRIVER_VERSION_MINOR
 
 
+/* bits for struct kgsl_context.priv */
+/* the context has been destroyed by userspace and is no longer using the gpu */
+#define KGSL_CONTEXT_DETACHED 0
+/* the context has caused a pagefault */
+#define KGSL_CONTEXT_PAGEFAULT 1
+
 /**
  * struct kgsl_context - Master structure for a KGSL context object
- * @refcount - kref object for reference counting the context
- * @id - integer identifier for the context
- * @dev_priv - pointer to the owning device instance
- * @devctxt - pointer to the device specific context information
- * @reset_status - status indication whether a gpu reset occured and whether
+ * @refcount: kref object for reference counting the context
+ * @id: integer identifier for the context
+ * @priv: in-kernel context flags, use KGSL_CONTEXT_* values
+ * @dev_priv: pointer to the owning device instance
+ * @reset_status: status indication whether a gpu reset occured and whether
  * this context was responsible for causing it
- * @wait_on_invalid_ts - flag indicating if this context has tried to wait on a
+ * @wait_on_invalid_ts: flag indicating if this context has tried to wait on a
  * bad timestamp
- * @timeline - sync timeline used to create fences that can be signaled when a
+ * @timeline: sync timeline used to create fences that can be signaled when a
  * sync_pt timestamp expires
- * @events - list head of pending events for this context
- * @events_list - list node for the list of all contexts that have pending events
+ * @events: list head of pending events for this context
+ * @events_list: list node for the list of all contexts that have pending events
+ * @pid: process that owns this context.
+ * @pagefault: flag set if this context caused a pagefault.
+ * @pagefault_ts: global timestamp of the pagefault, if KGSL_CONTEXT_PAGEFAULT
+ * is set.
  */
 struct kgsl_context {
 	struct kref refcount;
 	uint32_t id;
+	pid_t pid;
 	struct kgsl_device_private *dev_priv;
-	void *devctxt;
+	unsigned long priv;
+	struct kgsl_device *device;
+	struct kgsl_pagetable *pagetable;
 	unsigned int reset_status;
 	bool wait_on_invalid_ts;
 	struct sync_timeline *timeline;
 	struct list_head events;
 	struct list_head events_list;
+	unsigned int pagefault_ts;
 };
 
 struct kgsl_process_private {
@@ -316,6 +348,9 @@
 
 struct kgsl_device *kgsl_get_device(int dev_idx);
 
+int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
+	kgsl_event_func func, void *priv, void *owner);
+
 static inline void kgsl_process_add_stats(struct kgsl_process_private *priv,
 	unsigned int type, size_t size)
 {
@@ -429,6 +464,9 @@
 
 void kgsl_context_destroy(struct kref *kref);
 
+int kgsl_context_init(struct kgsl_device_private *, struct kgsl_context
+		*context);
+
 /**
  * kgsl_context_put() - Release context reference count
  * @context: Pointer to the KGSL context to be released
@@ -442,6 +480,22 @@
 	if (context)
 		kref_put(&context->refcount, kgsl_context_destroy);
 }
+
+/**
+ * kgsl_context_detached() - check if a context is detached
+ * @context: the context
+ *
+ * Check if a context has been destroyed by userspace and is only waiting
+ * for reference counts to go away. This check is used to weed out
+ * contexts that shouldn't use the gpu so NULL is considered detached.
+ */
+static inline bool kgsl_context_detached(struct kgsl_context *context)
+{
+	return (context == NULL || test_bit(KGSL_CONTEXT_DETACHED,
+						&context->priv));
+}
+
+
 /**
  * kgsl_context_get() - get a pointer to a KGSL context
  * @device: Pointer to the KGSL device that owns the context
@@ -462,7 +516,10 @@
 
 	context = idr_find(&device->context_idr, id);
 
-	if (context)
+	/* Don't return a context that has been detached */
+	if (kgsl_context_detached(context))
+		context = NULL;
+	else
 		kref_get(&context->refcount);
 
 	read_unlock(&device->context_lock);
@@ -471,6 +528,20 @@
 }
 
 /**
+* _kgsl_context_get() - lightweight function to just increment the ref count
+* @context: Pointer to the KGSL context
+*
+* Get a reference to the specified KGSL context structure. This is a
+* lightweight way to just increase the refcount on a known context rather than
+* walking through kgsl_context_get and searching the iterator
+*/
+static inline void _kgsl_context_get(struct kgsl_context *context)
+{
+	if (context)
+		kref_get(&context->refcount);
+}
+
+/**
  * kgsl_context_get_owner() - get a pointer to a KGSL context in a specific
  * process
  * @dev_priv: Pointer to the process struct
@@ -489,8 +560,8 @@
 
 	context = kgsl_context_get(dev_priv->device, id);
 
-	/* Verify that the context belongs to the dev_priv instance */
-	if (context && context->dev_priv != dev_priv) {
+	/* Verify that the context belongs to current calling process. */
+	if (context != NULL && context->pid != dev_priv->process_priv->pid) {
 		kgsl_context_put(context);
 		return NULL;
 	}
@@ -498,4 +569,30 @@
 	return context;
 }
 
+/**
+ * kgsl_context_cancel_events() - Cancel all events for a context
+ * @device:  Pointer to the KGSL device structure for the GPU
+ * @context: Pointer to the KGSL context
+ *
+ * Signal all pending events on the context with KGSL_EVENT_CANCELLED
+ */
+static inline void kgsl_context_cancel_events(struct kgsl_device *device,
+	struct kgsl_context *context)
+{
+	kgsl_signal_events(device, context, KGSL_EVENT_CANCELLED);
+}
+
+/**
+ * kgsl_context_cancel_events_timestamp() - cancel events for a given timestamp
+ * @device: Pointer to the KGSL device that owns the context
+ * @context: Pointer to the context that owns the event or NULL for global
+ * @timestamp: Timestamp to cancel events for
+ *
+ * Cancel events pending for a specific timestamp
+ */
+static inline void kgsl_cancel_events_timestamp(struct kgsl_device *device,
+	struct kgsl_context *context, unsigned int timestamp)
+{
+	kgsl_signal_event(device, context, timestamp, KGSL_EVENT_CANCELLED);
+}
 #endif  /* __KGSL_DEVICE_H */
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 1fc7467..c221c4a 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -385,6 +385,7 @@
 	kgsl_gem_free_memory(obj);
 	drm_gem_object_release(obj);
 	kfree(obj->driver_private);
+	kfree(obj);
 }
 
 int
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 0b75175..e4f502a 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -18,6 +18,12 @@
 
 #include "kgsl_trace.h"
 
+static inline struct list_head *_get_list_head(struct kgsl_device *device,
+		struct kgsl_context *context)
+{
+	return (context) ? &context->events : &device->events;
+}
+
 static void _add_event_to_list(struct list_head *head, struct kgsl_event *event)
 {
 	struct list_head *n;
@@ -36,27 +42,182 @@
 		list_add_tail(&event->list, head);
 }
 
+static inline void _do_signal_event(struct kgsl_device *device,
+		struct kgsl_event *event, unsigned int timestamp,
+		unsigned int type)
+{
+	int id = event->context ? event->context->id : KGSL_MEMSTORE_GLOBAL;
+
+	trace_kgsl_fire_event(id, timestamp, type, jiffies - event->created);
+
+	if (event->func)
+		event->func(device, event->priv, id, timestamp, type);
+
+	list_del(&event->list);
+	kgsl_context_put(event->context);
+	kfree(event);
+
+	kgsl_active_count_put(device);
+}
+
+static void _retire_events(struct kgsl_device *device,
+		struct list_head *head, unsigned int timestamp)
+{
+	struct kgsl_event *event, *tmp;
+
+	list_for_each_entry_safe(event, tmp, head, list) {
+		if (timestamp_cmp(timestamp, event->timestamp) < 0)
+			break;
+
+		_do_signal_event(device, event, event->timestamp,
+			KGSL_EVENT_TIMESTAMP_RETIRED);
+	}
+}
+
+static struct kgsl_event *_find_event(struct kgsl_device *device,
+		struct list_head *head, unsigned int timestamp,
+		kgsl_event_func func, void *priv)
+{
+	struct kgsl_event *event, *tmp;
+
+	list_for_each_entry_safe(event, tmp, head, list) {
+		if (timestamp == event->timestamp && func == event->func &&
+			event->priv == priv)
+			return event;
+	}
+
+	return NULL;
+}
+
+/**
+ * _signal_event() - send a signal to a specific event in the list
+ * @device: Pointer to the KGSL device struct
+ * @head: Pointer to the event list to process
+ * @timestamp: timestamp of the event to signal
+ * @cur: timestamp value to send to the callback
+ * @type: Signal ID to send to the callback
+ *
+ * Send the specified signal to the events in the list with the specified
+ * timestamp. The timestamp 'cur' is sent to the callback so it knows
+ * when the signal was delivered
+ */
+static void _signal_event(struct kgsl_device *device,
+		struct list_head *head, unsigned int timestamp,
+		unsigned int cur, unsigned int type)
+{
+	struct kgsl_event *event, *tmp;
+
+	list_for_each_entry_safe(event, tmp, head, list) {
+		if (timestamp_cmp(timestamp, event->timestamp) == 0)
+			_do_signal_event(device, event, cur, type);
+	}
+}
+
+/**
+ * _signal_events() - send a signal to all the events in a list
+ * @device: Pointer to the KGSL device struct
+ * @head: Pointer to the event list to process
+ * @timestamp: Timestamp to pass to the events (this should be the current
+ * timestamp when the signal is sent)
+ * @type: Signal ID to send to the callback
+ *
+ * Send the specified signal to all the events in the list and destroy them
+ */
+static void _signal_events(struct kgsl_device *device,
+		struct list_head *head, uint32_t timestamp,
+		unsigned int type)
+{
+	struct kgsl_event *event, *tmp;
+
+	list_for_each_entry_safe(event, tmp, head, list)
+		_do_signal_event(device, event, timestamp, type);
+
+}
+
+/**
+ * kgsl_signal_event() - send a signal to a specific event in the context
+ * @device: Pointer to the KGSL device struct
+ * @context: Pointer to the KGSL context
+ * @timestamp: Timestamp of the event to signal
+ * @type: Signal ID to send to the callback
+ *
+ * Send the specified signal to all the events in the context with the given
+ * timestamp
+ */
+void kgsl_signal_event(struct kgsl_device *device,
+		struct kgsl_context *context, unsigned int timestamp,
+		unsigned int type)
+{
+	struct list_head *head = _get_list_head(device, context);
+	uint32_t cur;
+
+	BUG_ON(!mutex_is_locked(&device->mutex));
+
+	cur = kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED);
+	_signal_event(device, head, timestamp, cur, type);
+
+	if (context && list_empty(&context->events))
+		list_del_init(&context->events_list);
+}
+EXPORT_SYMBOL(kgsl_signal_event);
+
+/**
+ * kgsl_signal_events() - send a signal to all events in the context
+ * @device: Pointer to the KGSL device struct
+ * @context: Pointer to the KGSL context
+ * @type: Signal ID to send to the callback function
+ *
+ * Send the specified signal to all the events in the context
+ */
+void kgsl_signal_events(struct kgsl_device *device,
+		struct kgsl_context *context, unsigned int type)
+{
+	struct list_head *head = _get_list_head(device, context);
+	uint32_t cur;
+
+	BUG_ON(!mutex_is_locked(&device->mutex));
+
+	/*
+	 * Send the current timestamp to the callback so it knows when the
+	 * signal occured
+	 */
+
+	cur = kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED);
+
+	_signal_events(device, head, cur, type);
+
+	/*
+	 * Remove the context from the master list since we know everything on
+	 * it has been removed
+	 */
+
+	if (context)
+		list_del_init(&context->events_list);
+}
+EXPORT_SYMBOL(kgsl_signal_events);
+
 /**
  * kgsl_add_event - Add a new timstamp event for the KGSL device
  * @device - KGSL device for the new event
  * @id - the context ID that the event should be added to
  * @ts - the timestamp to trigger the event on
- * @cb - callback function to call when the timestamp expires
+ * @func - callback function to call when the timestamp expires
  * @priv - private data for the specific event type
  * @owner - driver instance that owns this event
  *
  * @returns - 0 on success or error code on failure
  */
 int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
-	void (*cb)(struct kgsl_device *, void *, u32, u32), void *priv,
-	void *owner)
+	kgsl_event_func func, void *priv, void *owner)
 {
 	int ret;
 	struct kgsl_event *event;
 	unsigned int cur_ts;
 	struct kgsl_context *context = NULL;
 
-	if (cb == NULL)
+	BUG_ON(!mutex_is_locked(&device->mutex));
+
+	if (func == NULL)
 		return -EINVAL;
 
 	if (id != KGSL_MEMSTORE_GLOBAL) {
@@ -74,8 +235,9 @@
 	 */
 
 	if (timestamp_cmp(cur_ts, ts) >= 0) {
-		trace_kgsl_fire_event(id, ts, 0);
-		cb(device, priv, id, ts);
+		trace_kgsl_fire_event(id, cur_ts, ts, 0);
+
+		func(device, priv, id, ts, KGSL_EVENT_TIMESTAMP_RETIRED);
 		kgsl_context_put(context);
 		return 0;
 	}
@@ -100,7 +262,7 @@
 	event->context = context;
 	event->timestamp = ts;
 	event->priv = priv;
-	event->func = cb;
+	event->func = func;
 	event->owner = owner;
 	event->created = jiffies;
 
@@ -129,131 +291,60 @@
 EXPORT_SYMBOL(kgsl_add_event);
 
 /**
- * kgsl_cancel_events_ctxt - Cancel all events for a context
- * @device - KGSL device for the events to cancel
- * @context - context whose events we want to cancel
+ * kgsl_cancel_events() - Cancel all global events owned by a process
+ * @device: Pointer to the KGSL device struct
+ * @owner: driver instance that owns the events to cancel
  *
+ * Cancel all global events that match the owner pointer
  */
-void kgsl_cancel_events_ctxt(struct kgsl_device *device,
-	struct kgsl_context *context)
-{
-	struct kgsl_event *event, *event_tmp;
-	unsigned int id, cur;
-
-	cur = kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED);
-	id = context->id;
-
-	/*
-	 * Increment the refcount to avoid freeing the context while
-	 * cancelling its events
-	 */
-	kref_get(&context->refcount);
-
-	/* Remove ourselves from the master pending list */
-	list_del_init(&context->events_list);
-
-	list_for_each_entry_safe(event, event_tmp, &context->events, list) {
-		/*
-		 * "cancel" the events by calling their callback.
-		 * Currently, events are used for lock and memory
-		 * management, so if the process is dying the right
-		 * thing to do is release or free.
-		 *
-		 * Send the current timestamp so the event knows how far the
-		 * system got before the event was canceled
-		 */
-		list_del(&event->list);
-
-		trace_kgsl_fire_event(id, cur, jiffies - event->created);
-
-		if (event->func)
-			event->func(device, event->priv, id, cur);
-
-		kgsl_context_put(context);
-		kfree(event);
-
-		kgsl_active_count_put(device);
-	}
-	kgsl_context_put(context);
-}
-
-/**
- * kgsl_cancel_events - Cancel all generic events for a process
- * @device - KGSL device for the events to cancel
- * @owner - driver instance that owns the events to cancel
- *
- */
-void kgsl_cancel_events(struct kgsl_device *device,
-	void *owner)
+void kgsl_cancel_events(struct kgsl_device *device, void *owner)
 {
 	struct kgsl_event *event, *event_tmp;
 	unsigned int cur;
 
+	BUG_ON(!mutex_is_locked(&device->mutex));
+
 	cur = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED);
 
 	list_for_each_entry_safe(event, event_tmp, &device->events, list) {
 		if (event->owner != owner)
 			continue;
 
-		/*
-		 * "cancel" the events by calling their callback.
-		 * Currently, events are used for lock and memory
-		 * management, so if the process is dying the right
-		 * thing to do is release or free. Send the current timestamp so
-		 * the callback knows how far the GPU made it before things went
-		 * explosion
-		 */
-		list_del(&event->list);
-
-		trace_kgsl_fire_event(KGSL_MEMSTORE_GLOBAL, cur,
-			jiffies - event->created);
-
-		if (event->func)
-			event->func(device, event->priv, KGSL_MEMSTORE_GLOBAL,
-				cur);
-
-		if (event->context)
-			kgsl_context_put(event->context);
-		kfree(event);
-
-		kgsl_active_count_put(device);
+		_do_signal_event(device, event, cur, KGSL_EVENT_CANCELLED);
 	}
 }
 EXPORT_SYMBOL(kgsl_cancel_events);
 
-static void _process_event_list(struct kgsl_device *device,
-		struct list_head *head, unsigned int timestamp)
+/**
+ * kgsl_cancel_event() - send a cancel signal to a specific event
+ * @device: Pointer to the KGSL device struct
+ * @context: Pointer to the KGSL context
+ * @timestamp: Timestamp of the event to cancel
+ * @func: Callback function of the event - this is used to match the actual
+ * event
+ * @priv: Private data for the callback function - this is used to match to the
+ * actual event
+ *
+ * Send the a cancel signal to a specific event that matches all the parameters
+ */
+
+void kgsl_cancel_event(struct kgsl_device *device, struct kgsl_context *context,
+		unsigned int timestamp, kgsl_event_func func,
+		void *priv)
 {
-	struct kgsl_event *event, *tmp;
-	unsigned int id;
+	struct kgsl_event *event;
+	struct list_head *head = _get_list_head(device, context);
 
-	list_for_each_entry_safe(event, tmp, head, list) {
-		if (timestamp_cmp(timestamp, event->timestamp) < 0)
-			break;
+	event = _find_event(device, head, timestamp, func, priv);
 
-		id = event->context ? event->context->id : KGSL_MEMSTORE_GLOBAL;
+	if (event) {
+		unsigned int cur = kgsl_readtimestamp(device, context,
+			KGSL_TIMESTAMP_RETIRED);
 
-		/*
-		 * Send the timestamp of the expired event, not the current
-		 * timestamp.  This prevents the event handlers from getting
-		 * confused if they don't bother comparing the current timetamp
-		 * to the timestamp they wanted
-		 */
-		list_del(&event->list);
-
-		trace_kgsl_fire_event(id, event->timestamp,
-			jiffies - event->created);
-
-		if (event->func)
-			event->func(device, event->priv, id, event->timestamp);
-
-		if (event->context)
-			kgsl_context_put(event->context);
-		kfree(event);
-
-		kgsl_active_count_put(device);
+		_do_signal_event(device, event, cur, KGSL_EVENT_CANCELLED);
 	}
 }
+EXPORT_SYMBOL(kgsl_cancel_event);
 
 static inline int _mark_next_event(struct kgsl_device *device,
 		struct list_head *head)
@@ -282,7 +373,7 @@
 		unsigned int timestamp = kgsl_readtimestamp(device, context,
 			KGSL_TIMESTAMP_RETIRED);
 
-		_process_event_list(device, &context->events, timestamp);
+		_retire_events(device, &context->events, timestamp);
 
 		/*
 		 * _mark_next event will return 1 as long as the next event
@@ -313,7 +404,7 @@
 
 	/* Process expired global events */
 	timestamp = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED);
-	_process_event_list(device, &device->events, timestamp);
+	_retire_events(device, &device->events, timestamp);
 	_mark_next_event(device, &device->events);
 
 	/* Now process all of the pending contexts */
@@ -324,7 +415,7 @@
 		 * Increment the refcount to make sure that the list_del_init
 		 * is called with a valid context's list
 		 */
-		kref_get(&context->refcount);
+		_kgsl_context_get(context);
 		/*
 		 * If kgsl_timestamp_expired_context returns 0 then it no longer
 		 * has any pending events and can be removed from the list
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index ace6121..ecda5a7 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -38,6 +38,7 @@
 
 static struct kgsl_iommu_register_list kgsl_iommuv0_reg[KGSL_IOMMU_REG_MAX] = {
 	{ 0, 0 },			/* GLOBAL_BASE */
+	{ 0x0, 1 },			/* SCTLR */
 	{ 0x10, 1 },			/* TTBR0 */
 	{ 0x14, 1 },			/* TTBR1 */
 	{ 0x20, 1 },			/* FSR */
@@ -54,6 +55,7 @@
 
 static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = {
 	{ 0, 0 },			/* GLOBAL_BASE */
+	{ 0x0, 1 },			/* SCTLR */
 	{ 0x20, 1 },			/* TTBR0 */
 	{ 0x28, 1 },			/* TTBR1 */
 	{ 0x58, 1 },			/* FSR */
@@ -61,8 +63,8 @@
 	{ 0x008, 1 },			/* RESUME */
 	{ 0, 0 },			/* TLBLKCR not in V1 */
 	{ 0, 0 },			/* V2PUR not in V1 */
-	{ 0x68, 0 },			/* FSYNR0 */
-	{ 0x6C, 0 },			/* FSYNR1 */
+	{ 0x68, 1 },			/* FSYNR0 */
+	{ 0x6C, 1 },			/* FSYNR1 */
 	{ 0x7F0, 1 },			/* TLBSYNC */
 	{ 0x7F4, 1 },			/* TLBSTATUS */
 	{ 0x2000, 0 }			/* IMPLDEF_MICRO_MMU_CRTL */
@@ -325,7 +327,7 @@
 	unsigned int no_page_fault_log = 0;
 	unsigned int curr_context_id = 0;
 	unsigned int curr_global_ts = 0;
-	static struct kgsl_context *context;
+	struct kgsl_context *context;
 
 	ret = get_iommu_unit(dev, &mmu, &iommu_unit);
 	if (ret)
@@ -399,23 +401,16 @@
 	context = kgsl_context_get(device, curr_context_id);
 
 	if (context != NULL) {
-		struct adreno_context *drawctxt = context->devctxt;
-
 		kgsl_sharedmem_readl(&device->memstore, &curr_global_ts,
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 			eoptimestamp));
 
-		/*
-		 * Store pagefault's timestamp in adreno context,
-		 * this information will be used in GFT
-		 */
-
-		if (drawctxt != NULL) {
-			drawctxt->pagefault = 1;
-			drawctxt->pagefault_ts = curr_global_ts;
-		}
+		/* save pagefault timestamp for GFT */
+		set_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv);
+		context->pagefault_ts = curr_global_ts;
 
 		kgsl_context_put(context);
+		context = NULL;
 	}
 
 	trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
@@ -477,7 +472,8 @@
  * Return - void
  */
 static void kgsl_iommu_clk_disable_event(struct kgsl_device *device, void *data,
-					unsigned int id, unsigned int ts)
+					unsigned int id, unsigned int ts,
+					u32 type)
 {
 	struct kgsl_mmu *mmu = data;
 	struct kgsl_iommu *iommu = mmu->priv;
@@ -810,6 +806,7 @@
 	struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[unit_id];
 	int i, j;
 	int found_ctx;
+	int ret = 0;
 
 	for (j = 0; j < KGSL_IOMMU_MAX_DEVS_PER_UNIT; j++) {
 		found_ctx = 0;
@@ -823,16 +820,21 @@
 			break;
 		if (!data->iommu_ctxs[i].iommu_ctx_name) {
 			KGSL_CORE_ERR("Context name invalid\n");
-			return -EINVAL;
+			ret = -EINVAL;
+			goto done;
 		}
 
 		iommu_unit->dev[iommu_unit->dev_count].dev =
 			msm_iommu_get_ctx(data->iommu_ctxs[i].iommu_ctx_name);
-		if (iommu_unit->dev[iommu_unit->dev_count].dev == NULL) {
-			KGSL_CORE_ERR("Failed to get iommu dev handle for "
-			"device %s\n", data->iommu_ctxs[i].iommu_ctx_name);
-			return -EINVAL;
+		if (NULL == iommu_unit->dev[iommu_unit->dev_count].dev)
+			ret = -EINVAL;
+		if (IS_ERR(iommu_unit->dev[iommu_unit->dev_count].dev)) {
+			ret = PTR_ERR(
+				iommu_unit->dev[iommu_unit->dev_count].dev);
+			iommu_unit->dev[iommu_unit->dev_count].dev = NULL;
 		}
+		if (ret)
+			goto done;
 		iommu_unit->dev[iommu_unit->dev_count].ctx_id =
 						data->iommu_ctxs[i].ctx_id;
 		iommu_unit->dev[iommu_unit->dev_count].kgsldev = mmu->device;
@@ -844,12 +846,23 @@
 
 		iommu_unit->dev_count++;
 	}
-	if (!j) {
-		KGSL_CORE_ERR("No ctxts initialized, user ctxt absent\n ");
-		return -EINVAL;
+done:
+	if (!iommu_unit->dev_count && !ret)
+		ret = -EINVAL;
+	if (ret) {
+		/*
+		 * If at least the first context is initialized on v1
+		 * then we can continue
+		 */
+		if (!msm_soc_version_supports_iommu_v0() &&
+			iommu_unit->dev_count)
+			ret = 0;
+		else
+			KGSL_CORE_ERR(
+			"Failed to initialize iommu contexts, err: %d\n", ret);
 	}
 
-	return 0;
+	return ret;
 }
 
 /*
@@ -1581,6 +1594,8 @@
 	int status;
 	struct kgsl_iommu *iommu = mmu->priv;
 	int i, j;
+	int sctlr_val = 0;
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(mmu->device);
 
 	if (mmu->flags & KGSL_FLAGS_STARTED)
 		return 0;
@@ -1632,6 +1647,25 @@
 	for (i = 0; i < iommu->unit_count; i++) {
 		struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
 		for (j = 0; j < iommu_unit->dev_count; j++) {
+
+			/*
+			 * For IOMMU V1 do not halt IOMMU on pagefault if
+			 * FT pagefault policy is set accordingly
+			 */
+			if ((!msm_soc_version_supports_iommu_v0()) &&
+				(!(adreno_dev->ft_pf_policy &
+				   KGSL_FT_PAGEFAULT_GPUHALT_ENABLE))) {
+				sctlr_val = KGSL_IOMMU_GET_CTX_REG(iommu,
+						iommu_unit,
+						iommu_unit->dev[j].ctx_id,
+						SCTLR);
+				sctlr_val |= (0x1 <<
+						KGSL_IOMMU_SCTLR_HUPCF_SHIFT);
+				KGSL_IOMMU_SET_CTX_REG(iommu,
+						iommu_unit,
+						iommu_unit->dev[j].ctx_id,
+						SCTLR, sctlr_val);
+			}
 			if (sizeof(phys_addr_t) > sizeof(unsigned long)) {
 				iommu_unit->dev[j].default_ttbr0 =
 						KGSL_IOMMU_GET_CTX_REG_LL(iommu,
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index 5c4b17e..7dca40e 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -61,8 +61,12 @@
 #define KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_HALT BIT(2)
 #define KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_IDLE BIT(3)
 
+/* SCTLR fields */
+#define KGSL_IOMMU_SCTLR_HUPCF_SHIFT		8
+
 enum kgsl_iommu_reg_map {
 	KGSL_IOMMU_GLOBAL_BASE = 0,
+	KGSL_IOMMU_CTX_SCTLR,
 	KGSL_IOMMU_CTX_TTBR0,
 	KGSL_IOMMU_CTX_TTBR1,
 	KGSL_IOMMU_CTX_FSR,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 5e6d24b..5479ae9 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -79,6 +79,7 @@
 static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
 					  int requested_state);
 static void kgsl_pwrctrl_axi(struct kgsl_device *device, int state);
+static void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state);
 
 /* Update the elapsed time at a particular clock level
  * if the device is active(on_time = true).Otherwise
@@ -643,6 +644,9 @@
 		case KGSL_PWRFLAGS_AXI_ON:
 			kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON);
 			break;
+		case KGSL_PWRFLAGS_POWER_ON:
+			kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_ON);
+			break;
 		}
 		set_bit(flag, &device->pwrctrl.ctrl_flags);
 	} else {
@@ -713,6 +717,20 @@
 	return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_AXI_ON);
 }
 
+static int kgsl_pwrctrl_force_rail_on_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	return __force_on_show(dev, attr, buf, KGSL_PWRFLAGS_POWER_ON);
+}
+
+static int kgsl_pwrctrl_force_rail_on_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_POWER_ON);
+}
+
 DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show, kgsl_pwrctrl_gpuclk_store);
 DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show,
 	kgsl_pwrctrl_max_gpuclk_store);
@@ -749,6 +767,9 @@
 DEVICE_ATTR(force_bus_on, 0644,
 	kgsl_pwrctrl_force_bus_on_show,
 	kgsl_pwrctrl_force_bus_on_store);
+DEVICE_ATTR(force_rail_on, 0644,
+	kgsl_pwrctrl_force_rail_on_show,
+	kgsl_pwrctrl_force_rail_on_store);
 
 static const struct device_attribute *pwrctrl_attr_list[] = {
 	&dev_attr_gpuclk,
@@ -765,6 +786,7 @@
 	&dev_attr_reset_count,
 	&dev_attr_force_clk_on,
 	&dev_attr_force_bus_on,
+	&dev_attr_force_rail_on,
 	NULL
 };
 
@@ -917,6 +939,9 @@
 {
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 
+	if (test_bit(KGSL_PWRFLAGS_POWER_ON, &pwr->ctrl_flags))
+		return;
+
 	if (state == KGSL_PWRFLAGS_OFF) {
 		if (test_and_clear_bit(KGSL_PWRFLAGS_POWER_ON,
 			&pwr->power_flags)) {
@@ -1214,6 +1239,11 @@
 	}
 }
 
+bool kgsl_pwrctrl_isenabled(struct kgsl_device *device)
+{
+	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+	return (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags) != 0);
+}
 
 /**
  * kgsl_pre_hwaccess - Enforce preconditions for touching registers
@@ -1230,7 +1260,7 @@
 	/* In order to touch a register you must hold the device mutex...*/
 	BUG_ON(!mutex_is_locked(&device->mutex));
 	/* and have the clock on! */
-	BUG_ON(!test_bit(KGSL_PWRFLAGS_CLK_ON, &device->pwrctrl.power_flags));
+	BUG_ON(!kgsl_pwrctrl_isenabled(device));
 }
 EXPORT_SYMBOL(kgsl_pre_hwaccess);
 
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 3bf65ee..b7d9226 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -110,6 +110,8 @@
 void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device);
 void kgsl_pwrctrl_enable(struct kgsl_device *device);
 void kgsl_pwrctrl_disable(struct kgsl_device *device);
+bool kgsl_pwrctrl_isenabled(struct kgsl_device *device);
+
 static inline unsigned long kgsl_get_clkrate(struct clk *clk)
 {
 	return (clk != NULL) ? clk_get_rate(clk) : 0;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 35f24d9..333089a 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -109,7 +109,7 @@
 	struct kgsl_device *device;
 
 	if (context)
-		device = context->dev_priv->device;
+		device = context->device;
 	else
 		device = (struct kgsl_device *)data;
 
@@ -544,6 +544,16 @@
 	int remain = device->snapshot_maxsize - sizeof(*header);
 	void *snapshot;
 	struct timespec boot;
+	int ret = 0;
+
+	/*
+	 * Bail if failed to get active count for GPU,
+	 * try again
+	 */
+	if (kgsl_active_count_get(device)) {
+		KGSL_DRV_ERR(device, "Failed to get GPU active count");
+		return -EINVAL;
+	}
 
 	/* increment the hang count (on hang) for good book keeping */
 	if (hang)
@@ -558,19 +568,23 @@
 	 * of the state and never frozen.
 	 */
 
-	if (hang && device->snapshot_frozen == 1)
-		return 0;
+	if (hang && device->snapshot_frozen == 1) {
+		ret = 0;
+		goto done;
+	}
 
 	if (device->snapshot == NULL) {
 		KGSL_DRV_ERR(device,
 			"snapshot: No snapshot memory available\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto done;
 	}
 
 	if (remain < sizeof(*header)) {
 		KGSL_DRV_ERR(device,
 			"snapshot: Not enough memory for the header\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto done;
 	}
 
 	header->magic = SNAPSHOT_MAGIC;
@@ -606,7 +620,10 @@
 			__pa(device->snapshot),	device->snapshot_size);
 	if (hang)
 		sysfs_notify(&device->snapshot_kobj, NULL, "timestamp");
-	return 0;
+
+done:
+	kgsl_active_count_put(device);
+	return ret;
 }
 EXPORT_SYMBOL(kgsl_device_snapshot);
 
@@ -715,7 +732,10 @@
 {
 	if (device && count > 0) {
 		mutex_lock(&device->mutex);
-		kgsl_device_snapshot(device, 0);
+		if (!kgsl_active_count_get(device)) {
+				kgsl_device_snapshot(device, 0);
+				kgsl_active_count_put(device);
+		}
 		mutex_unlock(&device->mutex);
 	}
 
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 1853996c..5379670 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -86,7 +86,7 @@
  */
 
 static inline void kgsl_fence_event_cb(struct kgsl_device *device,
-	void *priv, u32 context_id, u32 timestamp)
+	void *priv, u32 context_id, u32 timestamp, u32 type)
 {
 	struct kgsl_fence_event_priv *ev = priv;
 	kgsl_sync_timeline_signal(ev->context->timeline, ev->timestamp);
@@ -239,7 +239,7 @@
 	char ktimeline_name[sizeof(context->timeline->name)] = {};
 	snprintf(ktimeline_name, sizeof(ktimeline_name),
 		"%s_%.15s(%d)-%.15s(%d)-%d",
-		context->dev_priv->device->name,
+		context->device->name,
 		current->group_leader->comm, current->group_leader->pid,
 		current->comm, current->pid, context->id);
 
@@ -250,7 +250,7 @@
 
 	ktimeline = (struct kgsl_sync_timeline *) context->timeline;
 	ktimeline->last_timestamp = 0;
-	ktimeline->device = context->dev_priv->device;
+	ktimeline->device = context->device;
 	ktimeline->context_id = context->id;
 
 	return 0;
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index abb7c35..831b13f 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -678,6 +678,28 @@
 	)
 );
 
+TRACE_EVENT(kgsl_context_destroy,
+
+	TP_PROTO(struct kgsl_device *device, struct kgsl_context *context),
+
+	TP_ARGS(device, context),
+
+	TP_STRUCT__entry(
+		__string(device_name, device->name)
+		__field(unsigned int, id)
+	),
+
+	TP_fast_assign(
+		__assign_str(device_name, device->name);
+		__entry->id = context->id;
+	),
+
+	TP_printk(
+		"d_name=%s ctx=%u",
+		__get_str(device_name), __entry->id
+	)
+);
+
 TRACE_EVENT(kgsl_mmu_pagefault,
 
 	TP_PROTO(struct kgsl_device *device, unsigned int page,
@@ -749,21 +771,25 @@
 
 TRACE_EVENT(kgsl_fire_event,
 		TP_PROTO(unsigned int id, unsigned int ts,
-			unsigned int age),
-		TP_ARGS(id, ts, age),
+			unsigned int type, unsigned int age),
+		TP_ARGS(id, ts, type, age),
 		TP_STRUCT__entry(
 			__field(unsigned int, id)
 			__field(unsigned int, ts)
+			__field(unsigned int, type)
 			__field(unsigned int, age)
 		),
 		TP_fast_assign(
 			__entry->id = id;
 			__entry->ts = ts;
+			__entry->type = type;
 			__entry->age = age;
 		),
 		TP_printk(
-			"ctx=%u ts=%u age=%u",
-			__entry->id, __entry->ts, __entry->age)
+			"ctx=%u ts=%u type=%s age=%u",
+			__entry->id, __entry->ts,
+			__print_symbolic(__entry->type, KGSL_EVENT_TYPES),
+			__entry->age)
 );
 
 TRACE_EVENT(kgsl_active_count,
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index cc1819d..883417f 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -859,11 +859,30 @@
 	return status;
 }
 
-static void
-z180_drawctxt_destroy(struct kgsl_device *device,
-			  struct kgsl_context *context)
+struct kgsl_context *
+z180_drawctxt_create(struct kgsl_device_private *dev_priv,
+			uint32_t *flags)
 {
-	struct z180_device *z180_dev = Z180_DEVICE(device);
+	int ret;
+	struct kgsl_context *context = kzalloc(sizeof(*context), GFP_KERNEL);
+	if (context == NULL)
+		return ERR_PTR(-ENOMEM);
+	ret = kgsl_context_init(dev_priv, context);
+	if (ret != 0) {
+		kfree(context);
+		return ERR_PTR(ret);
+	}
+	return context;
+}
+
+static void
+z180_drawctxt_detach(struct kgsl_context *context)
+{
+	struct kgsl_device *device;
+	struct z180_device *z180_dev;
+
+	device = context->device;
+	z180_dev = Z180_DEVICE(device);
 
 	z180_idle(device);
 
@@ -875,6 +894,12 @@
 	}
 }
 
+static void
+z180_drawctxt_destroy(struct kgsl_context *context)
+{
+	kfree(context);
+}
+
 static void z180_power_stats(struct kgsl_device *device,
 			    struct kgsl_power_stats *stats)
 {
@@ -941,7 +966,8 @@
 	.gpuid = z180_gpuid,
 	.irq_handler = z180_irq_handler,
 	/* Optional functions */
-	.drawctxt_create = NULL,
+	.drawctxt_create = z180_drawctxt_create,
+	.drawctxt_detach = z180_drawctxt_detach,
 	.drawctxt_destroy = z180_drawctxt_destroy,
 	.ioctl = NULL,
 	.postmortem_dump = z180_dump,
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index a587ed2..f7cf2df 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -65,6 +65,8 @@
 #define EPM_ADC_MILLI_VOLTS_SOURCE	4750
 #define EPM_ADC_SCALE_FACTOR		64
 #define GPIO_EPM_GLOBAL_ENABLE		86
+#define GPIO_EPM_MARKER1		85
+#define GPIO_EPM_MARKER2		96
 #define EPM_ADC_CONVERSION_TIME_MIN	50000
 #define EPM_ADC_CONVERSION_TIME_MAX	51000
 /* PSoc Commands */
@@ -92,6 +94,14 @@
 #define EPM_PSOC_CLEAR_BUFFER_RESPONSE_CMD		0x1e
 #define EPM_PSOC_SET_VADC_REFERENCE_CMD			0x1f
 #define EPM_PSOC_SET_VADC_REFERENCE_RESPONSE_CMD	0x20
+#define EPM_PSOC_PAUSE_CONVERSION			0x35
+#define EPM_PSOC_PAUSE_CONVERSION_RSP_CMD		0x36
+#define EPM_PSOC_UNPAUSE_CONVERSION			0x37
+#define EPM_PSOC_UNPAUSE_CONVERSION_RSP_CMD		0x38
+#define EPM_PSOC_GPIO_BUFFER_REQUEST_CMD		0x4f
+#define EPM_PSOC_GPIO_BUFFER_REQUEST_RESPONSE_CMD	0x50
+#define EPM_PSOC_GET_GPIO_BUFFER_CMD			0x51
+#define EPM_PSOC_GET_GPIO_BUFFER_RESPONSE_CMD		0x52
 
 #define EPM_PSOC_GLOBAL_ENABLE				81
 #define EPM_PSOC_VREF_VOLTAGE				2048
@@ -715,6 +725,130 @@
 	return 0;
 }
 
+static int epm_set_marker1(struct epm_marker_level *marker_init)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_EPM_MARKER1, "EPM_MARKER1");
+	if (!rc) {
+		gpio_direction_output(GPIO_EPM_MARKER1, 1);
+	} else {
+		pr_err("%s: Configure MARKER1 GPIO Failed\n",
+							__func__);
+		return rc;
+	}
+
+	gpio_set_value(GPIO_EPM_MARKER1, marker_init->level);
+
+	return 0;
+}
+
+static int epm_set_marker2(struct epm_marker_level *marker_init)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_EPM_MARKER2, "EPM_MARKER2");
+	if (!rc) {
+		gpio_direction_output(GPIO_EPM_MARKER2, 1);
+	} else {
+		pr_err("%s: Configure MARKER2 GPIO Failed\n",
+							__func__);
+		return rc;
+	}
+
+	gpio_set_value(GPIO_EPM_MARKER2, marker_init->level);
+
+	return 0;
+}
+
+static int epm_marker1_release(void)
+{
+	gpio_free(GPIO_EPM_MARKER1);
+
+	return 0;
+}
+
+static int epm_marker2_release(void)
+{
+	gpio_free(GPIO_EPM_MARKER2);
+
+	return 0;
+}
+
+static int epm_psoc_pause_conversion(struct epm_adc_drv *epm_adc)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[2], rx_buf[2];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = EPM_PSOC_PAUSE_CONVERSION;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc) {
+		pr_err("spi sync err with %d\n", rc);
+		return rc;
+	}
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc) {
+		pr_err("spi sync err with %d\n", rc);
+		return rc;
+	}
+
+	return rx_buf[0];
+}
+
+static int epm_psoc_unpause_conversion(struct epm_adc_drv *epm_adc)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[2], rx_buf[2];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = EPM_PSOC_UNPAUSE_CONVERSION;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc) {
+		pr_err("spi sync err with %d\n", rc);
+		return rc;
+	}
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc) {
+		pr_err("spi sync err with %d\n", rc);
+		return rc;
+	}
+
+	return rx_buf[0];
+}
+
 static int epm_psoc_init(struct epm_adc_drv *epm_adc,
 					struct epm_psoc_init_resp *init_resp)
 {
@@ -1240,6 +1374,84 @@
 	return rc;
 }
 
+static int epm_psoc_get_gpio_buffer_data(struct epm_adc_drv *epm_adc,
+			struct epm_get_gpio_buffer_resp *gpio_resp_pkt)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[7], rx_buf[7];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = EPM_PSOC_GET_GPIO_BUFFER_CMD;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	gpio_resp_pkt->cmd = rx_buf[0];
+	gpio_resp_pkt->status = rx_buf[1];
+	gpio_resp_pkt->bitmask_monitor_pin = rx_buf[2];
+	gpio_resp_pkt->timestamp = rx_buf[3] << 24 | rx_buf[4] << 16 |
+					rx_buf[5] << 8 | tx_buf[6];
+
+	return rc;
+}
+
+static int epm_psoc_gpio_buffer_request_configure(struct epm_adc_drv *epm_adc,
+			struct epm_gpio_buffer_request *gpio_request)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[2], rx_buf[2];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = EPM_PSOC_GPIO_BUFFER_REQUEST_CMD;
+	tx_buf[1] = gpio_request->bitmask_monitor_pin;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	gpio_request->cmd = rx_buf[0];
+	gpio_request->status = rx_buf[1];
+
+	return rc;
+}
+
 static long epm_adc_ioctl(struct file *file, unsigned int cmd,
 						unsigned long arg)
 {
@@ -1296,6 +1508,58 @@
 				return -EFAULT;
 			break;
 		}
+	case EPM_MARKER1_REQUEST:
+		{
+			struct epm_marker_level marker_init;
+			uint32_t result;
+
+			if (copy_from_user(&marker_init, (void __user *)arg,
+					sizeof(struct epm_marker_level)))
+				return -EFAULT;
+
+			result = epm_set_marker1(&marker_init);
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_MARKER2_REQUEST:
+		{
+			struct epm_marker_level marker_init;
+			uint32_t result;
+
+			if (copy_from_user(&marker_init, (void __user *)arg,
+					sizeof(struct epm_marker_level)))
+				return -EFAULT;
+
+			result = epm_set_marker2(&marker_init);
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_MARKER1_RELEASE:
+		{
+			uint32_t result;
+			result = epm_marker1_release();
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_MARKER2_RELEASE:
+		{
+			uint32_t result;
+			result = epm_marker2_release();
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
 	case EPM_PSOC_ADC_INIT:
 		{
 			struct epm_psoc_init_resp psoc_init;
@@ -1312,11 +1576,29 @@
 				return -EINVAL;
 			}
 
+			if (!rc) {
+				rc = epm_adc_psoc_gpio_init(true);
+				if (rc) {
+					pr_err("GPIO init failed\n");
+					return -EINVAL;
+				}
+			}
+
 			if (copy_to_user((void __user *)arg, &psoc_init,
 				sizeof(struct epm_psoc_init_resp)))
 				return -EFAULT;
 			break;
 		}
+	case EPM_PSOC_ADC_DEINIT:
+		{
+			uint32_t result;
+			result = epm_adc_psoc_gpio_init(false);
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
 	case EPM_PSOC_ADC_CHANNEL_ENABLE:
 	case EPM_PSOC_ADC_CHANNEL_DISABLE:
 		{
@@ -1539,6 +1821,70 @@
 				return -EFAULT;
 			break;
 		}
+	case EPM_PSOC_GPIO_BUFFER_REQUEST:
+		{
+			struct epm_gpio_buffer_request gpio_request;
+			int rc;
+
+			if (copy_from_user(&gpio_request,
+					(void __user *)arg,
+					sizeof(struct epm_gpio_buffer_request)))
+				return -EFAULT;
+
+			rc = epm_psoc_gpio_buffer_request_configure(epm_adc,
+							&gpio_request);
+			if (rc) {
+				pr_err("PSOC buffer request failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg, &gpio_request,
+				sizeof(struct epm_gpio_buffer_request)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_GET_GPIO_BUFFER_DATA:
+		{
+			struct epm_get_gpio_buffer_resp gpio_resp_pkt;
+			int rc;
+
+			if (copy_from_user(&gpio_resp_pkt,
+				(void __user *)arg,
+				sizeof(struct epm_get_gpio_buffer_resp)))
+				return -EFAULT;
+
+			rc = epm_psoc_get_gpio_buffer_data(epm_adc,
+							&gpio_resp_pkt);
+			if (rc) {
+				pr_err("PSOC get buffer data failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg, &gpio_resp_pkt,
+				sizeof(struct epm_get_gpio_buffer_resp)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_PAUSE_CONVERSION_REQUEST:
+		{
+			uint32_t result;
+			result = epm_psoc_pause_conversion(epm_adc);
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_UNPAUSE_CONVERSION_REQUEST:
+		{
+			uint32_t result;
+			result = epm_psoc_unpause_conversion(epm_adc);
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 8e350f0..4e77ca2 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -923,8 +923,12 @@
 			pr_err("Invalid channel fast average setup\n");
 			return -EINVAL;
 		}
-		calibration_param = of_get_property(child,
-				"qcom,calibration-type", NULL);
+		rc = of_property_read_string(child, "qcom,calibration-type",
+							&calibration_param);
+		if (rc) {
+			pr_err("Invalid calibration type\n");
+			return -EINVAL;
+		}
 		if (!strncmp(calibration_param, "absolute", 8))
 			calib_type = CALIB_ABSOLUTE;
 		else if (!strncmp(calibration_param, "ratiometric", 11))
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 9570327..f0793b2 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -499,10 +499,13 @@
 	return 0;
 }
 
+#define IADC_CENTER	0xC000
+#define IADC_READING_RESOLUTION_N	542535
+#define IADC_READING_RESOLUTION_D	100000
 static int32_t qpnp_convert_raw_offset_voltage(void)
 {
 	struct qpnp_iadc_drv *iadc = qpnp_iadc;
-	uint32_t num = 0;
+	s64 numerator;
 
 	if ((iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw) == 0) {
 		pr_err("raw offset errors! raw_gain:0x%x and raw_offset:0x%x\n",
@@ -510,19 +513,23 @@
 		return -EINVAL;
 	}
 
-	iadc->adc->calib.offset_uv = 0;
+	numerator = iadc->adc->calib.offset_raw - IADC_CENTER;
+	numerator *= IADC_READING_RESOLUTION_N;
+	iadc->adc->calib.offset_uv = div_s64(numerator,
+						IADC_READING_RESOLUTION_D);
 
-	num = iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw;
+	numerator = iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw;
+	numerator *= IADC_READING_RESOLUTION_N;
 
-	iadc->adc->calib.gain_uv = (num * QPNP_ADC_GAIN_NV)/
-		(iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw);
+	iadc->adc->calib.gain_uv = div_s64(numerator,
+						IADC_READING_RESOLUTION_D);
 
 	pr_debug("gain_uv:%d offset_uv:%d\n",
 			iadc->adc->calib.gain_uv, iadc->adc->calib.offset_uv);
 	return 0;
 }
 
-int32_t qpnp_iadc_calibrate_for_trim(void)
+int32_t qpnp_iadc_calibrate_for_trim(bool batfet_closed)
 {
 	struct qpnp_iadc_drv *iadc = qpnp_iadc;
 	uint8_t rslt_lsb, rslt_msb;
@@ -530,6 +537,9 @@
 	uint16_t raw_data;
 	uint32_t mode_sel = 0;
 
+	if (!iadc || !iadc->iadc_initialized)
+		return -EPROBE_DEFER;
+
 	mutex_lock(&iadc->adc->adc_lock);
 
 	rc = qpnp_iadc_configure(GAIN_CALIBRATION_17P857MV,
@@ -541,11 +551,29 @@
 
 	iadc->adc->calib.gain_raw = raw_data;
 
-	rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
+	/*
+	 * there is a features in the BMS where if the batfet is opened
+	 * the BMS reads from INTERNAL_RSENSE (channel 0) actually go to
+	 * OFFSET_CALIBRATION_CSP_CSN (channel 5). Hence if batfet is opened
+	 * we have to calibrate based on OFFSET_CALIBRATION_CSP_CSN even for
+	 * internal rsense.
+	 */
+	if (!batfet_closed || iadc->external_rsense) {
+		/* external offset calculation */
+		rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP_CSN,
 						&raw_data, mode_sel);
-	if (rc < 0) {
-		pr_err("qpnp adc result read failed with %d\n", rc);
-		goto fail;
+		if (rc < 0) {
+			pr_err("qpnp adc result read failed with %d\n", rc);
+			goto fail;
+		}
+	} else {
+		/* internal offset calculation */
+		rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
+						&raw_data, mode_sel);
+		if (rc < 0) {
+			pr_err("qpnp adc result read failed with %d\n", rc);
+			goto fail;
+		}
 	}
 
 	iadc->adc->calib.offset_raw = raw_data;
@@ -607,7 +635,7 @@
 	struct qpnp_iadc_drv *iadc = qpnp_iadc;
 	int rc = 0;
 
-	rc = qpnp_iadc_calibrate_for_trim();
+	rc = qpnp_iadc_calibrate_for_trim(true);
 	if (rc)
 		pr_debug("periodic IADC calibration failed\n");
 	else
@@ -702,9 +730,8 @@
 		die_temp_offset = -die_temp_offset;
 
 	if (die_temp_offset > QPNP_IADC_DIE_TEMP_CALIB_OFFSET) {
-		iadc->die_temp =
-			result_pmic_therm.physical;
-		rc = qpnp_iadc_calibrate_for_trim();
+		iadc->die_temp = result_pmic_therm.physical;
+		rc = qpnp_iadc_calibrate_for_trim(true);
 		if (rc)
 			pr_err("periodic IADC calibration failed\n");
 	}
@@ -994,7 +1021,7 @@
 	}
 	iadc->iadc_initialized = true;
 
-	rc = qpnp_iadc_calibrate_for_trim();
+	rc = qpnp_iadc_calibrate_for_trim(true);
 	if (rc)
 		dev_err(&spmi->dev, "failed to calibrate for USR trim\n");
 	schedule_delayed_work(&iadc->iadc_work,
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 309944e..53e43d1 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -866,6 +866,11 @@
 	amux_prescaling =
 		vadc->adc->adc_channels[dt_index].chan_path_prescaling;
 
+	if (amux_prescaling >= PATH_SCALING_NONE) {
+		rc = -EINVAL;
+		goto fail_unlock;
+	}
+
 	vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
 		qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
 	vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
@@ -1016,6 +1021,11 @@
 	amux_prescaling =
 		vadc->adc->adc_channels[dt_index].chan_path_prescaling;
 
+	if (amux_prescaling >= PATH_SCALING_NONE) {
+		rc = -EINVAL;
+		goto fail;
+	}
+
 	vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
 		qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
 	vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index b96349e..74a252f 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1385,7 +1385,8 @@
 	qup_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						"qup_phys_addr");
 	if (!qup_mem) {
-		dev_err(&pdev->dev, "no qup mem resource?\n");
+		dev_err(&pdev->dev,
+			"platform_get_resource_byname(qup_phys_addr) failed\n");
 		ret = -ENODEV;
 		goto get_res_failed;
 	}
@@ -1655,11 +1656,22 @@
 	return ret;
 }
 
+static void qup_i2c_mem_release(struct platform_device *pdev, const char *name)
+{
+	struct resource *res =
+		platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+
+	if (res)
+		release_mem_region(res->start, resource_size(res));
+	else
+		dev_dbg(&pdev->dev,
+			"platform_get_resource_byname(%s) failed\n", name);
+}
+
 static int __devexit
 qup_i2c_remove(struct platform_device *pdev)
 {
-	struct qup_i2c_dev	*dev = platform_get_drvdata(pdev);
-	struct resource		*qup_mem, *gsbi_mem;
+	struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
 
 	/* Grab mutex to ensure ongoing transaction is over */
 	mutex_lock(&dev->mlock);
@@ -1693,14 +1705,11 @@
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 
-	if (!(dev->pdata->use_gsbi_shared_mode)) {
-		gsbi_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-							"gsbi_qup_i2c_addr");
-		release_mem_region(gsbi_mem->start, resource_size(gsbi_mem));
-	}
-	qup_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						"qup_phys_addr");
-	release_mem_region(qup_mem->start, resource_size(qup_mem));
+	if (!(dev->pdata->use_gsbi_shared_mode))
+		qup_i2c_mem_release(pdev, "gsbi_qup_i2c_addr");
+
+	qup_i2c_mem_release(pdev, "qup_phys_addr");
+
 	if (dev->dev->of_node)
 		kfree(dev->pdata);
 	kfree(dev);
diff --git a/drivers/input/misc/bmp18x-core.c b/drivers/input/misc/bmp18x-core.c
index bac9059..4b5b710 100644
--- a/drivers/input/misc/bmp18x-core.c
+++ b/drivers/input/misc/bmp18x-core.c
@@ -441,7 +441,7 @@
 		mutex_unlock(&data->lock);
 
 	}
-	return success;
+	return count;
 }
 static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
 				show_enable, set_enable);
@@ -573,7 +573,7 @@
 	int err = 0;
 
 	if (pdata && pdata->init_hw) {
-		err = pdata->init_hw();
+		err = pdata->init_hw(data_bus);
 		if (err) {
 			printk(KERN_ERR "%s: init_hw failed!\n",
 				BMP18X_NAME);
@@ -633,7 +633,7 @@
 	kfree(data);
 exit:
 	if (pdata && pdata->deinit_hw)
-		pdata->deinit_hw();
+		pdata->deinit_hw(data_bus);
 	return err;
 }
 EXPORT_SYMBOL(bmp18x_probe);
@@ -655,9 +655,9 @@
 int bmp18x_disable(struct device *dev)
 {
 	struct bmp18x_platform_data *pdata = dev->platform_data;
-
+	struct bmp18x_data *data = dev_get_drvdata(dev);
 	if (pdata && pdata->deinit_hw)
-		pdata->deinit_hw();
+		pdata->deinit_hw(&data->data_bus);
 
 	return 0;
 }
@@ -666,9 +666,9 @@
 int bmp18x_enable(struct device *dev)
 {
 	struct bmp18x_platform_data *pdata = dev->platform_data;
-
+	struct bmp18x_data *data = dev_get_drvdata(dev);
 	if (pdata && pdata->init_hw)
-		return pdata->init_hw();
+		return pdata->init_hw(&data->data_bus);
 
 	return 0;
 }
diff --git a/drivers/input/misc/bmp18x-i2c.c b/drivers/input/misc/bmp18x-i2c.c
index 6c01ad3..abbe6e5 100644
--- a/drivers/input/misc/bmp18x-i2c.c
+++ b/drivers/input/misc/bmp18x-i2c.c
@@ -22,8 +22,137 @@
 
 #include <linux/module.h>
 #include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
 #include "bmp18x.h"
 
+struct sensor_regulator {
+	struct regulator *vreg;
+	const char *name;
+	u32	min_uV;
+	u32	max_uV;
+};
+
+struct sensor_regulator bmp_vreg[] = {
+	{NULL, "vdd", 2850000, 2850000},
+	{NULL, "vddio", 1800000, 1800000},
+};
+
+
+static int bmp18x_config_regulator(struct i2c_client *client, bool on)
+{
+	int rc = 0, i;
+	int num_vreg = ARRAY_SIZE(bmp_vreg);
+
+	if (on) {
+		for (i = 0; i < num_vreg; i++) {
+			bmp_vreg[i].vreg = regulator_get(&client->dev,
+					bmp_vreg[i].name);
+			if (IS_ERR(bmp_vreg[i].vreg)) {
+				rc = PTR_ERR(bmp_vreg[i].vreg);
+				dev_err(&client->dev, "%s:regulator get failed rc=%d\n",
+						__func__, rc);
+				bmp_vreg[i].vreg = NULL;
+				goto error_vdd;
+			}
+			if (regulator_count_voltages(bmp_vreg[i].vreg) > 0) {
+				rc = regulator_set_voltage(bmp_vreg[i].vreg,
+					bmp_vreg[i].min_uV, bmp_vreg[i].max_uV);
+				if (rc) {
+					dev_err(&client->dev, "%s:set_voltage failed rc=%d\n",
+							__func__, rc);
+					regulator_put(bmp_vreg[i].vreg);
+					bmp_vreg[i].vreg = NULL;
+					goto error_vdd;
+				}
+			}
+			rc = regulator_enable(bmp_vreg[i].vreg);
+			if (rc) {
+				dev_err(&client->dev, "%s: regulator_enable failed rc =%d\n",
+						__func__, rc);
+				if (regulator_count_voltages(bmp_vreg[i].vreg)
+						> 0) {
+					regulator_set_voltage(bmp_vreg[i].vreg,
+							0, bmp_vreg[i].max_uV);
+				}
+				regulator_put(bmp_vreg[i].vreg);
+				bmp_vreg[i].vreg = NULL;
+				goto error_vdd;
+			}
+		}
+		return rc;
+	} else {
+		i = num_vreg;
+	}
+error_vdd:
+	while (--i >= 0) {
+		if (!IS_ERR_OR_NULL(bmp_vreg[i].vreg)) {
+			if (regulator_count_voltages(
+				bmp_vreg[i].vreg) > 0) {
+				regulator_set_voltage(bmp_vreg[i].vreg, 0,
+						bmp_vreg[i].max_uV);
+			}
+			regulator_disable(bmp_vreg[i].vreg);
+			regulator_put(bmp_vreg[i].vreg);
+			bmp_vreg[i].vreg = NULL;
+		}
+	}
+	return rc;
+}
+
+static int bmp18x_init_hw(struct bmp18x_data_bus *data_bus)
+{
+	if (data_bus->client)
+		return bmp18x_config_regulator(data_bus->client, 1);
+	return 0;
+}
+
+static void bmp18x_deinit_hw(struct bmp18x_data_bus *data_bus)
+{
+	if (data_bus->client)
+		bmp18x_config_regulator(data_bus->client, 0);
+}
+
+#ifdef CONFIG_OF
+static int bmp18x_parse_dt(struct device *dev,
+			struct bmp18x_platform_data *pdata)
+{
+	int ret = 0;
+	u32 val;
+
+	ret = of_property_read_u32(dev->of_node, "bosch,chip-id", &val);
+	if (ret) {
+		dev_err(dev, "no chip_id from dt\n");
+		return ret;
+	}
+	pdata->chip_id = (u8)val;
+
+	ret = of_property_read_u32(dev->of_node, "bosch,oversample", &val);
+	if (ret) {
+		dev_err(dev, "no default_oversampling from dt\n");
+		return ret;
+	}
+	pdata->default_oversampling = (u8)val;
+
+	ret = of_property_read_u32(dev->of_node, "bosch,period",
+				&pdata->temp_measurement_period);
+	if (ret) {
+		dev_err(dev, "no temp_measurement_period from dt\n");
+		return ret;
+	}
+
+	pdata->default_sw_oversampling = of_property_read_bool(dev->of_node,
+			"bosch,sw-oversample");
+	return 0;
+}
+#else
+static int bmp18x_parse_dt(struct device *dev,
+			struct bmp18x_platform_data *pdata)
+{
+	return -EINVAL;
+}
+#endif
+
 static int bmp18x_i2c_read_block(void *client, u8 reg, int len, char *buf)
 {
 	return i2c_smbus_read_i2c_block_data(client, reg, len, buf);
@@ -52,7 +181,25 @@
 		.bops = &bmp18x_i2c_bus_ops,
 		.client = client
 	};
+	struct bmp18x_platform_data *pdata;
+	int ret;
 
+	if (client->dev.of_node) {
+		pdata = devm_kzalloc(&client->dev,
+			sizeof(struct bmp18x_platform_data), GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&client->dev, "Failed to allocate memory\n");
+			return -ENOMEM;
+		}
+		ret =  bmp18x_parse_dt(&client->dev, pdata);
+		if (ret) {
+			dev_err(&client->dev, "Failed to parse device tree\n");
+			return ret;
+		}
+		pdata->init_hw = bmp18x_init_hw;
+		pdata->deinit_hw = bmp18x_deinit_hw;
+		client->dev.platform_data = pdata;
+	}
 	return bmp18x_probe(&client->dev, &data_bus);
 }
 
@@ -89,6 +236,11 @@
 };
 MODULE_DEVICE_TABLE(i2c, bmp18x_id);
 
+static const struct of_device_id bmp18x_of_match[] = {
+	{ .compatible = "bosch,bmp180", },
+	{ },
+};
+
 static struct i2c_driver bmp18x_i2c_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
@@ -96,6 +248,7 @@
 #ifdef CONFIG_PM
 		.pm	= &bmp18x_i2c_pm_ops,
 #endif
+		.of_match_table = bmp18x_of_match,
 	},
 	.id_table	= bmp18x_id,
 	.probe		= bmp18x_i2c_probe,
diff --git a/drivers/input/misc/bmp18x.h b/drivers/input/misc/bmp18x.h
index f9d55ec..d1b1ee7 100644
--- a/drivers/input/misc/bmp18x.h
+++ b/drivers/input/misc/bmp18x.h
@@ -34,14 +34,6 @@
  * @init_hw: Callback for hw specific startup
  * @deinit_hw: Callback for hw specific shutdown
  */
-struct bmp18x_platform_data {
-	u8	chip_id;
-	u8	default_oversampling;
-	u8	default_sw_oversampling;
-	u32	temp_measurement_period;
-	int	(*init_hw)(void);
-	void	(*deinit_hw)(void);
-};
 
 struct bmp18x_bus_ops {
 	int	(*read_block)(void *client, u8 reg, int len, char *buf);
@@ -50,10 +42,19 @@
 };
 
 struct bmp18x_data_bus {
-	const struct bmp18x_bus_ops	*bops;
+	const struct bmp18x_bus_ops *bops;
 	void	*client;
 };
 
+struct bmp18x_platform_data {
+	u8	chip_id;
+	u8	default_oversampling;
+	u8	default_sw_oversampling;
+	u32	temp_measurement_period;
+	int	(*init_hw)(struct bmp18x_data_bus *);
+	void	(*deinit_hw)(struct bmp18x_data_bus *);
+};
+
 int bmp18x_probe(struct device *dev, struct bmp18x_data_bus *data_bus);
 int bmp18x_remove(struct device *dev);
 #ifdef CONFIG_PM
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index dd2e5d8..f879d78 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -756,7 +756,10 @@
 
 	kxtj9_pdata->negate_z = of_property_read_bool(np, "kionix,negate-z");
 
-	kxtj9_pdata->res_12bit = of_property_read_bool(np, "kionix,res-12bit");
+	if (of_property_read_bool(np, "kionix,res-12bit"))
+		kxtj9_pdata->res_ctl = RES_12BIT;
+	else
+		kxtj9_pdata->res_ctl = RES_8BIT;
 
 	return 0;
 }
@@ -834,7 +837,7 @@
 
 	i2c_set_clientdata(client, tj9);
 
-	tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range;
+	tj9->ctrl_reg1 = tj9->pdata.res_ctl | tj9->pdata.g_range;
 	tj9->last_poll_interval = tj9->pdata.init_interval;
 
 	if (client->irq) {
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index 335b8e7..4b78903 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -2,6 +2,9 @@
  *  mma8x5x.c - Linux kernel modules for 3-Axis Orientation/Motion
  *  Detection Sensor MMA8451/MMA8452/MMA8453
  *
+ *  Copyright (c) 2013, The Linux Foundation. All Rights Reserved.
+ *  Linux Foundation chooses to take subject only to the GPLv2 license
+ *  terms, and distributes only under these terms.
  *  Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -18,23 +21,16 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
+#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/pm.h>
-#include <linux/mutex.h>
 #include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/hwmon.h>
+#include <linux/i2c.h>
 #include <linux/input-polldev.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
 
-
-#define MMA8X5X_I2C_ADDR	0x1D
+#define ACCEL_INPUT_DEV_NAME		"accelerometer"
 #define MMA8451_ID			0x1A
 #define MMA8452_ID			0x2A
 #define MMA8453_ID			0x3A
@@ -50,10 +46,24 @@
 #define POLL_STOP_TIME		200
 #define INPUT_FUZZ			32
 #define INPUT_FLAT			32
+#define INPUT_DATA_DIVIDER	16
 #define MODE_CHANGE_DELAY_MS	100
 
 #define MMA8X5X_STATUS_ZYXDR	0x08
 #define MMA8X5X_BUF_SIZE	7
+
+struct sensor_regulator {
+	struct regulator *vreg;
+	const char *name;
+	u32	min_uV;
+	u32	max_uV;
+};
+
+static struct sensor_regulator mma_vreg[] = {
+	{NULL, "vdd", 2850000, 2850000},
+	{NULL, "vio", 1800000, 1800000},
+};
+
 /* register enum for mma8x5x registers */
 enum {
 	MMA8X5X_STATUS = 0x00,
@@ -138,6 +148,8 @@
 	int position;
 	u8 chip_id;
 	int mode;
+	int int_pin;
+	u32 int_flags;
 };
 /* Addresses scanned */
 static const unsigned short normal_i2c[] = {0x1c, 0x1d, I2C_CLIENT_END};
@@ -167,6 +179,67 @@
 	{{ 1,  0,  0}, { 0, -1,	0}, {0, 0,  -1} },
 };
 
+static int mma8x5x_config_regulator(struct i2c_client *client, bool on)
+{
+	int rc = 0, i;
+	int num_vreg = sizeof(mma_vreg)/sizeof(struct sensor_regulator);
+
+	if (on) {
+		for (i = 0; i < num_vreg; i++) {
+			mma_vreg[i].vreg = regulator_get(&client->dev,
+					mma_vreg[i].name);
+			if (IS_ERR(mma_vreg[i].vreg)) {
+				rc = PTR_ERR(mma_vreg[i].vreg);
+				dev_err(&client->dev, "%s:regulator get failed rc=%d\n",
+						__func__, rc);
+				mma_vreg[i].vreg = NULL;
+				goto error_vdd;
+			}
+			if (regulator_count_voltages(mma_vreg[i].vreg) > 0) {
+				rc = regulator_set_voltage(mma_vreg[i].vreg,
+					mma_vreg[i].min_uV, mma_vreg[i].max_uV);
+				if (rc) {
+					dev_err(&client->dev, "%s:set_voltage failed rc=%d\n",
+							__func__, rc);
+					regulator_put(mma_vreg[i].vreg);
+					mma_vreg[i].vreg = NULL;
+					goto error_vdd;
+				}
+			}
+			rc = regulator_enable(mma_vreg[i].vreg);
+			if (rc) {
+				dev_err(&client->dev, "%s: regulator_enable failed rc =%d\n",
+						__func__, rc);
+				if (regulator_count_voltages(mma_vreg[i].vreg)
+						> 0) {
+					regulator_set_voltage(mma_vreg[i].vreg,
+							0, mma_vreg[i].max_uV);
+				}
+				regulator_put(mma_vreg[i].vreg);
+				mma_vreg[i].vreg = NULL;
+				goto error_vdd;
+			}
+		}
+		return rc;
+	} else {
+		i = num_vreg;
+	}
+error_vdd:
+	while (--i >= 0) {
+		if (!IS_ERR_OR_NULL(mma_vreg[i].vreg)) {
+			if (regulator_count_voltages(
+				mma_vreg[i].vreg) > 0) {
+				regulator_set_voltage(mma_vreg[i].vreg, 0,
+						mma_vreg[i].max_uV);
+			}
+			regulator_disable(mma_vreg[i].vreg);
+			regulator_put(mma_vreg[i].vreg);
+			mma_vreg[i].vreg = NULL;
+		}
+	}
+	return rc;
+}
+
 static int mma8x5x_data_convert(struct mma8x5x_data *pdata,
 		struct mma8x5x_data_axis *axis_data)
 {
@@ -184,9 +257,9 @@
 			data[i] += rawdata[j] *
 				mma8x5x_position_setting[position][i][j];
 	}
-	axis_data->x = data[0];
-	axis_data->y = data[1];
-	axis_data->z = data[2];
+	axis_data->x = data[0]/INPUT_DATA_DIVIDER;
+	axis_data->y = data[1]/INPUT_DATA_DIVIDER;
+	axis_data->z = data[2]/INPUT_DATA_DIVIDER;
 	return 0;
 }
 static int mma8x5x_check_id(int id)
@@ -317,7 +390,8 @@
 				MMA8X5X_CTRL_REG1, val|0x01);
 		if (!ret) {
 			pdata->active = MMA_ACTIVED;
-			printk(KERN_INFO "mma enable setting active\n");
+			dev_dbg(dev,
+				"%s:mma enable setting active.\n", __func__);
 		}
 	} else if (enable == 0  && pdata->active == MMA_ACTIVED) {
 		val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
@@ -325,7 +399,8 @@
 			MMA8X5X_CTRL_REG1, val & 0xFE);
 		if (!ret) {
 			pdata->active = MMA_STANDBY;
-			printk(KERN_INFO "mma enable setting inactive\n");
+			dev_dbg(dev,
+				"%s:mma enable setting inactive.\n", __func__);
 		}
 	}
 	mutex_unlock(&pdata->data_lock);
@@ -384,11 +459,36 @@
 	chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);
 	if (!mma8x5x_check_id(chip_id))
 		return -ENODEV;
-	printk(KERN_INFO "check %s i2c address 0x%x\n",
-		mma8x5x_id2name(chip_id), client->addr);
+	dev_dbg(&client->dev, "%s,check %s i2c address 0x%x.\n",
+		__func__, mma8x5x_id2name(chip_id), client->addr);
 	strlcpy(info->type, "mma8x5x", I2C_NAME_SIZE);
 	return 0;
 }
+
+static int mma8x5x_parse_dt(struct device *dev, struct mma8x5x_data *data)
+{
+	int rc;
+	struct device_node *np = dev->of_node;
+	u32 temp_val;
+
+	data->int_pin = of_get_named_gpio_flags(np, "fsl,irq-gpio",
+				0, &data->int_flags);
+	if (data->int_pin < 0) {
+		dev_err(dev, "Unable to read irq-gpio\n");
+		return data->int_pin;
+	}
+
+	rc = of_property_read_u32(np, "fsl,sensors-position", &temp_val);
+	if (!rc)
+		data->position = temp_val;
+	else {
+		dev_err(dev, "Unable to read sensors-position\n");
+		return rc;
+	}
+
+	return 0;
+}
+
 static int __devinit mma8x5x_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
@@ -398,6 +498,11 @@
 	struct i2c_adapter *adapter;
 	struct input_polled_dev *poll_dev;
 	adapter = to_i2c_adapter(client->dev.parent);
+	/* power on the device */
+	result = mma8x5x_config_regulator(client, 1);
+	if (result)
+		goto err_power_on;
+
 	result = i2c_check_functionality(adapter,
 					 I2C_FUNC_SMBUS_BYTE |
 					 I2C_FUNC_SMBUS_BYTE_DATA);
@@ -414,20 +519,34 @@
 		result = -EINVAL;
 		goto err_out;
 	}
+	/* set the private data */
 	pdata = kzalloc(sizeof(struct mma8x5x_data), GFP_KERNEL);
 	if (!pdata) {
 		result = -ENOMEM;
 		dev_err(&client->dev, "alloc data memory error!\n");
 		goto err_out;
 	}
+
+	if (client->dev.of_node) {
+		result = mma8x5x_parse_dt(&client->dev, pdata);
+		if (result)
+			return result;
+	} else {
+		pdata->position = CONFIG_SENSORS_MMA_POSITION;
+		pdata->int_pin = -1;
+		pdata->int_flags = 0;
+	}
+
 	/* Initialize the MMA8X5X chip */
 	pdata->client = client;
 	pdata->chip_id = chip_id;
 	pdata->mode = MODE_2G;
-	pdata->position = CONFIG_SENSORS_MMA_POSITION;
+
 	mutex_init(&pdata->data_lock);
 	i2c_set_clientdata(client, pdata);
+	/* Initialize the MMA8X5X chip */
 	mma8x5x_device_init(client);
+	/* create the input poll device */
 	poll_dev = input_allocate_polled_device();
 	if (!poll_dev) {
 		result = -ENOMEM;
@@ -440,7 +559,7 @@
 	poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
 	poll_dev->private = pdata;
 	idev = poll_dev->input;
-	idev->name = "accelerometer";
+	idev->name = ACCEL_INPUT_DEV_NAME;
 	idev->uniq = mma8x5x_id2name(pdata->chip_id);
 	idev->id.bustype = BUS_I2C;
 	idev->evbit[0] = BIT_MASK(EV_ABS);
@@ -459,7 +578,10 @@
 		result = -EINVAL;
 		goto err_create_sysfs;
 	}
-	printk(KERN_INFO "mma8x5x device driver probe successfully\n");
+	dev_info(&client->dev,
+		"%s:mma8x5x device driver probe successfully, position =%d\n",
+		__func__, pdata->position);
+
 	return 0;
 err_create_sysfs:
 	input_unregister_polled_device(pdata->poll_dev);
@@ -468,14 +590,17 @@
 err_alloc_poll_device:
 	kfree(pdata);
 err_out:
+	mma8x5x_config_regulator(client, 0);
+err_power_on:
 	return result;
 }
 static int __devexit mma8x5x_remove(struct i2c_client *client)
 {
 	struct mma8x5x_data *pdata = i2c_get_clientdata(client);
-	struct input_polled_dev *poll_dev = pdata->poll_dev;
+	struct input_polled_dev *poll_dev;
 	mma8x5x_device_stop(client);
 	if (pdata) {
+		poll_dev = pdata->poll_dev;
 		input_unregister_polled_device(poll_dev);
 		input_free_polled_device(poll_dev);
 		kfree(pdata);
@@ -513,14 +638,20 @@
 };
 MODULE_DEVICE_TABLE(i2c, mma8x5x_id);
 
+static const struct of_device_id mma8x5x_of_match[] = {
+	{ .compatible = "fsl,mma8x5x", },
+	{ },
+};
+
 static SIMPLE_DEV_PM_OPS(mma8x5x_pm_ops, mma8x5x_suspend, mma8x5x_resume);
 static struct i2c_driver mma8x5x_driver = {
 	.class  = I2C_CLASS_HWMON,
 	.driver = {
-		   .name = "mma8x5x",
-		   .owner = THIS_MODULE,
-		   .pm = &mma8x5x_pm_ops,
-		   },
+		.name = "mma8x5x",
+		.owner = THIS_MODULE,
+		.pm = &mma8x5x_pm_ops,
+		.of_match_table = mma8x5x_of_match,
+	},
 	.probe = mma8x5x_probe,
 	.remove = __devexit_p(mma8x5x_remove),
 	.id_table = mma8x5x_id,
@@ -535,7 +666,7 @@
 
 	res = i2c_add_driver(&mma8x5x_driver);
 	if (res < 0) {
-		printk(KERN_INFO "add mma8x5x i2c driver failed\n");
+		pr_info("%s:add mma8x5x i2c driver failed\n", __func__);
 		return -ENODEV;
 	}
 	return res;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 479b788..b725200 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -393,6 +393,9 @@
 	bool update_cfg;
 	const char *fw_name;
 	bool no_force_update;
+	bool lpm_support;
+	bool regs_enabled;
+
 #if defined(CONFIG_SECURE_TOUCH)
 	atomic_t st_enabled;
 	atomic_t st_pending_irqs;
@@ -1993,7 +1996,7 @@
 		if (atomic_read(&data->st_enabled) == 0)
 			break;
 
-		pm_runtime_put(&data->client->adapter->dev);
+		pm_runtime_put(data->client->adapter->dev.parent);
 		atomic_set(&data->st_enabled, 0);
 		complete(&data->st_completion);
 		mxt_interrupt(data->client->irq, data);
@@ -2012,8 +2015,9 @@
 		}
 		INIT_COMPLETION(data->st_completion);
 		INIT_COMPLETION(data->st_powerdown);
-		atomic_set(&data->st_pending_irqs, 0);
 		atomic_set(&data->st_enabled, 1);
+		synchronize_irq(data->client->irq);
+		atomic_set(&data->st_pending_irqs, 0);
 		break;
 	default:
 		dev_err(&data->client->dev, "unsupported value: %lu\n", value);
@@ -2158,6 +2162,11 @@
 	if (on == false)
 		goto power_off;
 
+	if (data->regs_enabled) {
+		dev_dbg(&data->client->dev, "regs are already enabled\n");
+		return 0;
+	}
+
 	rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
 	if (rc < 0) {
 		dev_err(&data->client->dev,
@@ -2206,6 +2215,8 @@
 		}
 	}
 
+	data->regs_enabled = true;
+
 	msleep(130);
 
 	return 0;
@@ -2226,6 +2237,12 @@
 	return rc;
 
 power_off:
+
+	if (!data->regs_enabled) {
+		dev_dbg(&data->client->dev, "regs are already disabled\n");
+		return 0;
+	}
+
 	reg_set_optimum_mode_check(data->vcc_ana, 0);
 	regulator_disable(data->vcc_ana);
 	if (data->pdata->digital_pwr_regulator) {
@@ -2236,6 +2253,9 @@
 		reg_set_optimum_mode_check(data->vcc_i2c, 0);
 		regulator_disable(data->vcc_i2c);
 	}
+
+	data->regs_enabled = false;
+
 	msleep(50);
 	return 0;
 }
@@ -2435,8 +2455,9 @@
 	struct input_dev *input_dev = data->input_dev;
 	int error;
 
-	mutex_lock(&input_dev->mutex);
+	disable_irq(data->irq);
 
+	mutex_lock(&input_dev->mutex);
 	if (input_dev->users) {
 		error = mxt_stop(data);
 		if (error < 0) {
@@ -2444,16 +2465,24 @@
 			mutex_unlock(&input_dev->mutex);
 			return error;
 		}
-
 	}
 
 	mutex_unlock(&input_dev->mutex);
+	mxt_release_all(data);
 
 	/* put regulators in low power mode */
-	error = mxt_regulator_lpm(data, true);
-	if (error < 0) {
-		dev_err(dev, "failed to enter low power mode\n");
-		return error;
+	if (data->lpm_support) {
+		error = mxt_regulator_lpm(data, true);
+		if (error < 0) {
+			dev_err(dev, "failed to enter low power mode\n");
+			return error;
+		}
+	} else {
+		error = mxt_power_on(data, false);
+		if (error < 0) {
+			dev_err(dev, "failed to disable regulators\n");
+			return error;
+		}
 	}
 
 	return 0;
@@ -2466,13 +2495,25 @@
 	struct input_dev *input_dev = data->input_dev;
 	int error;
 
-	/* put regulators in high power mode */
-	error = mxt_regulator_lpm(data, false);
-	if (error < 0) {
-		dev_err(dev, "failed to enter high power mode\n");
-		return error;
+	/* put regulators back in active power mode */
+	if (data->lpm_support) {
+		error = mxt_regulator_lpm(data, false);
+		if (error < 0) {
+			dev_err(dev, "failed to enter high power mode\n");
+			return error;
+		}
+	} else {
+		error = mxt_power_on(data, true);
+		if (error < 0) {
+			dev_err(dev, "failed to enable regulators\n");
+			return error;
+		}
+		mxt_power_on_delay(data);
 	}
 
+	mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
+	mxt_reset_delay(data);
+
 	mutex_lock(&input_dev->mutex);
 
 	if (input_dev->users) {
@@ -2495,6 +2536,8 @@
 
 	mutex_unlock(&input_dev->mutex);
 
+	enable_irq(data->irq);
+
 	return 0;
 }
 
@@ -2672,6 +2715,9 @@
 	pdata->no_force_update = of_property_read_bool(np,
 						"atmel,no-force-update");
 
+	pdata->no_lpm_support = of_property_read_bool(np,
+					"atmel,no-lpm-support");
+
 	/* reset, irq gpio info */
 	pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
 				0, &pdata->reset_gpio_flags);
@@ -2877,6 +2923,7 @@
 	data->input_dev = input_dev;
 	data->pdata = pdata;
 	data->no_force_update = pdata->no_force_update;
+	data->lpm_support = !pdata->no_lpm_support;
 
 	__set_bit(EV_ABS, input_dev->evbit);
 	__set_bit(EV_KEY, input_dev->evbit);
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index 1041c9e8..8de6b1e 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -1309,7 +1309,7 @@
 	err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
 	if (err < 0) {
 		dev_err(&client->dev, "version read failed");
-		return err;
+		goto free_reset_gpio;
 	}
 
 	dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index c01ab0e..2a5fea7 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -1722,7 +1722,7 @@
 static struct bin_attribute dev_attr_data = {
 	.attr = {
 		.name = "data",
-		.mode = (S_IRUGO | S_IWUGO),
+		.mode = (S_IRUGO | S_IWUSR | S_IWGRP),
 	},
 	.size = 0,
 	.read = fwu_sysfs_show_image,
@@ -1730,25 +1730,25 @@
 };
 
 static struct device_attribute attrs[] = {
-	__ATTR(fw_name, S_IWUGO | S_IRUGO,
+	__ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP,
 			fwu_sysfs_fw_name_show,
 			fwu_sysfs_fw_name_store),
-	__ATTR(force_update_fw, S_IWUGO,
+	__ATTR(force_update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
 			synaptics_rmi4_show_error,
 			fwu_sysfs_force_reflash_store),
-	__ATTR(update_fw, S_IWUGO,
+	__ATTR(update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
 			synaptics_rmi4_show_error,
 			fwu_sysfs_do_reflash_store),
-	__ATTR(writeconfig, S_IWUGO,
+	__ATTR(writeconfig, S_IRUGO | S_IWUSR | S_IWGRP,
 			synaptics_rmi4_show_error,
 			fwu_sysfs_write_config_store),
-	__ATTR(readconfig, S_IWUGO,
+	__ATTR(readconfig, S_IRUGO | S_IWUSR | S_IWGRP,
 			synaptics_rmi4_show_error,
 			fwu_sysfs_read_config_store),
-	__ATTR(configarea, S_IWUGO,
+	__ATTR(configarea, S_IRUGO | S_IWUSR | S_IWGRP,
 			synaptics_rmi4_show_error,
 			fwu_sysfs_config_area_store),
-	__ATTR(imagesize, S_IWUGO,
+	__ATTR(imagesize, S_IRUGO | S_IWUSR | S_IWGRP,
 			synaptics_rmi4_show_error,
 			fwu_sysfs_image_size_store),
 	__ATTR(blocksize, S_IRUGO,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 9da095a..908d0d7 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -235,11 +235,11 @@
 
 static struct device_attribute attrs[] = {
 #ifdef CONFIG_PM
-	__ATTR(full_pm_cycle, (S_IRUGO | S_IWUGO),
+	__ATTR(full_pm_cycle, (S_IRUGO | S_IWUSR | S_IWGRP),
 			synaptics_rmi4_full_pm_cycle_show,
 			synaptics_rmi4_full_pm_cycle_store),
 #endif
-	__ATTR(reset, S_IWUGO,
+	__ATTR(reset, S_IRUGO | S_IWUSR | S_IWGRP,
 			synaptics_rmi4_show_error,
 			synaptics_rmi4_f01_reset_store),
 	__ATTR(productinfo, S_IRUGO,
@@ -251,13 +251,13 @@
 	__ATTR(flashprog, S_IRUGO,
 			synaptics_rmi4_f01_flashprog_show,
 			synaptics_rmi4_store_error),
-	__ATTR(0dbutton, (S_IRUGO | S_IWUGO),
+	__ATTR(0dbutton, (S_IRUGO | S_IWUSR | S_IWGRP),
 			synaptics_rmi4_0dbutton_show,
 			synaptics_rmi4_0dbutton_store),
-	__ATTR(flipx, (S_IRUGO | S_IWUGO),
+	__ATTR(flipx, (S_IRUGO | S_IWUSR | S_IWGRP),
 			synaptics_rmi4_flipx_show,
 			synaptics_rmi4_flipx_store),
-	__ATTR(flipy, (S_IRUGO | S_IWUGO),
+	__ATTR(flipy, (S_IRUGO | S_IWUSR | S_IWGRP),
 			synaptics_rmi4_flipy_show,
 			synaptics_rmi4_flipy_store),
 };
@@ -1056,6 +1056,8 @@
 
 	rmi4_pdata->i2c_pull_up = of_property_read_bool(np,
 			"synaptics,i2c-pull-up");
+	rmi4_pdata->power_down_enable = of_property_read_bool(np,
+			"synaptics,power-down");
 	rmi4_pdata->x_flip = of_property_read_bool(np, "synaptics,x-flip");
 	rmi4_pdata->y_flip = of_property_read_bool(np, "synaptics,y-flip");
 
@@ -2003,7 +2005,7 @@
 
 error_reg_en_vcc_i2c:
 	if (rmi4_data->board->i2c_pull_up)
-		reg_set_optimum_mode_check(rmi4_data->vdd, 0);
+		reg_set_optimum_mode_check(rmi4_data->vcc_i2c, 0);
 error_reg_opt_i2c:
 	regulator_disable(rmi4_data->vdd);
 error_reg_en_vdd:
@@ -2592,29 +2594,53 @@
 						bool on)
 {
 	int retval;
+	int load_ua;
 
 	if (on == false)
 		goto regulator_hpm;
 
-	retval = reg_set_optimum_mode_check(rmi4_data->vdd, RMI4_LPM_LOAD_UA);
+	load_ua = rmi4_data->board->power_down_enable ? 0 : RMI4_LPM_LOAD_UA;
+	retval = reg_set_optimum_mode_check(rmi4_data->vdd, load_ua);
 	if (retval < 0) {
 		dev_err(&rmi4_data->i2c_client->dev,
-			"Regulator vcc_ana set_opt failed rc=%d\n",
+			"Regulator vdd_ana set_opt failed rc=%d\n",
 			retval);
 		goto fail_regulator_lpm;
 	}
 
-	if (rmi4_data->board->i2c_pull_up) {
-		retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
-			RMI4_I2C_LPM_LOAD_UA);
-		if (retval < 0) {
+	if (rmi4_data->board->power_down_enable) {
+		retval = regulator_disable(rmi4_data->vdd);
+		if (retval) {
 			dev_err(&rmi4_data->i2c_client->dev,
-				"Regulator vcc_i2c set_opt failed rc=%d\n",
+				"Regulator vdd disable failed rc=%d\n",
 				retval);
 			goto fail_regulator_lpm;
 		}
 	}
 
+	if (rmi4_data->board->i2c_pull_up) {
+		load_ua = rmi4_data->board->power_down_enable ?
+			0 : RMI4_I2C_LPM_LOAD_UA;
+		retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
+			load_ua);
+		if (retval < 0) {
+			dev_err(&rmi4_data->i2c_client->dev,
+				"Regulator vcc_i2c set_opt failed " \
+				"rc=%d\n", retval);
+			goto fail_regulator_lpm;
+		}
+
+		if (rmi4_data->board->power_down_enable) {
+			retval = regulator_disable(rmi4_data->vcc_i2c);
+			if (retval) {
+				dev_err(&rmi4_data->i2c_client->dev,
+					"Regulator vcc_i2c disable failed " \
+					"rc=%d\n", retval);
+				goto fail_regulator_lpm;
+			}
+		}
+	}
+
 	return 0;
 
 regulator_hpm:
@@ -2628,6 +2654,16 @@
 		goto fail_regulator_hpm;
 	}
 
+	if (rmi4_data->board->power_down_enable) {
+		retval = regulator_enable(rmi4_data->vdd);
+		if (retval) {
+			dev_err(&rmi4_data->i2c_client->dev,
+				"Regulator vdd enable failed rc=%d\n",
+				retval);
+			goto fail_regulator_hpm;
+		}
+	}
+
 	if (rmi4_data->board->i2c_pull_up) {
 		retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
 			RMI4_I2C_LOAD_UA);
@@ -2637,6 +2673,26 @@
 				retval);
 			goto fail_regulator_hpm;
 		}
+
+		if (rmi4_data->board->power_down_enable) {
+			retval = regulator_enable(rmi4_data->vcc_i2c);
+			if (retval) {
+				dev_err(&rmi4_data->i2c_client->dev,
+					"Regulator vcc_i2c enable failed " \
+					"rc=%d\n", retval);
+				goto fail_regulator_hpm;
+			}
+		}
+	}
+
+	if (rmi4_data->board->power_down_enable) {
+		retval = synaptics_rmi4_reset_device(rmi4_data);
+		if (retval < 0) {
+			dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to issue reset command, rc = %d\n",
+					__func__, retval);
+			return retval;
+		}
 	}
 
 	return 0;
diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c
index c6b8a1c..c60ca23 100644
--- a/drivers/input/touchscreen/synaptics_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_rmi_dev.c
@@ -73,19 +73,19 @@
 };
 
 static struct device_attribute attrs[] = {
-	__ATTR(open, S_IWUGO,
+	__ATTR(open, S_IRUGO | S_IWUSR | S_IWGRP,
 			synaptics_rmi4_show_error,
 			rmidev_sysfs_open_store),
-	__ATTR(release, S_IWUGO,
+	__ATTR(release, S_IRUGO | S_IWUSR | S_IWGRP,
 			synaptics_rmi4_show_error,
 			rmidev_sysfs_release_store),
-	__ATTR(address, S_IWUGO,
+	__ATTR(address, S_IRUGO | S_IWUSR | S_IWGRP,
 			synaptics_rmi4_show_error,
 			rmidev_sysfs_address_store),
-	__ATTR(length, S_IWUGO,
+	__ATTR(length, S_IRUGO | S_IWUSR | S_IWGRP,
 			synaptics_rmi4_show_error,
 			rmidev_sysfs_length_store),
-	__ATTR(data, (S_IRUGO | S_IWUGO),
+	__ATTR(data, (S_IRUGO | S_IWUSR | S_IWGRP),
 			rmidev_sysfs_data_show,
 			rmidev_sysfs_data_store),
 };
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index fbcc243..3c2be38 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -170,11 +170,13 @@
 #define LED_MPP_SINK_CTRL(base)		(base + 0x4C)
 
 #define LED_MPP_CURRENT_DEFAULT		5
+#define LED_MPP_VIN_CTRL_DEFAULT	0
 #define LED_MPP_CURRENT_PER_SETTING	5
 #define LED_MPP_SOURCE_SEL_DEFAULT	LED_MPP_MODE_ENABLE
 
 #define LED_MPP_SINK_MASK		0x07
 #define LED_MPP_MODE_MASK		0x7F
+#define LED_MPP_VIN_MASK		0x03
 #define LED_MPP_EN_MASK			0x80
 #define LED_MPP_SRC_MASK		0x0F
 #define LED_MPP_MODE_CTRL_MASK		0x70
@@ -348,6 +350,8 @@
  *  @current_setting - current setting, 5ma-40ma in 5ma increments
  *  @source_sel - source selection
  *  @mode_ctrl - mode control
+ *  @vin_ctrl - input control
+ *  @min_brightness - minimum brightness supported
  *  @pwm_mode - pwm mode in use
  */
 struct mpp_config_data {
@@ -355,6 +359,8 @@
 	u8	current_setting;
 	u8	source_sel;
 	u8	mode_ctrl;
+	u8	vin_ctrl;
+	u8	min_brightness;
 	u8 pwm_mode;
 };
 
@@ -397,15 +403,22 @@
 /**
  *  kpdbl_config_data - kpdbl configuration data
  *  @pwm_cfg - device pwm configuration
- *  @row_src_sel_val - select source, 0 for vph_pwr and 1 for vbst
- *  @row_scan_en - enable row scan
- *  @row_scan_val - map to enable needed rows
+ *  @mode - running mode: pwm or lut
+ *  @row_id - row id of the led
+ *  @row_src_vbst - 0 for vph_pwr and 1 for vbst
+ *  @row_src_en - enable row source
+ *  @always_on - always on row
+ *  @lut_params - lut parameters to be used by pwm driver
+ *  @duty_cycles - duty cycles for lut
  */
 struct kpdbl_config_data {
 	struct pwm_config_data	*pwm_cfg;
-	u32	row_src_sel_val;
-	u32	row_scan_en;
-	u32	row_scan_val;
+	u32	row_id;
+	bool	row_src_vbst;
+	bool	row_src_en;
+	bool	always_on;
+	struct pwm_duty_cycles  *duty_cycles;
+	struct lut_params	lut_params;
 };
 
 /**
@@ -452,6 +465,8 @@
 	int			turn_off_delay_ms;
 };
 
+static int num_kpbl_leds_on;
+
 static int
 qpnp_led_masked_write(struct qpnp_led_data *led, u16 addr, u8 mask, u8 val)
 {
@@ -576,6 +591,13 @@
 	int duty_us;
 
 	if (led->cdev.brightness) {
+		if (led->cdev.brightness < led->mpp_cfg->min_brightness) {
+			dev_warn(&led->spmi_dev->dev,
+				"brightness is less than supported..." \
+				"set to minimum supported\n");
+			led->cdev.brightness = led->mpp_cfg->min_brightness;
+		}
+
 		if (led->mpp_cfg->pwm_mode != MANUAL_MODE) {
 			if (!led->mpp_cfg->pwm_cfg->blinking) {
 				led->mpp_cfg->pwm_cfg->mode =
@@ -893,35 +915,73 @@
 		if (!led->kpdbl_cfg->pwm_cfg->blinking)
 			led->kpdbl_cfg->pwm_cfg->mode =
 				led->kpdbl_cfg->pwm_cfg->default_mode;
-		rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
-				KPDBL_MODULE_EN_MASK, KPDBL_MODULE_EN);
-		duty_us = (led->kpdbl_cfg->pwm_cfg->pwm_period_us *
-			led->cdev.brightness) / KPDBL_MAX_LEVEL;
-		rc = pwm_config(led->kpdbl_cfg->pwm_cfg->pwm_dev, duty_us,
-				led->kpdbl_cfg->pwm_cfg->pwm_period_us);
-		if (rc < 0) {
-			dev_err(&led->spmi_dev->dev, "pwm config failed\n");
-			return rc;
+		if (!num_kpbl_leds_on) {
+			rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
+					KPDBL_MODULE_EN_MASK, KPDBL_MODULE_EN);
+			if (rc) {
+				dev_err(&led->spmi_dev->dev,
+					"Enable reg write failed(%d)\n", rc);
+				return rc;
+			}
 		}
+
+		if (led->kpdbl_cfg->pwm_cfg->mode == PWM_MODE) {
+			duty_us = (led->kpdbl_cfg->pwm_cfg->pwm_period_us *
+				led->cdev.brightness) / KPDBL_MAX_LEVEL;
+			rc = pwm_config(led->kpdbl_cfg->pwm_cfg->pwm_dev,
+					duty_us,
+					led->kpdbl_cfg->pwm_cfg->pwm_period_us);
+			if (rc < 0) {
+				dev_err(&led->spmi_dev->dev, "pwm config failed\n");
+				return rc;
+			}
+		}
+
 		rc = pwm_enable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
 		if (rc < 0) {
 			dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
 			return rc;
 		}
+
+		num_kpbl_leds_on++;
+
 	} else {
 		led->kpdbl_cfg->pwm_cfg->mode =
 			led->kpdbl_cfg->pwm_cfg->default_mode;
-		pwm_disable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
-		rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
-				KPDBL_MODULE_EN_MASK, KPDBL_MODULE_DIS);
-		if (rc) {
-			dev_err(&led->spmi_dev->dev,
-				"Failed to write led enable reg\n");
-			return rc;
+
+		if (led->kpdbl_cfg->always_on) {
+			rc = pwm_config(led->kpdbl_cfg->pwm_cfg->pwm_dev, 0,
+					led->kpdbl_cfg->pwm_cfg->pwm_period_us);
+			if (rc < 0) {
+				dev_err(&led->spmi_dev->dev,
+						"pwm config failed\n");
+				return rc;
+			}
+
+			rc = pwm_enable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
+			if (rc < 0) {
+				dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
+				return rc;
+			}
+		} else
+			pwm_disable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
+
+		if (num_kpbl_leds_on > 0)
+			num_kpbl_leds_on--;
+
+		if (!num_kpbl_leds_on) {
+			rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
+					KPDBL_MODULE_EN_MASK, KPDBL_MODULE_DIS);
+			if (rc) {
+				dev_err(&led->spmi_dev->dev,
+					"Failed to write led enable reg\n");
+				return rc;
+			}
 		}
 	}
 
 	led->kpdbl_cfg->pwm_cfg->blinking = false;
+
 	qpnp_dump_regs(led, kpdbl_debug_regs, ARRAY_SIZE(kpdbl_debug_regs));
 
 	return 0;
@@ -987,11 +1047,14 @@
 	struct qpnp_led_data *led;
 
 	led = container_of(led_cdev, struct qpnp_led_data, cdev);
-	if (value < LED_OFF || value > led->cdev.max_brightness) {
+	if (value < LED_OFF) {
 		dev_err(&led->spmi_dev->dev, "Invalid brightness value\n");
 		return;
 	}
 
+	if (value > led->cdev.max_brightness)
+		value = led->cdev.max_brightness;
+
 	led->cdev.brightness = value;
 	schedule_work(&led->work);
 }
@@ -2000,16 +2063,31 @@
 	int rc;
 	u8 val;
 
-	/* enable row source selct */
-	rc = qpnp_led_masked_write(led, KPDBL_ROW_SRC_SEL(led->base),
-		KPDBL_ROW_SRC_SEL_VAL_MASK, led->kpdbl_cfg->row_src_sel_val);
+	/* select row source - vbst or vph */
+	rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
+				KPDBL_ROW_SRC_SEL(led->base), &val, 1);
 	if (rc) {
 		dev_err(&led->spmi_dev->dev,
-			"Enable row src sel write failed(%d)\n", rc);
+			"Unable to read from addr=%x, rc(%d)\n",
+			KPDBL_ROW_SRC_SEL(led->base), rc);
 		return rc;
 	}
 
-	/* row source */
+	if (led->kpdbl_cfg->row_src_vbst)
+		val |= 1 << led->kpdbl_cfg->row_id;
+	else
+		val &= ~(1 << led->kpdbl_cfg->row_id);
+
+	rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
+				KPDBL_ROW_SRC_SEL(led->base), &val, 1);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Unable to read from addr=%x, rc(%d)\n",
+			KPDBL_ROW_SRC_SEL(led->base), rc);
+		return rc;
+	}
+
+	/* row source enable */
 	rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
 				KPDBL_ROW_SRC(led->base), &val, 1);
 	if (rc) {
@@ -2019,12 +2097,10 @@
 		return rc;
 	}
 
-	val &= ~KPDBL_ROW_SCAN_VAL_MASK;
-	val |= led->kpdbl_cfg->row_scan_val;
-
-	led->kpdbl_cfg->row_scan_en <<= KPDBL_ROW_SCAN_EN_SHIFT;
-	val &= ~KPDBL_ROW_SCAN_EN_MASK;
-	val |= led->kpdbl_cfg->row_scan_en;
+	if (led->kpdbl_cfg->row_src_en)
+		val |= KPDBL_ROW_SCAN_EN_MASK | (1 << led->kpdbl_cfg->row_id);
+	else
+		val &= ~(1 << led->kpdbl_cfg->row_id);
 
 	rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
 		KPDBL_ROW_SRC(led->base), &val, 1);
@@ -2093,6 +2169,14 @@
 	if (val < 0)
 		val = 0;
 
+	rc = qpnp_led_masked_write(led, LED_MPP_VIN_CTRL(led->base),
+		LED_MPP_VIN_MASK, led->mpp_cfg->vin_ctrl);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Failed to write led vin control reg\n");
+		return rc;
+	}
+
 	rc = qpnp_led_masked_write(led, LED_MPP_SINK_CTRL(led->base),
 		LED_MPP_SINK_MASK, val);
 	if (rc) {
@@ -2544,6 +2628,7 @@
 		dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
 		return -ENOMEM;
 	}
+
 	rc = of_property_read_string(node, "qcom,mode", &mode);
 	if (!rc) {
 		led_mode = qpnp_led_get_mode(mode);
@@ -2569,23 +2654,20 @@
 	if (rc < 0)
 		return rc;
 
-	rc = of_property_read_u32(node, "qcom,row-src-sel-val", &val);
+	rc = of_property_read_u32(node, "qcom,row-id", &val);
 	if (!rc)
-		led->kpdbl_cfg->row_src_sel_val = val;
+		led->kpdbl_cfg->row_id = val;
 	else
 		return rc;
 
-	rc = of_property_read_u32(node, "qcom,row-scan-val", &val);
-	if (!rc)
-		led->kpdbl_cfg->row_scan_val = val;
-	else
-		return rc;
+	led->kpdbl_cfg->row_src_vbst =
+			of_property_read_bool(node, "qcom,row-src-vbst");
 
-	rc = of_property_read_u32(node, "qcom,row-scan-en", &val);
-	if (!rc)
-		led->kpdbl_cfg->row_scan_en = val;
-	else
-		return rc;
+	led->kpdbl_cfg->row_src_en =
+			of_property_read_bool(node, "qcom,row-src-en");
+
+	led->kpdbl_cfg->always_on =
+			of_property_read_bool(node, "qcom,always-on");
 
 	return 0;
 }
@@ -2677,6 +2759,20 @@
 	else if (rc != -EINVAL)
 		return rc;
 
+	led->mpp_cfg->vin_ctrl = LED_MPP_VIN_CTRL_DEFAULT;
+	rc = of_property_read_u32(node, "qcom,vin-ctrl", &val);
+	if (!rc)
+		led->mpp_cfg->vin_ctrl = (u8) val;
+	else if (rc != -EINVAL)
+		return rc;
+
+	led->mpp_cfg->min_brightness = 0;
+	rc = of_property_read_u32(node, "qcom,min-brightness", &val);
+	if (!rc)
+		led->mpp_cfg->min_brightness = (u8) val;
+	else if (rc != -EINVAL)
+		return rc;
+
 	rc = of_property_read_string(node, "qcom,mode", &mode);
 	if (!rc) {
 		led_mode = qpnp_led_get_mode(mode);
@@ -2821,6 +2917,7 @@
 				goto fail_id_check;
 			}
 		} else if (strncmp(led_label, "kpdbl", sizeof("kpdbl")) == 0) {
+			num_kpbl_leds_on = 0;
 			rc = qpnp_get_config_kpdbl(led, temp);
 			if (rc < 0) {
 				dev_err(&led->spmi_dev->dev,
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index 74ec99a..4668d02 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -146,6 +146,15 @@
                 snapshot config = 3264 * 2448 at 18 fps.
                 2 lanes max fps is 18, 4 lanes max fps is 24.
 
+config OV5648
+	bool "Sensor OV5648 (BAYER 5M)"
+	depends on MSMB_CAMERA
+	---help---
+		OmniVision 5 MP Bayer Sensor, only use 1 mipi lane,
+		preview set to 1296*972 at 30 fps,
+		snapshot set to 2592*1944 at 12 fps,
+		This sensor driver does not support auto focus.
+
 config MT9M114
 	bool "Sensor MT9M114 (YUV 1.26MP)"
 	depends on MSMB_CAMERA
@@ -191,6 +200,15 @@
 		and QSXGA snapshot at 15 fps.
 		This sensor driver does not support auto focus.
 
+config OV12830
+	bool "OmniVision OV12830 (BAYER 12MP)"
+	depends on MSMB_CAMERA
+	---help---
+		OmniVision 12.8 MP Bayer Sensor with auto focus.uses
+		4 mipi lanes, preview config = 2112 * 1500 at 30 fps,
+		snapshot config = 4224 * 3000 at 15 fps.
+		2 lanes max fps is 18, 4 lanes max fps is 24.
+
 config MSM_V4L2_VIDEO_OVERLAY_DEVICE
 	tristate "Qualcomm MSM V4l2 video overlay device"
 	---help---
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 4c5f258..07a66e6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -22,7 +22,7 @@
 #include "msm.h"
 #include "msm_camera_io_util.h"
 
-#define VFE32_BURST_LEN 1
+#define VFE32_BURST_LEN 2
 #define VFE32_UB_SIZE 1024
 #define VFE32_EQUAL_SLICE_UB 204
 #define VFE32_WM_BASE(idx) (0x4C + 0x18 * idx)
@@ -146,7 +146,7 @@
 	/* BUS_CFG */
 	msm_camera_io_w(0x00000001, vfe_dev->vfe_base + 0x3C);
 	msm_camera_io_w(0x01000025, vfe_dev->vfe_base + 0x1C);
-	msm_camera_io_w_mb(0x1DFFFFFF, vfe_dev->vfe_base + 0x20);
+	msm_camera_io_w_mb(0x1CFFFFFF, vfe_dev->vfe_base + 0x20);
 	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x24);
 	msm_camera_io_w_mb(0x1FFFFFFF, vfe_dev->vfe_base + 0x28);
 }
@@ -161,8 +161,6 @@
 static void msm_vfe32_process_halt_irq(struct vfe_device *vfe_dev,
 	uint32_t irq_status0, uint32_t irq_status1)
 {
-	if (irq_status1 & BIT(24))
-		complete(&vfe_dev->halt_complete);
 }
 
 static void msm_vfe32_process_camif_irq(struct vfe_device *vfe_dev,
@@ -304,7 +302,7 @@
 	*irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x2C);
 	*irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x30);
 	msm_camera_io_w(*irq_status0, vfe_dev->vfe_base + 0x24);
-	msm_camera_io_w(*irq_status1, vfe_dev->vfe_base + 0x28);
+	msm_camera_io_w_mb(*irq_status1, vfe_dev->vfe_base + 0x28);
 	msm_camera_io_w_mb(1, vfe_dev->vfe_base + 0x18);
 
 	if (*irq_status1 & BIT(0))
@@ -750,14 +748,20 @@
 static long msm_vfe32_axi_halt(struct vfe_device *vfe_dev)
 {
 	uint32_t halt_mask;
+	uint32_t axi_busy_flag = true;
+
+	msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1D8);
+	while (axi_busy_flag) {
+		if (msm_camera_io_r(
+			vfe_dev->vfe_base + 0x1DC) & 0x1)
+			axi_busy_flag = false;
+	}
+	msm_camera_io_w_mb(0, vfe_dev->vfe_base + 0x1D8);
 	halt_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x20);
-	halt_mask |= BIT(24);
+	halt_mask &= 0xFEFFFFFF;
+	/* Disable AXI IRQ */
 	msm_camera_io_w_mb(halt_mask, vfe_dev->vfe_base + 0x20);
-	init_completion(&vfe_dev->halt_complete);
-	/*TD: Need to fix crashes with this*/
-	/*msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1D8);*/
-	return wait_for_completion_interruptible_timeout(
-		&vfe_dev->halt_complete, msecs_to_jiffies(500));
+	return 0;
 }
 
 static uint32_t msm_vfe32_get_wm_mask(
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 908d3c6..3806213 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
@@ -527,9 +527,11 @@
 		int i;
 		uint32_t *data_ptr = cfg_data +
 			reg_cfg_cmd->u.rw_info.cmd_data_offset/4;
-		for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++)
+		for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++) {
 			*data_ptr++ = msm_camera_io_r(vfe_dev->vfe_base +
-				reg_cfg_cmd->u.rw_info.reg_offset++);
+				reg_cfg_cmd->u.rw_info.reg_offset);
+			reg_cfg_cmd->u.rw_info.reg_offset += 4;
+		}
 		break;
 	}
 	}
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_core.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_core.c
index a2fc813..769e2a8 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_core.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_core.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
@@ -45,6 +45,7 @@
 	JPEG_DBG("%s: reset_done_ack rc %d", __func__, rc);
 	spin_lock_irqsave(&pgmn_dev->reset_lock, flags);
 	pgmn_dev->reset_done_ack = 0;
+	pgmn_dev->state = MSM_JPEG_RESET;
 	spin_unlock_irqrestore(&pgmn_dev->reset_lock, flags);
 
 	return 0;
@@ -196,7 +197,15 @@
 		jpeg_irq_status);
 
 	/*For reset and framedone IRQs, clear all bits*/
-	if (jpeg_irq_status & 0x10000000) {
+	if (pgmn_dev->state == MSM_JPEG_IDLE) {
+		JPEG_DBG_HIGH("%s %d ] Error IRQ received state %d",
+		__func__, __LINE__, pgmn_dev->state);
+		JPEG_DBG_HIGH("%s %d ] Ignoring the Error", __func__,
+		__LINE__);
+		msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
+			JPEG_IRQ_CLEAR_ALL, pgmn_dev->base);
+		return IRQ_HANDLED;
+	} else if (jpeg_irq_status & 0x10000000) {
 		msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
 			JPEG_IRQ_CLEAR_ALL, pgmn_dev->base);
 	} else if (jpeg_irq_status & 0x1) {
@@ -239,13 +248,25 @@
 
 	/* Unexpected/unintended HW interrupt */
 	if (msm_jpeg_hw_irq_is_err(jpeg_irq_status)) {
-		if (pgmn_dev->decode_flag)
-			msm_jpeg_decode_status(pgmn_dev->base);
-		msm_jpeg_core_return_buffers(pgmn_dev, jpeg_irq_status);
-		data = msm_jpeg_core_err_irq(jpeg_irq_status, pgmn_dev);
-		if (msm_jpeg_irq_handler)
-			msm_jpeg_irq_handler(MSM_JPEG_HW_MASK_COMP_ERR,
-				context, data);
+		if (pgmn_dev->state != MSM_JPEG_EXECUTING) {
+			/*Clear all the bits and ignore the IRQ*/
+			JPEG_DBG_HIGH("%s %d ] Error IRQ received state %d",
+			__func__, __LINE__, pgmn_dev->state);
+			JPEG_DBG_HIGH("%s %d ] Ignoring the Error", __func__,
+			__LINE__);
+			msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
+			JPEG_IRQ_CLEAR_ALL, pgmn_dev->base);
+			return IRQ_HANDLED;
+		} else {
+			if (pgmn_dev->decode_flag)
+				msm_jpeg_decode_status(pgmn_dev->base);
+			msm_jpeg_core_return_buffers(pgmn_dev, jpeg_irq_status);
+			data = msm_jpeg_core_err_irq(jpeg_irq_status, pgmn_dev);
+			if (msm_jpeg_irq_handler) {
+				msm_jpeg_irq_handler(MSM_JPEG_HW_MASK_COMP_ERR,
+					context, data);
+			}
+		}
 	}
 
 	return IRQ_HANDLED;
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 509567c..d6fa2b0 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
@@ -172,6 +172,8 @@
 	struct msm_jpeg_device *pgmn_dev =
 		(struct msm_jpeg_device *) context;
 
+	pgmn_dev->state = MSM_JPEG_IDLE;
+
 	jpeg_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!jpeg_mem) {
 		JPEG_PR_ERR("%s: no mem resource?\n", __func__);
@@ -271,6 +273,7 @@
 	pgmn_dev->jpeg_client = msm_ion_client_create(-1, "camera/jpeg");
 	JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
 
+	pgmn_dev->state = MSM_JPEG_INIT;
 	return rc;
 
 fail_request_irq:
@@ -345,6 +348,7 @@
 	iounmap(base);
 	release_mem_region(mem->start, resource_size(mem));
 	ion_client_destroy(pgmn_dev->jpeg_client);
+	pgmn_dev->state = MSM_JPEG_IDLE;
 	JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
 	return result;
 }
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
index 15b4b25..aa6f034 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
@@ -757,6 +757,7 @@
 	wmb();
 	rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, arg);
 	wmb();
+	pgmn_dev->state = MSM_JPEG_EXECUTING;
 	JPEG_DBG("%s:%d]", __func__, __LINE__);
 	return rc;
 }
@@ -768,15 +769,21 @@
 	struct msm_jpeg_ctrl_cmd ctrl_cmd;
 
 	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
-	if (copy_from_user(&ctrl_cmd, arg, sizeof(ctrl_cmd))) {
-		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
-		return -EFAULT;
-	}
 
+	if (pgmn_dev->state == MSM_JPEG_INIT) {
+		if (copy_from_user(&ctrl_cmd, arg, sizeof(ctrl_cmd))) {
+			JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+			return -EFAULT;
+		}
 	pgmn_dev->op_mode = ctrl_cmd.type;
 
 	rc = msm_jpeg_core_reset(pgmn_dev, pgmn_dev->op_mode, pgmn_dev->base,
 		resource_size(pgmn_dev->mem));
+	} else {
+		JPEG_PR_ERR("%s:%d] JPEG not been initialized Wrong state\n",
+			__func__, __LINE__);
+		rc = -1;
+	}
 	return rc;
 }
 
@@ -804,6 +811,7 @@
 
 	case MSM_JPEG_IOCTL_STOP:
 		rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, (void __user *) arg);
+		pgmn_dev->state = MSM_JPEG_STOPPED;
 		break;
 
 	case MSM_JPEG_IOCTL_START:
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h
index be889cd..c3a57e3 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h
@@ -26,6 +26,14 @@
 #define JPEG_8974_V1 0x10000000
 #define JPEG_8974_V2 0x10010000
 
+enum msm_jpeg_state {
+	MSM_JPEG_INIT,
+	MSM_JPEG_RESET,
+	MSM_JPEG_EXECUTING,
+	MSM_JPEG_STOPPED,
+	MSM_JPEG_IDLE
+};
+
 struct msm_jpeg_q {
 	char const	*name;
 	struct list_head  q;
@@ -98,6 +106,7 @@
 	wait_queue_head_t reset_wait;
 	uint32_t res_size;
 	uint32_t jpeg_bus_client;
+	enum msm_jpeg_state state;
 };
 
 int __msm_jpeg_open(struct msm_jpeg_device *pgmn_dev);
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 8d53e35..07f3b40 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -519,6 +519,7 @@
 	struct msm_session *session;
 	unsigned int session_id;
 	unsigned int stream_id;
+	unsigned long spin_flags = 0;
 
 	event_data = (struct msm_v4l2_event_data *)
 		((struct v4l2_event *)arg)->u.data;
@@ -564,9 +565,13 @@
 			break;
 		}
 
+		spin_lock_irqsave(&(session->command_ack_q.lock),
+		   spin_flags);
 		ret_cmd->event = *(struct v4l2_event *)arg;
 		msm_enqueue(&cmd_ack->command_q, &ret_cmd->list);
 		wake_up(&cmd_ack->wait);
+		spin_unlock_irqrestore(&(session->command_ack_q.lock),
+		   spin_flags);
 	}
 		break;
 
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 d238649..a4eb274 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
@@ -34,8 +34,8 @@
 #include <media/v4l2-event.h>
 #include <media/v4l2-ioctl.h>
 #include <media/msmb_camera.h>
-#include <media/msmb_pproc.h>
 #include <media/msmb_generic_buf_mgr.h>
+#include <media/msmb_pproc.h>
 #include "msm_cpp.h"
 #include "msm_isp_util.h"
 #include "msm_camera_io_util.h"
@@ -182,7 +182,7 @@
 
 static unsigned long msm_cpp_get_phy_addr(struct cpp_device *cpp_dev,
 	struct msm_cpp_buff_queue_info_t *buff_queue_info, uint32_t buff_index,
-	uint8_t native_buff)
+	uint8_t native_buff, int *fd)
 {
 	unsigned long phy_add = 0;
 	struct list_head *buff_head;
@@ -196,6 +196,7 @@
 	list_for_each_entry_safe(buff, save, buff_head, entry) {
 		if (buff->map_info.buff_info.index == buff_index) {
 			phy_add = buff->map_info.phy_addr;
+			*fd = buff->map_info.buff_info.fd;
 			break;
 		}
 	}
@@ -279,7 +280,7 @@
 
 static unsigned long msm_cpp_fetch_buffer_info(struct cpp_device *cpp_dev,
 	struct msm_cpp_buffer_info_t *buffer_info, uint32_t session_id,
-	uint32_t stream_id)
+	uint32_t stream_id, int *fd)
 {
 	unsigned long phy_addr = 0;
 	struct msm_cpp_buff_queue_info_t *buff_queue_info;
@@ -294,10 +295,11 @@
 	}
 
 	phy_addr = msm_cpp_get_phy_addr(cpp_dev, buff_queue_info,
-		buffer_info->index, native_buff);
+		buffer_info->index, native_buff, fd);
 	if ((phy_addr == 0) && (native_buff)) {
 		phy_addr = msm_cpp_queue_buffer_info(cpp_dev, buff_queue_info,
 			buffer_info);
+		*fd = buffer_info->fd;
 	}
 	return phy_addr;
 }
@@ -1034,7 +1036,7 @@
 }
 #endif
 
-void msm_cpp_do_timeout_work(struct work_struct *work)
+static void msm_cpp_do_timeout_work(struct work_struct *work)
 {
 	int ret;
 	uint32_t i = 0;
@@ -1044,6 +1046,11 @@
 
 	pr_err("cpp_timer_callback called idx:%d. (jiffies=%lu)\n",
 		del_timer_idx, jiffies);
+	if (!work || !this_frame) {
+		pr_err("Invalid work:%p, this_frame:%p, del_idx:%d\n",
+			work, this_frame, del_timer_idx);
+		return;
+	}
 	pr_err("fatal: cpp_timer expired for identity=0x%x, frame_id=%03d",
 		this_frame->identity, this_frame->frame_id);
 	cpp_timers[del_timer_idx].used = 0;
@@ -1196,6 +1203,7 @@
 		(struct msm_cpp_frame_info_t *)ioctl_ptr->ioctl_ptr;
 	int32_t status = 0;
 	uint8_t fw_version_1_2_x = 0;
+	int in_fd;
 
 	int i = 0;
 	if (!new_frame) {
@@ -1233,15 +1241,13 @@
 	in_phyaddr = msm_cpp_fetch_buffer_info(cpp_dev,
 		&new_frame->input_buffer_info,
 		((new_frame->identity >> 16) & 0xFFFF),
-		(new_frame->identity & 0xFFFF));
+		(new_frame->identity & 0xFFFF), &in_fd);
 	if (!in_phyaddr) {
 		pr_err("error gettting input physical address\n");
 		rc = -EINVAL;
 		goto ERROR2;
 	}
 
-	memset(&new_frame->output_buffer_info[0], 0,
-		sizeof(struct msm_cpp_buffer_info_t));
 	memset(&buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info));
 	buff_mgr_info.session_id = ((new_frame->identity >> 16) & 0xFFFF);
 	buff_mgr_info.stream_id = (new_frame->identity & 0xFFFF);
@@ -1256,7 +1262,8 @@
 	out_phyaddr0 = msm_cpp_fetch_buffer_info(cpp_dev,
 		&new_frame->output_buffer_info[0],
 		((new_frame->identity >> 16) & 0xFFFF),
-		(new_frame->identity & 0xFFFF));
+		(new_frame->identity & 0xFFFF),
+		&new_frame->output_buffer_info[0].fd);
 	if (!out_phyaddr0) {
 		pr_err("error gettting output physical address\n");
 		rc = -EINVAL;
@@ -1286,7 +1293,8 @@
 		out_phyaddr1 = msm_cpp_fetch_buffer_info(cpp_dev,
 			&new_frame->output_buffer_info[1],
 			((new_frame->duplicate_identity >> 16) & 0xFFFF),
-			(new_frame->duplicate_identity & 0xFFFF));
+			(new_frame->duplicate_identity & 0xFFFF),
+			&new_frame->output_buffer_info[1].fd);
 		if (!out_phyaddr1) {
 			pr_err("error gettting output physical address\n");
 			rc = -EINVAL;
@@ -1301,7 +1309,8 @@
 		(cpp_frame_msg[12] & 0x3FF);
 
 	fw_version_1_2_x = 0;
-	if (cpp_dev->hw_info.cpp_hw_version == 0x10010000)
+	if ((cpp_dev->hw_info.cpp_hw_version == CPP_HW_VERSION_1_1_0) ||
+		(cpp_dev->hw_info.cpp_hw_version == CPP_HW_VERSION_1_1_1))
 		fw_version_1_2_x = 2;
 
 	for (i = 0; i < num_stripes; i++) {
@@ -1462,12 +1471,27 @@
 			return -EINVAL;
 		}
 
+		if (u_stream_buff_info->num_buffs == 0) {
+			pr_err("%s:%d: Invalid number of buffers\n", __func__,
+				__LINE__);
+			kfree(u_stream_buff_info);
+			mutex_unlock(&cpp_dev->mutex);
+			return -EINVAL;
+		}
 		k_stream_buff_info.num_buffs = u_stream_buff_info->num_buffs;
 		k_stream_buff_info.identity = u_stream_buff_info->identity;
+
+		if (k_stream_buff_info.num_buffs > MSM_CAMERA_MAX_STREAM_BUF) {
+			pr_err("%s:%d: unexpected large num buff requested\n",
+				__func__, __LINE__);
+			kfree(u_stream_buff_info);
+			mutex_unlock(&cpp_dev->mutex);
+			return -EINVAL;
+		}
 		k_stream_buff_info.buffer_info =
 			kzalloc(k_stream_buff_info.num_buffs *
 			sizeof(struct msm_cpp_buffer_info_t), GFP_KERNEL);
-		if (!k_stream_buff_info.buffer_info) {
+		if (ZERO_OR_NULL_PTR(k_stream_buff_info.buffer_info)) {
 			pr_err("%s:%d: malloc error\n", __func__, __LINE__);
 			kfree(u_stream_buff_info);
 			mutex_unlock(&cpp_dev->mutex);
@@ -1552,6 +1576,33 @@
 		rc = 0;
 		break;
 	}
+	case VIDIOC_MSM_CPP_QUEUE_BUF: {
+		struct msm_pproc_queue_buf_info queue_buf_info;
+		rc = (copy_from_user(&queue_buf_info,
+				(void __user *)ioctl_ptr->ioctl_ptr,
+				sizeof(struct msm_pproc_queue_buf_info)) ?
+				-EFAULT : 0);
+		if (rc) {
+			ERR_COPY_FROM_USER();
+			break;
+		}
+
+		if (queue_buf_info.is_buf_dirty) {
+			rc = msm_cpp_buffer_ops(cpp_dev,
+				VIDIOC_MSM_BUF_MNGR_PUT_BUF,
+				&queue_buf_info.buff_mgr_info);
+		} else {
+			rc = msm_cpp_buffer_ops(cpp_dev,
+				VIDIOC_MSM_BUF_MNGR_BUF_DONE,
+				&queue_buf_info.buff_mgr_info);
+		}
+		if (rc < 0) {
+			pr_err("error in buf done\n");
+			rc = -EINVAL;
+		}
+
+		break;
+	}
 	}
 	mutex_unlock(&cpp_dev->mutex);
 	CPP_DBG("X\n");
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
index 0a70d37..796bede 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
@@ -21,6 +21,14 @@
 #include <media/v4l2-subdev.h>
 #include "msm_sd.h"
 
+/* hw version info:
+  31:28  Major version
+  27:16  Minor version
+  15:0   Revision bits
+**/
+#define CPP_HW_VERSION_1_1_0  0x10010000
+#define CPP_HW_VERSION_1_1_1  0x10010001
+
 #define MAX_ACTIVE_CPP_INSTANCE 8
 #define MAX_CPP_PROCESSING_FRAME 2
 #define MAX_CPP_V4l2_EVENTS 30
diff --git a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
index d53d766..d302131 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
@@ -25,8 +25,8 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-subdev.h>
 #include <media/media-entity.h>
-#include <media/msmb_pproc.h>
 #include <media/msmb_generic_buf_mgr.h>
+#include <media/msmb_pproc.h>
 #include "msm_vpe.h"
 #include "msm_camera_io_util.h"
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/Makefile b/drivers/media/platform/msm/camera_v2/sensor/Makefile
index 18ac623..bd1b10b 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/Makefile
@@ -9,9 +9,11 @@
 obj-$(CONFIG_IMX135) += imx135.o
 obj-$(CONFIG_OV8825) += ov8825.o
 obj-$(CONFIG_s5k4e1) += s5k4e1.o
+obj-$(CONFIG_OV12830) += ov12830.o
 obj-$(CONFIG_OV2720) += ov2720.o
 obj-$(CONFIG_OV9724) += ov9724.o
 obj-$(CONFIG_HI256) += hi256.o
+obj-$(CONFIG_OV5648) += ov5648.o
 obj-$(CONFIG_MT9M114) += mt9m114.o
 obj-$(CONFIG_SP1628) += sp1628.o
 obj-$(CONFIG_GC0339) += gc0339.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index a27ca99..4fa3085 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -46,30 +46,44 @@
 
 static void msm_cci_set_clk_param(struct cci_device *cci_dev)
 {
-	struct msm_cci_clk_params_t *clk_params = &cci_dev->cci_clk_params;
+	struct msm_cci_clk_params_t *clk_params = NULL;
+	uint8_t count = 0;
 
-	msm_camera_io_w(clk_params->hw_thigh << 16 | clk_params->hw_tlow,
-		cci_dev->base + CCI_I2C_M0_SCL_CTL_ADDR);
-	msm_camera_io_w(clk_params->hw_tsu_sto << 16 | clk_params->hw_tsu_sta,
-		cci_dev->base + CCI_I2C_M0_SDA_CTL_0_ADDR);
-	msm_camera_io_w(clk_params->hw_thd_dat << 16 | clk_params->hw_thd_sta,
-		cci_dev->base + CCI_I2C_M0_SDA_CTL_1_ADDR);
-	msm_camera_io_w(clk_params->hw_tbuf,
-		cci_dev->base + CCI_I2C_M0_SDA_CTL_2_ADDR);
-	msm_camera_io_w(clk_params->hw_scl_stretch_en << 8 |
-		clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
-		cci_dev->base + CCI_I2C_M0_MISC_CTL_ADDR);
-	msm_camera_io_w(clk_params->hw_thigh << 16 | clk_params->hw_tlow,
-		cci_dev->base + CCI_I2C_M1_SCL_CTL_ADDR);
-	msm_camera_io_w(clk_params->hw_tsu_sto << 16 | clk_params->hw_tsu_sta,
-		cci_dev->base + CCI_I2C_M1_SDA_CTL_0_ADDR);
-	msm_camera_io_w(clk_params->hw_thd_dat << 16 | clk_params->hw_thd_sta,
-		cci_dev->base + CCI_I2C_M1_SDA_CTL_1_ADDR);
-	msm_camera_io_w(clk_params->hw_tbuf,
-		cci_dev->base + CCI_I2C_M1_SDA_CTL_2_ADDR);
-	msm_camera_io_w(clk_params->hw_scl_stretch_en << 8 |
-		clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
-		cci_dev->base + CCI_I2C_M1_MISC_CTL_ADDR);
+	for (count = 0; count < MASTER_MAX; count++) {
+		if (MASTER_0 == count) {
+			clk_params = &cci_dev->cci_clk_params[count];
+			msm_camera_io_w(clk_params->hw_thigh << 16 |
+				clk_params->hw_tlow,
+				cci_dev->base + CCI_I2C_M0_SCL_CTL_ADDR);
+			msm_camera_io_w(clk_params->hw_tsu_sto << 16 |
+				clk_params->hw_tsu_sta,
+				cci_dev->base + CCI_I2C_M0_SDA_CTL_0_ADDR);
+			msm_camera_io_w(clk_params->hw_thd_dat << 16 |
+				clk_params->hw_thd_sta,
+				cci_dev->base + CCI_I2C_M0_SDA_CTL_1_ADDR);
+			msm_camera_io_w(clk_params->hw_tbuf,
+				cci_dev->base + CCI_I2C_M0_SDA_CTL_2_ADDR);
+			msm_camera_io_w(clk_params->hw_scl_stretch_en << 8 |
+				clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
+				cci_dev->base + CCI_I2C_M0_MISC_CTL_ADDR);
+		} else if (MASTER_1 == count) {
+			clk_params = &cci_dev->cci_clk_params[count];
+			msm_camera_io_w(clk_params->hw_thigh << 16 |
+				clk_params->hw_tlow,
+				cci_dev->base + CCI_I2C_M1_SCL_CTL_ADDR);
+			msm_camera_io_w(clk_params->hw_tsu_sto << 16 |
+				clk_params->hw_tsu_sta,
+				cci_dev->base + CCI_I2C_M1_SDA_CTL_0_ADDR);
+			msm_camera_io_w(clk_params->hw_thd_dat << 16 |
+				clk_params->hw_thd_sta,
+				cci_dev->base + CCI_I2C_M1_SDA_CTL_1_ADDR);
+			msm_camera_io_w(clk_params->hw_tbuf,
+				cci_dev->base + CCI_I2C_M1_SDA_CTL_2_ADDR);
+			msm_camera_io_w(clk_params->hw_scl_stretch_en << 8 |
+				clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
+				cci_dev->base + CCI_I2C_M1_MISC_CTL_ADDR);
+		}
+	}
 	return;
 }
 
@@ -910,58 +924,96 @@
 {
 	int32_t rc = 0;
 	uint32_t val = 0;
+	uint8_t count = 0;
 	struct device_node *of_node = cci_dev->pdev->dev.of_node;
+	struct device_node *src_node = NULL;
 
-	rc = of_property_read_u32(of_node, "qcom,hw-thigh", &val);
-	CDBG("%s qcom,hw-thigh %d, rc %d\n", __func__, val, rc);
-	if (!rc)
-		cci_dev->cci_clk_params.hw_thigh = val;
+	for (count = 0; count < MASTER_MAX; count++) {
 
-	rc = of_property_read_u32(of_node, "qcom,hw-tlow", &val);
-	CDBG("%s qcom,hw-tlow %d, rc %d\n", __func__, val, rc);
-	if (!rc)
-		cci_dev->cci_clk_params.hw_tlow = val;
+		if (MASTER_0 == count)
+			src_node = of_find_node_by_name(of_node,
+				"qcom,cci-master0");
+		else if (MASTER_1 == count)
+			src_node = of_find_node_by_name(of_node,
+				"qcom,cci-master1");
+		else
+			return;
 
-	rc = of_property_read_u32(of_node, "qcom,hw-tsu-sto", &val);
-	CDBG("%s qcom,hw-tsu-sto %d, rc %d\n", __func__, val, rc);
-	if (!rc)
-		cci_dev->cci_clk_params.hw_tsu_sto = val;
+		rc = of_property_read_u32(src_node, "qcom,hw-thigh", &val);
+		CDBG("%s qcom,hw-thigh %d, rc %d\n", __func__, val, rc);
+		if (!rc)
+			cci_dev->cci_clk_params[count].hw_thigh = val;
+		else
+			cci_dev->cci_clk_params[count].hw_thigh = 78;
 
-	rc = of_property_read_u32(of_node, "qcom,hw-tsu-sta", &val);
-	CDBG("%s qcom,hw-tsu-sta %d, rc %d\n", __func__, val, rc);
-	if (!rc)
-		cci_dev->cci_clk_params.hw_tsu_sta = val;
+		rc = of_property_read_u32(src_node, "qcom,hw-tlow", &val);
+		CDBG("%s qcom,hw-tlow %d, rc %d\n", __func__, val, rc);
+		if (!rc)
+			cci_dev->cci_clk_params[count].hw_tlow = val;
+		else
+			cci_dev->cci_clk_params[count].hw_tlow = 114;
 
-	rc = of_property_read_u32(of_node, "qcom,hw-thd-dat", &val);
-	CDBG("%s qcom,hw-thd-dat %d, rc %d\n", __func__, val, rc);
-	if (!rc)
-		cci_dev->cci_clk_params.hw_thd_dat = val;
+		rc = of_property_read_u32(src_node, "qcom,hw-tsu-sto", &val);
+		CDBG("%s qcom,hw-tsu-sto %d, rc %d\n", __func__, val, rc);
+		if (!rc)
+			cci_dev->cci_clk_params[count].hw_tsu_sto = val;
+		else
+			cci_dev->cci_clk_params[count].hw_tsu_sto = 28;
 
-	rc = of_property_read_u32(of_node, "qcom,hw-thd-sta", &val);
-	CDBG("%s qcom,hwthd-sta %d, rc %d\n", __func__, val, rc);
-	if (!rc)
-		cci_dev->cci_clk_params.hw_thd_sta = val;
+		rc = of_property_read_u32(src_node, "qcom,hw-tsu-sta", &val);
+		CDBG("%s qcom,hw-tsu-sta %d, rc %d\n", __func__, val, rc);
+		if (!rc)
+			cci_dev->cci_clk_params[count].hw_tsu_sta = val;
+		else
+			cci_dev->cci_clk_params[count].hw_tsu_sta = 28;
 
-	rc = of_property_read_u32(of_node, "qcom,hw-tbuf", &val);
-	CDBG("%s qcom,hw-tbuf %d, rc %d\n", __func__, val, rc);
-	if (!rc)
-		cci_dev->cci_clk_params.hw_tbuf = val;
+		rc = of_property_read_u32(src_node, "qcom,hw-thd-dat", &val);
+		CDBG("%s qcom,hw-thd-dat %d, rc %d\n", __func__, val, rc);
+		if (!rc)
+			cci_dev->cci_clk_params[count].hw_thd_dat = val;
+		else
+			cci_dev->cci_clk_params[count].hw_thd_dat = 10;
 
-	rc = of_property_read_u32(of_node, "qcom,hw-scl-stretch-en", &val);
-	CDBG("%s qcom,hw-scl-stretch-en %d, rc %d\n", __func__, val, rc);
-	if (!rc)
-		cci_dev->cci_clk_params.hw_scl_stretch_en = val;
+		rc = of_property_read_u32(src_node, "qcom,hw-thd-sta", &val);
+		CDBG("%s qcom,hwthd-sta %d, rc %d\n", __func__, val, rc);
+		if (!rc)
+			cci_dev->cci_clk_params[count].hw_thd_sta = val;
+		else
+			cci_dev->cci_clk_params[count].hw_thd_sta = 77;
 
-	rc = of_property_read_u32(of_node, "qcom,hw-trdhld", &val);
-	CDBG("%s qcom,hw-trdhld %d, rc %d\n", __func__, val, rc);
-	if (!rc)
-		cci_dev->cci_clk_params.hw_trdhld = val;
+		rc = of_property_read_u32(src_node, "qcom,hw-tbuf", &val);
+		CDBG("%s qcom,hw-tbuf %d, rc %d\n", __func__, val, rc);
+		if (!rc)
+			cci_dev->cci_clk_params[count].hw_tbuf = val;
+		else
+			cci_dev->cci_clk_params[count].hw_tbuf = 118;
 
-	rc = of_property_read_u32(of_node, "qcom,hw-tsp", &val);
-	CDBG("%s qcom,hw-tsp %d, rc %d\n", __func__, val, rc);
-	if (!rc)
-		cci_dev->cci_clk_params.hw_tsp = val;
+		rc = of_property_read_u32(src_node,
+			"qcom,hw-scl-stretch-en", &val);
+		CDBG("%s qcom,hw-scl-stretch-en %d, rc %d\n",
+			__func__, val, rc);
+		if (!rc)
+			cci_dev->cci_clk_params[count].hw_scl_stretch_en = val;
+		else
+			cci_dev->cci_clk_params[count].hw_scl_stretch_en = 0;
 
+		rc = of_property_read_u32(src_node, "qcom,hw-trdhld", &val);
+		CDBG("%s qcom,hw-trdhld %d, rc %d\n", __func__, val, rc);
+		if (!rc)
+			cci_dev->cci_clk_params[count].hw_trdhld = val;
+		else
+			cci_dev->cci_clk_params[count].hw_trdhld = 6;
+
+		rc = of_property_read_u32(src_node, "qcom,hw-tsp", &val);
+		CDBG("%s qcom,hw-tsp %d, rc %d\n", __func__, val, rc);
+		if (!rc)
+			cci_dev->cci_clk_params[count].hw_tsp = val;
+		else
+			cci_dev->cci_clk_params[count].hw_tsp = 1;
+
+		of_node_put(src_node);
+		src_node = NULL;
+	}
 	return;
 }
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
index f9e40f1..16edaae 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
@@ -139,7 +139,7 @@
 	struct msm_camera_cci_i2c_queue_info
 		cci_i2c_queue_info[NUM_MASTERS][NUM_QUEUES];
 	struct msm_camera_cci_master_info cci_master_info[NUM_MASTERS];
-	struct msm_cci_clk_params_t cci_clk_params;
+	struct msm_cci_clk_params_t cci_clk_params[MASTER_MAX];
 	struct gpio *cci_gpio_tbl;
 	uint8_t cci_gpio_tbl_size;
 };
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
index 0fbe238..21b9cdc 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
@@ -400,7 +400,6 @@
 	struct msm_camera_csi_lane_params *csi_lane_params;
 	uint16_t csi_lane_mask;
 	csi_lane_params = (struct msm_camera_csi_lane_params *)arg;
-	csi_lane_mask = csi_lane_params->csi_lane_mask;
 
 	if (!csiphy_dev || !csiphy_dev->ref_count) {
 		pr_err("%s csiphy dev NULL / ref_count ZERO\n", __func__);
@@ -413,19 +412,29 @@
 		return -EINVAL;
 	}
 
-	CDBG("%s csiphy_params, lane assign %x mask = %x\n",
-		__func__,
-		csi_lane_params->csi_lane_assign,
-		csi_lane_params->csi_lane_mask);
-
 	if (csiphy_dev->hw_version < CSIPHY_VERSION_V30) {
 		csiphy_dev->lane_mask[csiphy_dev->pdev->id] = 0;
 		for (i = 0; i < 4; i++)
 			msm_camera_io_w(0x0, csiphy_dev->base +
 				MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
 	} else {
+		if (!csi_lane_params) {
+			pr_err("%s:%d failed: csi_lane_params %p\n", __func__,
+				__LINE__, csi_lane_params);
+			return -EINVAL;
+		}
+		csi_lane_mask = csi_lane_params->csi_lane_mask;
+
+		CDBG("%s csiphy_params, lane assign %x mask = %x\n",
+			__func__,
+			csi_lane_params->csi_lane_assign,
+			csi_lane_params->csi_lane_mask);
+
+		if (!csi_lane_mask)
+			csi_lane_mask = 0x1f;
+
 		csiphy_dev->lane_mask[csiphy_dev->pdev->id] &=
-			~(csi_lane_params->csi_lane_mask);
+			~(csi_lane_mask);
 		i = 0;
 		while (csi_lane_mask & 0x1F) {
 			if (csi_lane_mask & 0x1) {
@@ -475,7 +484,6 @@
 	struct msm_camera_csi_lane_params *csi_lane_params;
 	uint16_t csi_lane_mask;
 	csi_lane_params = (struct msm_camera_csi_lane_params *)arg;
-	csi_lane_mask = csi_lane_params->csi_lane_mask;
 
 	if (!csiphy_dev || !csiphy_dev->ref_count) {
 		pr_err("%s csiphy dev NULL / ref_count ZERO\n", __func__);
@@ -488,19 +496,29 @@
 		return -EINVAL;
 	}
 
-	CDBG("%s csiphy_params, lane assign %x mask = %x\n",
-		__func__,
-		csi_lane_params->csi_lane_assign,
-		csi_lane_params->csi_lane_mask);
-
 	if (csiphy_dev->hw_version < CSIPHY_VERSION_V30) {
 		csiphy_dev->lane_mask[csiphy_dev->pdev->id] = 0;
 		for (i = 0; i < 4; i++)
 			msm_camera_io_w(0x0, csiphy_dev->base +
 				MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
 	} else {
+		if (!csi_lane_params) {
+			pr_err("%s:%d failed: csi_lane_params %p\n", __func__,
+				__LINE__, csi_lane_params);
+			return -EINVAL;
+		}
+		csi_lane_mask = csi_lane_params->csi_lane_mask;
+
+		CDBG("%s csiphy_params, lane assign %x mask = %x\n",
+			__func__,
+			csi_lane_params->csi_lane_assign,
+			csi_lane_params->csi_lane_mask);
+
+		if (!csi_lane_mask)
+			csi_lane_mask = 0x1f;
+
 		csiphy_dev->lane_mask[csiphy_dev->pdev->id] &=
-			~(csi_lane_params->csi_lane_mask);
+			~(csi_lane_mask);
 		i = 0;
 		while (csi_lane_mask & 0x1F) {
 			if (csi_lane_mask & 0x1) {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/gc0339.c b/drivers/media/platform/msm/camera_v2/sensor/gc0339.c
index 8cba04c..cc38b56 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/gc0339.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/gc0339.c
@@ -490,6 +490,11 @@
 			break;
 		}
 
+		if (conf_array.addr_type == MSM_CAMERA_I2C_WORD_ADDR
+			|| conf_array.data_type == MSM_CAMERA_I2C_WORD_DATA
+			|| !conf_array.size)
+			break;
+
 		reg_setting = kzalloc(conf_array.size *
 			(sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL);
 		if (!reg_setting) {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/hi256.c b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
index f1df703..de651df 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/hi256.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
@@ -1000,15 +1000,25 @@
 	{0x30, 0x06},
 	{0x31, 0x40},
 	{0x03, 0x20},
-	{0x88, 0x05},
-	{0x89, 0x7e},
-	{0x8a, 0x40},
+	{0x88, 0x01},
+	{0x89, 0x5f},
+	{0x8a, 0x90},
 	{0x03, 0x20},
 	{0x10, 0x9c},
 	{0x03, 0x22},
 	{0x10, 0xe9},
 };
 
+static struct msm_camera_i2c_reg_conf hi256_sleep_settings[] = {
+	{0x03, 0x00},
+	{0x01, 0xf1},
+	{0x03, 0x02},
+	{0x55, 0x10},
+	{0x01, 0xf1},
+	{0x01, 0xf3},
+	{0x01, 0xf1},
+};
+
 
 static const struct i2c_device_id hi256_i2c_id[] = {
 	{HI256_SENSOR_NAME, (kernel_ulong_t)&hi256_s_ctrl},
@@ -1073,6 +1083,13 @@
 
 }
 
+static int32_t hi256_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	hi256_i2c_write_table(s_ctrl, &hi256_sleep_settings[0],
+		ARRAY_SIZE(hi256_sleep_settings));
+	return msm_sensor_power_down(s_ctrl);
+}
+
 static int32_t hi256_platform_probe(struct platform_device *pdev)
 {
 	int32_t rc;
@@ -1393,7 +1410,7 @@
 static struct msm_sensor_fn_t hi256_sensor_func_tbl = {
 	.sensor_config = hi256_sensor_config,
 	.sensor_power_up = msm_sensor_power_up,
-	.sensor_power_down = msm_sensor_power_down,
+	.sensor_power_down = hi256_sensor_power_down,
 	.sensor_match_id = hi256_sensor_match_id,
 };
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
index 40d1155..3792247 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
@@ -338,17 +338,11 @@
 	enum msm_camera_i2c_data_type data_type)
 {
 	int32_t rc;
-	int i;
 	S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n",
 		__func__, addr, data, data_type);
 
-	for (i = 0; i < I2C_POLL_MAX_ITERATION; i++) {
-		rc = msm_camera_cci_i2c_compare(client,
-			addr, data, data_type);
-		if (rc == 0 || rc < 0)
-			break;
-		usleep_range(10000, 11000);
-	}
+	rc = msm_camera_cci_i2c_compare(client,
+		addr, data, data_type);
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 7f474bb..adbfbe7 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -569,7 +569,92 @@
 		CDBG("%s qcom,gpio-reset %d\n", __func__,
 			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_STANDBY]);
 	}
-	return rc;
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vio", &val);
+	if (!rc) {
+		if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vio invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VIO] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-vio %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VIO]);
+	} else if (rc != -EINVAL) {
+		pr_err("%s:%d read qcom,gpio-vio failed rc %d\n",
+			__func__, __LINE__, rc);
+		goto ERROR;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vana", &val);
+	if (!rc) {
+		if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vana invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VANA] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-vana %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VANA]);
+	} else if (rc != -EINVAL) {
+		pr_err("%s:%d read qcom,gpio-vana failed rc %d\n",
+			__func__, __LINE__, rc);
+		goto ERROR;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vdig", &val);
+	if (!rc) {
+		if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vdig invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VDIG] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-vdig %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VDIG]);
+	} else if (rc != -EINVAL) {
+		pr_err("%s:%d read qcom,gpio-vdig failed rc %d\n",
+			__func__, __LINE__, rc);
+		goto ERROR;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vaf", &val);
+	if (!rc) {
+		if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vaf invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VAF] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-vaf %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VAF]);
+	} else if (rc != -EINVAL) {
+		pr_err("%s:%d read qcom,gpio-vaf failed rc %d\n",
+			__func__, __LINE__, rc);
+		goto ERROR;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-af-pwdm", &val);
+	if (!rc) {
+		if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-af-pwdm invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_AF_PWDM] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-af-pwdm %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_AF_PWDM]);
+	} else if (rc != -EINVAL) {
+		pr_err("%s:%d read qcom,gpio-af-pwdm failed rc %d\n",
+			__func__, __LINE__, rc);
+		goto ERROR;
+	}
+	return 0;
 
 ERROR:
 	kfree(gconf->gpio_num_info);
@@ -1162,6 +1247,15 @@
 	return;
 }
 
+static int msm_sensor_get_af_status(struct msm_sensor_ctrl_t *s_ctrl,
+			void __user *argp)
+{
+	/* TO-DO: Need to set AF status register address and expected value
+	We need to check the AF status in the sensor register and
+	set the status in the *status variable accordingly*/
+	return 0;
+}
+
 static long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
 			unsigned int cmd, void *arg)
 {
@@ -1174,6 +1268,8 @@
 	switch (cmd) {
 	case VIDIOC_MSM_SENSOR_CFG:
 		return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
+	case VIDIOC_MSM_SENSOR_GET_AF_STATUS:
+		return msm_sensor_get_af_status(s_ctrl, argp);
 	case VIDIOC_MSM_SENSOR_RELEASE:
 		msm_sensor_stop_stream(s_ctrl);
 		return 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
index c1cf862..de4fcd0 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
@@ -1424,8 +1424,51 @@
 			break;
 		}
 		break;
-	}
-	default:
+		}
+		case CFG_SET_SATURATION: {
+			int32_t sat_lev;
+			if (copy_from_user(&sat_lev, (void *)cdata->cfg.setting,
+				sizeof(int32_t))) {
+				pr_err("%s:%d failed\n", __func__, __LINE__);
+				rc = -EFAULT;
+				break;
+			}
+		pr_debug("%s: Saturation Value is %d", __func__, sat_lev);
+		break;
+		}
+		case CFG_SET_CONTRAST: {
+			int32_t con_lev;
+			if (copy_from_user(&con_lev, (void *)cdata->cfg.setting,
+				sizeof(int32_t))) {
+				pr_err("%s:%d failed\n", __func__, __LINE__);
+				rc = -EFAULT;
+				break;
+			}
+		pr_debug("%s: Contrast Value is %d", __func__, con_lev);
+		break;
+		}
+		case CFG_SET_SHARPNESS: {
+			int32_t shp_lev;
+			if (copy_from_user(&shp_lev, (void *)cdata->cfg.setting,
+				sizeof(int32_t))) {
+				pr_err("%s:%d failed\n", __func__, __LINE__);
+				rc = -EFAULT;
+				break;
+			}
+		pr_debug("%s: Sharpness Value is %d", __func__, shp_lev);
+		break;
+		}
+		case CFG_SET_AUTOFOCUS: {
+		/* TO-DO: set the Auto Focus */
+		pr_debug("%s: Setting Auto Focus", __func__);
+		break;
+		}
+		case CFG_CANCEL_AUTOFOCUS: {
+		/* TO-DO: Cancel the Auto Focus */
+		pr_debug("%s: Cancelling Auto Focus", __func__);
+		break;
+		}
+		default:
 		rc = -EFAULT;
 		break;
 	}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov12830.c b/drivers/media/platform/msm/camera_v2/sensor/ov12830.c
new file mode 100644
index 0000000..593892e
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov12830.c
@@ -0,0 +1,197 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "msm_sensor.h"
+#define OV12830_SENSOR_NAME "ov12830"
+DEFINE_MSM_MUTEX(ov12830_mut);
+
+static struct msm_sensor_ctrl_t ov12830_s_ctrl;
+
+static struct msm_sensor_power_setting ov12830_power_setting[] = {
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VIO,
+		.config_val = 0,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VANA,
+		.config_val = 0,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_VDIG,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_VDIG,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VAF,
+		.config_val = 0,
+		.delay = 15,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_STANDBY,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 15,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_AF_PWDM,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_STANDBY,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_AF_PWDM,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_CLK,
+		.seq_val = SENSOR_CAM_MCLK,
+		.config_val = 24000000,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_I2C_MUX,
+		.seq_val = 0,
+		.config_val = 0,
+		.delay = 0,
+	},
+};
+
+static struct v4l2_subdev_info ov12830_subdev_info[] = {
+	{
+		.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.fmt    = 1,
+		.order    = 0,
+	},
+};
+
+static const struct i2c_device_id ov12830_i2c_id[] = {
+	{OV12830_SENSOR_NAME,
+	(kernel_ulong_t)&ov12830_s_ctrl},
+	{ }
+};
+
+static int msm_ov12830_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	return msm_sensor_i2c_probe(client, id, &ov12830_s_ctrl);
+}
+
+static struct i2c_driver ov12830_i2c_driver = {
+	.id_table = ov12830_i2c_id,
+	.probe  = msm_ov12830_i2c_probe,
+	.driver = {
+		.name = OV12830_SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client ov12830_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static const struct of_device_id ov12830_dt_match[] = {
+	{.compatible = "qcom,ov12830",
+	.data = &ov12830_s_ctrl},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, ov12830_dt_match);
+
+static struct platform_driver ov12830_platform_driver = {
+	.driver = {
+		.name = "qcom,ov12830",
+		.owner = THIS_MODULE,
+		.of_match_table = ov12830_dt_match,
+	},
+};
+
+static int32_t ov12830_platform_probe
+	(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	const struct of_device_id *match;
+	match = of_match_device(ov12830_dt_match, &pdev->dev);
+	rc = msm_sensor_platform_probe(pdev, match->data);
+	return rc;
+}
+
+static int __init ov12830_init_module(void)
+{
+	int32_t rc = 0;
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	rc = platform_driver_probe(&ov12830_platform_driver,
+		ov12830_platform_probe);
+	if (!rc)
+		return rc;
+	pr_debug("%s:%d rc %d\n", __func__, __LINE__, rc);
+	return i2c_add_driver(&ov12830_i2c_driver);
+}
+
+static void __exit ov12830_exit_module(void)
+{
+	pr_info("%s:%d\n", __func__, __LINE__);
+	if (ov12830_s_ctrl.pdev) {
+		msm_sensor_free_sensor_data(&ov12830_s_ctrl);
+		platform_driver_unregister
+			(&ov12830_platform_driver);
+	} else {
+		i2c_del_driver(&ov12830_i2c_driver);
+	}
+}
+
+static struct msm_sensor_ctrl_t ov12830_s_ctrl = {
+	.sensor_i2c_client = &ov12830_sensor_i2c_client,
+	.power_setting_array.power_setting = ov12830_power_setting,
+	.power_setting_array.size =
+		ARRAY_SIZE(ov12830_power_setting),
+	.msm_sensor_mutex = &ov12830_mut,
+	.sensor_v4l2_subdev_info = ov12830_subdev_info,
+	.sensor_v4l2_subdev_info_size =
+		ARRAY_SIZE(ov12830_subdev_info),
+};
+
+module_init(ov12830_init_module);
+module_exit(ov12830_exit_module);
+MODULE_DESCRIPTION("ov12830");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov5648.c b/drivers/media/platform/msm/camera_v2/sensor/ov5648.c
new file mode 100644
index 0000000..7877fcb
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov5648.c
@@ -0,0 +1,179 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "msm_sensor.h"
+
+#define OV5648_SENSOR_NAME "ov5648"
+DEFINE_MSM_MUTEX(ov5648_mut);
+
+static struct msm_sensor_ctrl_t ov5648_s_ctrl;
+
+static struct msm_sensor_power_setting ov5648_power_setting[] = {
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VIO,
+		.config_val = 0,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_VDIG,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 10,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_VDIG,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 10,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VANA,
+		.config_val = 0,
+		.delay = 10,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_STANDBY,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 30,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_STANDBY,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 30,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 30,
+	},
+	{
+		.seq_type = SENSOR_CLK,
+		.seq_val = SENSOR_CAM_MCLK,
+		.config_val = 24000000,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_I2C_MUX,
+		.seq_val = 0,
+		.config_val = 0,
+		.delay = 0,
+	},
+};
+
+static struct v4l2_subdev_info ov5648_subdev_info[] = {
+	{
+		.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.fmt    = 1,
+		.order    = 0,
+	},
+};
+
+static const struct i2c_device_id ov5648_i2c_id[] = {
+	{OV5648_SENSOR_NAME,
+		(kernel_ulong_t)&ov5648_s_ctrl},
+	{ }
+};
+
+static int32_t msm_ov5648_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	return msm_sensor_i2c_probe(client, id, &ov5648_s_ctrl);
+}
+
+static struct i2c_driver ov5648_i2c_driver = {
+	.id_table = ov5648_i2c_id,
+	.probe  = msm_ov5648_i2c_probe,
+	.driver = {
+		.name = OV5648_SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client ov5648_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static struct msm_sensor_ctrl_t ov5648_s_ctrl = {
+	.sensor_i2c_client = &ov5648_sensor_i2c_client,
+	.power_setting_array.power_setting = ov5648_power_setting,
+	.power_setting_array.size =
+			ARRAY_SIZE(ov5648_power_setting),
+	.msm_sensor_mutex = &ov5648_mut,
+	.sensor_v4l2_subdev_info = ov5648_subdev_info,
+	.sensor_v4l2_subdev_info_size =
+			ARRAY_SIZE(ov5648_subdev_info),
+};
+
+static const struct of_device_id ov5648_dt_match[] = {
+	{
+		.compatible = "qcom,ov5648",
+		.data = &ov5648_s_ctrl
+	},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, ov5648_dt_match);
+
+static struct platform_driver ov5648_platform_driver = {
+	.driver = {
+		.name = "qcom,ov5648",
+		.owner = THIS_MODULE,
+		.of_match_table = ov5648_dt_match,
+	},
+};
+
+static int32_t ov5648_platform_probe(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	const struct of_device_id *match;
+
+	match = of_match_device(ov5648_dt_match, &pdev->dev);
+	rc = msm_sensor_platform_probe(pdev, match->data);
+	return rc;
+}
+
+static int __init ov5648_init_module(void)
+{
+	int32_t rc = 0;
+
+	rc = platform_driver_probe(&ov5648_platform_driver,
+		ov5648_platform_probe);
+	if (!rc)
+		return rc;
+	return i2c_add_driver(&ov5648_i2c_driver);
+}
+
+static void __exit ov5648_exit_module(void)
+{
+	if (ov5648_s_ctrl.pdev) {
+		msm_sensor_free_sensor_data(&ov5648_s_ctrl);
+		platform_driver_unregister(&ov5648_platform_driver);
+	} else
+		i2c_del_driver(&ov5648_i2c_driver);
+	return;
+}
+
+module_init(ov5648_init_module);
+module_exit(ov5648_exit_module);
+MODULE_DESCRIPTION("ov5648");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 75b75ea..8de8997 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -99,6 +99,14 @@
 static int mpq_sdmx_debug;
 module_param(mpq_sdmx_debug, int, S_IRUGO | S_IWUSR);
 
+/*
+ * Indicates whether the demux should search for frame boundaries
+ * and notify on video packets on frame-basis or whether to provide
+ * only video PES packet payloads as-is.
+ */
+static int video_framing = 1;
+module_param(video_framing, int, S_IRUGO | S_IWUSR);
+
 /* Global data-structure for managing demux devices */
 static struct
 {
@@ -112,13 +120,6 @@
 	struct mpq_streambuffer
 		decoder_buffers[MPQ_ADAPTER_MAX_NUM_OF_INTERFACES];
 
-	/*
-	 * Indicates whether the video decoder handles framing
-	 * or we are required to provide framing information
-	 * in the meta-data passed to the decoder.
-	 */
-	int decoder_framing;
-
 	/* Indicates whether secure demux TZ application is available */
 	int secure_demux_app_loaded;
 } mpq_dmx_info;
@@ -466,6 +467,12 @@
 		&mpq_demux->decoder_ts_errors);
 
 	debugfs_create_u32(
+		"decoder_cc_errors",
+		S_IRUGO | S_IWUSR | S_IWGRP,
+		mpq_demux->demux.dmx.debugfs_demux_dir,
+		&mpq_demux->decoder_cc_errors);
+
+	debugfs_create_u32(
 		"sdmx_process_count",
 		S_IRUGO | S_IWUSR | S_IWGRP,
 		mpq_demux->demux.dmx.debugfs_demux_dir,
@@ -616,13 +623,6 @@
 
 	mpq_dmx_info.secure_demux_app_loaded = 0;
 
-	/*
-	 * TODO: the following should be set based on the decoder:
-	 * 0 means the decoder doesn't handle framing, so framing
-	 * is done by demux. 1 means the decoder handles framing.
-	 */
-	mpq_dmx_info.decoder_framing = 0;
-
 	/* Allocate memory for all MPQ devices */
 	mpq_dmx_info.devices =
 		vzalloc(mpq_demux_device_num*sizeof(struct mpq_demux));
@@ -1339,7 +1339,7 @@
 	struct mpq_streambuffer *stream_buffer;
 
 	/* get and store framing information if required */
-	if (!mpq_dmx_info.decoder_framing) {
+	if (video_framing) {
 		mpq_dmx_get_pattern_params(
 			mpq_feed->dvb_demux_feed->video_codec,
 			feed_data->patterns, &feed_data->patterns_num);
@@ -1457,6 +1457,7 @@
 	mpq_demux->decoder_out_interval_sum = 0;
 	mpq_demux->decoder_out_interval_max = 0;
 	mpq_demux->decoder_ts_errors = 0;
+	mpq_demux->decoder_cc_errors = 0;
 
 	return 0;
 
@@ -1635,7 +1636,17 @@
 			__func__, ret);
 		goto failed_unmap_metadata_buf;
 	}
-	metadata_buff_desc->base_addr = (void *)temp;
+
+	/*
+	 * NOTE: the following casting to u32 must be done
+	 * as long as TZ does not support LPAE. Once TZ supports
+	 * LPAE SDMX interface needs to be updated accordingly.
+	 */
+	if (temp > 0xFFFFFFFF)
+		MPQ_DVB_ERR_PRINT(
+			"%s: WARNNING - physical address %pa is larger than 32bits!\n",
+			__func__, &temp);
+	metadata_buff_desc->base_addr = (void *)(u32)temp;
 
 	dvb_ringbuffer_init(&feed->metadata_buf, metadata_buff_base,
 		SDMX_METADATA_BUFFER_SIZE);
@@ -2273,7 +2284,16 @@
 		return ret;
 	}
 
-	buf_desc->base_addr = (void *)phys_addr;
+	/*
+	 * NOTE: the following casting to u32 must be done
+	 * as long as TZ does not support LPAE. Once TZ supports
+	 * LPAE SDMX interface needs to be updated accordingly.
+	 */
+	if (phys_addr > 0xFFFFFFFF)
+		MPQ_DVB_ERR_PRINT(
+			"%s: WARNNING - physical address %pa is larger than 32bits!\n",
+			__func__, &phys_addr);
+	buf_desc->base_addr = (void *)(u32)phys_addr;
 	buf_desc->size = rbuf->size;
 
 	return 0;
@@ -2327,6 +2347,14 @@
 		meta_data.info.framing.pattern_type =
 			feed_data->last_framing_match_type;
 		meta_data.info.framing.stc = feed_data->last_framing_match_stc;
+		meta_data.info.framing.continuity_error_counter =
+			feed_data->continuity_errs;
+		meta_data.info.framing.transport_error_indicator_counter =
+			feed_data->tei_errs;
+		meta_data.info.framing.ts_dropped_bytes =
+			feed_data->ts_dropped_bytes;
+		meta_data.info.framing.ts_packets_num =
+			feed_data->ts_packets_num;
 
 		mpq_streambuffer_get_buffer_handle(stream_buffer,
 			0, /* current write buffer handle */
@@ -2396,7 +2424,6 @@
 
 		mpq_dmx_write_pts_dts(feed_data,
 			&(meta_data.info.pes.pts_dts_info));
-		mpq_dmx_save_pts_dts(feed_data);
 
 		meta_data.packet_type = DMX_PES_PACKET;
 		meta_data.info.pes.stc = feed_data->prev_stc;
@@ -2625,6 +2652,7 @@
 	mpq_dmx_check_continuity(feed_data,
 				ts_header->continuity_counter,
 				discontinuity_indicator);
+	mpq_demux->decoder_cc_errors += feed_data->continuity_errs;
 
 	/* Need to back-up the PTS information of the very first frame */
 	if (feed_data->first_pts_dts_copy) {
@@ -2769,6 +2797,15 @@
 				feed_data->last_framing_match_type;
 			meta_data.info.framing.stc =
 				feed_data->last_framing_match_stc;
+			meta_data.info.framing.continuity_error_counter =
+				feed_data->continuity_errs;
+			meta_data.info.framing.
+				transport_error_indicator_counter =
+				 feed_data->tei_errs;
+			meta_data.info.framing.ts_dropped_bytes =
+				feed_data->ts_dropped_bytes;
+			meta_data.info.framing.ts_packets_num =
+				feed_data->ts_packets_num;
 
 			mpq_streambuffer_get_buffer_handle(
 				stream_buffer,
@@ -2914,7 +2951,9 @@
 
 				mpq_dmx_write_pts_dts(feed_data,
 					&(meta_data.info.pes.pts_dts_info));
-				mpq_dmx_save_pts_dts(feed_data);
+
+				/* Mark that we detected start of new PES */
+				feed_data->first_pts_dts_copy = 1;
 
 				meta_data.packet_type = DMX_PES_PACKET;
 				meta_data.info.pes.stc = feed_data->prev_stc;
@@ -3019,7 +3058,7 @@
 
 	/*
 	 * Need to back-up the PTS information
-	 * of the very first PES
+	 * of the start of new PES
 	 */
 	if (feed_data->first_pts_dts_copy) {
 		mpq_dmx_save_pts_dts(feed_data);
@@ -3033,6 +3072,7 @@
 	mpq_dmx_check_continuity(feed_data,
 				ts_header->continuity_counter,
 				discontinuity_indicator);
+	mpq_demux->decoder_cc_errors += feed_data->continuity_errs;
 
 	if (mpq_streambuffer_data_write(
 				stream_buffer,
@@ -3124,7 +3164,7 @@
 		curr_stc *= 256; /* convert from 105.47 KHZ to 27MHz */
 	}
 
-	if (mpq_dmx_info.decoder_framing)
+	if (!video_framing)
 		return mpq_dmx_process_video_packet_no_framing(feed, buf,
 				curr_stc);
 	else
@@ -3405,8 +3445,19 @@
 
 	sg = sg_ptr->sgl;
 	for (i = 0; i < sg_ptr->nents; i++) {
+		/*
+		 * NOTE: the following casting to u32 must be done
+		 * as long as TZ does not support LPAE. Once TZ supports
+		 * LPAE SDMX interface needs to be updated accordingly.
+		 */
+		if (sg_dma_address(sg) > 0xFFFFFFFF)
+			MPQ_DVB_ERR_PRINT(
+				"%s: WARNNING - physical address %pa is larger than 32bits!\n",
+				__func__, &sg_dma_address(sg));
+
 		buff_chunks[i].base_addr =
-			(void *)sg_dma_address(sg);
+			(void *)(u32)sg_dma_address(sg);
+
 		if (sg->length > actual_buff_size)
 			chunk_size = actual_buff_size;
 		else
@@ -4855,7 +4906,7 @@
 		event.status = DMX_OK_EOS;
 		if (!feed->secure_mode.is_secured) {
 			if (dvb_dmx_is_video_feed(feed)) {
-				if (mpq_dmx_info.decoder_framing)
+				if (!video_framing)
 					mpq_dmx_decoder_pes_closure(mpq_demux,
 						mpq_feed);
 				else
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
index f095e00..adc4261 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
@@ -388,6 +388,8 @@
  * successive video frames output, exposed in debugfs.
  * @decoder_ts_errors: Counter for number of decoder packets with TEI bit
  * set, exposed in debugfs.
+ * @decoder_cc_errors: Counter for number of decoder packets with continuity
+ * counter errors, exposed in debugfs.
  * @sdmx_process_count: Total number of times sdmx_process is called.
  * @sdmx_process_time_sum: Total time sdmx_process takes.
  * @sdmx_process_time_average: Average time sdmx_process takes.
@@ -445,6 +447,7 @@
 	u32 decoder_out_interval_average;
 	u32 decoder_out_interval_max;
 	u32 decoder_ts_errors;
+	u32 decoder_cc_errors;
 	u32 sdmx_process_count;
 	u32 sdmx_process_time_sum;
 	u32 sdmx_process_time_average;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index 940a4bc..8179061 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -195,7 +195,7 @@
 } mpq_dmx_tspp_info;
 
 static void *tspp_mem_allocator(int channel_id, u32 size,
-				u32 *phys_base, void *user)
+				phys_addr_t *phys_base, void *user)
 {
 	void *virt_addr = NULL;
 	int i = TSPP_GET_TSIF_NUM(channel_id);
@@ -218,7 +218,7 @@
 }
 
 static void tspp_mem_free(int channel_id, u32 size,
-			void *virt_base, u32 phys_base, void *user)
+			void *virt_base, phys_addr_t phys_base, void *user)
 {
 	int i = TSPP_GET_TSIF_NUM(channel_id);
 
@@ -372,7 +372,18 @@
 
 	buff_start_addr_phys =
 		mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_phys_base;
-	input.base_addr = (void *)buff_start_addr_phys;
+
+	/*
+	 * NOTE: the following casting to u32 must be done
+	 * as long as TZ does not support LPAE. Once TZ supports
+	 * LPAE SDMX interface needs to be updated accordingly.
+	 */
+	if (buff_start_addr_phys > 0xFFFFFFFF)
+		MPQ_DVB_ERR_PRINT(
+			"%s: WARNNING - physical address %pa is larger than 32bits!\n",
+			__func__, &buff_start_addr_phys);
+
+	input.base_addr = (void *)(u32)buff_start_addr_phys;
 	input.size = mpq_dmx_tspp_info.tsif[tsif].buffer_count *
 		TSPP_DESCRIPTOR_SIZE;
 
@@ -381,7 +392,7 @@
 			"%s: SDMX Processing %d descriptors: %d bytes at start address 0x%x, read offset %d\n",
 			__func__, aggregate_count, aggregate_len,
 			(unsigned int)input.base_addr,
-			buff_current_addr_phys - buff_start_addr_phys);
+			(int)(buff_current_addr_phys - buff_start_addr_phys));
 
 		mpq_sdmx_process(mpq_demux, &input, aggregate_len,
 			buff_current_addr_phys - buff_start_addr_phys,
diff --git a/drivers/media/platform/msm/dvb/include/mpq_adapter.h b/drivers/media/platform/msm/dvb/include/mpq_adapter.h
index a2ade18..86f36a4 100644
--- a/drivers/media/platform/msm/dvb/include/mpq_adapter.h
+++ b/drivers/media/platform/msm/dvb/include/mpq_adapter.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
@@ -67,6 +67,24 @@
 
 	/** STC value attached to first TS packet holding the pattern */
 	u64 stc;
+
+	/*
+	 * Number of TS packets with Transport Error Indicator (TEI)
+	 * found while constructing the frame.
+	 */
+	__u32 transport_error_indicator_counter;
+
+	/* Number of continuity errors found while constructing the frame */
+	__u32 continuity_error_counter;
+
+	/*
+	 * Number of dropped bytes due to insufficient buffer space,
+	 * since last reported frame.
+	 */
+	__u32 ts_dropped_bytes;
+
+	/* Total number of TS packets holding the frame */
+	__u32 ts_packets_num;
 };
 
 struct dmx_pes_packet_info {
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 6e8c809..d92a9c1 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -360,6 +360,25 @@
 	return ret;
 }
 
+static u32 get_hfi_buf_mode(enum buffer_mode_type hal_buf_mode)
+{
+	u32 buf_mode;
+	switch (hal_buf_mode) {
+	case HAL_BUFFER_MODE_STATIC:
+		buf_mode = HFI_BUFFER_MODE_STATIC;
+		break;
+	case HAL_BUFFER_MODE_RING:
+		buf_mode = HFI_BUFFER_MODE_RING;
+		break;
+	default:
+		dprintk(VIDC_ERR, "Invalid buffer mode :0x%x\n",
+				hal_buf_mode);
+		buf_mode = 0;
+		break;
+	}
+	return buf_mode;
+}
+
 int create_pkt_cmd_session_set_buffers(
 		struct hfi_cmd_session_set_buffers_packet *pkt,
 		u32 session_id,
@@ -1277,6 +1296,39 @@
 		pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
 		break;
 	}
+	case HAL_PARAM_BUFFER_ALLOC_MODE:
+	{
+		u32 buffer_type;
+		u32 buffer_mode;
+		struct hfi_buffer_alloc_mode *hfi;
+		struct hal_buffer_alloc_mode *alloc_info = pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE;
+		hfi = (struct hfi_buffer_alloc_mode *)
+			&pkt->rg_property_data[1];
+		buffer_type = get_hfi_buffer(alloc_info->buffer_type);
+		if (buffer_type)
+			hfi->buffer_type = buffer_type;
+		else
+			return -EINVAL;
+		buffer_mode = get_hfi_buf_mode(alloc_info->buffer_mode);
+		if (buffer_mode)
+			hfi->buffer_mode = buffer_mode;
+		else
+			return -EINVAL;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_buffer_alloc_mode);
+		break;
+	}
+	case HAL_PARAM_VDEC_FRAME_ASSEMBLY:
+	{
+		struct hfi_enable *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VDEC_FRAME_ASSEMBLY;
+		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+		hfi->enable = ((struct hfi_enable *) pdata)->enable;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
+		break;
+	}
 	/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
 	case HAL_CONFIG_BUFFER_REQUIREMENTS:
 	case HAL_CONFIG_PRIORITY:
@@ -1343,3 +1395,17 @@
 	pkt->trigger_type = get_hfi_ssr_type(type);
 	return 0;
 }
+
+int create_pkt_cmd_sys_image_version(
+		struct hfi_cmd_sys_get_property_packet *pkt)
+{
+	if (!pkt) {
+		dprintk(VIDC_ERR, "%s invalid param :%p\n", __func__, pkt);
+		return -EINVAL;
+	}
+	pkt->size = sizeof(struct hfi_cmd_sys_get_property_packet);
+	pkt->packet_type = HFI_CMD_SYS_GET_PROPERTY;
+	pkt->num_properties = 1;
+	pkt->rg_property_data[0] = HFI_PROPERTY_SYS_IMAGE_VERSION;
+	return 0;
+}
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.h b/drivers/media/platform/msm/vidc/hfi_packetization.h
index df93906..20619c0 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.h
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.h
@@ -89,4 +89,7 @@
 
 int create_pkt_ssr_cmd(enum hal_ssr_trigger_type type,
 		struct hfi_cmd_sys_test_ssr_packet *pkt);
+
+int create_pkt_cmd_sys_image_version(
+		struct hfi_cmd_sys_get_property_packet *pkt);
 #endif
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 859345f..a63ee61 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
+#include <mach/msm_smem.h>
 #include "vidc_hfi_helper.h"
 #include "vidc_hfi_io.h"
 #include "msm_vidc_debug.h"
@@ -1089,6 +1090,44 @@
 	callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
 }
 
+void hfi_process_sys_property_info(
+		struct hfi_property_sys_image_version_info_type *pkt)
+{
+	int i = 0;
+	u32 smem_block_size = 0;
+	u8 *smem_table_ptr;
+	char version[256];
+	const u32 smem_image_index_venus = 14 * 128;
+
+	if (!pkt || !pkt->string_size) {
+		dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
+		return;
+	}
+
+	if (pkt->string_size < sizeof(version)) {
+		/*
+		 * The version string returned by firmware includes null
+		 * characters at the start and in between. Replace the null
+		 * characters with space, to print the version info.
+		 */
+		for (i = 0; i < pkt->string_size; i++) {
+			if (pkt->str_image_version[i] != '\0')
+				version[i] = pkt->str_image_version[i];
+			else
+				version[i] = ' ';
+		}
+		version[i] = '\0';
+		dprintk(VIDC_INFO, "F/W version: %s\n", version);
+	}
+
+	smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
+						&smem_block_size);
+	if (smem_table_ptr &&
+		((smem_image_index_venus + 128) <= smem_block_size))
+		memcpy(smem_table_ptr + smem_image_index_venus,
+			   (u8 *)pkt->str_image_version, 128);
+}
+
 u32 hfi_process_msg_packet(
 		msm_vidc_callback callback, u32 device_id,
 		struct vidc_hal_msg_pkt_hdr *msg_hdr)
@@ -1121,6 +1160,11 @@
 			(struct hfi_msg_sys_session_init_done_packet *)
 					msg_hdr);
 		break;
+	case HFI_MSG_SYS_PROPERTY_INFO:
+		hfi_process_sys_property_info(
+		   (struct hfi_property_sys_image_version_info_type *)
+			msg_hdr);
+		break;
 	case HFI_MSG_SYS_SESSION_END_DONE:
 		hfi_process_session_end_done(callback, device_id,
 			(struct hfi_msg_sys_session_end_done_packet *)
@@ -1186,7 +1230,7 @@
 			hfi_msg_sys_session_abort_done_packet*) msg_hdr);
 		break;
 	default:
-		dprintk(VIDC_ERR, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
+		dprintk(VIDC_DBG, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
 		break;
 	}
 	return rc;
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 96d95989..cf96ca2 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -387,7 +387,6 @@
 		goto exit;
 	}
 	for (i = 0; i < b->length; ++i) {
-		buffer_type = HAL_BUFFER_OUTPUT;
 		if (EXTRADATA_IDX(b->length) &&
 			(i == EXTRADATA_IDX(b->length)) &&
 			!b->m.planes[i].length) {
@@ -404,8 +403,20 @@
 			kfree(binfo);
 			goto exit;
 		}
-		if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-			buffer_type = HAL_BUFFER_INPUT;
+
+		if (vidc_inst->session_type == MSM_VIDC_DECODER) {
+			if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+				buffer_type = HAL_BUFFER_INPUT;
+			else /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
+				buffer_type = HAL_BUFFER_OUTPUT;
+		} else {
+			/* FIXME in the future.  See comment in msm_comm_get_\
+			 * domain_partition. Same problem here. */
+			if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+				buffer_type = HAL_BUFFER_OUTPUT;
+			else /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
+				buffer_type = HAL_BUFFER_INPUT;
+		}
 
 		temp = get_same_fd_buffer(&v4l2_inst->registered_bufs,
 				b->m.planes[i].reserved[0], &plane);
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 7547464..86928f2 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -68,6 +68,10 @@
 	"Extradata aspect ratio",
 	"Extradata mpeg2 seqdisp",
 };
+static const char *const mpeg_vidc_video_alloc_mode_type[] = {
+	"Buffer Allocation Static",
+	"Buffer Allocation Ring Buffer",
+};
 
 static const char *const perf_level[] = {
 	"Nominal",
@@ -249,6 +253,33 @@
 		.qmenu = perf_level,
 		.step = 0,
 	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE,
+		.name = "Buffer allocation mode",
+		.type = V4L2_CTRL_TYPE_MENU,
+		.minimum = V4L2_MPEG_VIDC_VIDEO_STATIC,
+		.maximum = V4L2_MPEG_VIDC_VIDEO_RING,
+		.default_value = V4L2_MPEG_VIDC_VIDEO_STATIC,
+		.menu_skip_mask = ~(
+			(1 << V4L2_MPEG_VIDC_VIDEO_STATIC) |
+			(1 << V4L2_MPEG_VIDC_VIDEO_RING)
+			),
+		.qmenu = mpeg_vidc_video_alloc_mode_type,
+		.step = 0,
+		.cluster = 0,
+	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY,
+		.name = "Video frame assembly",
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.minimum = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE,
+		.maximum = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_ENABLE,
+		.default_value =  V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE,
+		.step = 1,
+		.menu_skip_mask = 0,
+		.qmenu = NULL,
+		.cluster = 0,
+	},
 };
 
 #define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls)
@@ -934,6 +965,8 @@
 	struct hal_buffer_requirements *bufreq;
 	int extra_idx = 0;
 	struct hfi_device *hdev;
+	struct hal_buffer_count_actual new_buf_count;
+	enum hal_property property_id;
 	if (!q || !num_buffers || !num_planes
 		|| !sizes || !q->drv_priv) {
 		dprintk(VIDC_ERR, "Invalid input, q = %p, %p, %p\n",
@@ -960,6 +993,16 @@
 					i, inst->capability.height.max,
 					inst->capability.width.max);
 		}
+		property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
+		new_buf_count.buffer_type = HAL_BUFFER_INPUT;
+		new_buf_count.buffer_count_actual = *num_buffers;
+		rc = call_hfi_op(hdev, session_set_property,
+				inst->session, property_id, &new_buf_count);
+		if (rc) {
+			dprintk(VIDC_WARN,
+				"Failed to set new buffer count(%d) on FW, err: %d\n",
+				new_buf_count.buffer_count_actual, rc);
+		}
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		dprintk(VIDC_DBG, "Getting bufreqs on capture plane\n");
@@ -987,15 +1030,11 @@
 		}
 		if (*num_buffers && *num_buffers >
 			bufreq->buffer_count_actual) {
-			struct hal_buffer_count_actual new_buf_count;
-			enum hal_property property_id =
-				HAL_PARAM_BUFFER_COUNT_ACTUAL;
-
+			property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
 			new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
 			new_buf_count.buffer_count_actual = *num_buffers;
 			rc = call_hfi_op(hdev, session_set_property,
 				inst->session, property_id, &new_buf_count);
-
 		}
 		if (bufreq->buffer_count_actual > *num_buffers)
 			*num_buffers =  bufreq->buffer_count_actual;
@@ -1258,6 +1297,7 @@
 	u32 property_val = 0;
 	void *pdata = NULL;
 	struct hfi_device *hdev;
+	struct hal_extradata_enable extra;
 
 	if (!inst || !inst->core || !inst->core->device) {
 		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
@@ -1325,14 +1365,11 @@
 				!!(inst->flags & VIDC_SECURE));
 		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA:
-	{
-		struct hal_extradata_enable extra;
 		property_id = HAL_PARAM_INDEX_EXTRADATA;
 		extra.index = msm_comm_get_hal_extradata_index(ctrl->val);
 		extra.enable = 1;
 		pdata = &extra;
 		break;
-	}
 	case V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL:
 		switch (ctrl->val) {
 		case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL:
@@ -1349,13 +1386,29 @@
 		}
 
 		break;
+	case V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE:
+	{
+		struct hal_buffer_alloc_mode mode;
+		property_id = HAL_PARAM_BUFFER_ALLOC_MODE;
+		mode.buffer_mode = ctrl->val;
+		mode.buffer_type = HAL_BUFFER_INPUT;
+		pdata = &mode;
+		break;
+	}
+	case V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY:
+	{
+		property_id = HAL_PARAM_VDEC_FRAME_ASSEMBLY;
+		hal_property.enable = ctrl->val;
+		pdata = &hal_property;
+		break;
+	}
 	default:
 		break;
 	}
 
 	if (!rc && property_id) {
 		dprintk(VIDC_DBG,
-			"Control: HAL property = %d, ctrl_id = 0x%x, ctrl_value = %d\n",
+			"Control: HAL property=0x%x,ctrl: id=0x%x,value=0x%x\n",
 			property_id, ctrl->id, ctrl->val);
 			rc = call_hfi_op(hdev, session_set_property, (void *)
 				inst->session, property_id, pdata);
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 46da496..7897068 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1187,6 +1187,7 @@
 	void *pdata = NULL;
 	struct v4l2_ctrl *temp_ctrl = NULL;
 	struct hfi_device *hdev;
+	struct hal_extradata_enable extra;
 
 	if (!inst || !inst->core || !inst->core->device) {
 		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
@@ -1728,14 +1729,11 @@
 				!!(inst->flags & VIDC_SECURE));
 		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA:
-	{
-		struct hal_extradata_enable extra;
 		property_id = HAL_PARAM_INDEX_EXTRADATA;
 		extra.index = msm_comm_get_hal_extradata_index(ctrl->val);
 		extra.enable = 1;
 		pdata = &extra;
 		break;
-	}
 	case V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO:
 	{
 		struct v4l2_ctrl *rc_mode;
@@ -1761,7 +1759,7 @@
 		case V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED:
 			vui_timing_info.enable = 1;
 			vui_timing_info.fixed_frame_rate = cfr;
-			vui_timing_info.time_scale = inst->prop.fps;
+			vui_timing_info.time_scale = NSEC_PER_SEC;
 		}
 
 		pdata = &vui_timing_info;
@@ -1877,7 +1875,7 @@
 	inst->fmts[OUTPUT_PORT] = &venc_formats[0];
 	inst->prop.height = DEFAULT_HEIGHT;
 	inst->prop.width = DEFAULT_WIDTH;
-	inst->prop.fps = 30;
+	inst->prop.fps = 15;
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 1c43f1e..b6d031a 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -477,14 +477,14 @@
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to initialize vb2 queue on capture port\n");
-		goto fail_init;
+		goto fail_bufq_capture;
 	}
 	rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
 			session_type);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to initialize vb2 queue on capture port\n");
-		goto fail_init;
+		goto fail_bufq_output;
 	}
 	rc = msm_comm_try_state(inst, MSM_VIDC_CORE_INIT);
 	if (rc) {
@@ -502,6 +502,14 @@
 	mutex_unlock(&core->lock);
 	return inst;
 fail_init:
+	vb2_queue_release(&inst->bufq[OUTPUT_PORT].vb2_bufq);
+fail_bufq_output:
+	vb2_queue_release(&inst->bufq[CAPTURE_PORT].vb2_bufq);
+fail_bufq_capture:
+	if (session_type == MSM_VIDC_DECODER)
+		msm_vdec_ctrl_deinit(inst);
+	else if (session_type == MSM_VIDC_ENCODER)
+		msm_venc_ctrl_deinit(inst);
 	msm_smem_delete_client(inst->mem_client);
 fail_mem_client:
 	kfree(inst);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 77f838c..57b98dc 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -69,6 +69,20 @@
 	return false;
 }
 
+static bool is_thumbnail_session(struct msm_vidc_inst *inst)
+{
+	if (inst->session_type == MSM_VIDC_DECODER) {
+		int rc = 0;
+		struct v4l2_control ctrl = {
+			.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE
+		};
+		rc = v4l2_g_ctrl(&inst->ctrl_handler, &ctrl);
+		if (!rc && ctrl.value)
+			return true;
+	}
+	return false;
+}
+
 static int msm_comm_get_load(struct msm_vidc_core *core,
 	enum session_type type)
 {
@@ -83,7 +97,9 @@
 		if (inst->session_type == type &&
 			inst->state >= MSM_VIDC_OPEN_DONE &&
 			inst->state < MSM_VIDC_STOP_DONE) {
-			num_mbs_per_sec += NUM_MBS_PER_SEC(inst->prop.height,
+			if (!is_thumbnail_session(inst))
+				num_mbs_per_sec += NUM_MBS_PER_SEC(
+					inst->prop.height,
 					inst->prop.width, inst->prop.fps);
 		}
 		mutex_unlock(&inst->lock);
@@ -728,6 +744,15 @@
 	vb = response->clnt_data;
 	inst = (struct msm_vidc_inst *)response->session_id;
 	if (vb) {
+		vb->v4l2_planes[0].bytesused = response->input_done.filled_len;
+		vb->v4l2_planes[0].data_offset = response->input_done.offset;
+		if (vb->v4l2_planes[0].data_offset > vb->v4l2_planes[0].length)
+			dprintk(VIDC_ERR, "Error: data_offset overflow\n");
+		if (vb->v4l2_planes[0].bytesused > vb->v4l2_planes[0].length)
+			dprintk(VIDC_ERR, "Error: buffer overflow\n");
+		if ((u8 *)vb->v4l2_planes[0].m.userptr !=
+			response->input_done.packet_buffer)
+			dprintk(VIDC_ERR, "Error: unexpected buffer address\n");
 		mutex_lock(&inst->bufq[OUTPUT_PORT].lock);
 		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
 		mutex_unlock(&inst->bufq[OUTPUT_PORT].lock);
@@ -780,6 +805,8 @@
 			vb->v4l2_buf.flags |= V4L2_QCOM_BUF_FLAG_DECODEONLY;
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DATACORRUPT)
 			vb->v4l2_buf.flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
+		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME)
+			vb->v4l2_buf.flags |= V4L2_QCOM_BUF_DROP_FRAME;
 		switch (fill_buf_done->picture_type) {
 		case HAL_PICTURE_IDR:
 			vb->v4l2_buf.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
@@ -1889,10 +1916,19 @@
 		memset(&frame_data, 0 , sizeof(struct vidc_frame_data));
 		frame_data.alloc_len = vb->v4l2_planes[0].length;
 		frame_data.filled_len = vb->v4l2_planes[0].bytesused;
+		frame_data.offset = vb->v4l2_planes[0].data_offset;
 		frame_data.device_addr = vb->v4l2_planes[0].m.userptr;
 		frame_data.timestamp = time_usec;
 		frame_data.flags = 0;
 		frame_data.clnt_data = (u32)vb;
+		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+			(frame_data.filled_len > frame_data.alloc_len ||
+			frame_data.offset > frame_data.alloc_len)) {
+			dprintk(VIDC_ERR,
+				"Buffer will overflow, not queueing it\n");
+			rc = -EINVAL;
+			goto err_bad_input;
+		}
 		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 			frame_data.buffer_type = HAL_BUFFER_INPUT;
 			if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_EOS) {
@@ -1908,11 +1944,20 @@
 					"Received CODECCONFIG on output cap\n");
 			}
 			if (vb->v4l2_buf.flags &
+					V4L2_QCOM_BUF_FLAG_DECODEONLY) {
+				frame_data.flags |= HAL_BUFFERFLAG_DECODEONLY;
+				dprintk(VIDC_DBG,
+					"Received DECODEONLY on output cap\n");
+			}
+			if (vb->v4l2_buf.flags &
 				V4L2_QCOM_BUF_TIMESTAMP_INVALID)
 				frame_data.timestamp = LLONG_MAX;
 			dprintk(VIDC_DBG,
-				"Sending etb to hal: Alloc: %d :filled: %d\n",
-				frame_data.alloc_len, frame_data.filled_len);
+				"Sending etb to hal: device_addr: 0x%x"
+				"Alloc: %d, filled: %d, offset: %d\n",
+				frame_data.device_addr,
+				frame_data.alloc_len, frame_data.filled_len,
+				frame_data.offset);
 			rc = call_hfi_op(hdev, session_etb, (void *)
 					inst->session, &frame_data);
 			if (!rc)
@@ -1965,6 +2010,7 @@
 			rc = -EINVAL;
 		}
 	}
+err_bad_input:
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to queue buffer\n");
 err_no_mem:
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 28ea41a..47b88db 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1030,6 +1030,7 @@
 static int venus_hfi_core_init(void *device)
 {
 	struct hfi_cmd_sys_init_packet pkt;
+	struct hfi_cmd_sys_get_property_packet version_pkt;
 	int rc = 0;
 	struct venus_hfi_device *dev;
 
@@ -1088,6 +1089,10 @@
 		rc = -ENOTEMPTY;
 		goto err_core_init;
 	}
+	rc = create_pkt_cmd_sys_image_version(&version_pkt);
+	if (rc || venus_hfi_iface_cmdq_write(dev, &version_pkt))
+		dprintk(VIDC_WARN, "Failed to send image version pkt to f/w");
+
 	return rc;
 err_core_init:
 	disable_irq_nosync(dev->hal_data->irq);
@@ -1418,6 +1423,10 @@
 		break;
 	case HAL_SYS_DEBUG_CONFIG:
 		break;
+	case HAL_PARAM_BUFFER_ALLOC_MODE:
+		break;
+	case HAL_PARAM_VDEC_FRAME_ASSEMBLY:
+		break;
 	/*FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET*/
 	case HAL_CONFIG_BUFFER_REQUIREMENTS:
 	case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index bb72da7..874738b 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -39,6 +39,8 @@
 #define HFI_BUFFERFLAG_EOSEQ			0x00200000
 #define HFI_BUFFERFLAG_DISCONTINUITY	0x80000000
 #define HFI_BUFFERFLAG_TEI				0x40000000
+#define HFI_BUFFERFLAG_DROP_FRAME               0x20000000
+
 
 #define HFI_ERR_SESSION_EMPTY_BUFFER_DONE_OUTPUT_PENDING	\
 	(HFI_OX_BASE + 0x1001)
@@ -335,7 +337,6 @@
 #define HFI_MSG_SYS_OX_START			\
 (HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
 #define HFI_MSG_SYS_PING_ACK	(HFI_MSG_SYS_OX_START + 0x2)
-#define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_OX_START + 0x3)
 #define HFI_MSG_SYS_SESSION_ABORT_DONE	(HFI_MSG_SYS_OX_START + 0x4)
 
 #define HFI_MSG_SESSION_OX_START		\
@@ -408,7 +409,7 @@
 	u32 input_tag;
 	u8 *packet_buffer;
 	u8 *extra_data_buffer;
-	u32 rgData[0];
+	u32 rgData[1];
 };
 
 struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet {
@@ -427,7 +428,7 @@
 	u32 input_tag;
 	u8 *packet_buffer;
 	u8 *extra_data_buffer;
-	u32 rgData[0];
+	u32 rgData[1];
 };
 
 struct hfi_cmd_session_empty_buffer_uncompressed_plane1_packet {
@@ -436,7 +437,7 @@
 	u32 filled_len;
 	u32 offset;
 	u8 *packet_buffer2;
-	u32 rgData[0];
+	u32 rgData[1];
 };
 
 struct hfi_cmd_session_empty_buffer_uncompressed_plane2_packet {
@@ -445,7 +446,7 @@
 	u32 filled_len;
 	u32 offset;
 	u8 *packet_buffer3;
-	u32 rgData[0];
+	u32 rgData[1];
 };
 
 struct hfi_cmd_session_fill_buffer_packet {
@@ -459,7 +460,7 @@
 	u32 output_tag;
 	u8 *packet_buffer;
 	u8 *extra_data_buffer;
-	u32 rgData[0];
+	u32 rgData[1];
 };
 
 struct hfi_cmd_session_flush_packet {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 389c13f..5c22552 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -44,6 +44,8 @@
 #define HAL_BUFFERFLAG_READONLY         0x00000200
 #define HAL_BUFFERFLAG_ENDOFSUBFRAME    0x00000400
 #define HAL_BUFFERFLAG_EOSEQ            0x00200000
+#define HAL_BUFFERFLAG_DROP_FRAME       0x20000000
+
 
 #define HAL_DEBUG_MSG_LOW				0x00000001
 #define HAL_DEBUG_MSG_MEDIUM			0x00000002
@@ -172,6 +174,8 @@
 	HAL_PARAM_VENC_H264_VUI_TIMING_INFO,
 	HAL_PARAM_VENC_H264_GENERATE_AUDNAL,
 	HAL_PARAM_VENC_MAX_NUM_B_FRAMES,
+	HAL_PARAM_BUFFER_ALLOC_MODE,
+	HAL_PARAM_VDEC_FRAME_ASSEMBLY,
 };
 
 enum hal_domain {
@@ -860,6 +864,16 @@
 	HAL_UNUSED_SEQCHG = 0x10000000,
 };
 
+enum buffer_mode_type {
+	HAL_BUFFER_MODE_STATIC = 0x00000000,
+	HAL_BUFFER_MODE_RING,
+};
+
+struct hal_buffer_alloc_mode {
+	enum hal_buffer buffer_type;
+	enum buffer_mode_type buffer_mode;
+};
+
 /* HAL Response */
 
 enum command_response {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 2b6d6bb..0f1e896 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -197,6 +197,10 @@
 	(HFI_PROPERTY_SYS_COMMON_START + 0x003)
 #define HFI_PROPERTY_SYS_IDLE_INDICATOR         \
 	(HFI_PROPERTY_SYS_COMMON_START + 0x004)
+#define  HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL     \
+	(HFI_PROPERTY_SYS_COMMON_START + 0x005)
+#define  HFI_PROPERTY_SYS_IMAGE_VERSION    \
+	(HFI_PROPERTY_SYS_COMMON_START + 0x006)
 
 #define HFI_PROPERTY_PARAM_COMMON_START	\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x1000)
@@ -615,6 +619,11 @@
 	struct hfi_resource_ocmem_requirement rg_requirements[1];
 };
 
+struct hfi_property_sys_image_version_info_type {
+	u32 string_size;
+	u8  str_image_version[1];
+};
+
 struct hfi_venc_config_advanced {
 	u8 pipe2d;
 	u8 hw_mode;
@@ -703,6 +712,7 @@
 #define HFI_MSG_SYS_SESSION_INIT_DONE	(HFI_MSG_SYS_COMMON_START + 0x6)
 #define HFI_MSG_SYS_SESSION_END_DONE	(HFI_MSG_SYS_COMMON_START + 0x7)
 #define HFI_MSG_SYS_IDLE		(HFI_MSG_SYS_COMMON_START + 0x8)
+#define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_COMMON_START + 0xA)
 
 #define HFI_MSG_SESSION_COMMON_START		\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET +	\
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index 8121471..9cd199b 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -296,24 +296,13 @@
 static long set_default_properties(struct venc_inst *inst)
 {
 	struct v4l2_control ctrl = {0};
-	int rc;
 
 	/* Set the IDR period as 1.  The venus core doesn't give
 	 * the sps/pps for I-frames, only IDR. */
 	ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD;
 	ctrl.value = 1;
-	rc = msm_vidc_s_ctrl(inst->vidc_context, &ctrl);
-	if (rc)
-		WFD_MSG_WARN("Failed to set IDR period\n");
 
-	/* Set the default rc mode to VBR/VFR, client can change later */
-	ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL;
-	ctrl.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR;
-	rc = msm_vidc_s_ctrl(inst->vidc_context, &ctrl);
-	if (rc)
-		WFD_MSG_WARN("Failed to set rc mode\n");
-
-	return 0;
+	return msm_vidc_s_ctrl(inst->vidc_context, &ctrl);
 }
 
 static int subscribe_events(struct venc_inst *inst)
diff --git a/drivers/media/platform/msm/wfd/vsg-subdev.c b/drivers/media/platform/msm/wfd/vsg-subdev.c
index e0a46cc..6ffaffa 100644
--- a/drivers/media/platform/msm/wfd/vsg-subdev.c
+++ b/drivers/media/platform/msm/wfd/vsg-subdev.c
@@ -462,8 +462,16 @@
 static long vsg_return_ip_buffer(struct v4l2_subdev *sd, void *arg)
 {
 	struct vsg_context *context = NULL;
-	struct vsg_buf_info *buf_info = NULL, *last_buffer = NULL,
-			*expected_buffer = NULL;
+	struct vsg_buf_info *buf_info = NULL, *temp = NULL,
+			/* last buffer sent for encoding */
+			*last_buffer = NULL,
+			/* buffer we expected to get back, ideally ==
+			 * last_buffer, but might not be if sequence is
+			 * encode, encode, return */
+			*expected_buffer = NULL,
+			/* buffer that we've sent for encoding at some point */
+			*known_buffer = NULL;
+	bool is_last_buffer = false;
 	int rc = 0;
 
 	if (!arg || !sd) {
@@ -477,41 +485,47 @@
 	buf_info = (struct vsg_buf_info *)arg;
 	last_buffer = context->last_buffer;
 
+	WFD_MSG_DBG("Return frame with paddr %p\n",
+			(void *)buf_info->mdp_buf_info.paddr);
+
 	if (!list_empty(&context->busy_queue.node)) {
 		expected_buffer = list_first_entry(&context->busy_queue.node,
 				struct vsg_buf_info, node);
 	}
 
-	WFD_MSG_DBG("Return frame with paddr %p\n",
-			(void *)buf_info->mdp_buf_info.paddr);
-
-	if (!expected_buffer) {
-		WFD_MSG_ERR("Unexpectedly received buffer from enc with "
-			"paddr %p\n", (void *)buf_info->mdp_buf_info.paddr);
-		goto return_ip_buf_bad_buf;
+	list_for_each_entry(temp, &context->busy_queue.node, node) {
+		if (mdp_buf_info_equals(&temp->mdp_buf_info,
+				&buf_info->mdp_buf_info)) {
+			known_buffer = temp;
+			break;
+		}
 	}
 
-	expected_buffer->flags &= ~VSG_BUF_BEING_ENCODED;
-	if (mdp_buf_info_equals(&expected_buffer->mdp_buf_info,
-				&buf_info->mdp_buf_info)) {
-		bool is_same_buffer = context->last_buffer &&
-			mdp_buf_info_equals(
-					&context->last_buffer->mdp_buf_info,
-					&expected_buffer->mdp_buf_info);
-
-		list_del(&expected_buffer->node);
-		if (!is_same_buffer &&
-			!(expected_buffer->flags & VSG_NEVER_RELEASE)) {
-			vsg_release_input_buffer(context, expected_buffer);
-			kfree(expected_buffer);
-		}
-	} else {
-		WFD_MSG_ERR("Returned buffer %p is not latest buffer, "
-				"expected %p\n",
-				(void *)buf_info->mdp_buf_info.paddr,
-				(void *)expected_buffer->mdp_buf_info.paddr);
-		rc = -EINVAL;
+	if (!expected_buffer || !known_buffer) {
+		WFD_MSG_ERR("Unexpectedly received buffer from enc with "
+			"paddr %p\n", (void *)buf_info->mdp_buf_info.paddr);
+		rc = -EBADHANDLE;
 		goto return_ip_buf_bad_buf;
+	} else if (known_buffer != expected_buffer) {
+		/* Buffers can come back out of order if encoder decides to drop
+		 * a frame */
+		WFD_MSG_DBG(
+				"Got a buffer (%p) out of order. Preferred to get %p\n",
+				(void *)known_buffer->mdp_buf_info.paddr,
+				(void *)expected_buffer->mdp_buf_info.paddr);
+	}
+
+	known_buffer->flags &= ~VSG_BUF_BEING_ENCODED;
+	is_last_buffer = context->last_buffer &&
+		mdp_buf_info_equals(
+				&context->last_buffer->mdp_buf_info,
+				&known_buffer->mdp_buf_info);
+
+	list_del(&known_buffer->node);
+	if (!is_last_buffer &&
+			!(known_buffer->flags & VSG_NEVER_RELEASE)) {
+		vsg_release_input_buffer(context, known_buffer);
+		kfree(known_buffer);
 	}
 
 return_ip_buf_bad_buf:
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index 30a666d..6554947 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -715,6 +715,11 @@
 	if (rc)
 		WFD_MSG_ERR("Failed to stop MDP\n");
 
+	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
+			ENCODE_FLUSH, (void *)inst->venc_inst);
+	if (rc)
+		WFD_MSG_ERR("Failed to flush encoder\n");
+
 	WFD_MSG_DBG("vsg stop\n");
 	rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl,
 			 VSG_STOP, NULL);
@@ -723,10 +728,6 @@
 
 	complete(&inst->stop_mdp_thread);
 	kthread_stop(inst->mdp_task);
-	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
-			ENCODE_FLUSH, (void *)inst->venc_inst);
-	if (rc)
-		WFD_MSG_ERR("Failed to flush encoder\n");
 	WFD_MSG_DBG("enc stop\n");
 	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
 			ENCODE_STOP, (void *)inst->venc_inst);
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 50a1ea1..7934234 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -2416,9 +2416,15 @@
 	ev.tune_freq = *((int *) &skb->data[0]);
 	ev.pi_code = *((__le16 *) &skb->data[PI_CODE_OFFSET]);
 	ev.af_size = skb->data[AF_SIZE_OFFSET];
-	memcpy(&ev.af_list[0], &skb->data[AF_LIST_OFFSET], ev.af_size);
+	if (ev.af_size > AF_LIST_MAX) {
+		FMDERR("AF list size received more than available size");
+		return;
+	}
+	memcpy(&ev.af_list[0], &skb->data[AF_LIST_OFFSET],
+					ev.af_size * sizeof(int));
 	iris_q_event(radio, IRIS_EVT_NEW_AF_LIST);
-	iris_q_evt_data(radio, (char *)&ev, sizeof(ev), IRIS_BUF_AF_LIST);
+	iris_q_evt_data(radio, (char *)&ev, (7 + ev.af_size * sizeof(int)),
+							IRIS_BUF_AF_LIST);
 }
 
 static void hci_ev_rds_lock_status(struct radio_hci_dev *hdev,
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index ea7032b..e0a99e2 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -1932,6 +1932,7 @@
 	if (bahama_present == -ENODEV)
 		return -ENODEV;
 
+	marimba_set_fm_status(radio->marimba, true);
 	if (bahama_present)
 		radio->marimba->mod_id = SLAVE_ID_BAHAMA;
 	else
@@ -2066,7 +2067,6 @@
 
 	radio->handle_irq = 0;
 	radio->marimba->mod_id = SLAVE_ID_BAHAMA;
-	marimba_set_fm_status(radio->marimba, true);
 	return 0;
 
 
@@ -2082,6 +2082,7 @@
 config_i2s_err:
 	radio->pdata->fm_shutdown(radio->pdata);
 open_err_setup:
+	marimba_set_fm_status(radio->marimba, false);
 	radio->handle_irq = 1;
 	atomic_inc(&radio->users);
 	return retval;
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index eb8320f..24fd5c1 100644
--- a/drivers/mfd/pm8xxx-pwm.c
+++ b/drivers/mfd/pm8xxx-pwm.c
@@ -35,7 +35,7 @@
  */
 #define PM8XXX_LPG_V0_PWM_CHANNELS	8
 #define PM8XXX_LPG_V1_PWM_CHANNELS	6
-#define PM8XXX_LPG_CTL_REGS		7
+#define PM8XXX_LPG_CTL_REGS		8
 
 /* PM8XXX PWM */
 #define SSBI_REG_ADDR_PWM1_CTRL1	0x88
@@ -66,6 +66,7 @@
 #define SSBI_REG_ADDR_LPG_LUT_CFG0	0x145
 #define SSBI_REG_ADDR_LPG_LUT_CFG1	0x146
 #define SSBI_REG_ADDR_LPG_TEST		0x147
+#define SSBI_REG_ADDR_LPG_CTL_7		0x14D
 
 /* LPG Control 0 */
 #define PM8XXX_PWM_1KHZ_COUNT_MASK	0xF0
@@ -126,6 +127,7 @@
 
 #define PM8XXX_PWM_PAUSE_ENABLE_HIGH		0x02
 #define PM8XXX_PWM_SIZE_9_BIT			0x01
+#define PM8XXX_PWM_SIZE_7_BIT			0x04
 
 /* LPG Control 6 */
 #define PM8XXX_PWM_PAUSE_COUNT_LO_MASK		0xFC
@@ -369,17 +371,22 @@
 }
 
 static void pm8xxx_pwm_calc_period(unsigned int period_us,
-				   struct pm8xxx_pwm_period *period)
+				   struct pwm_device *pwm)
 {
 	int	n, m, clk, div;
 	int	best_m, best_div, best_clk;
 	unsigned int	last_err, cur_err, min_err;
 	unsigned int	tmp_p, period_n;
+	struct	pm8xxx_pwm_period *period = &pwm->period;
+
+	if (pwm->banks == PM_PWM_BANK_LO)
+		n = 7;
+	else
+		n = 6;
 
 	/* PWM Period / N */
 	if (period_us < ((unsigned)(-1) / NSEC_PER_USEC)) {
-		period_n = (period_us * NSEC_PER_USEC) >> 6;
-		n = 6;
+		period_n = (period_us * NSEC_PER_USEC) >> n;
 	} else {
 		period_n = (period_us >> 9) * NSEC_PER_USEC;
 		n = 9;
@@ -458,6 +465,9 @@
 	int	rc = 0;
 
 	pwm_size = (pwm->pwm_lpg_ctl[5] & PM8XXX_PWM_SIZE_9_BIT) ? 9 : 6;
+	if (pwm->period.pwm_size == 7)
+		pwm_size = 7;
+
 	max_pwm_value = (1 << pwm_size) - 1;
 	for (i = 0; i < len; i++) {
 		if (raw_value)
@@ -512,9 +522,16 @@
 			PM8XXX_LPG_PWM_PREDIVIDE_MASK | PM8XXX_LPG_PWM_M_MASK;
 		pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[4], mask, val);
 
-		val = (pwm->period.pwm_size > 6) ? PM8XXX_PWM_SIZE_9_BIT : 0;
-		mask = PM8XXX_PWM_SIZE_9_BIT;
-		pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[5], mask, val);
+		if (pwm->period.pwm_size == 7) {
+			val = PM8XXX_PWM_SIZE_7_BIT;
+			mask = PM8XXX_PWM_SIZE_7_BIT;
+			pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[7], mask, val);
+		} else {
+			val = (pwm->period.pwm_size > 6) ?
+					PM8XXX_PWM_SIZE_9_BIT : 0;
+			mask = PM8XXX_PWM_SIZE_9_BIT;
+			pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[5], mask, val);
+		}
 	} else {
 		val = ((pwm->period.clk + 1) << PM8XXX_PWM_CLK_SEL_SHIFT)
 			& PM8XXX_PWM_CLK_SEL_MASK;
@@ -639,8 +656,18 @@
 {
 	int	i, rc;
 
+	if (end == 7) {
+		rc = pm8xxx_writeb(pwm->chip->dev->parent,
+				SSBI_REG_ADDR_LPG_CTL_7,
+				pwm->pwm_lpg_ctl[end]);
+		if (rc) {
+			pr_err("pm8xxx_writeb(): rc=%d (PWM Ctl[7])\n", rc);
+			return rc;
+		}
+	}
+
 	/* Write in reverse way so 0 would be the last */
-	for (i = end - 1; i >= start; i--) {
+	for (i = end - 2; i >= start; i--) {
 		rc = pm8xxx_writeb(pwm->chip->dev->parent,
 				   SSBI_REG_ADDR_LPG_CTL(i),
 				   pwm->pwm_lpg_ctl[i]);
@@ -788,7 +815,7 @@
 	}
 
 	if (pwm->pwm_period != period_us) {
-		pm8xxx_pwm_calc_period(period_us, period);
+		pm8xxx_pwm_calc_period(period_us, pwm);
 		pm8xxx_pwm_save_period(pwm);
 		pwm->pwm_period = period_us;
 	}
@@ -801,7 +828,7 @@
 				PM8XXX_PWM_BYPASS_LUT, PM8XXX_PWM_BYPASS_LUT);
 
 		pm8xxx_pwm_bank_sel(pwm);
-		rc = pm8xxx_lpg_pwm_write(pwm, 1, 6);
+		rc = pm8xxx_lpg_pwm_write(pwm, 1, 7);
 	} else {
 		rc = pm8xxx_pwm_write(pwm);
 	}
@@ -851,7 +878,7 @@
 			 * PWM mode.
 			 */
 			if (pwm->chip->is_pwm_enable_sync_workaround_needed)
-				rc = pm8xxx_lpg_pwm_write(pwm, 3, 4);
+				rc = pm8xxx_lpg_pwm_write(pwm, 3, 5);
 
 		} else {
 			pm8xxx_pwm_enable(pwm);
@@ -921,7 +948,7 @@
 
 	if (pwm_chip->is_lpg_supported) {
 		pm8xxx_pwm_bank_sel(pwm);
-		rc = pm8xxx_lpg_pwm_write(pwm, 4, 6);
+		rc = pm8xxx_lpg_pwm_write(pwm, 4, 7);
 	} else {
 		rc = pm8xxx_pwm_write(pwm);
 	}
@@ -965,7 +992,7 @@
 		pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[1],
 				PM8XXX_PWM_BYPASS_LUT, PM8XXX_PWM_BYPASS_LUT);
 		pm8xxx_pwm_bank_sel(pwm);
-		rc = pm8xxx_lpg_pwm_write(pwm, 1, 6);
+		rc = pm8xxx_lpg_pwm_write(pwm, 1, 7);
 	} else {
 		rc = pm8xxx_pwm_write(pwm);
 	}
@@ -996,7 +1023,6 @@
 			  int idx_len, int pause_lo, int pause_hi, int flags)
 {
 	struct pm8xxx_pwm_lut	lut;
-	struct pm8xxx_pwm_period *period;
 	int	len;
 	int	rc;
 
@@ -1032,7 +1058,6 @@
 		return -EINVAL;
 	}
 
-	period = &pwm->period;
 	mutex_lock(&pwm->chip->pwm_mutex);
 
 	if (flags & PM_PWM_BANK_HI)
@@ -1052,7 +1077,7 @@
 	}
 
 	if (pwm->pwm_period != period_us) {
-		pm8xxx_pwm_calc_period(period_us, period);
+		pm8xxx_pwm_calc_period(period_us, pwm);
 		pm8xxx_pwm_save_period(pwm);
 		pwm->pwm_period = period_us;
 	}
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 9d0bc61..bd838fc 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -69,6 +69,8 @@
 /* Check if enterprise security is activate */
 #define	SCM_IS_ACTIVATED_ID		0x02
 
+#define RPMB_SERVICE			0x2000
+
 enum qseecom_clk_definitions {
 	CLK_DFAB = 0,
 	CLK_SFPB,
@@ -212,6 +214,8 @@
 /* Function proto types */
 static int qsee_vote_for_clock(struct qseecom_dev_handle *, int32_t);
 static void qsee_disable_clock_vote(struct qseecom_dev_handle *, int32_t);
+static int __qseecom_enable_clk(enum qseecom_ce_hw_instance ce);
+static void __qseecom_disable_clk(enum qseecom_ce_hw_instance ce);
 
 static int __qseecom_is_svc_unique(struct qseecom_dev_handle *data,
 		struct qseecom_register_listener_req *svc)
@@ -520,6 +524,10 @@
 			msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle,
 					ptr_svc->sb_virt, ptr_svc->sb_length,
 						ION_IOC_CLEAN_INV_CACHES);
+
+		if (lstnr == RPMB_SERVICE)
+			__qseecom_enable_clk(CLK_QSEE);
+
 		ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
 					(const void *)&send_data_rsp,
 					sizeof(send_data_rsp), resp,
@@ -527,6 +535,8 @@
 		if (ret) {
 			pr_err("scm_call() failed with err: %d (app_id = %d)\n",
 				ret, data->client.app_id);
+			if (lstnr == RPMB_SERVICE)
+				__qseecom_disable_clk(CLK_QSEE);
 			return ret;
 		}
 		if ((resp->result != QSEOS_RESULT_SUCCESS) &&
@@ -535,6 +545,9 @@
 				resp->result, data->client.app_id, lstnr);
 			ret = -EINVAL;
 		}
+		if (lstnr == RPMB_SERVICE)
+			__qseecom_disable_clk(CLK_QSEE);
+
 	}
 	if (rc)
 		return rc;
@@ -997,7 +1010,6 @@
 	return ret;
 }
 
-
 static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp)
 {
 	int ret = 0;
@@ -1018,8 +1030,29 @@
 	return ret;
 }
 
-static int __qseecom_update_cmd_buf(struct qseecom_send_modfd_cmd_req *req,
-								bool cleanup)
+static int qseecom_unprotect_buffer(void __user *argp)
+{
+	int ret = 0;
+	struct ion_handle *ihandle;
+	int32_t ion_fd;
+
+	ret = copy_from_user(&ion_fd, argp, sizeof(ion_fd));
+	if (ret) {
+		pr_err("copy_from_user failed");
+		return ret;
+	}
+
+	ihandle = ion_import_dma_buf(qseecom.ion_clnt, ion_fd);
+
+	ret = msm_ion_unsecure_buffer(qseecom.ion_clnt, ihandle);
+	if (ret)
+		return -EINVAL;
+	return 0;
+}
+
+static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
+					struct qseecom_dev_handle *data,
+					bool listener_svc)
 {
 	struct ion_handle *ihandle;
 	char *field;
@@ -1027,76 +1060,119 @@
 	int i = 0;
 	uint32_t len = 0;
 	struct scatterlist *sg;
+	struct qseecom_send_modfd_cmd_req *cmd_req = NULL;
+	struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL;
+	struct qseecom_registered_listener_list *this_lstnr = NULL;
+
+	if (msg == NULL) {
+		pr_err("Invalid address\n");
+		return -EINVAL;
+	}
+	if (listener_svc) {
+		lstnr_resp = (struct qseecom_send_modfd_listener_resp *)msg;
+		this_lstnr = __qseecom_find_svc(data->listener.id);
+		if (IS_ERR_OR_NULL(this_lstnr)) {
+			pr_err("Invalid listener ID\n");
+			return -ENOMEM;
+		}
+	} else {
+		cmd_req = (struct qseecom_send_modfd_cmd_req *)msg;
+	}
 
 	for (i = 0; i < MAX_ION_FD; i++) {
 		struct sg_table *sg_ptr = NULL;
-		if (req->ifd_data[i].fd > 0) {
-			/* Get the handle of the shared fd */
+		if ((!listener_svc) && (cmd_req->ifd_data[i].fd > 0)) {
 			ihandle = ion_import_dma_buf(qseecom.ion_clnt,
-						req->ifd_data[i].fd);
+					cmd_req->ifd_data[i].fd);
 			if (IS_ERR_OR_NULL(ihandle)) {
 				pr_err("Ion client can't retrieve the handle\n");
 				return -ENOMEM;
 			}
-			field = (char *) req->cmd_req_buf +
-						req->ifd_data[i].cmd_buf_offset;
-
-			/* Populate the cmd data structure with the phys_addr */
-			sg_ptr = ion_sg_table(qseecom.ion_clnt, ihandle);
-			if (sg_ptr == NULL) {
-				pr_err("IOn client could not retrieve sg table\n");
-				goto err;
+			field = (char *) cmd_req->cmd_req_buf +
+				cmd_req->ifd_data[i].cmd_buf_offset;
+		} else if ((listener_svc) &&
+				(lstnr_resp->ifd_data[i].fd > 0)) {
+			ihandle = ion_import_dma_buf(qseecom.ion_clnt,
+						lstnr_resp->ifd_data[i].fd);
+			if (IS_ERR_OR_NULL(ihandle)) {
+				pr_err("Ion client can't retrieve the handle\n");
+				return -ENOMEM;
 			}
-			if (sg_ptr->nents == 0) {
-				pr_err("Num of scattered entries is 0\n");
-				goto err;
+			switch (lstnr_resp->protection_mode) {
+			case QSEOS_PROTECT_BUFFER:
+				 ret = msm_ion_secure_buffer(qseecom.ion_clnt,
+								ihandle,
+								VIDEO_PIXEL,
+								0);
+				break;
+			case QSEOS_UNPROTECT_PROTECTED_BUFFER:
+				ret = msm_ion_unsecure_buffer(qseecom.ion_clnt,
+								ihandle);
+				break;
+			case QSEOS_UNPROTECTED_BUFFER:
+			default:
+				break;
 			}
-			if (sg_ptr->nents > QSEECOM_MAX_SG_ENTRY) {
-				pr_err("Num of scattered entries");
-				pr_err(" (%d) is greater than max supported %d\n",
-					sg_ptr->nents, QSEECOM_MAX_SG_ENTRY);
-				goto err;
-			}
-			sg = sg_ptr->sgl;
-			if (sg_ptr->nents == 1) {
-				uint32_t *update;
-				update = (uint32_t *) field;
-				if (cleanup)
-					*update = 0;
-				else
-					*update = (uint32_t)sg_dma_address(
-								sg_ptr->sgl);
-				len += (uint32_t)sg->length;
-			} else {
-				struct qseecom_sg_entry *update;
-				int j = 0;
-				update = (struct qseecom_sg_entry *) field;
-				for (j = 0; j < sg_ptr->nents; j++) {
-					if (cleanup) {
-						update->phys_addr = 0;
-						update->len = 0;
-					} else {
-						update->phys_addr = (uint32_t)
-							sg_dma_address(sg);
-						update->len = sg->length;
-					}
-					len += sg->length;
-					update++;
-					sg = sg_next(sg);
-				}
-			}
-			if (cleanup)
-				msm_ion_do_cache_op(qseecom.ion_clnt,
-						ihandle, NULL, len,
-						ION_IOC_INV_CACHES);
-			else
-				msm_ion_do_cache_op(qseecom.ion_clnt,
-						ihandle, NULL, len,
-						ION_IOC_CLEAN_INV_CACHES);
-			/* Deallocate the handle */
-			if (!IS_ERR_OR_NULL(ihandle))
-				ion_free(qseecom.ion_clnt, ihandle);
+			field = lstnr_resp->resp_buf_ptr +
+				lstnr_resp->ifd_data[i].cmd_buf_offset;
+		} else {
+			return ret;
 		}
+		/* Populate the cmd data structure with the phys_addr */
+		sg_ptr = ion_sg_table(qseecom.ion_clnt, ihandle);
+		if (sg_ptr == NULL) {
+			pr_err("IOn client could not retrieve sg table\n");
+			goto err;
+		}
+		if (sg_ptr->nents == 0) {
+			pr_err("Num of scattered entries is 0\n");
+			goto err;
+		}
+		if (sg_ptr->nents > QSEECOM_MAX_SG_ENTRY) {
+			pr_err("Num of scattered entries");
+			pr_err(" (%d) is greater than max supported %d\n",
+				sg_ptr->nents, QSEECOM_MAX_SG_ENTRY);
+			goto err;
+		}
+			sg = sg_ptr->sgl;
+		if (sg_ptr->nents == 1) {
+			uint32_t *update;
+			update = (uint32_t *) field;
+			if (cleanup)
+				*update = 0;
+			else
+				*update = (uint32_t)sg_dma_address(
+							sg_ptr->sgl);
+				len += (uint32_t)sg->length;
+		} else {
+			struct qseecom_sg_entry *update;
+			int j = 0;
+			update = (struct qseecom_sg_entry *) field;
+			for (j = 0; j < sg_ptr->nents; j++) {
+				if (cleanup) {
+					update->phys_addr = 0;
+					update->len = 0;
+				} else {
+					update->phys_addr = (uint32_t)
+						sg_dma_address(sg);
+					update->len = sg->length;
+				}
+					len += sg->length;
+				update++;
+				sg = sg_next(sg);
+			}
+		}
+		if (cleanup)
+			msm_ion_do_cache_op(qseecom.ion_clnt,
+					ihandle, NULL, len,
+					ION_IOC_INV_CACHES);
+		else
+			msm_ion_do_cache_op(qseecom.ion_clnt,
+					ihandle, NULL, len,
+					ION_IOC_CLEAN_INV_CACHES);
+		/* Deallocate the handle */
+		if (!IS_ERR_OR_NULL(ihandle))
+			ion_free(qseecom.ion_clnt, ihandle);
 	}
 	return ret;
 err:
@@ -1122,13 +1198,13 @@
 	send_cmd_req.resp_buf = req.resp_buf;
 	send_cmd_req.resp_len = req.resp_len;
 
-	ret = __qseecom_update_cmd_buf(&req, false);
+	ret = __qseecom_update_cmd_buf(&req, false, data, false);
 	if (ret)
 		return ret;
 	ret = __qseecom_send_cmd(data, &send_cmd_req);
 	if (ret)
 		return ret;
-	ret = __qseecom_update_cmd_buf(&req, true);
+	ret = __qseecom_update_cmd_buf(&req, true, data, false);
 	if (ret)
 		return ret;
 	pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%p\n",
@@ -1707,6 +1783,23 @@
 	return 0;
 }
 
+
+static int qseecom_send_modfd_resp(struct qseecom_dev_handle *data,
+						void __user *argp)
+{
+	struct qseecom_send_modfd_listener_resp resp;
+
+	if (copy_from_user(&resp, argp, sizeof(resp))) {
+		pr_err("copy_from_user failed");
+		return -EINVAL;
+	}
+	__qseecom_update_cmd_buf(&resp, false, data, true);
+	qseecom.send_resp_flag = 1;
+	wake_up_interruptible(&qseecom.send_resp_wq);
+	return 0;
+}
+
+
 static int qseecom_get_qseos_version(struct qseecom_dev_handle *data,
 						void __user *argp)
 {
@@ -2777,6 +2870,26 @@
 		mutex_unlock(&app_access_lock);
 		break;
 	}
+	case QSEECOM_IOCTL_SEND_MODFD_RESP: {
+		/* Only one client allowed here at a time */
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_send_modfd_resp(data, argp);
+		atomic_dec(&data->ioctl_count);
+		wake_up_all(&data->abort_wq);
+		if (ret)
+			pr_err("failed qseecom_send_mod_resp: %d\n", ret);
+		break;
+	}
+	case QSEECOM_IOCTL_UNPROTECT_BUF: {
+		/* Only one client allowed here at a time */
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_unprotect_buffer(argp);
+		atomic_dec(&data->ioctl_count);
+		wake_up_all(&data->abort_wq);
+		if (ret)
+			pr_err("failed qseecom_unprotect: %d\n", ret);
+		break;
+	}
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index aa71b74..36bdf45 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -617,8 +617,8 @@
 				break;
 
 			if (iovec.addr != channel->waiting->sps.phys_base)
-				pr_err("tspp: buffer mismatch 0x%08x",
-					channel->waiting->sps.phys_base);
+				pr_err("tspp: buffer mismatch %pa",
+					&channel->waiting->sps.phys_base);
 
 			complete = 1;
 			channel->waiting->state = TSPP_BUF_STATE_DATA;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index ca1d7cb..064d5ec 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -59,6 +59,9 @@
  */
 #define MMC_BKOPS_MAX_TIMEOUT	(30 * 1000) /* max time to wait in ms */
 
+/* Flushing a large amount of cached data may take a long time. */
+#define MMC_FLUSH_REQ_TIMEOUT_MS 30000 /* msec */
+
 static struct workqueue_struct *workqueue;
 
 /*
@@ -3323,7 +3326,7 @@
 int mmc_flush_cache(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	int err = 0;
+	int err = 0, rc;
 
 	if (!(host->caps2 & MMC_CAP2_CACHE_CTRL))
 		return err;
@@ -3332,10 +3335,19 @@
 			(card->ext_csd.cache_size > 0) &&
 			(card->ext_csd.cache_ctrl & 1)) {
 		err = mmc_switch_ignore_timeout(card, EXT_CSD_CMD_SET_NORMAL,
-				EXT_CSD_FLUSH_CACHE, 1, 0);
-		if (err)
+						EXT_CSD_FLUSH_CACHE, 1,
+						MMC_FLUSH_REQ_TIMEOUT_MS);
+		if (err == -ETIMEDOUT) {
+			pr_debug("%s: cache flush timeout\n",
+					mmc_hostname(card->host));
+			rc = mmc_interrupt_hpi(card);
+			if (rc)
+				pr_err("%s: mmc_interrupt_hpi() failed (%d)\n",
+						mmc_hostname(host), rc);
+		} else if (err) {
 			pr_err("%s: cache flush error %d\n",
 					mmc_hostname(card->host), err);
+		}
 	}
 
 	return err;
@@ -3351,8 +3363,8 @@
 int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
 {
 	struct mmc_card *card = host->card;
-	unsigned int timeout;
-	int err = 0;
+	unsigned int timeout = card->ext_csd.generic_cmd6_time;
+	int err = 0, rc;
 
 	if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
 			mmc_card_is_removable(host))
@@ -3363,17 +3375,28 @@
 		enable = !!enable;
 
 		if (card->ext_csd.cache_ctrl ^ enable) {
-			timeout = enable ? card->ext_csd.generic_cmd6_time : 0;
+			if (!enable)
+				timeout = MMC_FLUSH_REQ_TIMEOUT_MS;
+
 			err = mmc_switch_ignore_timeout(card,
 					EXT_CSD_CMD_SET_NORMAL,
 					EXT_CSD_CACHE_CTRL, enable, timeout);
-			if (err)
+
+			if (err == -ETIMEDOUT && !enable) {
+				pr_debug("%s:cache disable operation timeout\n",
+						mmc_hostname(card->host));
+				rc = mmc_interrupt_hpi(card);
+				if (rc)
+					pr_err("%s: mmc_interrupt_hpi() failed (%d)\n",
+							mmc_hostname(host), rc);
+			} else if (err) {
 				pr_err("%s: cache %s error %d\n",
 						mmc_hostname(card->host),
 						enable ? "on" : "off",
 						err);
-			else
+			} else {
 				card->ext_csd.cache_ctrl = enable;
+			}
 		}
 	}
 
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 9b9c1ed..90d9826 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -892,9 +892,12 @@
 				MMC_SEND_TUNING_BLOCK_HS200);
 		mmc_host_clk_release(card->host);
 
-		if (err)
-			pr_warn("%s: %s: tuning execution failed %d\n",
-				   mmc_hostname(card->host), __func__, err);
+		if (err) {
+			pr_warn("%s: %s: tuning execution failed %d. Restoring to previous clock %lu\n",
+				   mmc_hostname(card->host), __func__, err,
+				   host->clk_scaling.curr_freq);
+			mmc_set_clock(host, host->clk_scaling.curr_freq);
+		}
 	}
 out:
 	mmc_release_host(host);
@@ -1576,9 +1579,7 @@
 	if (err)
 		goto out;
 
-	if (mmc_can_poweroff_notify(host->card))
-		err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
-	else if (mmc_card_can_sleep(host))
+	if (mmc_card_can_sleep(host))
 		err = mmc_card_sleep(host);
 	else if (!mmc_host_is_spi(host))
 		mmc_deselect_cards(host);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index ddf9a87..a4498d2 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -666,9 +666,12 @@
 				MMC_SEND_TUNING_BLOCK);
 		mmc_host_clk_release(card->host);
 
-		if (err)
-			pr_warn("%s: %s: tuning execution failed %d\n",
-				   mmc_hostname(card->host), __func__, err);
+		if (err) {
+			pr_warn("%s: %s: tuning execution failed %d. Restoring to previous clock %lu\n",
+				   mmc_hostname(card->host), __func__, err,
+				   host->clk_scaling.curr_freq);
+			mmc_set_clock(host, host->clk_scaling.curr_freq);
+		}
 	}
 
 out:
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index b386318..89e3472 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -6065,6 +6065,10 @@
 
 	msmsdcc_msm_bus_cancel_work_and_set_vote(host, &mmc->ios);
 
+	/* Disable SDHCi mode if supported */
+	if (is_sdhci_supported(host))
+		writel_relaxed(0, (host->base + MCI_CORE_HC_MODE));
+
 	/* Apply Hard reset to SDCC to put it in power on default state */
 	msmsdcc_hard_reset(host);
 
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index bcfde57..3668d75 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -197,6 +197,8 @@
 #define MAX_TESTBUS		8
 #define MCI_TESTBUS_ENA		(1 << 3)
 
+#define MCI_CORE_HC_MODE	0x78
+
 #define MCI_SDCC_DEBUG_REG	0x124
 
 #define MCI_IRQENABLE	\
@@ -456,6 +458,7 @@
 #define MSMSDCC_SW_RST_CFG_BROKEN	(1 << 11)
 #define MSMSDCC_DATA_PEND_FOR_CMD53	(1 << 12)
 #define MSMSDCC_TESTBUS_DEBUG		(1 << 13)
+#define MSMSDCC_SDHCI_MODE_SUPPORTED	(1 << 14)
 
 #define set_hw_caps(h, val)		((h)->hw_caps |= val)
 #define is_sps_mode(h)			((h)->hw_caps & MSMSDCC_SPS_BAM_SUP)
@@ -473,6 +476,7 @@
 				((h)->hw_caps & MSMSDCC_SW_RST_CFG_BROKEN)
 #define is_data_pend_for_cmd53(h) ((h)->hw_caps & MSMSDCC_DATA_PEND_FOR_CMD53)
 #define is_testbus_debug(h) ((h)->hw_caps & MSMSDCC_TESTBUS_DEBUG)
+#define is_sdhci_supported(h) ((h)->hw_caps & MSMSDCC_SDHCI_MODE_SUPPORTED)
 
 /* Set controller capabilities based on version */
 static inline void set_default_hw_caps(struct msmsdcc_host *host)
@@ -511,7 +515,8 @@
 				 MSMSDCC_AUTO_CMD21 |
 				 MSMSDCC_DATA_PEND_FOR_CMD53 |
 				 MSMSDCC_TESTBUS_DEBUG |
-				 MSMSDCC_SW_RST_CFG_BROKEN;
+				 MSMSDCC_SW_RST_CFG_BROKEN |
+				 MSMSDCC_SDHCI_MODE_SUPPORTED;
 }
 
 int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 01c75e5..3495f4d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -89,6 +89,9 @@
 #define CORE_TESTBUS_ENA	(1 << 3)
 #define CORE_TESTBUS_SEL2	(1 << 4)
 
+#define CORE_MCI_VERSION	0x050
+#define CORE_VERSION_310	0x10000011
+
 /*
  * Waiting until end of potential AHB access for data:
  * 16 AHB cycles (160ns for 100MHz and 320ns for 50MHz) +
@@ -594,6 +597,7 @@
 int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
 {
 	unsigned long flags;
+	int tuning_seq_cnt = 3;
 	u8 phase, *data_buf, tuned_phases[16], tuned_phase_cnt = 0;
 	const u32 *tuning_block_pattern = tuning_block_64;
 	int size = sizeof(tuning_block_64); /* Tuning pattern size in bytes */
@@ -620,17 +624,18 @@
 	}
 	spin_unlock_irqrestore(&host->lock, flags);
 
-	/* first of all reset the tuning block */
-	rc = msm_init_cm_dll(host);
-	if (rc)
-		goto out;
-
 	data_buf = kmalloc(size, GFP_KERNEL);
 	if (!data_buf) {
 		rc = -ENOMEM;
 		goto out;
 	}
 
+retry:
+	/* first of all reset the tuning block */
+	rc = msm_init_cm_dll(host);
+	if (rc)
+		goto kfree;
+
 	phase = 0;
 	do {
 		struct mmc_command cmd = {0};
@@ -687,10 +692,12 @@
 		pr_debug("%s: %s: finally setting the tuning phase to %d\n",
 				mmc_hostname(mmc), __func__, phase);
 	} else {
+		if (--tuning_seq_cnt)
+			goto retry;
 		/* tuning failed */
 		pr_err("%s: %s: no tuning point found\n",
 			mmc_hostname(mmc), __func__);
-		rc = -EAGAIN;
+		rc = -EIO;
 	}
 
 kfree:
@@ -2166,6 +2173,12 @@
 	struct sdhci_msm_host *msm_host = pltfm_host->priv;
 	u32 value;
 	int ret;
+	u32 version;
+
+	version = readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION);
+	/* Core version 3.1.0 doesn't need this workaround */
+	if (version == CORE_VERSION_310)
+		return;
 
 	value = readl_relaxed(msm_host->core_mem + CORE_MCI_DATA_CTRL);
 	value &= ~(u32)CORE_MCI_DPSM_ENABLE;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2aff67d..578cc14 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -130,6 +130,33 @@
 	pr_info(DRIVER_NAME ": ===========================================\n");
 }
 
+#define MAX_PM_QOS_TIMEOUT_VALUE	100000 /* 100 ms */
+static ssize_t
+show_sdhci_pm_qos_tout(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%d us\n", host->pm_qos_timeout_us);
+}
+
+static ssize_t
+store_sdhci_pm_qos_tout(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	uint32_t value;
+	unsigned long flags;
+
+	if (!kstrtou32(buf, 0, &value)) {
+		spin_lock_irqsave(&host->lock, flags);
+		if (value <= MAX_PM_QOS_TIMEOUT_VALUE)
+			host->pm_qos_timeout_us = value;
+		spin_unlock_irqrestore(&host->lock, flags);
+	}
+	return count;
+}
+
 /*****************************************************************************\
  *                                                                           *
  * Low level functions                                                       *
@@ -1361,15 +1388,55 @@
 {
 	struct sdhci_host *host = mmc_priv(mmc);
 
-	if (host->cpu_dma_latency_us)
-		pm_qos_update_request(&host->pm_qos_req_dma,
+	if (host->cpu_dma_latency_us) {
+		/*
+		 * In performance mode, release QoS vote after a timeout to
+		 * make sure back-to-back requests don't suffer from latencies
+		 * that are involved to wake CPU from low power modes in cases
+		 * where the CPU goes into low power mode as soon as QoS vote is
+		 * released.
+		 */
+		if (host->power_policy == SDHCI_PERFORMANCE_MODE)
+			pm_qos_update_request_timeout(&host->pm_qos_req_dma,
+					host->cpu_dma_latency_us,
+					host->pm_qos_timeout_us);
+		else
+			pm_qos_update_request(&host->pm_qos_req_dma,
 					PM_QOS_DEFAULT_VALUE);
+	}
+
 	if (host->ops->platform_bus_voting)
 		host->ops->platform_bus_voting(host, 0);
 
 	return 0;
 }
 
+static inline void sdhci_update_power_policy(struct sdhci_host *host,
+		enum sdhci_power_policy policy)
+{
+	host->power_policy = policy;
+}
+
+static int sdhci_notify_load(struct mmc_host *mmc, enum mmc_load state)
+{
+	int err = 0;
+	struct sdhci_host *host = mmc_priv(mmc);
+
+	switch (state) {
+	case MMC_LOAD_HIGH:
+		sdhci_update_power_policy(host, SDHCI_PERFORMANCE_MODE);
+		break;
+	case MMC_LOAD_LOW:
+		sdhci_update_power_policy(host, SDHCI_POWER_SAVE_MODE);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
 static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
 			  bool is_first_req)
 {
@@ -1496,9 +1563,11 @@
 	int vdd_bit = -1;
 	u8 ctrl;
 
+	mutex_lock(&host->ios_mutex);
 	if (host->flags & SDHCI_DEVICE_DEAD) {
 		if (host->vmmc && ios->power_mode == MMC_POWER_OFF)
 			mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
+		mutex_unlock(&host->ios_mutex);
 		return;
 	}
 
@@ -1508,6 +1577,7 @@
 	spin_lock_irqsave(&host->lock, flags);
 	if (!host->clock) {
 		spin_unlock_irqrestore(&host->lock, flags);
+		mutex_unlock(&host->ios_mutex);
 		return;
 	}
 	spin_unlock_irqrestore(&host->lock, flags);
@@ -1664,6 +1734,7 @@
 		sdhci_set_clock(host, ios->clock);
 
 	mmiowb();
+	mutex_unlock(&host->ios_mutex);
 }
 
 static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -1932,7 +2003,7 @@
 	if (host->ops->execute_tuning) {
 		spin_unlock(&host->lock);
 		enable_irq(host->irq);
-		host->ops->execute_tuning(host, opcode);
+		err = host->ops->execute_tuning(host, opcode);
 		disable_irq(host->irq);
 		spin_lock(&host->lock);
 		goto out;
@@ -2196,6 +2267,7 @@
 	.disable	= sdhci_disable,
 	.stop_request = sdhci_stop_request,
 	.get_xfer_remain = sdhci_get_xfer_remain,
+	.notify_load	= sdhci_notify_load,
 };
 
 /*****************************************************************************\
@@ -2900,6 +2972,7 @@
 	host->mmc = mmc;
 
 	spin_lock_init(&host->lock);
+	mutex_init(&host->ios_mutex);
 
 	return host;
 }
@@ -3355,9 +3428,22 @@
 
 	mmiowb();
 
-	if (host->cpu_dma_latency_us)
+	if (host->cpu_dma_latency_us) {
+		host->pm_qos_timeout_us = 10000; /* default value */
 		pm_qos_add_request(&host->pm_qos_req_dma,
 				PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
+
+		host->pm_qos_tout.show = show_sdhci_pm_qos_tout;
+		host->pm_qos_tout.store = store_sdhci_pm_qos_tout;
+		sysfs_attr_init(&host->pm_qos_tout.attr);
+		host->pm_qos_tout.attr.name = "pm_qos_unvote_delay";
+		host->pm_qos_tout.attr.mode = S_IRUGO | S_IWUSR;
+		ret = device_create_file(mmc_dev(mmc), &host->pm_qos_tout);
+		if (ret)
+			pr_err("%s: cannot create pm_qos_unvote_delay %d\n",
+					mmc_hostname(mmc), ret);
+	}
+
 	mmc_add_host(mmc);
 
 	pr_info("%s: SDHCI controller on %s [%s] using %s\n",
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index 16012bd..7f02187 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -2229,7 +2229,8 @@
 	return err;
 }
 
-#define BAM_APPS_PIPE_LOCK_GRP 0
+#define BAM_APPS_PIPE_LOCK_GRP0 0
+#define BAM_APPS_PIPE_LOCK_GRP1 1
 /*
  * This function allocates, configures, connects an end point and
  * also registers event notification for an end point. It also allocates
@@ -2273,7 +2274,13 @@
 	}
 
 	sps_config->options = SPS_O_AUTO_ENABLE | SPS_O_DESC_DONE;
-	sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP;
+
+	if (pipe_index == SPS_DATA_PROD_PIPE_INDEX ||
+			pipe_index == SPS_DATA_CONS_PIPE_INDEX)
+		sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP0;
+	else if (pipe_index == SPS_CMD_CONS_PIPE_INDEX)
+		sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP1;
+
 	/*
 	 * Descriptor FIFO is a cyclic FIFO. If SPS_MAX_DESC_NUM descriptors
 	 * are allowed to be submitted before we get any ack for any of them,
diff --git a/drivers/net/ethernet/msm/msm_rmnet_wwan.c b/drivers/net/ethernet/msm/msm_rmnet_wwan.c
index 3e4605f..b857ee3 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_wwan.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_wwan.c
@@ -188,9 +188,14 @@
 		      __func__, skb);
 		netif_wake_queue(dev);
 	}
-	if (a2_mux_is_ch_empty(a2_mux_lcid_by_ch_id[wwan_ptr->ch_id]))
-		ipa_rm_inactivity_timer_release_resource(
-			ipa_rm_resource_by_ch_id[wwan_ptr->ch_id]);
+	if (a2_mux_is_ch_empty(a2_mux_lcid_by_ch_id[wwan_ptr->ch_id])) {
+		if (ipa_emb_ul_pipes_empty())
+			ipa_rm_inactivity_timer_release_resource(
+				ipa_rm_resource_by_ch_id[wwan_ptr->ch_id]);
+		else
+			pr_err("%s: ch=%d empty but UL desc FIFOs not empty\n",
+					__func__, wwan_ptr->ch_id);
+	}
 	spin_unlock_irqrestore(&wwan_ptr->lock, flags);
 }
 
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index 0772592..d1f3748 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -200,8 +200,10 @@
 		dev->get_encap_failure_cnt++;
 		usb_unanchor_urb(dev->rcvurb);
 		usb_autopm_put_interface(dev->intf);
-		dev_err(dev->devicep,
-		"%s: Error submitting Read URB %d\n", __func__, status);
+		if (status != -ENODEV)
+			dev_err(dev->devicep,
+			"%s: Error submitting Read URB %d\n",
+			__func__, status);
 		goto resubmit_int_urb;
 	}
 
@@ -214,7 +216,9 @@
 		status = usb_submit_urb(dev->inturb, GFP_KERNEL);
 		if (status) {
 			usb_unanchor_urb(dev->inturb);
-			dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
+			if (status != -ENODEV)
+				dev_err(dev->devicep,
+				"%s: Error re-submitting Int URB %d\n",
 				__func__, status);
 		}
 	}
@@ -286,8 +290,10 @@
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
 		usb_unanchor_urb(urb);
-		dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
-		__func__, status);
+		if (status != -ENODEV)
+			dev_err(dev->devicep,
+			"%s: Error re-submitting Int URB %d\n",
+			__func__, status);
 	}
 
 	return;
@@ -383,7 +389,9 @@
 		status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
 		if (status) {
 			usb_unanchor_urb(dev->inturb);
-			dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
+			if (status != -ENODEV)
+				dev_err(dev->devicep,
+				"%s: Error re-submitting Int URB %d\n",
 				__func__, status);
 		}
 	}
@@ -397,8 +405,9 @@
 	retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
 	if (retval < 0) {
 		usb_unanchor_urb(dev->inturb);
-		dev_err(dev->devicep, "%s Intr submit %d\n", __func__,
-				retval);
+		if (retval != -ENODEV)
+			dev_err(dev->devicep,
+			"%s Intr submit %d\n", __func__, retval);
 	}
 
 	return retval;
@@ -527,7 +536,9 @@
 	dev->snd_encap_cmd_cnt++;
 	result = usb_submit_urb(sndurb, GFP_KERNEL);
 	if (result < 0) {
-		dev_err(dev->devicep, "%s: Submit URB error %d\n",
+		if (result != -ENODEV)
+			dev_err(dev->devicep,
+			"%s: Submit URB error %d\n",
 			__func__, result);
 		dev->snd_encap_cmd_cnt--;
 		usb_autopm_put_interface(dev->intf);
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 5e22c35..657fc2f 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -115,6 +115,9 @@
 #define MSM_PRONTO_SAW2_BASE			0xfb219000
 #define PRONTO_SAW2_SPM_STS_OFFSET		0x0c
 
+#define MSM_PRONTO_PLL_BASE				0xfb21b1c0
+#define PRONTO_PLL_STATUS_OFFSET		0x1c
+
 #define WCNSS_DEF_WLAN_RX_BUFF_COUNT		1024
 
 #define WCNSS_CTRL_CHANNEL			"WCNSS_CTRL"
@@ -292,6 +295,7 @@
 	void __iomem *pronto_a2xb_base;
 	void __iomem *pronto_ccpu_base;
 	void __iomem *pronto_saw2_base;
+	void __iomem *pronto_pll_base;
 	void __iomem *fiq_reg;
 	int	ssr_boot;
 	int	nv_downloaded;
@@ -487,6 +491,10 @@
 	reg = readl_relaxed(reg_addr);
 	pr_info_ratelimited("%s: PRONTO_SAW2_SPM_STS %08x\n", __func__, reg);
 
+	reg_addr = penv->pronto_pll_base + PRONTO_PLL_STATUS_OFFSET;
+	reg = readl_relaxed(reg_addr);
+	pr_info_ratelimited("%s: PRONTO_PLL_STATUS %08x\n", __func__, reg);
+
 	tst_addr = penv->pronto_a2xb_base + A2XB_TSTBUS_OFFSET;
 	tst_ctrl_addr = penv->pronto_a2xb_base + A2XB_TSTBUS_CTRL_OFFSET;
 
@@ -1699,6 +1707,15 @@
 			ret = -ENOMEM;
 			goto fail_ioremap5;
 		}
+		penv->pronto_pll_base = ioremap_nocache(MSM_PRONTO_PLL_BASE,
+				SZ_64);
+		if (!penv->pronto_pll_base) {
+			pr_err("%s: ioremap wcnss physical(pll) failed\n",
+					__func__);
+			ret = -ENOMEM;
+			goto fail_ioremap6;
+		}
+
 	}
 
 	/* trigger initialization of the WCNSS */
@@ -1715,6 +1732,9 @@
 fail_pil:
 	if (penv->riva_ccu_base)
 		iounmap(penv->riva_ccu_base);
+	if (penv->pronto_pll_base)
+		iounmap(penv->pronto_pll_base);
+fail_ioremap6:
 	if (penv->pronto_saw2_base)
 		iounmap(penv->pronto_saw2_base);
 fail_ioremap5:
diff --git a/drivers/nfc/nfc-nci.c b/drivers/nfc/nfc-nci.c
index 9e9a4ea..e832716 100644
--- a/drivers/nfc/nfc-nci.c
+++ b/drivers/nfc/nfc-nci.c
@@ -27,7 +27,6 @@
 #include <linux/regulator/consumer.h>
 #include "nfc-nci.h"
 
-
 struct qca199x_platform_data {
 	unsigned int irq_gpio;
 	unsigned int dis_gpio;
@@ -62,6 +61,7 @@
 	bool irq_enabled;
 	spinlock_t irq_enabled_lock;
 	unsigned int count_irq;
+	enum	nfcc_state	state;
 };
 
 /*
@@ -69,6 +69,12 @@
  * IOCTL NFC_KERNEL_LOGGING_MODE.
  */
 static int logging_level;
+/*
+ * FTM-RAW-I2C RD/WR MODE
+ */
+static struct	devicemode	device_mode;
+static int	ftm_raw_write_mode;
+static int	ftm_werr_code;
 
 static void qca199x_init_stat(struct qca199x_dev *qca199x_dev)
 {
@@ -104,7 +110,6 @@
 	struct qca199x_dev *qca199x_dev = dev_id;
 	unsigned long flags;
 
-
 	spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
 	qca199x_dev->count_irq++;
 	spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
@@ -119,7 +124,6 @@
 	unsigned int mask = 0;
 	unsigned long flags;
 
-
 	poll_wait(filp, &qca199x_dev->read_wq, wait);
 
 	spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
@@ -129,17 +133,33 @@
 	}
 	spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
 
-
 	return mask;
 }
 
+/*
+ * ONLY for FTM-RAW-I2C Mode
+ * Required to instigate a read, which comes from DT layer. This means we need
+ * to spoof an interrupt and send a wake up event.
+ */
+void ftm_raw_trigger_read(struct qca199x_dev *qca199x_dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
+	qca199x_dev->count_irq++;
+	spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
+	wake_up(&qca199x_dev->read_wq);
+}
+
 static ssize_t nfc_read(struct file *filp, char __user *buf,
 					size_t count, loff_t *offset)
 {
 	struct qca199x_dev *qca199x_dev = filp->private_data;
-	unsigned char tmp[MAX_BUFFER_SIZE];
+	unsigned char tmp[MAX_BUFFER_SIZE], rd_byte;
 	unsigned char len[PAYLOAD_HEADER_LENGTH];
 	int total, length, ret;
+	int ftm_rerr_code;
+	enum ehandler_mode dmode;
 
 	total = 0;
 	length = 0;
@@ -147,6 +167,36 @@
 		count = MAX_BUFFER_SIZE;
 
 	mutex_lock(&qca199x_dev->read_mutex);
+	dmode = device_mode.handle_flavour;
+	/* FTM-RAW-I2C RD/WR MODE - Special Case */
+	if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
+		(dmode == SOLICITED_FTM_RAW_MODE)) {
+		/* READ */
+		if ((ftm_raw_write_mode == 0) && (ftm_werr_code == 0)) {
+			ftm_rerr_code = i2c_master_recv(qca199x_dev->client,
+						&rd_byte, 1);
+			if (ftm_rerr_code == 0x1)
+				ftm_rerr_code = 0;
+			tmp[0] = (unsigned char)ftm_rerr_code;
+			tmp[1] = rd_byte;
+			total  = 2;
+			ret = copy_to_user(buf, tmp, total);
+		}
+		/* WRITE */
+		else if ((ftm_raw_write_mode == 1) || (ftm_werr_code != 0)) {
+			tmp[0] = (unsigned char)ftm_werr_code;
+			total = 1;
+			ret = copy_to_user(buf, tmp, total);
+		} else {
+			/* Invalid case */
+			total = 0;
+			ret = copy_to_user(buf, tmp, total);
+		}
+		mutex_unlock(&qca199x_dev->read_mutex);
+		goto done;
+	}
+
+	/* NORMAL NCI Behaviour */
 	/* Read the header */
 	ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
 	if (ret != PAYLOAD_HEADER_LENGTH)
@@ -174,7 +224,7 @@
 err:
 	if (ret < 0)
 		mutex_unlock(&qca199x_dev->read_mutex);
-
+done:
 	return total;
 }
 
@@ -183,7 +233,8 @@
 {
 	struct qca199x_dev *qca199x_dev = filp->private_data;
 	char tmp[MAX_BUFFER_SIZE];
-	int ret;
+	int ret = 0;
+	enum ehandler_mode dmode;
 
 	if (count > MAX_BUFFER_SIZE) {
 		dev_err(&qca199x_dev->client->dev, "out of memory\n");
@@ -195,10 +246,39 @@
 		return -EFAULT;
 	}
 	mutex_lock(&qca199x_dev->read_mutex);
-	ret = i2c_master_send(qca199x_dev->client, tmp, count);
+	dmode = device_mode.handle_flavour;
+	/* FTM-DIRECT-I2C RD/WR MODE */
+	/* This is a special FTM-i2c mode case,where tester is not using NCI */
+	if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
+		(dmode == SOLICITED_FTM_RAW_MODE)) {
+		/* Read From Register */
+		if (count == 1) {
+			ftm_raw_write_mode = 0;
+			ret = i2c_master_send(qca199x_dev->client, tmp, count);
+			if (ret == 1)
+				ftm_werr_code = 0;
+			else
+				ftm_werr_code = ret;
+			ftm_raw_trigger_read(qca199x_dev);
+		}
+		/* Write to Register */
+		if (count == 2) {
+			ftm_raw_write_mode = 1;
+			ret = i2c_master_send(qca199x_dev->client, tmp, count);
+			if (ret == 2)
+				ftm_werr_code = 0;
+			else
+				ftm_werr_code = ret;
+			ftm_raw_trigger_read(qca199x_dev);
+		}
+	} else {
+		/* NORMAL NCI behaviour - NB :
+		We can be in FTM mode here also */
+		ret = i2c_master_send(qca199x_dev->client, tmp, count);
+	}
 	if (ret != count) {
 		dev_err(&qca199x_dev->client->dev,
-			"NFC: failed to write %d\n", ret);
+		"NFC: failed to write %d\n", ret);
 		ret = -EIO;
 	}
 	mutex_unlock(&qca199x_dev->read_mutex);
@@ -225,7 +305,7 @@
 /*
  * Wake/Sleep Mode
  */
-int nfcc_wake(int level, struct nfc_info *info)
+int nfcc_wake(int level, struct file *filp)
 {
 	int r = 0;
 	unsigned char raw_nci_sleep[] = {0x2F, 0x03, 0x00};
@@ -233,32 +313,32 @@
 	unsigned char raw_nci_wake[]  = {0x10, 0x0F};
 	unsigned short	slave_addr	=	0xE;
 	unsigned short	curr_addr;
+	struct qca199x_dev *qca199x_dev = filp->private_data;
 
-	struct i2c_client *client = info->i2c_dev;
-
-	dev_dbg(&client->dev, "nfcc_wake: %s: info: %p\n", __func__, info);
+	dev_dbg(&qca199x_dev->client->dev, "nfcc_wake: %s: info: %p\n",
+			__func__, qca199x_dev);
 
 	if (level == NFCC_SLEEP) {
-		r = nfc_i2c_write(client, &raw_nci_sleep[0],
+		r = i2c_master_send(qca199x_dev->client, &raw_nci_sleep[0],
 						sizeof(raw_nci_sleep));
 
+		r = sizeof(raw_nci_sleep);
 		if (r != sizeof(raw_nci_sleep))
 			return -EMSGSIZE;
-		info->state = NFCC_STATE_NORMAL_SLEEP;
+		qca199x_dev->state = NFCC_STATE_NORMAL_SLEEP;
 	} else {
-		curr_addr = client->addr;
-		client->addr = slave_addr;
-		r = nfc_i2c_write(client, &raw_nci_wake[0],
+		curr_addr = qca199x_dev->client->addr;
+		qca199x_dev->client->addr = slave_addr;
+		r = nfc_i2c_write(qca199x_dev->client, &raw_nci_wake[0],
 						sizeof(raw_nci_wake));
 		/* Restore original NFCC slave I2C address */
-		client->addr = curr_addr;
-
-		if (r != sizeof(raw_nci_sleep))
+		qca199x_dev->client->addr = curr_addr;
+		r = sizeof(raw_nci_wake);
+		if (r != sizeof(raw_nci_wake))
 			return -EMSGSIZE;
-
-		info->state = NFCC_STATE_NORMAL_WAKE;
+		qca199x_dev->state = NFCC_STATE_NORMAL_WAKE;
 	}
-	msleep(20);
+
 	return r;
 }
 
@@ -284,41 +364,35 @@
 {
 	int r = 0;
 	struct qca199x_dev *qca199x_dev = filp->private_data;
-	struct nfc_info *info = container_of(filp->private_data,
-					       struct nfc_info, miscdev);
-
-	struct i2c_client *client = info->i2c_dev;
-
-	r = gpio_request(qca199x_dev->dis_gpio, "nfc_reset_gpio");
-	if (r) {
-		dev_err(&client->dev, "unable to request gpio [%d]\n",
-				qca199x_dev->dis_gpio);
-			goto err_req;
-	}
-	gpio_set_value(qca199x_dev->dis_gpio, 0);
-	r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
-	if (r) {
-		dev_err(&client->dev, "unable to set direction for gpio [%d]\n",
-				qca199x_dev->irq_gpio);
-			goto err_req;
-	}
 
 	if (arg == 0) {
 		gpio_set_value(qca199x_dev->dis_gpio, 0);
-		msleep(20);
+		r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
+		if (r) {
+			dev_err(&qca199x_dev->client->dev,
+					"unable to set direction for gpio [%d]\n",
+					qca199x_dev->dis_gpio);
+			goto err_req;
+		}
+		gpio_set_value(qca199x_dev->dis_gpio, 0);
 	} else if (arg == 1) {
+		gpio_set_value(qca199x_dev->dis_gpio, 0);
+		r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
+		if (r) {
+			dev_err(&qca199x_dev->client->dev,
+					"unable to set direction for gpio [%d]\n",
+					qca199x_dev->dis_gpio);
+			goto err_req;
+		}
 		gpio_set_value(qca199x_dev->dis_gpio, 1);
-		msleep(20);
 	} else if (arg == 2) {
 		msleep(20);
 	} else if (arg == 3) {
 		msleep(20);
 	} else if (arg == 4) {
-		nfcc_wake(NFCC_WAKE, info);
-		msleep(20);
+		nfcc_wake(NFCC_WAKE, filp);
 	} else if (arg == 5) {
-		nfcc_wake(NFCC_SLEEP, info);
-		msleep(20);
+		nfcc_wake(NFCC_SLEEP, filp);
 	} else {
 		r = -ENOIOCTLCMD;
 	}
@@ -327,6 +401,63 @@
 	return r;
 }
 
+
+/*
+ * Inside nfc_ioctl_nfcc_mode
+ *
+ * @brief   nfc_ioctl_nfcc_mode
+ *
+ * (arg = 0) ; NORMAL_MODE - Standard mode, unsolicited read behaviour
+ * (arg = 1) ; SOLICITED_MODE - As above but reads are solicited from User Land
+ * (arg = 2) ; UNSOLICITED_FTM_RAW MODE - NORMAL_MODE but messages from FTM and
+ *             not NCI Host.
+ * (arg = 2) ; SOLICITED_FTM_RAW_MODE - As SOLICITED_MODE but messages from FTM
+ *             and not NCI Host.
+ *
+ *
+ *
+ */
+int nfc_ioctl_nfcc_mode(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	int retval = 0;
+
+	static unsigned short nci_addr;
+	struct qca199x_dev *qca199x_dev = filp->private_data;
+	struct qca199x_platform_data *platform_data;
+
+	platform_data = qca199x_dev->client->dev.platform_data;
+
+	if (arg == 0) {
+		device_mode.handle_flavour = UNSOLICITED_MODE;
+		qca199x_dev->client->addr = NCI_I2C_SLAVE;
+		/* enable interrupts again */
+		qca199x_enable_irq(qca199x_dev);
+	} else if (arg == 1) {
+		device_mode.handle_flavour = SOLICITED_MODE;
+		qca199x_dev->client->addr = qca199x_dev->client->addr;
+		/* enable interrupts again */
+		qca199x_enable_irq(qca199x_dev);
+	} else if (arg == 2) {
+		device_mode.handle_flavour = UNSOLICITED_FTM_RAW_MODE;
+		nci_addr = qca199x_dev->client->addr;
+		/* replace with new client slave address*/
+		qca199x_dev->client->addr = 0xE;
+		/* We also need to disable interrupts */
+		qca199x_disable_irq(qca199x_dev);
+	} else if (arg == 3) {
+		device_mode.handle_flavour = SOLICITED_FTM_RAW_MODE;
+		nci_addr = qca199x_dev->client->addr;
+		/* replace with new client slave address*/
+		qca199x_dev->client->addr = 0xE;
+		/* We also need to disable interrupts */
+		qca199x_disable_irq(qca199x_dev);
+	} else {
+		device_mode.handle_flavour = UNSOLICITED_MODE;
+		qca199x_dev->client->addr = NCI_I2C_SLAVE;
+	}
+	return retval;
+}
+
 /*
  * Inside nfc_ioctl_kernel_logging
  *
@@ -371,6 +502,7 @@
 		nfc_ioctl_power_states(pfile, cmd, arg);
 		break;
 	case NFCC_MODE:
+		nfc_ioctl_nfcc_mode(pfile, cmd, arg);
 		break;
 	case NFC_KERNEL_LOGGING_MODE:
 		nfc_ioctl_kernel_logging(arg, pfile);
@@ -447,66 +579,75 @@
 	unsigned char raw_s73[]			= {0x73, 0x02};
 	unsigned char raw_slave1_rd		= {0x0};
 	unsigned char raw_1P8_PAD_CFG_CLK_REQ[]	= {0xA5, 0x1};
-	unsigned char buf[4];
+	unsigned char raw_1P8_PAD_CFG_PWR_REQ[]	= {0xA7, 0x1};
+	unsigned char buf = 0;
 
-	/* Set I2C address to enable configuration of QCA1990 */
 	client->addr = curr_addr;
-	RAW(s73, 0x02);
+	r = i2c_master_send(client, &buf, 1);
+	buf = 0;
+	r = i2c_master_recv(client, &buf, 1);
+	if (0x10 != (0x10 & buf)) {
+		RAW(s73, 0x02);
 
-	r = nfc_i2c_write(client, &raw_s73[0], sizeof(raw_s73));
-	usleep(1000);
-	RAW(1p8_CONTROL_011, XTAL_CLOCK | 0x01);
+		r = nfc_i2c_write(client, &raw_s73[0], sizeof(raw_s73));
+		usleep(1000);
+		RAW(1p8_CONTROL_011, XTAL_CLOCK | 0x01);
 
-	r = nfc_i2c_write(client, &raw_1p8_CONTROL_011[0],
+		r = nfc_i2c_write(client, &raw_1p8_CONTROL_011[0],
 						sizeof(raw_1p8_CONTROL_011));
-	usleep(1000);
-	RAW(1P8_CONTROL_010, (0x8));
-	r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
-					sizeof(raw_1P8_CONTROL_010));
-
-	usleep(10000);  /* 10ms wait */
-	RAW(1P8_CONTROL_010, (0xC));
-	r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
-					sizeof(raw_1P8_CONTROL_010));
-	usleep(100);  /* 100uS wait */
-	RAW(1P8_X0_0B0, (FREQ_SEL_19));
-	r = nfc_i2c_write(client, &raw_1P8_X0_0B0[0], sizeof(raw_1P8_X0_0B0));
-	usleep(1000);
-
-	/* PWR_EN = 1 */
-	RAW(1P8_CONTROL_010, (0xd));
-	r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
+		usleep(1000);
+		RAW(1P8_CONTROL_010, (0x8));
+		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
 						sizeof(raw_1P8_CONTROL_010));
-	usleep(20000);  /* 20ms wait */
-	/* LS_EN = 1 */
-	RAW(1P8_CONTROL_010, 0xF);
-	r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
-						sizeof(raw_1P8_CONTROL_010));
-	usleep(20000);  /* 20ms wait */
 
-	/* Enable the PMIC clock */
-	RAW(1P8_PAD_CFG_CLK_REQ, (0x1));
-	r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_CLK_REQ[0],
+		usleep(10000);  /* 10ms wait */
+		RAW(1P8_CONTROL_010, (0xC));
+		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
+					sizeof(raw_1P8_CONTROL_010));
+		usleep(100);  /* 100uS wait */
+		RAW(1P8_X0_0B0, (FREQ_SEL_19));
+		r = nfc_i2c_write(client, &raw_1P8_X0_0B0[0],
+						sizeof(raw_1P8_X0_0B0));
+		usleep(1000);
+
+		/* PWR_EN = 1 */
+		RAW(1P8_CONTROL_010, (0xd));
+		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
+						sizeof(raw_1P8_CONTROL_010));
+		usleep(20000);  /* 20ms wait */
+		/* LS_EN = 1 */
+		RAW(1P8_CONTROL_010, 0xF);
+		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
+						sizeof(raw_1P8_CONTROL_010));
+		usleep(20000);  /* 20ms wait */
+
+		/* Enable the PMIC clock */
+		RAW(1P8_PAD_CFG_CLK_REQ, (0x1));
+		r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_CLK_REQ[0],
 					  sizeof(raw_1P8_PAD_CFG_CLK_REQ));
-	usleep(1000);
+		usleep(1000);
 
-	RAW(slave2, 0x10);
-	r = nfc_i2c_write(client, &raw_slave2[0], sizeof(raw_slave2));
-	usleep(1000);
-	{
-		r = i2c_master_send(client, buf, 1);
-		memset(buf, 0xAA, sizeof(buf));
-		r = i2c_master_recv(client, buf, 1);
+		RAW(1P8_PAD_CFG_PWR_REQ, (0x1));
+		r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_PWR_REQ[0],
+					  sizeof(raw_1P8_PAD_CFG_PWR_REQ));
+		usleep(1000);
+
+		RAW(slave2, 0x10);
+		r = nfc_i2c_write(client, &raw_slave2[0], sizeof(raw_slave2));
+		usleep(1000);
+
+		RAW(slave1, NCI_I2C_SLAVE);
+		r = nfc_i2c_write(client, &raw_slave1[0], sizeof(raw_slave1));
+		usleep(1000);
+
+		/* QCA199x NFCC CPU should now boot... */
+		r = i2c_master_recv(client, &raw_slave1_rd, 1);
+		/* Talk on NCI slave address NCI_I2C_SLAVE 0x2C*/
+		client->addr = NCI_I2C_SLAVE;
+		r = 0;
+	} else {
+		r = 1;
 	}
-	RAW(slave1, NCI_I2C_SLAVE);
-	r = nfc_i2c_write(client, &raw_slave1[0], sizeof(raw_slave1));
-	usleep(1000);
-
-	/* QCA199x NFCC CPU should now boot... */
-	r = i2c_master_recv(client, &raw_slave1_rd, 1);
-	/* Talk on NCI slave address NCI_I2C_SLAVE 0x2C*/
-	client->addr = NCI_I2C_SLAVE;
-
 	return r;
 }
 
@@ -623,6 +764,9 @@
 		dev_err(&client->dev, "dis gpio not provided\n");
 		goto err_irq;
 	}
+	gpio_set_value(qca199x_dev->dis_gpio, 1);
+	msleep(20);
+	gpio_set_value(qca199x_dev->dis_gpio, 0);
 
 	nfc_clk  = clk_get(&client->dev, "ref_clk");
 
@@ -640,7 +784,7 @@
 		r = gpio_request(platform_data->ven_gpio, "nfc_ven_gpio");
 		if (r) {
 			dev_err(&client->dev, "unable to request gpio [%d]\n",
-						platform_data->irq_gpio);
+						platform_data->ven_gpio);
 			goto err_ven_gpio;
 		}
 		r = gpio_direction_input(platform_data->ven_gpio);
@@ -648,7 +792,7 @@
 
 			dev_err(&client->dev,
 			"unable to set direction for gpio [%d]\n",
-						platform_data->irq_gpio);
+						platform_data->ven_gpio);
 			goto err_ven_gpio;
 		}
 
@@ -681,7 +825,12 @@
 	/* request irq.  The irq is set whenever the chip has data available
 	* for reading.  It is cleared when all data has been read.
 	*/
-	nfcc_initialise(client, platform_data->reg);
+	device_mode.handle_flavour = UNSOLICITED_MODE;
+	r = nfcc_initialise(client, platform_data->reg);
+	if (r) {
+		dev_err(&client->dev, "nfc-nci probe: request nfcc initialise failed\n");
+		goto err_nfcc_init_failed;
+	}
 
 	qca199x_dev->irq_enabled = true;
 	r = request_irq(client->irq, qca199x_dev_irq_handler,
@@ -697,6 +846,7 @@
 		 __func__);
 	return 0;
 
+err_nfcc_init_failed:
 err_request_irq_failed:
 	misc_deregister(&qca199x_dev->qca199x_device);
 err_misc_register:
diff --git a/drivers/nfc/nfc-nci.h b/drivers/nfc/nfc-nci.h
index 4398df7..c3cabc2 100644
--- a/drivers/nfc/nfc-nci.h
+++ b/drivers/nfc/nfc-nci.h
@@ -30,8 +30,10 @@
 };
 
 enum ehandler_mode {
-	UNSOLICITED_READ_MODE = 0,
-	SOLICITED_READ_MODE
+	UNSOLICITED_MODE = 0,
+	SOLICITED_MODE,
+	UNSOLICITED_FTM_RAW_MODE,
+	SOLICITED_FTM_RAW_MODE
 };
 
 enum ekernel_logging_mode {
@@ -43,9 +45,9 @@
 	LEVEL_5
 };
 
-struct DeviceMode {
+struct devicemode {
 	enum ehandler_mode	handle_flavour;
-} tDeviceMode;
+} tdevicemode;
 
 #define NFC_DRIVER_NAME			"nfc-nci"
 #define NFC_I2C_DRIVER_NAME		"NCI NFC I2C Interface",
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index acd42ae3..a3f8ec9 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -113,4 +113,9 @@
 	help
 	  OpenFirmware CoreSight accessors
 
+config OF_BATTERYDATA
+	def_bool y
+	help
+	  OpenFirmware BatteryData accessors
+
 endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 61a99f2..8b52306 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -16,3 +16,4 @@
 obj-$(CONFIG_OF_MTD)	+= of_mtd.o
 obj-$(CONFIG_OF_SLIMBUS)	+= of_slimbus.o
 obj-$(CONFIG_OF_CORESIGHT) += of_coresight.o
+obj-$(CONFIG_OF_BATTERYDATA)	+= of_batterydata.o
diff --git a/drivers/of/of_batterydata.c b/drivers/of/of_batterydata.c
new file mode 100644
index 0000000..c2585a7
--- /dev/null
+++ b/drivers/of/of_batterydata.c
@@ -0,0 +1,265 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/batterydata-lib.h>
+
+static int of_batterydata_read_lut(const struct device_node *np,
+			int max_cols, int max_rows, int *ncols, int *nrows,
+			int *col_legend_data, int *row_legend_data,
+			int *lut_data)
+{
+	struct property *prop;
+	const __be32 *data;
+	int cols, rows, size, i, j, *out_values;
+
+	prop = of_find_property(np, "qcom,lut-col-legend", NULL);
+	if (!prop) {
+		pr_err("%s: No col legend found\n", np->name);
+		return -EINVAL;
+	} else if (!prop->value) {
+		pr_err("%s: No col legend value found, np->name\n", np->name);
+		return -ENODATA;
+	} else if (prop->length > max_cols * sizeof(int)) {
+		pr_err("%s: Too many columns\n", np->name);
+		return -EINVAL;
+	}
+
+	cols = prop->length/sizeof(int);
+	*ncols = cols;
+	data = prop->value;
+	for (i = 0; i < cols; i++)
+		*col_legend_data++ = be32_to_cpup(data++);
+
+	prop = of_find_property(np, "qcom,lut-row-legend", NULL);
+	if (!prop || row_legend_data == NULL) {
+		/* single row lut */
+		rows = 1;
+	} else if (!prop->value) {
+		pr_err("%s: No row legend value found\n", np->name);
+		return -ENODATA;
+	} else if (prop->length > max_rows * sizeof(int)) {
+		pr_err("%s: Too many rows\n", np->name);
+		return -EINVAL;
+	} else {
+		rows = prop->length/sizeof(int);
+		*nrows = rows;
+		data = prop->value;
+		for (i = 0; i < rows; i++)
+			*row_legend_data++ = be32_to_cpup(data++);
+	}
+
+	prop = of_find_property(np, "qcom,lut-data", NULL);
+	data = prop->value;
+	size = prop->length/sizeof(int);
+	if (!prop || size != cols * rows) {
+		pr_err("%s: data size mismatch, %dx%d != %d\n",
+				np->name, cols, rows, size);
+		return -EINVAL;
+	}
+	for (i = 0; i < rows; i++) {
+		out_values = lut_data + (max_cols * i);
+		for (j = 0; j < cols; j++) {
+			*out_values++ = be32_to_cpup(data++);
+			pr_debug("Value = %d\n", *(out_values-1));
+		}
+	}
+
+	return 0;
+}
+
+static int of_batterydata_read_sf_lut(struct device_node *data_node,
+				const char *name, struct sf_lut *lut)
+{
+	struct device_node *node = of_find_node_by_name(data_node, name);
+	int rc;
+
+	if (!lut) {
+		pr_debug("No lut provided, skipping\n");
+		return 0;
+	} else if (!node) {
+		pr_err("Couldn't find %s node.\n", name);
+		return -EINVAL;
+	}
+
+	rc = of_batterydata_read_lut(node, PC_CC_COLS, PC_CC_ROWS,
+			&lut->cols, &lut->rows, lut->row_entries,
+			lut->percent, *lut->sf);
+	if (rc) {
+		pr_err("Failed to read %s node.\n", name);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int of_batterydata_read_pc_temp_ocv_lut(struct device_node *data_node,
+				const char *name, struct pc_temp_ocv_lut *lut)
+{
+	struct device_node *node = of_find_node_by_name(data_node, name);
+	int rc;
+
+	if (!lut) {
+		pr_debug("No lut provided, skipping\n");
+		return 0;
+	} else if (!node) {
+		pr_err("Couldn't find %s node.\n", name);
+		return -EINVAL;
+	}
+	rc = of_batterydata_read_lut(node, PC_TEMP_COLS, PC_TEMP_ROWS,
+			&lut->cols, &lut->rows, lut->temp, lut->percent,
+			*lut->ocv);
+	if (rc) {
+		pr_err("Failed to read %s node.\n", name);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int of_batterydata_read_single_row_lut(struct device_node *data_node,
+				const char *name, struct single_row_lut *lut)
+{
+	struct device_node *node = of_find_node_by_name(data_node, name);
+	int rc;
+
+	if (!lut) {
+		pr_debug("No lut provided, skipping\n");
+		return 0;
+	} else if (!node) {
+		pr_err("Couldn't find %s node.\n", name);
+		return -EINVAL;
+	}
+
+	rc = of_batterydata_read_lut(node, MAX_SINGLE_LUT_COLS, 1,
+			&lut->cols, NULL, lut->x, NULL, lut->y);
+	if (rc) {
+		pr_err("Failed to read %s node.\n", name);
+		return rc;
+	}
+
+	return 0;
+}
+
+#define OF_PROP_READ(property, qpnp_dt_property, node, rc, optional)	\
+do {									\
+	rc = of_property_read_u32(node, "qcom," qpnp_dt_property,	\
+					&property);			\
+									\
+	if ((rc == -EINVAL) && optional) {				\
+		property = -EINVAL;					\
+		rc = 0;							\
+	} else if (rc) {						\
+		pr_err("Error reading " #qpnp_dt_property		\
+				" property rc = %d\n", rc);		\
+		return rc;						\
+	}								\
+} while (0)
+
+static int of_batterydata_load_battery_data(struct device_node *node,
+				struct bms_battery_data *batt_data)
+{
+	int rc;
+
+	rc = of_batterydata_read_single_row_lut(node, "qcom,fcc-temp-lut",
+			batt_data->fcc_temp_lut);
+	if (rc)
+		return rc;
+
+	rc = of_batterydata_read_pc_temp_ocv_lut(node,
+			"qcom,pc-temp-ocv-lut",
+			batt_data->pc_temp_ocv_lut);
+	if (rc)
+		return rc;
+
+	rc = of_batterydata_read_sf_lut(node, "qcom,rbatt-sf-lut",
+			batt_data->rbatt_sf_lut);
+	if (rc)
+		return rc;
+
+	OF_PROP_READ(batt_data->fcc, "fcc-mah", node, rc, false);
+	OF_PROP_READ(batt_data->default_rbatt_mohm,
+			"default-rbatt-mohm", node, rc, false);
+	OF_PROP_READ(batt_data->rbatt_capacitive_mohm,
+			"rbatt-capacitive-mohm", node, rc, false);
+	OF_PROP_READ(batt_data->batt_id_kohm, "batt-id-kohm", node, rc, false);
+	OF_PROP_READ(batt_data->flat_ocv_threshold_uv,
+			"flat-ocv-threshold", node, rc, true);
+	OF_PROP_READ(batt_data->max_voltage_uv,
+			"max-voltage-uv", node, rc, true);
+	OF_PROP_READ(batt_data->cutoff_uv, "v-cutoff-uv", node, rc, true);
+	OF_PROP_READ(batt_data->iterm_ua, "chg-term-ua", node, rc, true);
+
+	return rc;
+}
+
+static int64_t of_batterydata_convert_battery_id_kohm(int batt_id_uv,
+				int rpull_up, int vadc_vdd)
+{
+	int64_t resistor_value_kohm, denom;
+
+	/* calculate the battery id resistance reported via ADC */
+	denom = div64_s64(vadc_vdd * 1000000LL, batt_id_uv) - 1000000LL;
+
+	resistor_value_kohm = div64_s64(rpull_up * 1000000LL + denom/2, denom);
+
+	pr_debug("batt id voltage = %d, resistor value = %lld\n",
+			batt_id_uv, resistor_value_kohm);
+
+	return resistor_value_kohm;
+}
+
+int of_batterydata_read_data(struct device_node *batterydata_container_node,
+				struct bms_battery_data *batt_data,
+				int batt_id_uv)
+{
+	struct device_node *node, *best_node;
+	uint32_t id_kohm;
+	int delta, best_delta, batt_id_kohm, rpull_up_kohm, vadc_vdd_uv, rc = 0;
+
+	node = batterydata_container_node;
+	OF_PROP_READ(rpull_up_kohm, "rpull-up-kohm", node, rc, false);
+	OF_PROP_READ(vadc_vdd_uv, "vref-batt-therm", node, rc, false);
+
+	batt_id_kohm = of_batterydata_convert_battery_id_kohm(batt_id_uv,
+					rpull_up_kohm, vadc_vdd_uv);
+	best_node = NULL;
+	best_delta = 0;
+
+	/*
+	 * Find the battery data with a battery id resistor closest to this one
+	 */
+	for_each_child_of_node(batterydata_container_node, node) {
+		rc = of_property_read_u32(node, "qcom,batt-id-kohm", &id_kohm);
+		if (rc)
+			continue;
+		delta = abs((int)id_kohm - batt_id_kohm);
+		if (delta < best_delta || !best_node) {
+			best_node = node;
+			best_delta = delta;
+		}
+	}
+
+	if (best_node == NULL) {
+		pr_err("No battery data found\n");
+		return -ENODATA;
+	}
+
+	return of_batterydata_load_battery_data(best_node, batt_data);
+}
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/msm/ipa/ipa_bridge.c b/drivers/platform/msm/ipa/ipa_bridge.c
index f9401f0..f626397 100644
--- a/drivers/platform/msm/ipa/ipa_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_bridge.c
@@ -575,3 +575,34 @@
 	return 0;
 }
 EXPORT_SYMBOL(ipa_bridge_teardown);
+
+bool ipa_emb_ul_pipes_empty(void)
+{
+	struct sps_pipe *emb_ipa_ul =
+		ipa_ctx->sys[IPA_A5_LAN_WAN_OUT].ep->ep_hdl;
+	struct sps_pipe *emb_ipa_to_dma =
+		bridge[IPA_BRIDGE_TYPE_EMBEDDED].pipe[IPA_UL_FROM_IPA].pipe;
+	struct sps_pipe *emb_dma_to_a2 =
+		bridge[IPA_BRIDGE_TYPE_EMBEDDED].pipe[IPA_UL_TO_A2].pipe;
+	u32 emb_ipa_ul_empty;
+	u32 emb_ipa_to_dma_empty;
+	u32 emb_dma_to_a2_empty;
+
+	if (sps_is_pipe_empty(emb_ipa_ul, &emb_ipa_ul_empty)) {
+		IPAERR("emb_ip_ul pipe empty check fail\n");
+		return false;
+	}
+
+	if (sps_is_pipe_empty(emb_ipa_to_dma, &emb_ipa_to_dma_empty)) {
+		IPAERR("emb_ipa_to_dma pipe empty check fail\n");
+		return false;
+	}
+
+	if (sps_is_pipe_empty(emb_dma_to_a2, &emb_dma_to_a2_empty)) {
+		IPAERR("emb_dma_to_a2 pipe empty check fail\n");
+		return false;
+	}
+
+	return emb_ipa_ul_empty && emb_ipa_to_dma_empty && emb_dma_to_a2_empty;
+}
+EXPORT_SYMBOL(ipa_emb_ul_pipes_empty);
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index f20f37f..3aaec07 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -45,7 +45,7 @@
 	if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1) {
 		ipa_write_reg(ipa_ctx->mmio,
 				IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 1);
-		usleep(IPA_PKT_FLUSH_TO_US);
+		udelay(IPA_PKT_FLUSH_TO_US);
 		if (IPA_CLIENT_IS_CONS(ep->client) &&
 				ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
 				ep->cfg.aggr.aggr_time_limit)
diff --git a/drivers/platform/msm/ipa/ipa_rm_resource.c b/drivers/platform/msm/ipa/ipa_rm_resource.c
index dba4430..986892b 100644
--- a/drivers/platform/msm/ipa/ipa_rm_resource.c
+++ b/drivers/platform/msm/ipa/ipa_rm_resource.c
@@ -787,15 +787,11 @@
 				&producer->resource.state_lock, flags);
 			consumer_result = ipa_rm_resource_consumer_release(
 				(struct ipa_rm_resource_cons *)consumer);
-			if (consumer_result == -EINPROGRESS) {
-				result = -EINPROGRESS;
-			} else {
-				spin_lock_irqsave(
-					&producer->resource.state_lock, flags);
-				producer->pending_release--;
-				spin_unlock_irqrestore(
-					&producer->resource.state_lock, flags);
-			}
+			spin_lock_irqsave(
+				&producer->resource.state_lock, flags);
+			producer->pending_release--;
+			spin_unlock_irqrestore(
+				&producer->resource.state_lock, flags);
 		}
 	}
 	spin_lock_irqsave(&producer->resource.state_lock, flags);
diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c
index 8c0adbd..8d6d5e6 100644
--- a/drivers/platform/msm/ipa/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_rt.c
@@ -74,23 +74,6 @@
 		rule_hdr->u.hdr.hdr_offset = 0;
 	}
 	buf += sizeof(struct ipa_rt_rule_hw_hdr);
-	if ((ip == IPA_IP_v4) &&
-		(entry->rule.attrib.attrib_mask & IPA_FLT_TOS)) {
-			entry->rule.attrib.tos_value =
-				(entry->rule.attrib.u.v4.tos << 5);
-			entry->rule.attrib.tos_mask = 0xe0;
-			entry->rule.attrib.attrib_mask &= ~IPA_FLT_TOS;
-			entry->rule.attrib.attrib_mask |= IPA_FLT_TOS_MASKED;
-	}
-
-	if ((ip == IPA_IP_v6) &&
-		(entry->rule.attrib.attrib_mask & IPA_FLT_TC)) {
-			entry->rule.attrib.tos_value =
-				(entry->rule.attrib.u.v6.tc << 5);
-			entry->rule.attrib.tos_mask = 0xe0;
-			entry->rule.attrib.attrib_mask &= ~IPA_FLT_TC;
-			entry->rule.attrib.attrib_mask |= IPA_FLT_TOS_MASKED;
-	}
 
 	if (ipa_generate_hw_rule(ip, &rule->attrib, &buf, &en_rule)) {
 		IPAERR("fail to generate hw rule\n");
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index e38b796..4a5fa4d 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -1396,12 +1396,8 @@
 	if (__ratelimit(&_rs)) {
 		ipa_inc_client_enable_clks();
 		pr_err("IPA BAM START\n");
-		sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 1048575, 0, 0);
+		sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 479182, 0, 0);
 		sps_get_bam_debug_info(ipa_ctx->bam_handle, 93, 0, 0, 0);
-		pr_err("BAM-DMA BAM START\n");
-		sps_get_bam_debug_info(sps_dma_get_bam_handle(), 5, 1044480,
-				0, 0);
-		sps_get_bam_debug_info(sps_dma_get_bam_handle(), 93, 0, 0, 0);
 		ipa_dec_client_disable_clks();
 	}
 }
diff --git a/drivers/platform/msm/ipa/teth_bridge.c b/drivers/platform/msm/ipa/teth_bridge.c
index 93f2366..b3a6b17 100644
--- a/drivers/platform/msm/ipa/teth_bridge.c
+++ b/drivers/platform/msm/ipa/teth_bridge.c
@@ -373,8 +373,8 @@
 		/* Add a header entry for USB */
 		res = add_eth_hdrs(USB_ETH_HDR_NAME_IPV4,
 				   USB_ETH_HDR_NAME_IPV6,
-				   teth_ctx->mac_addresses.host_pc_mac_addr,
-				   teth_ctx->mac_addresses.device_mac_addr);
+				   teth_ctx->mac_addresses.device_mac_addr,
+				   teth_ctx->mac_addresses.host_pc_mac_addr);
 		if (res) {
 			TETH_ERR("Failed adding USB Ethernet header\n");
 			goto bail;
@@ -384,8 +384,8 @@
 		/* Add a header entry for A2 */
 		res = add_eth_hdrs(A2_ETH_HDR_NAME_IPV4,
 				   A2_ETH_HDR_NAME_IPV6,
-				   teth_ctx->mac_addresses.device_mac_addr,
-				   teth_ctx->mac_addresses.host_pc_mac_addr);
+				   teth_ctx->mac_addresses.host_pc_mac_addr,
+				   teth_ctx->mac_addresses.device_mac_addr);
 		if (res) {
 			TETH_ERR("Failed adding A2 Ethernet header\n");
 			goto bail;
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index 087cfa8..b4edce8 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -33,6 +33,7 @@
 #define QPNP_PON_DBC_CTL(base)			(base + 0x71)
 
 /* PON/RESET sources register addresses */
+#define QPNP_PON_REASON1(base)			(base + 0x8)
 #define QPNP_PON_WARM_RESET_REASON1(base)	(base + 0xA)
 #define QPNP_PON_WARM_RESET_REASON2(base)	(base + 0xB)
 #define QPNP_PON_KPDPWR_S1_TIMER(base)		(base + 0x40)
@@ -73,8 +74,7 @@
 #define QPNP_PON_KPDPWR_RESIN_BARK_N_SET	BIT(5)
 
 #define QPNP_PON_RESET_EN			BIT(7)
-#define QPNP_PON_WARM_RESET			BIT(0)
-#define QPNP_PON_SHUTDOWN			BIT(2)
+#define QPNP_PON_POWER_OFF_MASK			0xF
 
 /* Ranges */
 #define QPNP_PON_S1_TIMER_MAX			10256
@@ -83,6 +83,7 @@
 #define QPNP_PON_S3_DBC_DELAY_MASK		0x07
 #define QPNP_PON_RESET_TYPE_MAX			0xF
 #define PON_S1_COUNT_MAX			0xF
+#define PON_REASON_MAX				8
 
 #define QPNP_KEY_STATUS_DELAY			msecs_to_jiffies(250)
 #define QPNP_PON_REV_B				0x01
@@ -124,6 +125,17 @@
 	3072, 4480, 6720, 10256
 };
 
+static const char * const qpnp_pon_reason[] = {
+	[0] = "Triggered from Hard Reset",
+	[1] = "Triggered from SMPL (sudden momentary power loss)",
+	[2] = "Triggered from RTC (RTC alarm expiry)",
+	[3] = "Triggered from DC (DC charger insertion)",
+	[4] = "Triggered from USB (USB charger insertion)",
+	[5] = "Triggered from PON1 (secondary PMIC)",
+	[6] = "Triggered from CBL (external power supply)",
+	[7] = "Triggered from KPD (power key press)",
+};
+
 static int
 qpnp_pon_masked_write(struct qpnp_pon *pon, u16 addr, u8 mask, u8 val)
 {
@@ -150,14 +162,14 @@
 
 /**
  * qpnp_pon_system_pwr_off - Configure system-reset PMIC for shutdown or reset
- * @reset: Configures for shutdown if 0, or reset if 1.
+ * @type: Determines the type of power off to perform - shutdown, reset, etc
  *
  * This function will only configure a single PMIC. The other PMICs in the
  * system are slaved off of it and require no explicit configuration. Once
  * the system-reset PMIC is configured properly, the MSM can drop PS_HOLD to
  * activate the specified configuration.
  */
-int qpnp_pon_system_pwr_off(bool reset)
+int qpnp_pon_system_pwr_off(enum pon_power_off_type type)
 {
 	int rc;
 	u8 reg;
@@ -194,8 +206,7 @@
 	udelay(500);
 
 	rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon->base),
-			   QPNP_PON_WARM_RESET | QPNP_PON_SHUTDOWN,
-			   reset ? QPNP_PON_WARM_RESET : QPNP_PON_SHUTDOWN);
+				   QPNP_PON_POWER_OFF_MASK, type);
 	if (rc)
 		dev_err(&pon->spmi->dev,
 			"Unable to write to addr=%x, rc(%d)\n",
@@ -207,6 +218,8 @@
 		dev_err(&pon->spmi->dev,
 			"Unable to write to addr=%x, rc(%d)\n", rst_en_reg, rc);
 
+	dev_dbg(&pon->spmi->dev, "power off type = 0x%02X\n", type);
+
 	return rc;
 }
 EXPORT_SYMBOL(qpnp_pon_system_pwr_off);
@@ -966,7 +979,8 @@
 	struct resource *pon_resource;
 	struct device_node *itr = NULL;
 	u32 delay = 0, s3_debounce = 0;
-	int rc, sys_reset;
+	int rc, sys_reset, index;
+	u8 pon_sts = 0;
 
 	pon = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_pon),
 							GFP_KERNEL);
@@ -1007,6 +1021,19 @@
 	}
 	pon->base = pon_resource->start;
 
+	/* PON reason */
+	rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
+				QPNP_PON_REASON1(pon->base), &pon_sts, 1);
+	if (rc) {
+		dev_err(&pon->spmi->dev, "Unable to read PON_RESASON1 reg\n");
+		return rc;
+	}
+	index = ffs(pon_sts);
+	if ((index > PON_REASON_MAX) || (index < 0))
+		index = 0;
+	pr_info("PMIC@SID%d Power-on reason: %s\n", pon->spmi->sid,
+			index ? qpnp_pon_reason[index - 1] : "Unknown");
+
 	rc = of_property_read_u32(pon->spmi->dev.of_node,
 				"qcom,pon-dbc-delay", &delay);
 	if (rc) {
diff --git a/drivers/platform/msm/qpnp-pwm.c b/drivers/platform/msm/qpnp-pwm.c
index 4e94b90..2fdc427 100644
--- a/drivers/platform/msm/qpnp-pwm.c
+++ b/drivers/platform/msm/qpnp-pwm.c
@@ -43,21 +43,32 @@
 #define QPNP_EN_PAUSE_LO_MASK		0x01
 
 /* LPG Control for LPG_PWM_SIZE_CLK */
+#define QPNP_PWM_SIZE_SHIFT_SUB_TYPE		2
+#define QPNP_PWM_SIZE_MASK_SUB_TYPE		0x4
+#define QPNP_PWM_FREQ_CLK_SELECT_MASK_SUB_TYPE	0x03
+#define QPNP_PWM_SIZE_9_BIT_SUB_TYPE		0x01
+
+#define QPNP_SET_PWM_CLK_SUB_TYPE(val, clk, pwm_size) \
+do { \
+	val = (clk + 1) & QPNP_PWM_FREQ_CLK_SELECT_MASK_SUB_TYPE; \
+	val |= ((pwm_size > 6 ? QPNP_PWM_SIZE_9_BIT_SUB_TYPE : 0) << \
+		QPNP_PWM_SIZE_SHIFT_SUB_TYPE) & QPNP_PWM_SIZE_MASK_SUB_TYPE; \
+} while (0)
+
 #define QPNP_PWM_SIZE_SHIFT			4
 #define QPNP_PWM_SIZE_MASK			0x30
-#define QPNP_PWM_FREQ_CLK_SELECT_SHIFT		0
 #define QPNP_PWM_FREQ_CLK_SELECT_MASK		0x03
-#define QPNP_PWM_SIZE_9_BIT			0x03
-
+#define QPNP_MIN_PWM_BIT_SIZE		6
+#define QPNP_MAX_PWM_BIT_SIZE		9
 #define QPNP_SET_PWM_CLK(val, clk, pwm_size) \
 do { \
 	val = (clk + 1) & QPNP_PWM_FREQ_CLK_SELECT_MASK; \
-	val |= ((pwm_size > 6 ? QPNP_PWM_SIZE_9_BIT : 0) << \
-			QPNP_PWM_SIZE_SHIFT) & QPNP_PWM_SIZE_MASK; \
+	val |= (((pwm_size - QPNP_MIN_PWM_BIT_SIZE) << \
+		QPNP_PWM_SIZE_SHIFT) & QPNP_PWM_SIZE_MASK); \
 } while (0)
 
 #define QPNP_GET_PWM_SIZE(reg) ((reg & QPNP_PWM_SIZE_MASK) \
-					>> QPNP_PWM_SIZE_SHIFT)
+				>> QPNP_PWM_SIZE_SHIFT)
 
 /* LPG Control for LPG_PWM_FREQ_PREDIV_CLK */
 #define QPNP_PWM_FREQ_PRE_DIVIDE_SHIFT		5
@@ -68,7 +79,7 @@
 do { \
 	val = (pre_div << QPNP_PWM_FREQ_PRE_DIVIDE_SHIFT) & \
 				QPNP_PWM_FREQ_PRE_DIVIDE_MASK;	\
-	val |= pre_div_exp & QPNP_PWM_FREQ_EXP_MASK;	\
+	val |= (pre_div_exp & QPNP_PWM_FREQ_EXP_MASK);	\
 } while (0)
 
 /* LPG Control for LPG_PWM_TYPE_CONFIG */
@@ -104,13 +115,27 @@
 
 #define QPNP_DISABLE_PWM(value)  (value &= ~QPNP_EN_PWM_OUTPUT_MASK)
 
+/* LPG Control for PWM_SYNC */
+#define QPNP_PWM_SYNC_VALUE			0x01
+#define QPNP_PWM_SYNC_MASK			0x01
+
 /* LPG Control for RAMP_CONTROL */
 #define QPNP_RAMP_START_MASK			0x01
+#define QPNP_RAMP_CONTROL_SHIFT			8
 
 #define QPNP_ENABLE_LUT_V0(value) (value |= QPNP_RAMP_START_MASK)
 #define QPNP_DISABLE_LUT_V0(value) (value &= ~QPNP_RAMP_START_MASK)
-#define QPNP_ENABLE_LUT_V1(value, id) (value |= BIT(id))
-#define QPNP_DISABLE_LUT_V1(value, id) (value &= ~BIT(id))
+#define QPNP_ENABLE_LUT_V1(value, id) \
+do { \
+	(id < 8) ? (value |= BIT(id)) : \
+	(value |= (BIT(id) >> QPNP_RAMP_CONTROL_SHIFT)); \
+} while (0)
+
+#define QPNP_DISABLE_LUT_V1(value, id) \
+do { \
+	(id < 8) ? (value &= ~BIT(id)) : \
+	(value &= (~BIT(id) >> QPNP_RAMP_CONTROL_SHIFT)); \
+} while (0)
 
 /* LPG Control for RAMP_STEP_DURATION_LSB */
 #define QPNP_RAMP_STEP_DURATION_LSB_MASK	0xFF
@@ -159,9 +184,18 @@
 #define SPMI_LPG_REG_BASE_OFFSET	0x40
 #define SPMI_LPG_REVISION2_OFFSET	0x1
 #define SPMI_LPG_REV1_RAMP_CONTROL_OFFSET	0x86
+#define SPMI_LPG_SUB_TYPE_OFFSET	0x5
+#define SPMI_LPG_PWM_SYNC		0x7
 #define SPMI_LPG_REG_ADDR(b, n)	(b + SPMI_LPG_REG_BASE_OFFSET + (n))
 #define SPMI_MAX_BUF_LEN	8
 
+#define QPNP_GPLED_LPG_CHANNEL_RANGE_START 8
+#define QPNP_GPLED_LPG_CHANNEL_RANGE_END 11
+#define qpnp_check_gpled_lpg_channel(id) \
+	(id >= QPNP_GPLED_LPG_CHANNEL_RANGE_START && \
+	id <= QPNP_GPLED_LPG_CHANNEL_RANGE_END)
+#define QPNP_PWM_LUT_NOT_SUPPORTED	0x1
+
 /* LPG revisions */
 enum qpnp_lpg_revision {
 	QPNP_LPG_REVISION_0 = 0x0,
@@ -277,6 +311,8 @@
 	struct	qpnp_lpg_config	lpg_config;
 	u8	qpnp_lpg_registers[QPNP_TOTAL_LPG_SPMI_REGISTERS];
 	enum qpnp_lpg_revision	revision;
+	u8			sub_type;
+	u32			flags;
 };
 
 /* Internal functions */
@@ -374,20 +410,29 @@
  * (PWM Period / N) = (Pre-divide * Clock Period) * 2^m
  */
 static void qpnp_lpg_calc_period(unsigned int period_us,
-				   struct pwm_period_config *period)
+				   struct qpnp_pwm_config *pwm_conf)
 {
 	int		n, m, clk, div;
 	int		best_m, best_div, best_clk;
 	unsigned int	last_err, cur_err, min_err;
 	unsigned int	tmp_p, period_n;
+	int		id = pwm_conf->channel_id;
+	struct pwm_period_config *period = &pwm_conf->period;
 
 	/* PWM Period / N */
-	if (period_us < ((unsigned)(-1) / NSEC_PER_USEC)) {
-		period_n = (period_us * NSEC_PER_USEC) >> 6;
+	if (qpnp_check_gpled_lpg_channel(id))
+		n = 7;
+	else
 		n = 6;
+
+	if (period_us < ((unsigned)(-1) / NSEC_PER_USEC)) {
+		period_n = (period_us * NSEC_PER_USEC) >> n;
 	} else {
-		period_n = (period_us >> 9) * NSEC_PER_USEC;
-		n = 9;
+		if (qpnp_check_gpled_lpg_channel(id))
+			n = 8;
+		else
+			n = 9;
+		period_n = (period_us >> n) * NSEC_PER_USEC;
 	}
 
 	min_err = last_err = (unsigned)(-1);
@@ -422,10 +467,22 @@
 		}
 	}
 
-	/* Use higher resolution */
-	if (best_m >= 3 && n == 6) {
-		n += 3;
-		best_m -= 3;
+	/* Adapt to optimal pwm size, the higher the resolution the better */
+	if (qpnp_check_gpled_lpg_channel(id)) {
+		if (n == 7 && best_m >= 1) {
+			n += 1;
+			best_m -= 1;
+		}
+	} else {
+		if (n == 6 && best_m >= 3) {
+			n += 3;
+			best_m -= 3;
+		} else {
+			if (n == 6) {
+				n += best_m;
+				best_m -= best_m;
+			}
+		}
 	}
 
 	period->pwm_size = n;
@@ -467,8 +524,8 @@
 	int			offset = (lut->lo_index << 1) - 2;
 
 	pwm_size = QPNP_GET_PWM_SIZE(
-			chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]) &
-						QPNP_PWM_SIZE_9_BIT ? 9 : 6;
+			chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]) +
+				QPNP_MIN_PWM_BIT_SIZE;
 
 	max_pwm_value = (1 << pwm_size) - 1;
 
@@ -489,20 +546,30 @@
 		if (pwm_value > max_pwm_value)
 			pwm_value = max_pwm_value;
 
-		lut->duty_pct_list[i*2] = pwm_value;
-		lut->duty_pct_list[(i*2)+1] = (pwm_value >>
+		if (qpnp_check_gpled_lpg_channel(pwm->pwm_config.channel_id)) {
+			lut->duty_pct_list[i] = pwm_value;
+		} else {
+			lut->duty_pct_list[i*2] = pwm_value;
+			lut->duty_pct_list[(i*2)+1] = (pwm_value >>
 			 QPNP_PWM_VALUE_MSB_SHIFT) & QPNP_PWM_VALUE_MSB_MASK;
+		}
 	}
 
+	/*
+	 * For the Keypad Backlight Lookup Table (KPDBL_LUT),
+	 * offset is lo_index.
+	 */
+	if (qpnp_check_gpled_lpg_channel(pwm->pwm_config.channel_id))
+		offset = lut->lo_index;
+
 	/* Write with max allowable burst mode, each entry is of two bytes */
-	for (i = 0; i < list_len;) {
+	for (i = 0; i < list_len; i += burst_size) {
 		if (i + burst_size >= list_len)
 			burst_size = list_len - i;
 		rc = spmi_ext_register_writel(chip->spmi_dev->ctrl,
 			chip->spmi_dev->sid,
 			chip->lpg_config.lut_base_addr + offset + i,
 			lut->duty_pct_list + i, burst_size);
-		i += burst_size;
 	}
 
 	return rc;
@@ -514,7 +581,11 @@
 	struct qpnp_lpg_chip	*chip = pwm->chip;
 	struct qpnp_pwm_config	*pwm_config = &pwm->pwm_config;
 
-	QPNP_SET_PWM_CLK(val, pwm_config->period.clk,
+	if (chip->sub_type == 0x0B)
+		QPNP_SET_PWM_CLK_SUB_TYPE(val, pwm_config->period.clk,
+				pwm_config->period.pwm_size);
+	else
+		QPNP_SET_PWM_CLK(val, pwm_config->period.clk,
 				pwm_config->period.pwm_size);
 
 	mask = QPNP_PWM_SIZE_MASK | QPNP_PWM_FREQ_CLK_SELECT_MASK;
@@ -542,8 +613,8 @@
 	int rc;
 
 	pwm_size = QPNP_GET_PWM_SIZE(
-			chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]) &
-						QPNP_PWM_SIZE_9_BIT ? 9 : 6;
+			chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]) +
+			QPNP_MIN_PWM_BIT_SIZE;
 
 	max_pwm_value = (1 << pwm_size) - 1;
 
@@ -565,10 +636,21 @@
 
 	mask = QPNP_PWM_VALUE_MSB_MASK;
 
-	return qpnp_lpg_save_and_write(value, mask,
+	rc = qpnp_lpg_save_and_write(value, mask,
 			&pwm->chip->qpnp_lpg_registers[QPNP_PWM_VALUE_MSB],
 			SPMI_LPG_REG_ADDR(lpg_config->base_addr,
 			QPNP_PWM_VALUE_MSB), 1, chip);
+	if (rc)
+		return rc;
+
+	if (chip->sub_type == 0x0B) {
+		value = QPNP_PWM_SYNC_VALUE & QPNP_PWM_SYNC_MASK;
+		rc = spmi_ext_register_writel(chip->spmi_dev->ctrl,
+			chip->spmi_dev->sid,
+			SPMI_LPG_REG_ADDR(lpg_config->base_addr,
+			SPMI_LPG_PWM_SYNC), &value, 1);
+	}
+	return rc;
 }
 
 static int qpnp_lpg_configure_pattern(struct pwm_device *pwm)
@@ -910,13 +992,9 @@
 					addr1, 1, chip);
 }
 
-#define QPNP_GPLED_LPG_CHANNEL_RANGE_START 8
-#define QPNP_GPLED_LPG_CHANNEL_RANGE_END 11
-
 static inline int qpnp_enable_pwm_mode(struct qpnp_pwm_config *pwm_conf)
 {
-	if (pwm_conf->channel_id >= QPNP_GPLED_LPG_CHANNEL_RANGE_START &&
-		pwm_conf->channel_id <= QPNP_GPLED_LPG_CHANNEL_RANGE_END)
+	if (qpnp_check_gpled_lpg_channel(pwm_conf->channel_id))
 		return QPNP_ENABLE_PWM_MODE_GPLED_CHANNEL;
 	return QPNP_ENABLE_PWM_MODE;
 }
@@ -968,7 +1046,7 @@
 	period = &pwm_config->period;
 
 	if (pwm_config->pwm_period != period_us) {
-		qpnp_lpg_calc_period(period_us, period);
+		qpnp_lpg_calc_period(period_us, pwm_config);
 		qpnp_lpg_save_period(pwm);
 		pwm_config->pwm_period = period_us;
 	}
@@ -1024,7 +1102,7 @@
 	period = &pwm_config->period;
 
 	if (pwm_config->pwm_period != period_us) {
-		qpnp_lpg_calc_period(period_us, period);
+		qpnp_lpg_calc_period(period_us, pwm_config);
 		qpnp_lpg_save_period(pwm);
 		pwm_config->pwm_period = period_us;
 	}
@@ -1077,7 +1155,7 @@
 
 static int _pwm_enable(struct pwm_device *pwm)
 {
-	int rc;
+	int rc = 0;
 	struct qpnp_lpg_chip *chip;
 	unsigned long flags;
 
@@ -1086,10 +1164,11 @@
 	spin_lock_irqsave(&pwm->chip->lpg_lock, flags);
 
 	if (QPNP_IS_PWM_CONFIG_SELECTED(
-		chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL]))
+		chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL])) {
 		rc = qpnp_lpg_configure_pwm_state(pwm, QPNP_PWM_ENABLE);
-	else
-		rc = qpnp_lpg_configure_lut_state(pwm, QPNP_LUT_ENABLE);
+	} else if (!(chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED)) {
+			rc = qpnp_lpg_configure_lut_state(pwm, QPNP_LUT_ENABLE);
+	}
 
 	spin_unlock_irqrestore(&pwm->chip->lpg_lock, flags);
 
@@ -1160,7 +1239,8 @@
 
 	if (pwm_config->in_use) {
 		qpnp_lpg_configure_pwm_state(pwm, QPNP_PWM_DISABLE);
-		qpnp_lpg_configure_lut_state(pwm, QPNP_LUT_DISABLE);
+		if (!(pwm->chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED))
+			qpnp_lpg_configure_lut_state(pwm, QPNP_LUT_DISABLE);
 		pwm_config->in_use = 0;
 		pwm_config->lable = NULL;
 	}
@@ -1249,12 +1329,13 @@
 
 	if (pwm_config->in_use) {
 		if (QPNP_IS_PWM_CONFIG_SELECTED(
-			chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL]))
+			chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL])) {
 			rc = qpnp_lpg_configure_pwm_state(pwm,
 						QPNP_PWM_DISABLE);
-		else
-			rc = qpnp_lpg_configure_lut_state(pwm,
-						QPNP_LUT_DISABLE);
+		} else if (!(chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED)) {
+				rc = qpnp_lpg_configure_lut_state(pwm,
+							QPNP_LUT_DISABLE);
+		}
 	}
 
 	spin_unlock_irqrestore(&pwm->chip->lpg_lock, flags);
@@ -1435,6 +1516,11 @@
 	if (pwm->chip == NULL)
 		return -ENODEV;
 
+	if (pwm->chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED) {
+		pr_err("LUT mode isn't supported\n");
+		return -EINVAL;
+	}
+
 	if (!pwm->pwm_config.in_use) {
 		pr_err("channel_id: %d: stale handle?\n",
 				pwm->pwm_config.channel_id);
@@ -1588,7 +1674,7 @@
 static int qpnp_parse_dt_config(struct spmi_device *spmi,
 					struct qpnp_lpg_chip *chip)
 {
-	int			rc, enable;
+	int			rc, enable, lut_entry_size;
 	const char		*lable;
 	struct resource		*res;
 	struct device_node	*node;
@@ -1599,6 +1685,14 @@
 	struct qpnp_lpg_config	*lpg_config = &chip->lpg_config;
 	struct qpnp_lut_config	*lut_config = &lpg_config->lut_config;
 
+	rc = of_property_read_u32(of_node, "qcom,channel-id",
+				&pwm_dev->pwm_config.channel_id);
+	if (rc) {
+		dev_err(&spmi->dev, "%s: node is missing LPG channel id\n",
+								__func__);
+		goto out;
+	}
+
 	res = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
 					QPNP_LPG_CHANNEL_BASE);
 	if (!res) {
@@ -1612,28 +1706,27 @@
 	res = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
 						QPNP_LPG_LUT_BASE);
 	if (!res) {
-		dev_err(&spmi->dev, "%s: node is missing LUT base address\n",
-								__func__);
-		return -EINVAL;
-	}
+		chip->flags |= QPNP_PWM_LUT_NOT_SUPPORTED;
+	} else {
+		lpg_config->lut_base_addr = res->start;
+		/* Each entry of LUT is of 2 bytes for generic LUT and of 1 byte
+		 * for KPDBL/GLED LUT.
+		 */
+		lpg_config->lut_size = resource_size(res) >> 1;
+		lut_entry_size = sizeof(u16);
 
-	lpg_config->lut_base_addr = res->start;
-	/* Each entry of LUT is of 2 bytes */
-	lpg_config->lut_size = resource_size(res) >> 1;
+		if (qpnp_check_gpled_lpg_channel(
+				pwm_dev->pwm_config.channel_id)) {
+			lpg_config->lut_size = resource_size(res);
+			lut_entry_size = sizeof(u8);
+		}
 
-	lut_config->duty_pct_list = kzalloc(lpg_config->lut_size *
-						sizeof(u16), GFP_KERNEL);
-	if (!lut_config->duty_pct_list) {
-		pr_err("can not allocate duty pct list\n");
-		return -ENOMEM;
-	}
-
-	rc = of_property_read_u32(of_node, "qcom,channel-id",
-				&pwm_dev->pwm_config.channel_id);
-	if (rc) {
-		dev_err(&spmi->dev, "%s: node is missing LPG channel id\n",
-								__func__);
-		goto out;
+		lut_config->duty_pct_list = kzalloc(lpg_config->lut_size *
+					lut_entry_size, GFP_KERNEL);
+		if (!lut_config->duty_pct_list) {
+			pr_err("can not allocate duty pct list\n");
+			return -ENOMEM;
+		}
 	}
 
 	for_each_child_of_node(of_node, node) {
@@ -1648,7 +1741,8 @@
 			if (rc)
 				goto out;
 			found_pwm_subnode = 1;
-		} else if (!strncmp(lable, "lpg", 3)) {
+		} else if (!strncmp(lable, "lpg", 3) &&
+				!(chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED)) {
 			qpnp_parse_lpg_dt_config(node, of_node, chip);
 			if (rc)
 				goto out;
@@ -1722,6 +1816,11 @@
 		goto failed_insert;
 	}
 
+	spmi_ext_register_readl(chip->spmi_dev->ctrl,
+		chip->spmi_dev->sid,
+		chip->lpg_config.base_addr + SPMI_LPG_SUB_TYPE_OFFSET,
+		&chip->sub_type, 1);
+
 	rc = radix_tree_insert(&lpg_dev_tree, id, chip);
 
 	if (rc) {
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index 6412fc0..d6af279 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -53,6 +53,7 @@
 #define IRQ_EN                      (0x1c)
 #define AHB_MASTER_ERR_CTRLS        (0x24)
 #define AHB_MASTER_ERR_ADDR         (0x28)
+#define AHB_MASTER_ERR_ADDR_MSB     (0x104)
 #define AHB_MASTER_ERR_DATA         (0x2c)
 #define TRUST_REG                   (0x70)
 #define TEST_BUS_SEL                (0x74)
@@ -61,6 +62,7 @@
 #define IRQ_SRCS_EE(n)             (0x800 + 128 * (n))
 #define IRQ_SRCS_MSK_EE(n)         (0x804 + 128 * (n))
 #define IRQ_SRCS_UNMASKED_EE(n)    (0x808 + 128 * (n))
+#define PIPE_ATTR_EE(n)            (0x80c + 128 * (n))
 
 #define P_CTRL(n)                  (0x1000 + 4096 * (n))
 #define P_RST(n)                   (0x1004 + 4096 * (n))
@@ -74,10 +76,13 @@
 #define P_CNSMR_SDBND(n)           (0x1028 + 4096 * (n))
 #define P_TRUST_REG(n)             (0x1030 + 4096 * (n))
 #define P_EVNT_DEST_ADDR(n)        (0x182c + 4096 * (n))
+#define P_EVNT_DEST_ADDR_MSB(n)    (0x1934 + 4096 * (n))
 #define P_EVNT_REG(n)              (0x1818 + 4096 * (n))
 #define P_SW_OFSTS(n)              (0x1800 + 4096 * (n))
 #define P_DATA_FIFO_ADDR(n)        (0x1824 + 4096 * (n))
+#define P_DATA_FIFO_ADDR_MSB(n)    (0x1924 + 4096 * (n))
 #define P_DESC_FIFO_ADDR(n)        (0x181c + 4096 * (n))
+#define P_DESC_FIFO_ADDR_MSB(n)    (0x1914 + 4096 * (n))
 #define P_EVNT_GEN_TRSHLD(n)       (0x1828 + 4096 * (n))
 #define P_FIFO_SIZES(n)            (0x1820 + 4096 * (n))
 #define P_RETR_CNTXT(n)            (0x1834 + 4096 * (n))
@@ -86,6 +91,7 @@
 #define P_AU_PSM_CNTXT_1(n)        (0x1804 + 4096 * (n))
 #define P_PSM_CNTXT_2(n)           (0x1808 + 4096 * (n))
 #define P_PSM_CNTXT_3(n)           (0x180c + 4096 * (n))
+#define P_PSM_CNTXT_3_MSB(n)       (0x1904 + 4096 * (n))
 #define P_PSM_CNTXT_4(n)           (0x1810 + 4096 * (n))
 #define P_PSM_CNTXT_5(n)           (0x1814 + 4096 * (n))
 
@@ -95,6 +101,7 @@
  *
  */
 /* CTRL */
+#define BAM_MESS_ONLY_CANCEL_WB               0x100000
 #define CACHE_MISS_ERR_RESP_EN                 0x80000
 #define LOCAL_CLK_GATING                       0x60000
 #define IBC_DISABLE                            0x10000
@@ -115,7 +122,7 @@
 #define BAM_SECURED                            0x10000
 #define BAM_USE_VMIDMT                          0x8000
 #define BAM_AXI_ACTIVE                          0x4000
-#define BAM_CE_BUFFER_SIZE                      0x2000
+#define BAM_CE_BUFFER_SIZE                      0x3000
 #define BAM_NUM_EES                              0xf00
 #define BAM_REVISION                              0xff
 
@@ -127,6 +134,7 @@
 /* NUM_PIPES */
 #define BAM_NON_PIPE_GRP                    0xff000000
 #define BAM_PERIPH_NON_PIPE_GRP               0xff0000
+#define BAM_DATA_ADDR_BUS_WIDTH                 0xC000
 #define BAM_NUM_PIPES                             0xff
 
 /* TIMER */
@@ -188,6 +196,7 @@
 #define BAM_TESTBUS_SEL                           0x7f
 
 /* CNFG_BITS */
+#define CNFG_BITS_AOS_OVERFLOW_PRVNT		 0x80000000
 #define CNFG_BITS_MULTIPLE_EVENTS_DESC_AVAIL_EN  0x40000000
 #define CNFG_BITS_MULTIPLE_EVENTS_SIZE_EN        0x20000000
 #define CNFG_BITS_BAM_ZLT_W_CD_SUPPORT           0x10000000
@@ -210,6 +219,10 @@
 #define CNFG_BITS_BAM_FULL_PIPE                       0x800
 #define CNFG_BITS_BAM_PIPE_CNFG                         0x4
 
+/* PIPE_ATTR_EEn*/
+#define BAM_ENABLED                              0x80000000
+#define P_ATTR                                   0x7fffffff
+
 /* P_ctrln */
 #define P_LOCK_GROUP                          0x1f0000
 #define P_WRITE_NWD                              0x800
@@ -234,6 +247,8 @@
 #define BAM_P_EE                                   0x7
 
 /* P_IRQ_STTSn */
+#define P_IRQ_STTS_P_HRESP_ERR_IRQ                0x80
+#define P_IRQ_STTS_P_PIPE_RST_ERR_IRQ             0x40
 #define P_IRQ_STTS_P_TRNSFR_END_IRQ               0x20
 #define P_IRQ_STTS_P_ERR_IRQ                      0x10
 #define P_IRQ_STTS_P_OUT_OF_DESC_IRQ               0x8
@@ -242,6 +257,8 @@
 #define P_IRQ_STTS_P_PRCSD_DESC_IRQ                0x1
 
 /* P_IRQ_CLRn */
+#define P_IRQ_CLR_P_HRESP_ERR_CLR                 0x80
+#define P_IRQ_CLR_P_PIPE_RST_ERR_CLR              0x40
 #define P_IRQ_CLR_P_TRNSFR_END_CLR                0x20
 #define P_IRQ_CLR_P_ERR_CLR                       0x10
 #define P_IRQ_CLR_P_OUT_OF_DESC_CLR                0x8
@@ -250,6 +267,8 @@
 #define P_IRQ_CLR_P_PRCSD_DESC_CLR                 0x1
 
 /* P_IRQ_ENn */
+#define P_IRQ_EN_P_HRESP_ERR_EN                   0x80
+#define P_IRQ_EN_P_PIPE_RST_ERR_EN                0x40
 #define P_IRQ_EN_P_TRNSFR_END_EN                  0x20
 #define P_IRQ_EN_P_ERR_EN                         0x10
 #define P_IRQ_EN_P_OUT_OF_DESC_EN                  0x8
@@ -404,6 +423,7 @@
 /* NUM_PIPES */
 #define BAM_NON_PIPE_GRP                    0xff000000
 #define BAM_PERIPH_NON_PIPE_GRP               0xff0000
+#define BAM_DATA_ADDR_BUS_WIDTH                 0xC000
 #define BAM_NUM_PIPES                             0xff
 
 /* DESC_CNT_TRSHLD */
@@ -686,8 +706,16 @@
 		bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 0);
 	else
 		bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 1);
-#endif
 
+	if (enhd_pipe) {
+		if (options & SPS_BAM_CANCEL_WB)
+			bam_write_reg_field(base, CTRL,
+					BAM_MESS_ONLY_CANCEL_WB, 1);
+		else
+			bam_write_reg_field(base, CTRL,
+					BAM_MESS_ONLY_CANCEL_WB, 0);
+	}
+#endif
 	bam_write_reg(base, DESC_CNT_TRSHLD, summing_threshold);
 
 	bam_write_reg(base, CNFG_BITS, cfg_bits);
@@ -786,18 +814,43 @@
 	return 0;
 }
 
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+static inline u32 bam_get_pipe_attr(void *base, u32 ee, bool global)
+{
+	u32 val;
+
+	if (global)
+		val = bam_read_reg_field(base, PIPE_ATTR_EE(ee), BAM_ENABLED);
+	else
+		val = bam_read_reg_field(base, PIPE_ATTR_EE(ee), P_ATTR);
+
+	return val;
+}
+#else
+static inline u32 bam_get_pipe_attr(void *base, u32 ee, bool global)
+{
+	return 0;
+}
+#endif
+
 /**
  * Verify that a BAM device is enabled and gathers the hardware
  * configuration.
  *
  */
-int bam_check(void *base, u32 *version, u32 *num_pipes)
+int bam_check(void *base, u32 *version, u32 ee, u32 *num_pipes)
 {
 	u32 ver = 0;
+	u32 enabled = 0;
 
 	SPS_DBG2("sps:%s:bam=0x%x(va).", __func__, (u32) base);
 
-	if (!bam_read_reg_field(base, CTRL, BAM_EN)) {
+	if (!enhd_pipe)
+		enabled = bam_read_reg_field(base, CTRL, BAM_EN);
+	else
+		enabled = bam_get_pipe_attr(base, ee, true);
+
+	if (!enabled) {
 		SPS_ERR("sps:%s:bam 0x%x(va) is not enabled.\n",
 				__func__, (u32) base);
 		return -ENODEV;
@@ -843,10 +896,11 @@
  * including the TEST_BUS register content under
  * different TEST_BUS_SEL values.
  */
-static void bam_output_register_content(void *base)
+void bam_output_register_content(void *base, u32 ee)
 {
 	u32 num_pipes;
 	u32 i;
+	u32 pipe_attr = 0;
 
 	print_bam_test_bus_reg(base, 0);
 
@@ -857,8 +911,18 @@
 	SPS_INFO("sps:bam 0x%x(va) has %d pipes.",
 			(u32) base, num_pipes);
 
-	for (i = 0; i < num_pipes; i++)
-		print_bam_pipe_selected_reg(base, i);
+	pipe_attr = enhd_pipe ?
+		bam_get_pipe_attr(base, ee, false) : 0x0;
+
+	if (!enhd_pipe || !pipe_attr)
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_selected_reg(base, i);
+	else {
+		for (i = 0; i < num_pipes; i++) {
+			if (pipe_attr & (1UL << i))
+				print_bam_pipe_selected_reg(base, i);
+		}
+	}
 }
 
 /**
@@ -878,13 +942,13 @@
 			SPS_ERR("sps:bam 0x%x(va);bam irq status="
 				"0x%x.\nsps: BAM_ERROR_IRQ\n",
 				(u32) base, status);
-			bam_output_register_content(base);
+			bam_output_register_content(base, ee);
 			*cb_case = SPS_CALLBACK_BAM_ERROR_IRQ;
 		} else if (status & IRQ_STTS_BAM_HRESP_ERR_IRQ) {
 			SPS_ERR("sps:bam 0x%x(va);bam irq status="
 				"0x%x.\nsps: BAM_HRESP_ERR_IRQ\n",
 				(u32) base, status);
-			bam_output_register_content(base);
+			bam_output_register_content(base, ee);
 			*cb_case = SPS_CALLBACK_BAM_HRESP_ERR_IRQ;
 #ifdef CONFIG_SPS_SUPPORT_NDP_BAM
 		} else if (status & IRQ_STTS_BAM_TIMER_IRQ) {
@@ -926,7 +990,8 @@
 
 	bam_write_reg(base, P_EVNT_GEN_TRSHLD(pipe), param->event_threshold);
 
-	bam_write_reg(base, P_DESC_FIFO_ADDR(pipe), param->desc_base);
+	bam_write_reg(base, P_DESC_FIFO_ADDR(pipe),
+			SPS_GET_LOWER_ADDR(param->desc_base));
 	bam_write_reg_field(base, P_FIFO_SIZES(pipe), P_DESC_FIFO_SIZE,
 			    param->desc_size);
 
@@ -934,6 +999,10 @@
 			    param->stream_mode);
 
 #ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+	if (SPS_LPAE)
+		bam_write_reg(base, P_DESC_FIFO_ADDR_MSB(pipe),
+				SPS_GET_UPPER_ADDR(param->desc_base));
+
 	bam_write_reg_field(base, P_CTRL(pipe), P_LOCK_GROUP,
 				param->lock_group);
 
@@ -946,7 +1015,7 @@
 				      P_EVNT_REG(param->peer_pipe);
 
 		bam_write_reg(base, P_DATA_FIFO_ADDR(pipe),
-			      param->data_base);
+			      SPS_GET_LOWER_ADDR(param->data_base));
 		bam_write_reg_field(base, P_FIFO_SIZES(pipe),
 				    P_DATA_FIFO_SIZE, param->data_size);
 
@@ -959,6 +1028,12 @@
 			param->peer_pipe);
 
 #ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+		if (SPS_LPAE) {
+			bam_write_reg(base, P_EVNT_DEST_ADDR_MSB(pipe), 0x0);
+			bam_write_reg(base, P_DATA_FIFO_ADDR_MSB(pipe),
+				      SPS_GET_UPPER_ADDR(param->data_base));
+		}
+
 		bam_write_reg_field(base, P_CTRL(pipe), P_WRITE_NWD,
 					param->write_nwd);
 
@@ -1033,6 +1108,24 @@
 		      u32 src_mask, u32 ee)
 {
 	SPS_DBG2("sps:%s:bam=0x%x(va).pipe=%d.", __func__, (u32) base, pipe);
+	if (src_mask & BAM_PIPE_IRQ_RST_ERROR) {
+		if (enhd_pipe)
+			bam_write_reg_field(base, IRQ_EN,
+					IRQ_EN_BAM_ERROR_EN, 0);
+		else {
+			src_mask &= ~BAM_PIPE_IRQ_RST_ERROR;
+			SPS_DBG2("sps: SPS_O_RST_ERROR is not supported\n");
+		}
+	}
+	if (src_mask & BAM_PIPE_IRQ_HRESP_ERROR) {
+		if (enhd_pipe)
+			bam_write_reg_field(base, IRQ_EN,
+					IRQ_EN_BAM_HRESP_ERR_EN, 0);
+		else {
+			src_mask &= ~BAM_PIPE_IRQ_HRESP_ERROR;
+			SPS_DBG2("sps: SPS_O_HRESP_ERROR is not supported\n");
+		}
+	}
 
 	bam_write_reg(base, P_IRQ_EN(pipe), src_mask);
 	bam_write_reg_field(base, IRQ_SRCS_MSK_EE(ee), (1 << pipe), irq_en);
@@ -1294,6 +1387,7 @@
 
 	u32 bam_num_pipes;
 	u32 bam_pipe_num;
+	u32 bam_data_addr_bus_width;
 
 	u32 bam_desc_cnt_trshld;
 	u32 bam_desc_cnt_trd_val;
@@ -1304,6 +1398,7 @@
 	u32 bam_irq_src_ee = 0;
 	u32 bam_irq_msk_ee = 0;
 	u32 bam_irq_unmsk_ee = 0;
+	u32 bam_pipe_attr_ee = 0;
 
 	u32 bam_ahb_err_ctrl;
 	u32 bam_ahb_err_addr;
@@ -1313,6 +1408,7 @@
 	u32 bam_sw_rev = 0;
 	u32 bam_timer = 0;
 	u32 bam_timer_ctrl = 0;
+	u32 bam_ahb_err_addr_msb = 0;
 
 	if (base == NULL)
 		return;
@@ -1324,6 +1420,8 @@
 
 	bam_num_pipes = bam_read_reg(base, NUM_PIPES);
 	bam_pipe_num = bam_read_reg_field(base, NUM_PIPES, BAM_NUM_PIPES);
+	bam_data_addr_bus_width = bam_read_reg_field(base, NUM_PIPES,
+					BAM_DATA_ADDR_BUS_WIDTH);
 
 	bam_desc_cnt_trshld = bam_read_reg(base, DESC_CNT_TRSHLD);
 	bam_desc_cnt_trd_val = bam_read_reg_field(base, DESC_CNT_TRSHLD,
@@ -1347,6 +1445,11 @@
 	bam_sw_rev = bam_read_reg(base, SW_REVISION);
 	bam_timer = bam_read_reg(base, TIMER);
 	bam_timer_ctrl = bam_read_reg(base, TIMER_CTRL);
+	bam_ahb_err_addr_msb = SPS_LPAE ?
+		bam_read_reg(base, AHB_MASTER_ERR_ADDR_MSB) : 0;
+	if (ee < BAM_MAX_EES)
+		bam_pipe_attr_ee = enhd_pipe ?
+			bam_read_reg(base, PIPE_ATTR_EE(ee)) : 0x0;
 #endif
 
 
@@ -1358,6 +1461,8 @@
 	SPS_INFO("    NUM_EES: %d\n", bam_rev_ee_num);
 	SPS_INFO("BAM_SW_REVISION: 0x%x\n", bam_sw_rev);
 	SPS_INFO("BAM_NUM_PIPES: %d\n", bam_num_pipes);
+	SPS_INFO("BAM_DATA_ADDR_BUS_WIDTH: %d\n",
+			((bam_data_addr_bus_width == 0x0) ? 32 : 36));
 	SPS_INFO("    NUM_PIPES: %d\n", bam_pipe_num);
 	SPS_INFO("BAM_DESC_CNT_TRSHLD: 0x%x\n", bam_desc_cnt_trshld);
 	SPS_INFO("    DESC_CNT_TRSHLD: 0x%x (%d)\n", bam_desc_cnt_trd_val,
@@ -1371,10 +1476,12 @@
 		SPS_INFO("BAM_IRQ_SRCS_MSK_EE(%d): 0x%x\n", ee, bam_irq_msk_ee);
 		SPS_INFO("BAM_IRQ_SRCS_UNMASKED_EE(%d): 0x%x\n", ee,
 				bam_irq_unmsk_ee);
+		SPS_INFO("BAM_PIPE_ATTR_EE(%d): 0x%x\n", ee, bam_pipe_attr_ee);
 	}
 
 	SPS_INFO("BAM_AHB_MASTER_ERR_CTRLS: 0x%x\n", bam_ahb_err_ctrl);
 	SPS_INFO("BAM_AHB_MASTER_ERR_ADDR: 0x%x\n", bam_ahb_err_addr);
+	SPS_INFO("BAM_AHB_MASTER_ERR_ADDR_MSB: 0x%x\n", bam_ahb_err_addr_msb);
 	SPS_INFO("BAM_AHB_MASTER_ERR_DATA: 0x%x\n", bam_ahb_err_data);
 
 	SPS_INFO("BAM_CNFG_BITS: 0x%x\n", bam_cnfg_bits);
@@ -1421,9 +1528,12 @@
 	u32 p_write_pointer;
 
 	u32 p_evnt_dest;
+	u32 p_evnt_dest_msb = 0;
 	u32 p_desc_fifo_addr;
+	u32 p_desc_fifo_addr_msb = 0;
 	u32 p_desc_fifo_size;
 	u32 p_data_fifo_addr;
+	u32 p_data_fifo_addr_msb = 0;
 	u32 p_data_fifo_size;
 	u32 p_fifo_sizes;
 
@@ -1439,6 +1549,7 @@
 	u32 p_au_ct1;
 	u32 p_psm_ct2;
 	u32 p_psm_ct3;
+	u32 p_psm_ct3_msb = 0;
 	u32 p_psm_ct4;
 	u32 p_psm_ct5;
 
@@ -1520,6 +1631,15 @@
 	p_timer_ctrl = bam_read_reg(base, P_TIMER_CTRL(pipe));
 
 #ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+	p_evnt_dest_msb = SPS_LPAE ?
+		bam_read_reg(base, P_EVNT_DEST_ADDR_MSB(pipe)) : 0;
+
+	p_desc_fifo_addr_msb = SPS_LPAE ?
+		bam_read_reg(base, P_DESC_FIFO_ADDR_MSB(pipe)) : 0;
+	p_data_fifo_addr_msb = SPS_LPAE ?
+		bam_read_reg(base, P_DATA_FIFO_ADDR_MSB(pipe)) : 0;
+
+	p_psm_ct3_msb = SPS_LPAE ? bam_read_reg(base, P_PSM_CNTXT_3(pipe)) : 0;
 	p_lock_group = bam_read_reg_field(base, P_CTRL(pipe), P_LOCK_GROUP);
 	p_df_ct = bam_read_reg(base, P_DF_CNTXT(pipe));
 	p_df_offset = bam_read_reg_field(base, P_DF_CNTXT(pipe),
@@ -1568,7 +1688,9 @@
 	SPS_INFO("    DF_OFFSET: 0x%x\n", p_df_offset);
 
 	SPS_INFO("BAM_P_DESC_FIFO_ADDR: 0x%x\n", p_desc_fifo_addr);
+	SPS_INFO("BAM_P_DESC_FIFO_ADDR_MSB: 0x%x\n", p_desc_fifo_addr_msb);
 	SPS_INFO("BAM_P_DATA_FIFO_ADDR: 0x%x\n", p_data_fifo_addr);
+	SPS_INFO("BAM_P_DATA_FIFO_ADDR_MSB: 0x%x\n", p_data_fifo_addr_msb);
 	SPS_INFO("BAM_P_FIFO_SIZES: 0x%x\n", p_fifo_sizes);
 	SPS_INFO("    DESC_FIFO_SIZE: 0x%x (%d)\n", p_desc_fifo_size,
 							p_desc_fifo_size);
@@ -1576,6 +1698,7 @@
 							p_data_fifo_size);
 
 	SPS_INFO("BAM_P_EVNT_DEST_ADDR: 0x%x\n", p_evnt_dest);
+	SPS_INFO("BAM_P_EVNT_DEST_ADDR_MSB: 0x%x\n", p_evnt_dest_msb);
 	SPS_INFO("BAM_P_EVNT_GEN_TRSHLD: 0x%x\n", p_evnt_trd);
 	SPS_INFO("    EVNT_GEN_TRSHLD: 0x%x (%d)\n", p_evnt_trd_val,
 							p_evnt_trd_val);
@@ -1583,6 +1706,7 @@
 	SPS_INFO("BAM_P_AU_PSM_CNTXT_1: 0x%x\n", p_au_ct1);
 	SPS_INFO("BAM_P_PSM_CNTXT_2: 0x%x\n", p_psm_ct2);
 	SPS_INFO("BAM_P_PSM_CNTXT_3: 0x%x\n", p_psm_ct3);
+	SPS_INFO("BAM_P_PSM_CNTXT_3_MSB: 0x%x\n", p_psm_ct3_msb);
 	SPS_INFO("BAM_P_PSM_CNTXT_4: 0x%x\n", p_psm_ct4);
 	SPS_INFO("BAM_P_PSM_CNTXT_5: 0x%x\n", p_psm_ct5);
 	SPS_INFO("BAM_P_TIMER: 0x%x\n", p_timer);
diff --git a/drivers/platform/msm/sps/bam.h b/drivers/platform/msm/sps/bam.h
index 2a7f05b..d34a7d3 100644
--- a/drivers/platform/msm/sps/bam.h
+++ b/drivers/platform/msm/sps/bam.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
@@ -72,7 +72,7 @@
 	enum bam_pipe_dir dir;
 	enum bam_pipe_mode mode;
 	enum bam_write_nwd write_nwd;
-	u32 desc_base;	/* Physical address of descriptor FIFO */
+	phys_addr_t desc_base;	/* Physical address of descriptor FIFO */
 	u32 desc_size;	/* Size (bytes) of descriptor FIFO */
 	u32 lock_group;	/* The lock group this pipe belongs to */
 	enum bam_stream_mode stream_mode;
@@ -81,7 +81,7 @@
 	/* The following are only valid if mode is BAM2BAM */
 	u32 peer_phys_addr;
 	u32 peer_pipe;
-	u32 data_base;	/* Physical address of data FIFO */
+	phys_addr_t data_base;	/* Physical address of data FIFO */
 	u32 data_size;	/* Size (bytes) of data FIFO */
 };
 
@@ -139,12 +139,14 @@
  *
  * @version - return BAM hardware version
  *
+ * @ee - BAM execution environment index
+ *
  * @num_pipes - return number of pipes
  *
  * @return 0 on success, negative value on error
  *
  */
-int bam_check(void *base, u32 *version, u32 *num_pipes);
+int bam_check(void *base, u32 *version, u32 ee, u32 *num_pipes);
 
 /**
  * Disable a BAM device
@@ -159,6 +161,17 @@
 void bam_exit(void *base, u32 ee);
 
 /**
+ * This function prints BAM register content
+ * including TEST_BUS and PIPE register content.
+ *
+ * @base - BAM virtual base address.
+ *
+ * @ee - BAM execution environment index
+ */
+void bam_output_register_content(void *base, u32 ee);
+
+
+/**
  * Get BAM IRQ source and clear global IRQ status
  *
  * This function gets BAM IRQ source.
@@ -178,6 +191,7 @@
 u32 bam_check_irq_source(void *base, u32 ee, u32 mask,
 				enum sps_callback_case *cb_case);
 
+
 /**
  * Initialize a BAM pipe
  *
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 2e77114..6ccfd29 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -80,6 +80,7 @@
 static struct sps_drv *sps;
 
 u32 d_type;
+bool enhd_pipe;
 
 static void sps_device_de_init(void);
 
@@ -1610,7 +1611,7 @@
  * Perform a single DMA transfer on an SPS connection end point
  *
  */
-int sps_transfer_one(struct sps_pipe *h, u32 addr, u32 size,
+int sps_transfer_one(struct sps_pipe *h, phys_addr_t addr, u32 size,
 		     void *user, u32 flags)
 {
 	struct sps_pipe *pipe = h;
@@ -1632,7 +1633,8 @@
 		return SPS_ERROR;
 
 	result = sps_bam_pipe_transfer_one(bam, pipe->pipe_index,
-					   addr, size, user, flags);
+				SPS_GET_LOWER_ADDR(addr), size, user,
+				DESC_FLAG_WORD(flags, addr));
 
 	sps_bam_unlock(bam);
 
@@ -2454,6 +2456,11 @@
 	} else
 		SPS_DBG("sps:device type is %d.", d_type);
 
+	enhd_pipe = of_property_read_bool((&pdev->dev)->of_node,
+			"qcom,pipe-attr-ee");
+	SPS_DBG2("sps:PIPE_ATTR_EE is %s supported.\n",
+			(enhd_pipe ? "" : "not"));
+
 	return 0;
 }
 
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index 80056f5..d972e7b 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -76,7 +76,9 @@
 	{SPS_EVENT_INACTIVE, SPS_O_INACTIVE, BAM_PIPE_IRQ_TIMER},
 	{SPS_EVENT_OUT_OF_DESC, SPS_O_OUT_OF_DESC,
 		BAM_PIPE_IRQ_OUT_OF_DESC},
-	{SPS_EVENT_ERROR, SPS_O_ERROR, BAM_PIPE_IRQ_ERROR}
+	{SPS_EVENT_ERROR, SPS_O_ERROR, BAM_PIPE_IRQ_ERROR},
+	{SPS_EVENT_RST_ERROR, SPS_O_RST_ERROR, BAM_PIPE_IRQ_RST_ERROR},
+	{SPS_EVENT_HRESP_ERROR, SPS_O_HRESP_ERROR, BAM_PIPE_IRQ_HRESP_ERROR}
 };
 
 /* Pipe event source handler */
@@ -260,7 +262,8 @@
 				  dev->props.options);
 	else
 		/* No, so just verify that it is enabled */
-		rc = bam_check(dev->base, &dev->version, &num_pipes);
+		rc = bam_check(dev->base, &dev->version,
+				dev->props.ee, &num_pipes);
 
 	if (rc) {
 		SPS_ERR("sps:Fail to init BAM 0x%x IRQ %d\n",
@@ -1283,14 +1286,19 @@
 
 	desc->addr = addr;
 	desc->size = size;
+
 	if ((flags & SPS_IOVEC_FLAG_DEFAULT) == 0) {
-		desc->flags = flags & BAM_IOVEC_FLAG_MASK;
+		desc->flags = (flags & BAM_IOVEC_FLAG_MASK)
+				| DESC_UPPER_ADDR(flags);
 	} else {
 		if (pipe->mode == SPS_MODE_SRC)
-			desc->flags = SPS_IOVEC_FLAG_INT;
+			desc->flags = SPS_IOVEC_FLAG_INT
+					| DESC_UPPER_ADDR(flags);
 		else
-			desc->flags = SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT;
+			desc->flags = (SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT)
+					| DESC_UPPER_ADDR(flags);
 	}
+
 #ifdef SPS_BAM_STATISTICS
 	if ((flags & SPS_IOVEC_FLAG_INT))
 		pipe->sys.int_flags++;
@@ -1763,6 +1771,30 @@
 			return;
 	}
 
+	if ((status & SPS_O_RST_ERROR) && enhd_pipe) {
+		SPS_ERR("sps:bam 0x%x ;pipe 0x%x irq status=0x%x.\n"
+				"sps: BAM_PIPE_IRQ_RST_ERROR\n",
+				BAM_ID(dev), pipe_index, status);
+		bam_output_register_content(dev->base, dev->props.ee);
+		pipe_handler_generic(dev, pipe,
+					     SPS_EVENT_RST_ERROR);
+		status &= ~SPS_O_RST_ERROR;
+		if (status == 0)
+			return;
+	}
+
+	if ((status & SPS_O_HRESP_ERROR) && enhd_pipe) {
+		SPS_ERR("sps:bam 0x%x ;pipe 0x%x irq status=0x%x.\n"
+				"sps: BAM_PIPE_IRQ_HRESP_ERROR\n",
+				BAM_ID(dev), pipe_index, status);
+		bam_output_register_content(dev->base, dev->props.ee);
+		pipe_handler_generic(dev, pipe,
+					     SPS_EVENT_HRESP_ERROR);
+		status &= ~SPS_O_HRESP_ERROR;
+		if (status == 0)
+			return;
+	}
+
 	if ((status & SPS_EVENT_ERROR))
 		pipe_handler_generic(dev, pipe, SPS_EVENT_ERROR);
 }
diff --git a/drivers/platform/msm/sps/sps_bam.h b/drivers/platform/msm/sps/sps_bam.h
index dede487..da5dafd 100644
--- a/drivers/platform/msm/sps/sps_bam.h
+++ b/drivers/platform/msm/sps/sps_bam.h
@@ -50,6 +50,10 @@
 	BAM_PIPE_IRQ_ERROR = 0x00000010,
 	/* End-Of-Transfer */
 	BAM_PIPE_IRQ_EOT = 0x00000020,
+	/* Pipe RESET unsuccessful */
+	BAM_PIPE_IRQ_RST_ERROR = 0x00000040,
+	/* Errorneous Hresponse by AHB MASTER */
+	BAM_PIPE_IRQ_HRESP_ERROR = 0x00000080,
 };
 
 /* Halt Type */
diff --git a/drivers/platform/msm/sps/sps_map.c b/drivers/platform/msm/sps/sps_map.c
index d007b31..70735c3 100644
--- a/drivers/platform/msm/sps/sps_map.c
+++ b/drivers/platform/msm/sps/sps_map.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
@@ -96,16 +96,16 @@
 	 */
 	desc = spsi_get_mem_ptr(map->desc_base);
 	if (desc == NULL) {
-		SPS_ERR("sps:Cannot get virt addr for I/O buffer: 0x%x",
-			map->desc_base);
+		SPS_ERR("sps:Cannot get virt addr for I/O buffer: %pa\n",
+			&map->desc_base);
 		return SPS_ERROR;
 	}
 
 	if (map->data_size > 0 && map->data_base != SPS_ADDR_INVALID) {
 		data = spsi_get_mem_ptr(map->data_base);
 		if (data == NULL) {
-			SPS_ERR("sps:Can't get virt addr for I/O buffer: 0x%x",
-				map->data_base);
+			SPS_ERR("sps:Can't get virt addr for I/O buffer: %pa",
+				&map->data_base);
 			return SPS_ERROR;
 		}
 	} else {
diff --git a/drivers/platform/msm/sps/sps_map.h b/drivers/platform/msm/sps/sps_map.h
index 7db8043..7ee4713 100644
--- a/drivers/platform/msm/sps/sps_map.h
+++ b/drivers/platform/msm/sps/sps_map.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, 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
@@ -36,9 +36,9 @@
 
 	/* Resource parameters */
 	u32 config;	 /* Configuration (stream) identifier */
-	u32 desc_base;	 /* Physical address of descriptor FIFO */
+	phys_addr_t desc_base;	 /* Physical address of descriptor FIFO */
 	u32 desc_size;	 /* Size (bytes) of descriptor FIFO */
-	u32 data_base;	 /* Physical address of data FIFO */
+	phys_addr_t data_base;	 /* Physical address of data FIFO */
 	u32 data_size;	 /* Size (bytes) of data FIFO */
 
 };
diff --git a/drivers/platform/msm/sps/sps_mem.c b/drivers/platform/msm/sps/sps_mem.c
index b44e3c4..faa1618 100644
--- a/drivers/platform/msm/sps/sps_mem.c
+++ b/drivers/platform/msm/sps/sps_mem.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
@@ -25,7 +25,7 @@
 #include "sps_bam.h"
 #include "spsi.h"
 
-static u32 iomem_phys;
+static phys_addr_t iomem_phys;
 static void *iomem_virt;
 static u32 iomem_size;
 static u32 iomem_offset;
@@ -40,7 +40,7 @@
  * Translate physical to virtual address
  *
  */
-void *spsi_get_mem_ptr(u32 phys_addr)
+void *spsi_get_mem_ptr(phys_addr_t phys_addr)
 {
 	void *virt = NULL;
 
@@ -49,8 +49,8 @@
 		virt = (u8 *) iomem_virt + (phys_addr - iomem_phys);
 	} else {
 		virt = phys_to_virt(phys_addr);
-		SPS_ERR("sps:spsi_get_mem_ptr.invalid phys addr=0x%x.",
-			phys_addr);
+		SPS_ERR("sps:spsi_get_mem_ptr.invalid phys addr=0x%pa.",
+			&phys_addr);
 	}
 	return virt;
 }
@@ -59,9 +59,9 @@
  * Allocate I/O (pipe) memory
  *
  */
-u32 sps_mem_alloc_io(u32 bytes)
+phys_addr_t sps_mem_alloc_io(u32 bytes)
 {
-	u32 phys_addr = SPS_ADDR_INVALID;
+	phys_addr_t phys_addr = SPS_ADDR_INVALID;
 	u32 virt_addr = 0;
 
 	virt_addr = gen_pool_alloc(pool, bytes);
@@ -74,8 +74,8 @@
 		return SPS_ADDR_INVALID;
 	}
 
-	SPS_DBG2("sps:sps_mem_alloc_io.phys=0x%x.virt=0x%x.size=0x%x.",
-		phys_addr, virt_addr, bytes);
+	SPS_DBG2("sps:sps_mem_alloc_io.phys=%pa.virt=0x%x.size=0x%x.",
+		&phys_addr, virt_addr, bytes);
 
 	return phys_addr;
 }
@@ -84,15 +84,15 @@
  * Free I/O memory
  *
  */
-void sps_mem_free_io(u32 phys_addr, u32 bytes)
+void sps_mem_free_io(phys_addr_t phys_addr, u32 bytes)
 {
 	u32 virt_addr = 0;
 
 	iomem_offset = phys_addr - iomem_phys;
 	virt_addr = (u32) iomem_virt + iomem_offset;
 
-	SPS_DBG2("sps:sps_mem_free_io.phys=0x%x.virt=0x%x.size=0x%x.",
-		phys_addr, virt_addr, bytes);
+	SPS_DBG2("sps:sps_mem_free_io.phys=%pa.virt=0x%x.size=0x%x.",
+		&phys_addr, virt_addr, bytes);
 
 	gen_pool_free(pool, virt_addr, bytes);
 	total_free += bytes;
@@ -102,7 +102,7 @@
  * Initialize driver memory module
  *
  */
-int sps_mem_init(u32 pipemem_phys_base, u32 pipemem_size)
+int sps_mem_init(phys_addr_t pipemem_phys_base, u32 pipemem_size)
 {
 	int res;
 
@@ -125,8 +125,8 @@
 		}
 
 		iomem_offset = 0;
-		SPS_DBG("sps:sps_mem_init.iomem_phys=0x%x,iomem_virt=0x%x.",
-			iomem_phys, (u32) iomem_virt);
+		SPS_DBG("sps:sps_mem_init.iomem_phys=%pa,iomem_virt=0x%x.",
+			&iomem_phys, (u32) iomem_virt);
 	}
 
 	pool = gen_pool_create(min_alloc_order, nid);
diff --git a/drivers/platform/msm/sps/sps_rm.c b/drivers/platform/msm/sps/sps_rm.c
index 2b46203..7d7e1a6 100644
--- a/drivers/platform/msm/sps/sps_rm.c
+++ b/drivers/platform/msm/sps/sps_rm.c
@@ -499,8 +499,8 @@
 		map->desc.phys_base = map->alloc_desc_base;
 		map->desc.base = spsi_get_mem_ptr(map->desc.phys_base);
 		if (map->desc.base == NULL) {
-			SPS_ERR("sps:Cannot get virt addr for I/O buffer:0x%x",
-				map->desc.phys_base);
+			SPS_ERR("sps:Cannot get virt addr for I/O buffer:%pa",
+				&map->desc.phys_base);
 			goto exit_err;
 		}
 	}
@@ -516,8 +516,8 @@
 		map->data.phys_base = map->alloc_data_base;
 		map->data.base = spsi_get_mem_ptr(map->data.phys_base);
 		if (map->data.base == NULL) {
-			SPS_ERR("sps:Cannot get virt addr for I/O buffer:0x%x",
-				map->data.phys_base);
+			SPS_ERR("sps:Cannot get virt addr for I/O buffer:%pa",
+				&map->data.phys_base);
 			goto exit_err;
 		}
 	}
diff --git a/drivers/platform/msm/sps/spsi.h b/drivers/platform/msm/sps/spsi.h
index 8da3b40..f65fef7 100644
--- a/drivers/platform/msm/sps/spsi.h
+++ b/drivers/platform/msm/sps/spsi.h
@@ -27,6 +27,12 @@
 
 #include "sps_map.h"
 
+#ifdef CONFIG_ARM_LPAE
+#define SPS_LPAE (true)
+#else
+#define SPS_LPAE (false)
+#endif
+
 #define BAM_MAX_PIPES              31
 #define BAM_MAX_P_LOCK_GROUP_NUM   31
 
@@ -43,6 +49,7 @@
 #define MAX_MSG_LEN 80
 
 extern u32 d_type;
+extern bool enhd_pipe;
 
 #ifdef CONFIG_DEBUG_FS
 extern u8 debugfs_record_enabled;
@@ -165,8 +172,9 @@
 	/* Dynamically allocated resouces, if required */
 	u32 alloc_src_pipe;	/* Source pipe index */
 	u32 alloc_dest_pipe;	/* Destination pipe index */
-	u32 alloc_desc_base;	/* Physical address of descriptor FIFO */
-	u32 alloc_data_base;	/* Physical address of data FIFO */
+	/* Physical address of descriptor FIFO */
+	phys_addr_t alloc_desc_base;
+	phys_addr_t alloc_data_base;	/* Physical address of data FIFO */
 };
 
 /* Event bookkeeping descriptor struct */
@@ -218,7 +226,7 @@
  * @return virtual memory pointer
  *
  */
-void *spsi_get_mem_ptr(u32 phys_addr);
+void *spsi_get_mem_ptr(phys_addr_t phys_addr);
 
 /**
  * Allocate I/O (pipe) memory
@@ -229,7 +237,7 @@
  *
  * @return physical address of allocated memory, or SPS_ADDR_INVALID on error
  */
-u32 sps_mem_alloc_io(u32 bytes);
+phys_addr_t sps_mem_alloc_io(u32 bytes);
 
 /**
  * Free I/O (pipe) memory
@@ -240,7 +248,7 @@
  *
  * @bytes - number of bytes to free.
  */
-void sps_mem_free_io(u32 phys_addr, u32 bytes);
+void sps_mem_free_io(phys_addr_t phys_addr, u32 bytes);
 
 /**
  * Find matching connection mapping
@@ -324,7 +332,7 @@
  * @return 0 on success, negative value on error
  *
  */
-int sps_mem_init(u32 pipemem_phys_base, u32 pipemem_size);
+int sps_mem_init(phys_addr_t pipemem_phys_base, u32 pipemem_size);
 
 /**
  * De-initialize driver memory module
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 4889a79..7c73a82 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -140,6 +140,7 @@
 	int bus_suspend;
 	bool disconnected;
 	bool in_lpm[MAX_BAMS];
+	bool pending_lpm;
 
 	int (*wake_cb)(void *);
 	void *wake_param;
@@ -634,15 +635,25 @@
 static void usb_bam_start_lpm(bool disconnect)
 {
 	struct usb_phy *trans = usb_get_transceiver();
+
 	BUG_ON(trans == NULL);
-		pr_debug("%s: Going to LPM\n", __func__);
+
 	spin_lock(&usb_bam_ipa_handshake_info_lock);
+
 	info.lpm_wait_handshake[HSUSB_BAM] = false;
 	info.lpm_wait_pipes = 0;
+
 	if (disconnect)
 		pm_runtime_put_noidle(trans->dev);
-	spin_unlock(&usb_bam_ipa_handshake_info_lock);
-	pm_runtime_suspend(trans->dev);
+
+	if (info.pending_lpm) {
+		info.pending_lpm = 0;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_debug("%s: Going to LPM\n", __func__);
+		pm_runtime_suspend(trans->dev);
+	} else
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
 }
 
 int usb_bam_connect(u8 idx, u32 *bam_pipe_idx)
@@ -1438,6 +1449,7 @@
 			info.lpm_wait_handshake[HSUSB_BAM] = true;
 			info.connect_complete = 0;
 			info.disconnected = 0;
+			info.pending_lpm = 0;
 			info.lpm_wait_pipes = 1;
 			info.bus_suspend = 0;
 			info.cons_stopped = 0;
@@ -1998,8 +2010,18 @@
 			ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
 				ipa_rm_resource_cons[cur_bam]);
 		}
-		pr_debug("%s Ended disconnect sequence\n", __func__);
-		usb_bam_start_lpm(1);
+
+		if (cur_bam == HSUSB_BAM) {
+			/*
+			 * Currently we have for HSUSB BAM only one consumer
+			 * pipe. Therefore ending disconnect sequence and
+			 * starting hsusb lpm. This limitation will be changed
+			 * in future patch.
+			 */
+			pr_debug("%s Ended disconnect sequence\n", __func__);
+			usb_bam_start_lpm(1);
+		}
+
 		mutex_unlock(&info.suspend_resume_mutex);
 		return 0;
 	}
@@ -2138,6 +2160,7 @@
 	u8 i = 0;
 	bool reset_bam;
 	enum usb_bam bam;
+	u32 addr;
 
 	ctx.max_connections = 0;
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
@@ -2154,9 +2177,11 @@
 	}
 
 	rc = of_property_read_u32(node, "qcom,usb-bam-fifo-baseaddr",
-		&pdata->usb_bam_fifo_baseaddr);
+			&addr);
 	if (rc)
 		pr_debug("%s: Invalid usb base address property\n", __func__);
+	else
+		pdata->usb_bam_fifo_baseaddr = addr;
 
 	pdata->ignore_core_reset_ack = of_property_read_bool(node,
 		"qcom,ignore-core-reset-ack");
@@ -2629,10 +2654,12 @@
 {
 	spin_lock(&usb_bam_ipa_handshake_info_lock);
 	if (info.lpm_wait_handshake[HSUSB_BAM] || info.lpm_wait_pipes) {
+		info.pending_lpm = 1;
 		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Scheduling LPM for later\n", __func__);
 		return 0;
 	} else {
+		info.pending_lpm = 0;
 		info.in_lpm[HSUSB_BAM] = true;
 		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Going to LPM now\n", __func__);
@@ -2641,6 +2668,16 @@
 }
 EXPORT_SYMBOL(msm_bam_lpm_ok);
 
+void msm_bam_notify_lpm_resume()
+{
+	/*
+	 * If core was resumed from lpm, just clear the
+	 * pending indication, in case it is set.
+	*/
+	info.pending_lpm = 0;
+}
+EXPORT_SYMBOL(msm_bam_notify_lpm_resume);
+
 static int usb_bam_remove(struct platform_device *pdev)
 {
 	destroy_workqueue(ctx.usb_bam_wq);
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 1fd4434..b518f1f 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -22,8 +22,8 @@
 #include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/ccadc.h>
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
 #include <linux/mfd/pm8xxx/batt-alarm.h>
+#include <linux/batterydata-lib.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/debugfs.h>
@@ -2118,6 +2118,10 @@
 	if (the_chip->start_percent == -EINVAL)
 		return prev_soc;
 
+	/* do not scale at 100 */
+	if (new_soc == 100)
+		return new_soc;
+
 	chg_time_sec = DIV_ROUND_UP(the_chip->charge_time_us, USEC_PER_SEC);
 	catch_up_sec = DIV_ROUND_UP(the_chip->catch_up_time_us, USEC_PER_SEC);
 	if (catch_up_sec == 0)
@@ -2501,7 +2505,7 @@
 	}
 
 	/* last_soc < soc  ... scale and catch up */
-	if (last_soc != -EINVAL && last_soc < soc && soc != 100)
+	if (last_soc != -EINVAL && last_soc < soc)
 		soc = scale_soc_while_chg(chip, delta_time_us, soc, last_soc);
 
 	if (last_soc != -EINVAL) {
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 1ad7f21..d5b2cc6 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -2616,8 +2616,7 @@
 {
 	if (usb_target_ma)
 		schedule_delayed_work(&the_chip->vin_collapse_check_work,
-				      round_jiffies_relative(msecs_to_jiffies
-						(VIN_MIN_COLLAPSE_CHECK_MS)));
+			      msecs_to_jiffies(VIN_MIN_COLLAPSE_CHECK_MS));
 	else
 	    handle_usb_insertion_removal(data);
 	return IRQ_HANDLED;
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 11e6cc1..982c30b 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -147,7 +147,9 @@
 	POWER_SUPPLY_ATTR(voltage_min_design),
 	POWER_SUPPLY_ATTR(voltage_now),
 	POWER_SUPPLY_ATTR(voltage_avg),
+	POWER_SUPPLY_ATTR(input_voltage_regulation),
 	POWER_SUPPLY_ATTR(current_max),
+	POWER_SUPPLY_ATTR(input_current_max),
 	POWER_SUPPLY_ATTR(current_now),
 	POWER_SUPPLY_ATTR(current_avg),
 	POWER_SUPPLY_ATTR(power_now),
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 14d5b6a..86d923d 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -25,11 +25,11 @@
 #include <linux/delay.h>
 #include <linux/qpnp/qpnp-adc.h>
 #include <linux/qpnp/power-on.h>
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/of_batterydata.h>
 
 /* BMS Register Offsets */
-#define BMS1_REVISION1			0x0
-#define BMS1_REVISION2			0x1
+#define REVISION1			0x0
+#define REVISION2			0x1
 #define BMS1_STATUS1			0x8
 #define BMS1_MODE_CTL			0X40
 /* Coulomb counter clear registers */
@@ -64,15 +64,16 @@
 /* Extra bms registers */
 #define SOC_STORAGE_REG			0xB0
 #define IAVG_STORAGE_REG		0xB1
-#define BMS_BATT_REMOVED_REG		0xB2
-#define BMS1_BMS_DATA_REG_3		0xB3
-#define CHARGE_INCREASE_STORAGE		0xB4
-#define FCC_BATT_TEMP_STORAGE		0xB5
-#define FCC_STORAGE_LSB			0xBC /* LSB=0xBC, MSB=0xBD */
+#define BMS_FCC_COUNT			0xB2
+#define BMS_FCC_BASE_REG		0xB3 /* FCC updates - 0xB3 to 0xB7 */
+#define BMS_CHGCYL_BASE_REG		0xB8 /* FCC chgcyl - 0xB8 to 0xBC */
+#define CHARGE_INCREASE_STORAGE		0xBD
 #define CHARGE_CYCLE_STORAGE_LSB	0xBE /* LSB=0xBE, MSB=0xBF */
 
 /* IADC Channel Select */
 #define IADC1_BMS_ADC_CH_SEL_CTL	0x48
+#define IADC1_BMS_ADC_INT_RSNSN_CTL	0x49
+#define IADC1_BMS_FAST_AVG_EN		0x5B
 
 /* Configuration for saving of shutdown soc/iavg */
 #define IGNORE_SOC_TEMP_DECIDEG		50
@@ -84,8 +85,11 @@
 #define IAVG_SAMPLES 16
 
 /* FCC learning constants */
+#define MAX_FCC_CYCLES				5
 #define DELTA_FCC_PERCENT                       5
 #define VALID_FCC_CHGCYL_RANGE                  50
+#define CHGCYL_RESOLUTION			20
+#define FCC_DEFAULT_TEMP			250
 
 #define QPNP_BMS_DEV_NAME "qcom,qpnp-bms"
 
@@ -116,9 +120,8 @@
 	int		last_good_ocv_uv;
 };
 
-struct fcc_data {
+struct fcc_sample {
 	int fcc_new;
-	int batt_temp;
 	int chargecycles;
 };
 
@@ -143,6 +146,10 @@
 
 	u8				revision1;
 	u8				revision2;
+
+	u8				iadc_bms_revision1;
+	u8				iadc_bms_revision2;
+
 	int				battery_present;
 	int				battery_status;
 	bool				new_battery;
@@ -244,7 +251,8 @@
 	int				ocv_low_threshold_uv;
 	unsigned long			last_recalc_time;
 
-	struct fcc_data			*fcc_table;
+	struct fcc_sample		*fcc_learning_samples;
+	u8				fcc_sample_count;
 	int				enable_fcc_learning;
 	int				min_fcc_learning_soc;
 	int				min_fcc_ocv_pc;
@@ -259,8 +267,8 @@
 	int				fcc_new_batt_temp;
 	uint16_t			charge_cycles;
 	u8				charge_increase;
-	int				fcc_new_sysfs;
-	int				fcc_update_complete;
+	int				fcc_resolution;
+	bool				battery_removed;
 	struct bms_irq			sw_cc_thr_irq;
 	struct bms_irq			ocv_thr_irq;
 };
@@ -285,45 +293,10 @@
 	POWER_SUPPLY_PROP_CYCLE_COUNT,
 };
 
+static int discard_backup_fcc_data(struct qpnp_bms_chip *chip);
+static void backup_charge_cycle(struct qpnp_bms_chip *chip);
+
 static bool bms_reset;
-static int min_fcc_cycles = -EINVAL;
-static int last_fcc_update_count;
-static int battery_removed;
-
-static int
-bms_ro_ops_set(const char *val, const struct kernel_param *kp)
-{
-	return -EINVAL;
-}
-
-static int
-bms_last_fcc_count_set(const char *val, const struct kernel_param *kp)
-{
-	int rc;
-
-	if (battery_removed) {
-		last_fcc_update_count = 0;
-		return 0;
-	}
-	rc = param_set_int(val, kp);
-	if (rc)
-		pr_err("Failed to set last_fcc_update_count rc=%d\n", rc);
-
-	return rc;
-}
-
-static struct kernel_param_ops bms_ro_param_ops = {
-	.set = bms_ro_ops_set,
-	.get = param_get_int,
-};
-static struct kernel_param_ops bms_last_fcc_count_param_ops = {
-	.set = bms_last_fcc_count_set,
-	.get = param_get_int,
-};
-module_param_cb(min_fcc_cycles, &bms_ro_param_ops, &min_fcc_cycles, 0644);
-module_param_cb(battery_removed, &bms_ro_param_ops, &battery_removed, 0644);
-module_param_cb(last_fcc_update_count, &bms_last_fcc_count_param_ops,
-						&last_fcc_update_count, 0644);
 
 static int qpnp_read_wrapper(struct qpnp_bms_chip *chip, u8 *val,
 			u16 base, int count)
@@ -871,6 +844,19 @@
 	chip->last_cc_uah = INT_MIN;
 	chip->last_ocv_temp = batt_temp;
 	chip->prev_batt_terminal_uv = 0;
+	if (chip->enable_fcc_learning) {
+		chip->adjusted_fcc_temp_lut = NULL;
+		chip->fcc_new_mah = -EINVAL;
+		/* reset the charge-cycle and charge-increase registers */
+		chip->charge_increase = 0;
+		chip->charge_cycles = 0;
+		backup_charge_cycle(chip);
+		/* discard all the FCC learnt data and reset the local table */
+		discard_backup_fcc_data(chip);
+		memset(chip->fcc_learning_samples, 0,
+			chip->min_fcc_learning_samples *
+				sizeof(struct fcc_sample));
+	}
 }
 
 #define OCV_RAW_UNINITIALIZED	0xFFFF
@@ -2342,12 +2328,14 @@
 
 	bms_stay_awake(&chip->soc_wake_source);
 	mutex_lock(&chip->vbat_monitor_mutex);
-	qpnp_adc_tm_channel_measure(&chip->vbat_monitor_params);
+	if (chip->vbat_monitor_params.state_request !=
+			ADC_TM_HIGH_LOW_THR_DISABLE)
+		qpnp_adc_tm_channel_measure(&chip->vbat_monitor_params);
 	mutex_unlock(&chip->vbat_monitor_mutex);
 	if (chip->use_voltage_soc) {
 		soc = calculate_soc_from_voltage(chip);
 	} else {
-		qpnp_iadc_calibrate_for_trim();
+		qpnp_iadc_calibrate_for_trim(true);
 		rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
 		if (rc) {
 			pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
@@ -2539,9 +2527,10 @@
 	int rc;
 
 	chip->vbat_monitor_params.state_request = ADC_TM_HIGH_LOW_THR_DISABLE;
-	rc = qpnp_adc_tm_channel_measure(&chip->vbat_monitor_params);
+
+	rc = qpnp_adc_tm_disable_chan_meas(&chip->vbat_monitor_params);
 	if (rc) {
-		pr_err("tm measure failed: %d\n", rc);
+		pr_err("tm disable failed: %d\n", rc);
 		return rc;
 	}
 	if (wake_lock_active(&chip->low_voltage_wake_lock)) {
@@ -2565,11 +2554,6 @@
 		return -EPROBE_DEFER;
 	}
 
-	if (!is_battery_present(chip)) {
-		pr_debug("no battery inserted, do not setup vbat monitoring\n");
-		return 0;
-	}
-
 	chip->vbat_monitor_params.low_thr = chip->low_voltage_threshold;
 	chip->vbat_monitor_params.high_thr = chip->max_voltage_uv
 							- VBATT_ERROR_MARGIN;
@@ -2581,10 +2565,17 @@
 	pr_debug("set low thr to %d and high to %d\n",
 			chip->vbat_monitor_params.low_thr,
 			chip->vbat_monitor_params.high_thr);
-	rc = qpnp_adc_tm_channel_measure(&chip->vbat_monitor_params);
-	if (rc) {
-		pr_err("tm setup failed: %d\n", rc);
-		return rc;
+
+	if (!is_battery_present(chip)) {
+		pr_debug("no battery inserted, do not enable vbat monitoring\n");
+		chip->vbat_monitor_params.state_request =
+			ADC_TM_HIGH_LOW_THR_DISABLE;
+	} else {
+		rc = qpnp_adc_tm_channel_measure(&chip->vbat_monitor_params);
+		if (rc) {
+			pr_err("tm setup failed: %d\n", rc);
+			return rc;
+		}
 	}
 	pr_debug("setup complete\n");
 	return 0;
@@ -2624,26 +2615,85 @@
 	kfree(old);
 }
 
-
-static void backup_fcc_new(struct qpnp_bms_chip *chip)
+static int read_fcc_data_from_backup(struct qpnp_bms_chip *chip)
 {
-	int rc = 0;
-	u8 temp = 0;
+	int rc, i;
+	u8 fcc = 0, chgcyl = 0;
 
-	if (chip->fcc_new_mah > 0) {
-		rc = qpnp_write_wrapper(chip, (u8 *)&chip->fcc_new_mah,
-					chip->base + FCC_STORAGE_LSB, 2);
-		if (rc)
-			pr_err("Unable to backup new_fcc\n");
-
-		temp = chip->fcc_new_batt_temp / 10;
-		rc = qpnp_write_wrapper(chip, &temp,
-				chip->base + FCC_BATT_TEMP_STORAGE, 1);
-		if (rc)
-			pr_err("Unable to backup fcc temp.\n");
+	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+		rc = qpnp_read_wrapper(chip, &fcc,
+			chip->base + BMS_FCC_BASE_REG + i, 1);
+		rc |= qpnp_read_wrapper(chip, &chgcyl,
+			chip->base + BMS_CHGCYL_BASE_REG + i, 1);
+		if (rc) {
+			pr_err("Unable to read FCC data\n");
+			return rc;
+		}
+		if (fcc == 0 || (fcc == 0xFF && chgcyl == 0xFF)) {
+			/* FCC invalid/not present */
+			chip->fcc_learning_samples[i].fcc_new = 0;
+			chip->fcc_learning_samples[i].chargecycles = 0;
+		} else {
+			/* valid FCC data */
+			chip->fcc_sample_count++;
+			chip->fcc_learning_samples[i].fcc_new =
+						fcc * chip->fcc_resolution;
+			chip->fcc_learning_samples[i].chargecycles =
+						chgcyl * CHGCYL_RESOLUTION;
+		}
 	}
+
+	return 0;
 }
 
+static int discard_backup_fcc_data(struct qpnp_bms_chip *chip)
+{
+	int rc = 0, i;
+	u8 temp_u8 = 0;
+
+	chip->fcc_sample_count = 0;
+	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+		rc = qpnp_write_wrapper(chip, &temp_u8,
+			chip->base + BMS_FCC_BASE_REG + i, 1);
+		rc |= qpnp_write_wrapper(chip, &temp_u8,
+			chip->base + BMS_CHGCYL_BASE_REG + i, 1);
+		if (rc) {
+			pr_err("Unable to clear FCC data\n");
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+static void
+average_fcc_samples_and_readjust_fcc_table(struct qpnp_bms_chip *chip)
+{
+	int i, temp_fcc_avg = 0, temp_fcc_delta = 0, new_fcc_avg = 0;
+	struct fcc_sample *ft;
+
+	for (i = 0; i < chip->min_fcc_learning_samples; i++)
+		temp_fcc_avg += chip->fcc_learning_samples[i].fcc_new;
+
+	temp_fcc_avg /= chip->min_fcc_learning_samples;
+	temp_fcc_delta = div_u64(temp_fcc_avg * DELTA_FCC_PERCENT, 100);
+
+	/* fix the fcc if its an outlier i.e. > 5% of the average */
+	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+		ft = &chip->fcc_learning_samples[i];
+		if (abs(ft->fcc_new - temp_fcc_avg) > temp_fcc_delta)
+			new_fcc_avg += temp_fcc_avg;
+		else
+			new_fcc_avg += ft->fcc_new;
+	}
+	new_fcc_avg /= chip->min_fcc_learning_samples;
+
+	chip->fcc_new_mah = new_fcc_avg;
+	chip->fcc_new_batt_temp = FCC_DEFAULT_TEMP;
+	pr_info("FCC update: New fcc_mah=%d, fcc_batt_temp=%d\n",
+				new_fcc_avg, FCC_DEFAULT_TEMP);
+	readjust_fcc_table(chip);
+}
 
 static void backup_charge_cycle(struct qpnp_bms_chip *chip)
 {
@@ -2651,7 +2701,7 @@
 
 	if (chip->charge_increase >= 0) {
 		rc = qpnp_write_wrapper(chip, &chip->charge_increase,
-				chip->base + CHARGE_INCREASE_STORAGE, 1);
+			chip->base + CHARGE_INCREASE_STORAGE, 1);
 		if (rc)
 			pr_err("Unable to backup charge_increase\n");
 	}
@@ -2664,9 +2714,31 @@
 	}
 }
 
-static void restore_fcc_data(struct qpnp_bms_chip *chip)
+static bool chargecycles_in_range(struct qpnp_bms_chip *chip)
 {
-	int rc = 0;
+	int i, min_cycle, max_cycle, valid_range;
+
+	/* find the smallest and largest charge cycle */
+	max_cycle = min_cycle = chip->fcc_learning_samples[0].chargecycles;
+	for (i = 1; i < chip->min_fcc_learning_samples; i++) {
+		if (min_cycle > chip->fcc_learning_samples[i].chargecycles)
+			min_cycle = chip->fcc_learning_samples[i].chargecycles;
+		if (max_cycle < chip->fcc_learning_samples[i].chargecycles)
+			max_cycle = chip->fcc_learning_samples[i].chargecycles;
+	}
+
+	/* check if chargecyles are in range to continue with FCC update */
+	valid_range = DIV_ROUND_UP(VALID_FCC_CHGCYL_RANGE,
+					CHGCYL_RESOLUTION) * CHGCYL_RESOLUTION;
+	if (abs(max_cycle - min_cycle) > valid_range)
+		return false;
+
+	return true;
+}
+
+static int read_chgcycle_data_from_backup(struct qpnp_bms_chip *chip)
+{
+	int rc;
 	uint16_t temp_u16 = 0;
 	u8 temp_u8 = 0;
 
@@ -2680,25 +2752,18 @@
 	if (!rc && temp_u16 != 0xFFFF)
 		chip->charge_cycles = temp_u16;
 
-	rc = qpnp_read_wrapper(chip, (u8 *)&temp_u16,
-				chip->base + FCC_STORAGE_LSB, 2);
-	if (!rc && temp_u16 != 0xFFFF) {
-		chip->fcc_new_mah = temp_u16;
-	} else {
-		pr_debug("Backed-up FCC not initialized, FCC not updated\n");
-		return;
-	}
+	return rc;
+}
 
-	rc = qpnp_read_wrapper(chip, &temp_u8,
-				chip->base + FCC_BATT_TEMP_STORAGE, 1);
-	if (!rc && temp_u8 != 0xFF) {
-		chip->fcc_new_batt_temp = (s8)temp_u8 * 10;
-	} else {
-		pr_debug("Backed-up temp. not initialized, FCC not updated\n");
-		return;
-	}
-	/* readjust the FCC table if fcc and temp are valid */
-	readjust_fcc_table(chip);
+static void
+attempt_learning_new_fcc(struct qpnp_bms_chip *chip)
+{
+	pr_debug("Total FCC sample count=%d\n", chip->fcc_sample_count);
+
+	/* update FCC if we have the required samples */
+	if ((chip->fcc_sample_count == chip->min_fcc_learning_samples) &&
+						chargecycles_in_range(chip))
+		average_fcc_samples_and_readjust_fcc_table(chip);
 }
 
 static int calculate_real_soc(struct qpnp_bms_chip *chip,
@@ -2712,82 +2777,80 @@
 	return ((rc_uah - cc_uah) * 100) / fcc_uah;
 }
 
-static void update_fcc_table_for_temp(struct qpnp_bms_chip *chip,
-						int batt_temp_final)
-{
-	int i, fcc_t1, fcc_t2, fcc_final;
-	struct fcc_data *ft;
+#define MAX_U8_VALUE		((u8)(~0U))
 
-	/* Interpolate all the FCC entries to the same temperature */
-	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
-		ft = &chip->fcc_table[i];
-		if (ft->batt_temp == batt_temp_final)
-			continue;
-		fcc_t1 = interpolate_fcc(chip->fcc_temp_lut, ft->batt_temp);
-		fcc_t2 = interpolate_fcc(chip->fcc_temp_lut, batt_temp_final);
-		fcc_final = (ft->fcc_new / fcc_t1) * fcc_t2;
-		ft->fcc_new = fcc_final;
-		ft->batt_temp = batt_temp_final;
+static int backup_new_fcc(struct qpnp_bms_chip *chip, int fcc_mah,
+							int chargecycles)
+{
+	int rc, min_cycle, i;
+	u8 fcc_new, chgcyl, pos = 0;
+	struct fcc_sample *ft;
+
+	if ((fcc_mah > (chip->fcc_resolution * MAX_U8_VALUE)) ||
+		(chargecycles > (CHGCYL_RESOLUTION * MAX_U8_VALUE))) {
+		pr_warn("FCC/Chgcyl beyond storage limit. FCC=%d, chgcyl=%d\n",
+							fcc_mah, chargecycles);
+		return -EINVAL;
 	}
+
+	if (chip->fcc_sample_count == chip->min_fcc_learning_samples) {
+		/* search best location - oldest entry */
+		min_cycle = chip->fcc_learning_samples[0].chargecycles;
+		for (i = 1; i < chip->min_fcc_learning_samples; i++) {
+			if (min_cycle >
+				chip->fcc_learning_samples[i].chargecycles)
+				pos = i;
+		}
+	} else {
+		/* find an empty location */
+		for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+			ft = &chip->fcc_learning_samples[i];
+			if (ft->fcc_new == 0 || (ft->fcc_new == 0xFF &&
+						ft->chargecycles == 0xFF)) {
+				pos = i;
+				break;
+			}
+		}
+		chip->fcc_sample_count++;
+	}
+	chip->fcc_learning_samples[pos].fcc_new = fcc_mah;
+	chip->fcc_learning_samples[pos].chargecycles = chargecycles;
+
+	fcc_new = DIV_ROUND_UP(fcc_mah, chip->fcc_resolution);
+	rc = qpnp_write_wrapper(chip, (u8 *)&fcc_new,
+			chip->base + BMS_FCC_BASE_REG + pos, 1);
+	if (rc)
+		return rc;
+
+	chgcyl = DIV_ROUND_UP(chargecycles, CHGCYL_RESOLUTION);
+	rc = qpnp_write_wrapper(chip, (u8 *)&chgcyl,
+			chip->base + BMS_CHGCYL_BASE_REG + pos, 1);
+	if (rc)
+		return rc;
+
+	pr_debug("Backup new FCC: fcc_new=%d, chargecycle=%d, pos=%d\n",
+						fcc_new, chgcyl, pos);
+
+	return rc;
 }
 
 static void update_fcc_learning_table(struct qpnp_bms_chip *chip,
-		int fcc_uah, int new_fcc_uah, int chargecycles, int batt_temp)
+			int new_fcc_uah, int chargecycles, int batt_temp)
 {
-	int i, count, new_fcc_avg = 0, temp_fcc_avg = 0, temp_fcc_delta = 0;
-	struct fcc_data *ft;
+	int rc, fcc_default, fcc_temp;
 
-	count = last_fcc_update_count % chip->min_fcc_learning_samples;
-	ft = &chip->fcc_table[count];
-	ft->fcc_new = chip->fcc_new_sysfs = new_fcc_uah;
-	ft->batt_temp = batt_temp;
-	ft->chargecycles = chargecycles;
-	last_fcc_update_count++;
-	/* update userspace */
-	sysfs_notify(&chip->dev->kobj, NULL, "fcc_data");
+	/* convert the fcc at batt_temp to new fcc at FCC_DEFAULT_TEMP */
+	fcc_default = calculate_fcc(chip, FCC_DEFAULT_TEMP) / 1000;
+	fcc_temp = calculate_fcc(chip, batt_temp) / 1000;
+	new_fcc_uah = (new_fcc_uah / fcc_temp) * fcc_default;
 
-	pr_debug("Updated fcc table. new_fcc=%d, chargecycle=%d, temp=%d fcc_update_count=%d\n",
-		new_fcc_uah, chargecycles, batt_temp, last_fcc_update_count);
-
-	if (last_fcc_update_count < chip->min_fcc_learning_samples) {
-		pr_debug("Not enough FCC samples. Current count = %d\n",
-						last_fcc_update_count);
-		return; /* Not enough samples to update fcc */
+	rc = backup_new_fcc(chip, new_fcc_uah / 1000, chargecycles);
+	if (rc) {
+		pr_err("Unable to backup new FCC\n");
+		return;
 	}
-
-	/* reject entries if they are > 50 chargecycles apart */
-	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
-		if ((chip->fcc_table[i].chargecycles + VALID_FCC_CHGCYL_RANGE)
-							< chargecycles) {
-			pr_debug("Charge cycle too old (> %d cycles apart)\n",
-							VALID_FCC_CHGCYL_RANGE);
-			return; /* Samples old, > 50 cycles apart*/
-		}
-	}
-	/* update the fcc table for temperature difference*/
-	update_fcc_table_for_temp(chip, batt_temp);
-
-	for (i = 0; i < chip->min_fcc_learning_samples; i++)
-		temp_fcc_avg += chip->fcc_table[i].fcc_new;
-
-	temp_fcc_avg /= chip->min_fcc_learning_samples;
-	temp_fcc_delta = div_u64(temp_fcc_avg * DELTA_FCC_PERCENT, 100);
-
-	/* fix the fcc if its an outlier i.e. > 5% of the average */
-	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
-		ft = &chip->fcc_table[i];
-		if (abs(ft->fcc_new - temp_fcc_avg) > temp_fcc_delta)
-			ft->fcc_new = temp_fcc_avg;
-		new_fcc_avg += ft->fcc_new;
-	}
-	new_fcc_avg /= chip->min_fcc_learning_samples;
-
-	chip->fcc_new_mah = new_fcc_avg / 1000;
-	chip->fcc_new_batt_temp = batt_temp;
-	pr_info("FCC update: New fcc_mah=%d, fcc_batt_temp=%d\n",
-					new_fcc_avg, batt_temp);
-	readjust_fcc_table(chip);
-	backup_fcc_new(chip);
+	/* check if FCC can be updated */
+	attempt_learning_new_fcc(chip);
 }
 
 static bool is_new_fcc_valid(int new_fcc_uah, int fcc_uah)
@@ -2841,8 +2904,8 @@
 			chip->start_cc_uah, chip->end_cc_uah, new_fcc_uah);
 
 		if (is_new_fcc_valid(new_fcc_uah, fcc_uah))
-			update_fcc_learning_table(chip, fcc_uah,
-				new_fcc_uah, chip->charge_cycles, batt_temp);
+			update_fcc_learning_table(chip, new_fcc_uah,
+					chip->charge_cycles, batt_temp);
 	}
 }
 
@@ -2938,6 +3001,8 @@
 	}
 }
 
+#define CALIB_WRKARND_DIG_MAJOR_MAX		0x03
+
 static void battery_insertion_check(struct qpnp_bms_chip *chip)
 {
 	bool present = is_battery_present(chip);
@@ -3013,123 +3078,6 @@
 	return 0;
 }
 
-static ssize_t fcc_data_set(struct device *dev, struct device_attribute *attr,
-						const char *buf, size_t count)
-{
-	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-	static int i;
-	int fcc_new = 0, rc;
-
-	if (chip->fcc_update_complete) {
-		pr_debug("Invalid FCC update\n");
-		return count;
-	}
-
-	i %= chip->min_fcc_learning_samples;
-	rc = sscanf(buf, "%d", &fcc_new);
-	if (rc != 1)
-		return -EINVAL;
-	chip->fcc_table[i].fcc_new = fcc_new;
-	pr_debug("Rcvd: [%d] fcc_new=%d\n", i, fcc_new);
-	i++;
-
-	return count;
-}
-
-static ssize_t fcc_data_get(struct device *dev, struct device_attribute *attr,
-								char *buf)
-{
-	int count = 0;
-	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
-	count = snprintf(buf, PAGE_SIZE, "%d", chip->fcc_new_sysfs);
-	pr_debug("Sent: fcc_new=%d\n", chip->fcc_new_sysfs);
-	chip->fcc_update_complete = 1;
-
-	return count;
-}
-
-static ssize_t fcc_temp_set(struct device *dev, struct device_attribute *attr,
-						const char *buf, size_t count)
-{
-	static int i;
-	int batt_temp = 0, rc;
-	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
-	if (chip->fcc_update_complete)
-		return count;
-
-	i %= chip->min_fcc_learning_samples;
-	rc = sscanf(buf, "%d", &batt_temp);
-	if (rc != 1)
-		return -EINVAL;
-	chip->fcc_table[i].batt_temp = batt_temp;
-	pr_debug("Rcvd: [%d] batt_temp=%d\n", i, batt_temp);
-	i++;
-
-	return count;
-}
-
-static ssize_t fcc_chgcyl_set(struct device *dev, struct device_attribute *attr,
-						const char *buf, size_t count)
-{
-	static int i;
-	int chargecycle = 0, rc;
-	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
-	if (chip->fcc_update_complete)
-		return count;
-
-	i %= chip->min_fcc_learning_samples;
-	rc = sscanf(buf, "%d", &chargecycle);
-	if (rc != 1)
-		return -EINVAL;
-	chip->fcc_table[i].chargecycles = chargecycle;
-	pr_debug("Rcvd: [%d] chargecycle=%d\n", i, chargecycle);
-	i++;
-
-	return count;
-}
-
-static ssize_t fcc_list_get(struct device *dev, struct device_attribute *attr,
-								char *buf)
-{
-	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-	struct fcc_data *ft;
-	int i = 0, j, count = 0;
-
-	if (last_fcc_update_count < chip->min_fcc_learning_samples)
-		i = last_fcc_update_count;
-	else
-		i = chip->min_fcc_learning_samples;
-
-	for (j = 0; j < i; j++) {
-		ft = &chip->fcc_table[j];
-		count += snprintf(buf + count, PAGE_SIZE - count,
-			"%d %d %d\n", ft->fcc_new, ft->chargecycles,
-			ft->batt_temp);
-	}
-
-	return count;
-}
-
-static DEVICE_ATTR(fcc_data, 0664, fcc_data_get, fcc_data_set);
-static DEVICE_ATTR(fcc_temp, 0664, NULL, fcc_temp_set);
-static DEVICE_ATTR(fcc_chgcyl, 0664, NULL, fcc_chgcyl_set);
-static DEVICE_ATTR(fcc_list, 0664, fcc_list_get, NULL);
-
-static struct attribute *fcc_attrs[] = {
-	&dev_attr_fcc_data.attr,
-	&dev_attr_fcc_temp.attr,
-	&dev_attr_fcc_chgcyl.attr,
-	&dev_attr_fcc_list.attr,
-	NULL
-};
-
-static const struct attribute_group fcc_attr_group = {
-	.attrs = fcc_attrs,
-};
-
 #define OCV_USE_LIMIT_EN		BIT(7)
 static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
 					int low_voltage_threshold,
@@ -3213,10 +3161,19 @@
 		}
 	}
 
-	pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d\n",
+	/* read the SOC storage to determine if there was a battery removal */
+	rc = qpnp_read_wrapper(chip, &temp, chip->base + SOC_STORAGE_REG, 1);
+	if (!rc) {
+		if (temp == SOC_INVALID)
+			chip->battery_removed = true;
+	}
+
+
+	pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d, battery_removed = %d\n",
 			chip->shutdown_soc,
 			chip->shutdown_iavg_ma,
-			chip->shutdown_soc_invalid);
+			chip->shutdown_soc_invalid,
+			chip->battery_removed);
 }
 
 static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *_chip)
@@ -3239,11 +3196,7 @@
 	return IRQ_HANDLED;
 }
 
-#define PALLADIUM_ID_MIN	0x7F40
-#define PALLADIUM_ID_MAX	0x7F5A
-#define DESAY_5200_ID_MIN	0x7F7F
-#define DESAY_5200_ID_MAX	0x802F
-static int32_t read_battery_id(struct qpnp_bms_chip *chip)
+static int64_t read_battery_id(struct qpnp_bms_chip *chip)
 {
 	int rc;
 	struct qpnp_vadc_result result;
@@ -3254,16 +3207,16 @@
 					LR_MUX2_BAT_ID, rc);
 		return rc;
 	}
-	pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
-						result.measurement);
-	pr_debug("raw_code = 0x%x\n", result.adc_code);
-	return result.adc_code;
+
+	return result.physical;
 }
 
 static int set_battery_data(struct qpnp_bms_chip *chip)
 {
 	int64_t battery_id;
+	int rc;
 	struct bms_battery_data *batt_data;
+	struct device_node *node;
 
 	if (chip->batt_type == BATT_DESAY) {
 		batt_data = &desay_5200_data;
@@ -3283,12 +3236,30 @@
 			return battery_id;
 		}
 
-		if (is_between(PALLADIUM_ID_MIN, PALLADIUM_ID_MAX,
-							battery_id)) {
-			batt_data = &palladium_1500_data;
-		} else if (is_between(DESAY_5200_ID_MIN, DESAY_5200_ID_MAX,
-					battery_id)) {
-			batt_data = &desay_5200_data;
+		node = of_find_node_by_name(chip->spmi->dev.of_node,
+				"qcom,battery-data");
+		if (node) {
+			batt_data = kzalloc(sizeof(struct bms_battery_data),
+					GFP_KERNEL);
+			batt_data->fcc_temp_lut = kzalloc(
+					sizeof(struct single_row_lut),
+					GFP_KERNEL);
+			batt_data->pc_temp_ocv_lut = kzalloc(
+					sizeof(struct pc_temp_ocv_lut),
+					GFP_KERNEL);
+			batt_data->rbatt_sf_lut = kzalloc(
+					sizeof(struct sf_lut), GFP_KERNEL);
+
+			rc = of_batterydata_read_data(node,
+					batt_data, battery_id);
+			if (rc) {
+				pr_err("battery data load failed, using palladium 1500\n");
+				kfree(batt_data->fcc_temp_lut);
+				kfree(batt_data->pc_temp_ocv_lut);
+				kfree(batt_data->rbatt_sf_lut);
+				kfree(batt_data);
+				batt_data = &palladium_1500_data;
+			}
 		} else {
 			pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
 					battery_id);
@@ -3306,6 +3277,14 @@
 	chip->rbatt_capacitive_mohm = batt_data->rbatt_capacitive_mohm;
 	chip->flat_ocv_threshold_uv = batt_data->flat_ocv_threshold_uv;
 
+	/* Override battery properties if specified in the battery profile */
+	if (batt_data->max_voltage_uv >= 0)
+		chip->max_voltage_uv = batt_data->max_voltage_uv;
+	if (batt_data->cutoff_uv >= 0)
+		chip->v_cutoff_uv = batt_data->cutoff_uv;
+	if (batt_data->iterm_ua >= 0)
+		chip->chg_term_ua = batt_data->iterm_ua;
+
 	if (chip->pc_temp_ocv_lut == NULL) {
 		pr_err("temp ocv lut table is NULL\n");
 		return -EINVAL;
@@ -3325,6 +3304,12 @@
 	}								\
 } while (0)
 
+#define SPMI_PROP_READ_BOOL(chip_prop, qpnp_spmi_property)		\
+do {									\
+	chip->chip_prop = of_property_read_bool(chip->spmi->dev.of_node,\
+				"qcom," qpnp_spmi_property);		\
+} while (0)
+
 static inline int bms_read_properties(struct qpnp_bms_chip *chip)
 {
 	int rc;
@@ -3371,8 +3356,7 @@
 	if (chip->adjust_soc_low_threshold >= 45)
 		chip->adjust_soc_low_threshold = 45;
 
-	chip->enable_fcc_learning = of_property_read_bool(
-		chip->spmi->dev.of_node, "qcom,enable-fcc-learning");
+	SPMI_PROP_READ_BOOL(enable_fcc_learning, "enable-fcc-learning");
 	if (chip->enable_fcc_learning) {
 		SPMI_PROP_READ(min_fcc_learning_soc,
 				"min-fcc-learning-soc", rc);
@@ -3380,12 +3364,16 @@
 				"min-fcc-ocv-pc", rc);
 		SPMI_PROP_READ(min_fcc_learning_samples,
 				"min-fcc-learning-samples", rc);
-		chip->fcc_table = kzalloc((sizeof(struct fcc_data) *
-			chip->min_fcc_learning_samples), GFP_KERNEL);
+		SPMI_PROP_READ(fcc_resolution,
+				"fcc-resolution", rc);
+		if (chip->min_fcc_learning_samples > MAX_FCC_CYCLES)
+			chip->min_fcc_learning_samples = MAX_FCC_CYCLES;
+		chip->fcc_learning_samples = devm_kzalloc(&chip->spmi->dev,
+				(sizeof(struct fcc_sample) *
+				chip->min_fcc_learning_samples), GFP_KERNEL);
 		pr_debug("min-fcc-soc=%d, min-fcc-pc=%d, min-fcc-cycles=%d\n",
 			chip->min_fcc_learning_soc, chip->min_fcc_ocv_pc,
 			chip->min_fcc_learning_samples);
-		min_fcc_cycles = chip->min_fcc_learning_samples;
 	}
 
 	pr_debug("dts data: r_sense_uohm:%d, v_cutoff_uv:%d, max_v:%d\n",
@@ -3533,7 +3521,11 @@
 	return 0;
 }
 
-#define ADC_CH_SEL_MASK			0x7
+#define ADC_CH_SEL_MASK				0x7
+#define ADC_INT_RSNSN_CTL_MASK			0x3
+#define ADC_INT_RSNSN_CTL_VALUE_EXT_RENSE	0x2
+#define FAST_AVG_EN_MASK			0x80
+#define FAST_AVG_EN_VALUE_EXT_RSENSE		0x80
 static int read_iadc_channel_select(struct qpnp_bms_chip *chip)
 {
 	u8 iadc_channel_select;
@@ -3601,6 +3593,34 @@
 		pr_debug("rds_rsense = %d nOhm, saved as %d uOhm\n",
 					rds_rsense_nohm, chip->r_sense_uohm);
 	}
+	/* prevent shorting of leads by IADC_BMS when external Rsense is used */
+	if (chip->use_external_rsense) {
+		if (chip->iadc_bms_revision2 > CALIB_WRKARND_DIG_MAJOR_MAX) {
+			rc = qpnp_masked_write_iadc(chip,
+					IADC1_BMS_ADC_INT_RSNSN_CTL,
+					ADC_INT_RSNSN_CTL_MASK,
+					ADC_INT_RSNSN_CTL_VALUE_EXT_RENSE);
+			if (rc) {
+				pr_err("Unable to set batfet config %x to %x: %d\n",
+					IADC1_BMS_ADC_INT_RSNSN_CTL,
+					ADC_INT_RSNSN_CTL_VALUE_EXT_RENSE, rc);
+				return rc;
+			}
+		} else {
+			/* In older PMICS use FAST_AVG_EN register bit 7 */
+			rc = qpnp_masked_write_iadc(chip,
+					IADC1_BMS_FAST_AVG_EN,
+					FAST_AVG_EN_MASK,
+					FAST_AVG_EN_VALUE_EXT_RSENSE);
+			if (rc) {
+				pr_err("Unable to set batfet config %x to %x: %d\n",
+					IADC1_BMS_FAST_AVG_EN,
+					FAST_AVG_EN_VALUE_EXT_RSENSE, rc);
+				return rc;
+			}
+		}
+	}
+
 	return 0;
 }
 
@@ -3662,28 +3682,6 @@
 	return 0;
 }
 
-static void check_battery_removal(struct qpnp_bms_chip *chip)
-{
-	int rc;
-	u8 temp = 0;
-
-	/* check if battery was removed at PON */
-	rc = qpnp_read_wrapper(chip, &temp,
-				chip->base + BMS_BATT_REMOVED_REG, 1);
-	if (temp == 0xFF) {
-		pr_debug("New battery inserted at PON\n");
-		temp = battery_removed = 1;
-		rc = qpnp_write_wrapper(chip, &temp,
-				chip->base + BMS_BATT_REMOVED_REG, 1);
-		if (rc)
-			pr_err("Unable to set BMS_BATT_REMOVED_REG\n");
-	} else {
-		if (rc)
-			pr_err("Unable to read BMS_BATT_REMOVED_REG\n");
-		battery_removed = 0;
-	}
-}
-
 static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
 {
 	struct qpnp_bms_chip *chip;
@@ -3711,6 +3709,12 @@
 		goto error_read;
 	}
 
+	mutex_init(&chip->bms_output_lock);
+	mutex_init(&chip->last_ocv_uv_mutex);
+	mutex_init(&chip->vbat_monitor_mutex);
+	mutex_init(&chip->soc_invalidation_mutex);
+	mutex_init(&chip->last_soc_mutex);
+
 	warm_reset = qpnp_pon_is_warm_reset();
 	rc = warm_reset;
 	if (rc < 0)
@@ -3723,20 +3727,36 @@
 	}
 
 	rc = qpnp_read_wrapper(chip, &chip->revision1,
-			chip->base + BMS1_REVISION1, 1);
+			chip->base + REVISION1, 1);
 	if (rc) {
 		pr_err("error reading version register %d\n", rc);
 		goto error_read;
 	}
 
 	rc = qpnp_read_wrapper(chip, &chip->revision2,
-			chip->base + BMS1_REVISION2, 1);
+			chip->base + REVISION2, 1);
 	if (rc) {
 		pr_err("Error reading version register %d\n", rc);
 		goto error_read;
 	}
 	pr_debug("BMS version: %hhu.%hhu\n", chip->revision2, chip->revision1);
 
+	rc = qpnp_read_wrapper(chip, &chip->iadc_bms_revision2,
+			chip->iadc_base + REVISION2, 1);
+	if (rc) {
+		pr_err("Error reading version register %d\n", rc);
+		goto error_read;
+	}
+
+	rc = qpnp_read_wrapper(chip, &chip->iadc_bms_revision1,
+			chip->iadc_base + REVISION1, 1);
+	if (rc) {
+		pr_err("Error reading version register %d\n", rc);
+		goto error_read;
+	}
+	pr_debug("IADC_BMS version: %hhu.%hhu\n",
+			chip->iadc_bms_revision2, chip->iadc_bms_revision1);
+
 	rc = bms_read_properties(chip);
 	if (rc) {
 		pr_err("Unable to read all bms properties, rc = %d\n", rc);
@@ -3768,12 +3788,6 @@
 
 	bms_initialize_constants(chip);
 
-	mutex_init(&chip->bms_output_lock);
-	mutex_init(&chip->last_ocv_uv_mutex);
-	mutex_init(&chip->vbat_monitor_mutex);
-	mutex_init(&chip->soc_invalidation_mutex);
-	mutex_init(&chip->last_soc_mutex);
-
 	wakeup_source_init(&chip->soc_wake_source.source, "qpnp_soc_wake");
 	wake_lock_init(&chip->low_voltage_wake_lock, WAKE_LOCK_SUSPEND,
 			"qpnp_low_voltage_lock");
@@ -3786,20 +3800,26 @@
 	read_shutdown_soc_and_iavg(chip);
 
 	if (chip->enable_fcc_learning) {
-		restore_fcc_data(chip);
-		rc = sysfs_create_group(&spmi->dev.kobj, &fcc_attr_group);
-		if (rc) {
-			pr_err("Unable to create sysfs entries\n");
-			goto error_setup;
+		if (chip->battery_removed) {
+			rc = discard_backup_fcc_data(chip);
+			if (rc)
+				pr_err("Could not discard backed-up FCC data\n");
+		} else {
+			rc = read_chgcycle_data_from_backup(chip);
+			if (rc)
+				pr_err("Unable to restore charge-cycle data\n");
+
+			rc = read_fcc_data_from_backup(chip);
+			if (rc)
+				pr_err("Unable to restore FCC-learning data\n");
+			else
+				attempt_learning_new_fcc(chip);
 		}
 	}
 
 	dev_set_drvdata(&spmi->dev, chip);
 	device_init_wakeup(&spmi->dev, 1);
 
-	check_battery_removal(chip);
-
-
 	rc = setup_vbat_monitoring(chip);
 	if (rc < 0) {
 		pr_err("failed to set up voltage notifications: %d\n", rc);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 2a007ca..88e00ba 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -28,6 +28,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/regulator/machine.h>
+#include <linux/of_batterydata.h>
 
 /* Interrupt offsets */
 #define INT_RT_STS(base)			(base + 0x10)
@@ -273,6 +274,7 @@
 	struct qpnp_chg_irq		chg_failed;
 	struct qpnp_chg_irq		chg_vbatdet_lo;
 	struct qpnp_chg_irq		batt_pres;
+	struct qpnp_chg_irq		vchg_loop;
 	bool				bat_is_cool;
 	bool				bat_is_warm;
 	bool				chg_done;
@@ -290,6 +292,7 @@
 	unsigned int			safe_voltage_mv;
 	unsigned int			max_voltage_mv;
 	unsigned int			min_voltage_mv;
+	int				prev_usb_max_ma;
 	int				set_vddmax_mv;
 	int				delta_vddmax_mv;
 	unsigned int			warm_bat_mv;
@@ -650,6 +653,92 @@
 	return rc;
 }
 
+#define QPNP_CHG_VINMIN_MIN_MV		4200
+#define QPNP_CHG_VINMIN_HIGH_MIN_MV	5600
+#define QPNP_CHG_VINMIN_HIGH_MIN_VAL	0x2B
+#define QPNP_CHG_VINMIN_MAX_MV		9600
+#define QPNP_CHG_VINMIN_STEP_MV		50
+#define QPNP_CHG_VINMIN_STEP_HIGH_MV	200
+#define QPNP_CHG_VINMIN_MASK		0x1F
+#define QPNP_CHG_VINMIN_MIN_VAL	0x10
+static int
+qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
+{
+	u8 temp;
+
+	if (voltage < QPNP_CHG_VINMIN_MIN_MV
+			|| voltage > QPNP_CHG_VINMIN_MAX_MV) {
+		pr_err("bad mV=%d asked to set\n", voltage);
+		return -EINVAL;
+	}
+	if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
+		temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
+		temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
+			/ QPNP_CHG_VINMIN_STEP_HIGH_MV;
+	} else {
+		temp = QPNP_CHG_VINMIN_MIN_VAL;
+		temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
+			/ QPNP_CHG_VINMIN_STEP_MV;
+	}
+
+	pr_debug("voltage=%d setting %02x\n", voltage, temp);
+	return qpnp_chg_masked_write(chip,
+			chip->chgr_base + CHGR_VIN_MIN,
+			QPNP_CHG_VINMIN_MASK, temp, 1);
+}
+
+static int
+qpnp_chg_vinmin_get(struct qpnp_chg_chip *chip)
+{
+	int rc, vin_min_mv;
+	u8 vin_min;
+
+	rc = qpnp_chg_read(chip, &vin_min, chip->chgr_base + CHGR_VIN_MIN, 1);
+	if (rc) {
+		pr_err("failed to read VIN_MIN rc=%d\n", rc);
+		return 0;
+	}
+
+	if (vin_min == 0)
+		vin_min_mv = QPNP_CHG_I_MAX_MIN_100;
+	else if (vin_min > QPNP_CHG_VINMIN_HIGH_MIN_VAL)
+		vin_min_mv = QPNP_CHG_VINMIN_HIGH_MIN_MV +
+			(vin_min - QPNP_CHG_VINMIN_HIGH_MIN_VAL)
+				* QPNP_CHG_VINMIN_STEP_HIGH_MV;
+	else
+		vin_min_mv = QPNP_CHG_VINMIN_MIN_MV +
+			(vin_min - QPNP_CHG_VINMIN_MIN_VAL)
+				* QPNP_CHG_VINMIN_STEP_MV;
+	pr_debug("vin_min= 0x%02x, ma = %d\n", vin_min, vin_min_mv);
+
+	return vin_min_mv;
+}
+
+static int
+qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
+{
+	int rc, iusbmax_ma;
+	u8 iusbmax;
+
+	rc = qpnp_chg_read(chip, &iusbmax,
+		chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
+	if (rc) {
+		pr_err("failed to read IUSB_MAX rc=%d\n", rc);
+		return 0;
+	}
+
+	if (iusbmax == 0)
+		iusbmax_ma = QPNP_CHG_I_MAX_MIN_100;
+	else if (iusbmax == 0x01)
+		iusbmax_ma = QPNP_CHG_I_MAX_MIN_150;
+	else
+		iusbmax_ma = iusbmax * QPNP_CHG_I_MAXSTEP_MA;
+
+	pr_debug("iusbmax = 0x%02x, ma = %d\n", iusbmax, iusbmax_ma);
+
+	return iusbmax_ma;
+}
+
 #define USB_SUSPEND_BIT	BIT(0)
 static int
 qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
@@ -797,6 +886,17 @@
 		pr_err("request ADC error\n");
 }
 
+static irqreturn_t
+qpnp_chg_buck_vchg_loop_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+
+	if (chip->bat_if_base)
+		power_supply_changed(&chip->batt_psy);
+
+	return IRQ_HANDLED;
+}
+
 #define EOC_CHECK_PERIOD_MS	10000
 static irqreturn_t
 qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
@@ -867,6 +967,7 @@
 		if (!usb_present) {
 			qpnp_chg_usb_suspend_enable(chip, 1);
 			chip->chg_done = false;
+			chip->prev_usb_max_ma = -EINVAL;
 		} else {
 			schedule_delayed_work(&chip->eoc_work,
 				msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
@@ -966,6 +1067,12 @@
 qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
 {
 	struct qpnp_chg_chip *chip = _chip;
+	u8 chgr_sts;
+	int rc;
+
+	rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
+	if (rc)
+		pr_err("failed to read interrupt sts %d\n", rc);
 
 	pr_debug("FAST_CHG IRQ triggered\n");
 	chip->chg_done = false;
@@ -978,7 +1085,12 @@
 		chip->resuming_charging = false;
 		qpnp_chg_set_appropriate_vbatdet(chip);
 	}
+
 	qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
+	if (chgr_sts & FAST_CHG_ON_IRQ)
+		qpnp_chg_enable_irq(&chip->vchg_loop);
+	else
+		qpnp_chg_disable_irq(&chip->vchg_loop);
 
 	return IRQ_HANDLED;
 }
@@ -1004,6 +1116,8 @@
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
 	case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 		return 1;
 	default:
 		break;
@@ -1109,6 +1223,9 @@
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN,
+	POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 	POWER_SUPPLY_PROP_CHARGE_FULL,
 	POWER_SUPPLY_PROP_TEMP,
@@ -1124,6 +1241,9 @@
 	"bms",
 };
 
+static int charger_monitor;
+module_param(charger_monitor, int, 0644);
+
 #define USB_WALL_THRESHOLD_MA	500
 static int
 qpnp_power_get_property_mains(struct power_supply *psy,
@@ -1143,7 +1263,7 @@
 		val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
-		val->intval = chip->maxinput_dc_ma;
+		val->intval = chip->maxinput_dc_ma * 1000;
 		break;
 	default:
 		return -EINVAL;
@@ -1375,6 +1495,23 @@
 	return ret.intval;
 }
 
+static int get_prop_vchg_loop(struct qpnp_chg_chip *chip)
+{
+	u8 buck_sts;
+	int rc;
+
+	rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
+
+	if (rc) {
+		pr_err("spmi read failed: addr=%03X, rc=%d\n",
+				INT_RT_STS(chip->buck_base), rc);
+		return rc;
+	}
+	pr_debug("buck usb sts 0x%x\n", buck_sts);
+
+	return (buck_sts & VCHG_LOOP_IRQ) ? 1 : 0;
+}
+
 static void
 qpnp_batt_external_power_changed(struct power_supply *psy)
 {
@@ -1392,16 +1529,28 @@
 	if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
 		chip->usb_psy->get_property(chip->usb_psy,
 			  POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
+
+		if (chip->prev_usb_max_ma == ret.intval)
+			goto skip_set_iusb_max;
+
 		if (ret.intval <= 2 && !chip->use_default_batt_values &&
 						get_prop_batt_present(chip)) {
 			qpnp_chg_usb_suspend_enable(chip, 1);
 			qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
 		} else {
 			qpnp_chg_usb_suspend_enable(chip, 0);
-			qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
+			if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
+					&& (charger_monitor)) {
+				qpnp_chg_iusbmax_set(chip,
+						USB_WALL_THRESHOLD_MA);
+			} else {
+				qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
+			}
 		}
+		chip->prev_usb_max_ma = ret.intval;
 	}
 
+skip_set_iusb_max:
 	pr_debug("end of power supply changed\n");
 	power_supply_changed(&chip->batt_psy);
 }
@@ -1463,6 +1612,15 @@
 	case POWER_SUPPLY_PROP_CYCLE_COUNT:
 		val->intval = get_prop_cycle_count(chip);
 		break;
+	case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
+		val->intval = get_prop_vchg_loop(chip);
+		break;
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
+		val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+		val->intval = qpnp_chg_vinmin_get(chip) * 1000;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1502,38 +1660,6 @@
 			mask, btc_cfg, 1);
 }
 
-#define QPNP_CHG_VINMIN_MIN_MV		4200
-#define QPNP_CHG_VINMIN_HIGH_MIN_MV	5600
-#define QPNP_CHG_VINMIN_HIGH_MIN_VAL	0x2B
-#define QPNP_CHG_VINMIN_MAX_MV		9600
-#define QPNP_CHG_VINMIN_STEP_MV		50
-#define QPNP_CHG_VINMIN_STEP_HIGH_MV	200
-#define QPNP_CHG_VINMIN_MASK		0x1F
-static int
-qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
-{
-	u8 temp;
-
-	if (voltage < QPNP_CHG_VINMIN_MIN_MV
-			|| voltage > QPNP_CHG_VINMIN_MAX_MV) {
-		pr_err("bad mV=%d asked to set\n", voltage);
-		return -EINVAL;
-	}
-	if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
-		temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
-		temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
-			/ QPNP_CHG_VINMIN_STEP_HIGH_MV;
-	} else {
-		temp = (voltage - QPNP_CHG_VINMIN_MIN_MV)
-			/ QPNP_CHG_VINMIN_STEP_MV;
-	}
-
-	pr_debug("voltage=%d setting %02x\n", voltage, temp);
-	return qpnp_chg_masked_write(chip,
-			chip->chgr_base + CHGR_VIN_MIN,
-			QPNP_CHG_VINMIN_MASK, temp, 1);
-}
-
 #define QPNP_CHG_IBATSAFE_MIN_MA		100
 #define QPNP_CHG_IBATSAFE_MAX_MA		3250
 #define QPNP_CHG_I_STEP_MA		50
@@ -2214,6 +2340,12 @@
 	case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
 		qpnp_batt_system_temp_level_set(chip, val->intval);
 		break;
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
+		qpnp_chg_iusbmax_set(chip, val->intval / 1000);
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+		qpnp_chg_vinmin_set(chip, val->intval / 1000);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -2352,7 +2484,8 @@
 			}
 			rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
 				qpnp_chg_bat_if_batt_pres_irq_handler,
-				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+				| IRQF_SHARED | IRQF_ONESHOT,
 				"batt-pres", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d batt-pres irq: %d\n",
@@ -2362,6 +2495,29 @@
 
 			enable_irq_wake(chip->batt_pres.irq);
 			break;
+		case SMBB_BUCK_SUBTYPE:
+		case SMBBP_BUCK_SUBTYPE:
+		case SMBCL_BUCK_SUBTYPE:
+			chip->vchg_loop.irq = spmi_get_irq_byname(spmi,
+						spmi_resource, "vchg-loop");
+			if (chip->vchg_loop.irq < 0) {
+				pr_err("Unable to get vchg-loop irq\n");
+				return rc;
+			}
+			rc = devm_request_irq(chip->dev, chip->vchg_loop.irq,
+				qpnp_chg_buck_vchg_loop_irq_handler,
+				IRQF_TRIGGER_RISING,
+				"vchg-loop", chip);
+			if (rc < 0) {
+				pr_err("Can't request %d vchg-loop irq: %d\n",
+						chip->vchg_loop.irq, rc);
+				return rc;
+			}
+
+			enable_irq_wake(chip->vchg_loop.irq);
+			qpnp_chg_disable_irq(&chip->vchg_loop);
+			break;
+
 		case SMBB_USB_CHGPTH_SUBTYPE:
 		case SMBBP_USB_CHGPTH_SUBTYPE:
 		case SMBCL_USB_CHGPTH_SUBTYPE:
@@ -2425,6 +2581,41 @@
 	return rc;
 }
 
+static int
+qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
+{
+	struct bms_battery_data batt_data;
+	struct device_node *node;
+	struct qpnp_vadc_result result;
+	int rc;
+
+	node = of_find_node_by_name(chip->spmi->dev.of_node,
+			"qcom,battery-data");
+	if (node) {
+		memset(&batt_data, 0, sizeof(struct bms_battery_data));
+		rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
+		if (rc) {
+			pr_err("error reading batt id channel = %d, rc = %d\n",
+						LR_MUX2_BAT_ID, rc);
+			return rc;
+		}
+
+		rc = of_batterydata_read_data(node,
+				&batt_data, result.physical);
+		if (rc) {
+			pr_err("failed to read battery data: %d\n", rc);
+			return rc;
+		}
+
+		if (batt_data.max_voltage_uv >= 0)
+			chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
+		if (batt_data.iterm_ua >= 0)
+			chip->term_current = batt_data.iterm_ua / 1000;
+	}
+
+	return 0;
+}
+
 #define WDOG_EN_BIT	BIT(7)
 static int
 qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
@@ -2766,13 +2957,6 @@
 	chip->duty_cycle_100p = of_property_read_bool(
 					chip->spmi->dev.of_node,
 					"qcom,duty-cycle-100p");
-	if (chip->duty_cycle_100p) {
-		rc = qpnp_buck_set_100_duty_cycle_enable(chip, 1);
-		if (rc) {
-			pr_err("failed to enable duty cycle %d\n", rc);
-			return rc;
-		}
-	}
 
 	/* Get the fake-batt-values property */
 	chip->use_default_batt_values =
@@ -2824,6 +3008,7 @@
 		return -ENOMEM;
 	}
 
+	chip->prev_usb_max_ma = -EINVAL;
 	chip->dev = &(spmi->dev);
 	chip->spmi = spmi;
 
@@ -2839,7 +3024,10 @@
 	if (rc)
 		goto fail_chg_enable;
 
-	/* Check if bat_if is set in DT and make sure VADC is present */
+	/*
+	 * Check if bat_if is set in DT and make sure VADC is present
+	 * Also try loading the battery data profile if bat_if exists
+	 */
 	spmi_for_each_container_dev(spmi_resource, spmi) {
 		if (!spmi_resource) {
 			pr_err("qpnp_chg: spmi resource absent\n");
@@ -2869,6 +3057,10 @@
 			rc = qpnp_vadc_is_ready();
 			if (rc)
 				goto fail_chg_enable;
+
+			rc = qpnp_chg_load_battery_data(chip);
+			if (rc)
+				goto fail_chg_enable;
 		}
 	}
 
@@ -2938,6 +3130,16 @@
 				0xFF,
 				0x80, 1);
 
+			if (chip->duty_cycle_100p) {
+				rc = qpnp_buck_set_100_duty_cycle_enable(chip,
+						1);
+				if (rc) {
+					pr_err("failed to set duty cycle %d\n",
+						rc);
+					goto fail_chg_enable;
+				}
+			}
+
 			break;
 		case SMBB_BAT_IF_SUBTYPE:
 		case SMBBP_BAT_IF_SUBTYPE:
@@ -3182,6 +3384,66 @@
 	return rc;
 }
 
+static int
+qpnp_chg_ops_set(const char *val, const struct kernel_param *kp)
+{
+	return -EINVAL;
+}
+
+#define MAX_LEN_VADC	10
+static int
+qpnp_chg_usb_in_get(char *val, const struct kernel_param *kp)
+{
+	int rc;
+	struct qpnp_vadc_result results;
+
+	rc = qpnp_vadc_is_ready();
+	if (rc)
+		return rc;
+
+	rc = qpnp_vadc_read(USBIN, &results);
+	if (rc) {
+		pr_err("Unable to read vchg rc=%d\n", rc);
+		return 0;
+	}
+	rc = snprintf(val, MAX_LEN_VADC, "%lld\n", results.physical);
+
+	return rc;
+}
+
+static int
+qpnp_chg_vchg_get(char *val, const struct kernel_param *kp)
+{
+	int rc;
+	struct qpnp_vadc_result results;
+
+	rc = qpnp_vadc_is_ready();
+	if (rc)
+		return rc;
+
+	rc = qpnp_vadc_read(VCHG_SNS, &results);
+	if (rc) {
+		pr_err("Unable to read vchg rc=%d\n", rc);
+		return 0;
+	}
+	rc = snprintf(val, MAX_LEN_VADC, "%lld\n", results.physical);
+
+	return rc;
+}
+
+static struct kernel_param_ops usb_in_uv_param_ops = {
+	.set = qpnp_chg_ops_set,
+	.get = qpnp_chg_usb_in_get,
+};
+
+static struct kernel_param_ops vchg_uv_param_ops = {
+	.set = qpnp_chg_ops_set,
+	.get = qpnp_chg_vchg_get,
+};
+
+module_param_cb(usb_in_uv, &usb_in_uv_param_ops, NULL, 0644);
+module_param_cb(vchg_uv, &vchg_uv_param_ops, NULL, 0644);
+
 static const struct dev_pm_ops qpnp_chg_pm_ops = {
 	.resume		= qpnp_chg_resume,
 	.suspend	= qpnp_chg_suspend,
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index c7db832..863339b 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -1426,9 +1426,10 @@
 				dma_coherent_post_ops();
 				memcpy(dd->read_buf + offset, dd->rx_padding,
 				       dd->rx_unaligned_len);
-				memcpy(dd->cur_transfer->rx_buf,
-				       dd->read_buf + prev_xfr->len,
-				       dd->cur_transfer->len);
+				if (dd->cur_transfer->rx_buf)
+					memcpy(dd->cur_transfer->rx_buf,
+					       dd->read_buf + prev_xfr->len,
+					       dd->cur_transfer->len);
 			}
 		}
 		kfree(dd->temp_buf);
@@ -3121,7 +3122,7 @@
 	msm_spi_disable_irqs(dd);
 	clk_disable_unprepare(dd->clk);
 	clk_disable_unprepare(dd->pclk);
-	if (!dd->pdata->active_only)
+	if (dd->pdata && !dd->pdata->active_only)
 		msm_spi_clk_path_unvote(dd);
 
 	/* Free  the spi clk, miso, mosi, cs gpio */
diff --git a/drivers/spmi/qpnp-int.c b/drivers/spmi/qpnp-int.c
index 082c9ff..eedb1e5 100644
--- a/drivers/spmi/qpnp-int.c
+++ b/drivers/spmi/qpnp-int.c
@@ -578,11 +578,14 @@
 	unsigned long hwirq, busno;
 	int irq;
 
+	if (!spec || !spmi_ctrl)
+		return -EINVAL;
+
 	pr_debug("spec slave = %u per = %u irq = %u\n",
 					spec->slave, spec->per, spec->irq);
 
 	busno = spmi_ctrl->nr;
-	if (!spec || !spmi_ctrl || busno >= QPNPINT_MAX_BUSSES)
+	if (busno >= QPNPINT_MAX_BUSSES)
 		return -EINVAL;
 
 	hwirq = qpnpint_encode_hwirq(spec);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 52608af..6933163 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -77,6 +77,9 @@
 
 #define TSENS_EEPROM_8X10_1(n)		((n) + 0x1a4)
 #define TSENS_EEPROM_8X10_1_OFFSET	8
+#define TSENS_EEPROM_8X10_2(n)		((n) + 0x1a8)
+#define TSENS_EEPROM_8X10_SPARE_1(n)	((n) + 0xd8)
+#define TSENS_EEPROM_8X10_SPARE_2(n)	((n) + 0xdc)
 
 /* TSENS calibration Mask data */
 #define TSENS_BASE1_MASK		0xff
@@ -207,6 +210,8 @@
 #define TSENS_8X10_TSENS_CAL_SEL	0x70000000
 #define TSENS1_8X10_POINT1_MASK		0x3f
 #define TSENS1_8X10_POINT2_MASK		0xfc0
+#define TSENS_8X10_REDUN_SEL_MASK	0x6000000
+#define TSENS_8X10_REDUN_SEL_SHIFT	25
 
 #define TSENS_BIT_APPEND		0x3
 #define TSENS_CAL_DEGC_POINT1		30
@@ -559,6 +564,9 @@
 	unsigned int reg_cntl;
 	int code, hi_code, lo_code, code_err_chk, sensor_sw_id = 0, rc = 0;
 
+	if (!tm_sensor || trip < 0 || !temp)
+		return -EINVAL;
+
 	rc = tsens_get_sw_id_mapping(tm_sensor->sensor_hw_num, &sensor_sw_id);
 	if (rc < 0) {
 		pr_err("tsens mapping index not found\n");
@@ -721,17 +729,30 @@
 	int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
 	int tsens0_point2 = 0, tsens1_point2 = 0;
 	int tsens_base1_data = 0, tsens_calibration_mode = 0;
-	uint32_t calib_data[2];
+	uint32_t calib_data[2], calib_redun_sel;
 	uint32_t calib_tsens_point1_data[2], calib_tsens_point2_data[2];
 
 	if (tmdev->calibration_less_mode)
 		goto calibration_less_mode;
 
-	calib_data[0] = readl_relaxed(
+	calib_redun_sel = readl_relaxed(
+			TSENS_EEPROM_8X10_2(tmdev->tsens_calib_addr));
+	calib_redun_sel = calib_redun_sel & TSENS_8X10_REDUN_SEL_MASK;
+	calib_redun_sel >>= TSENS_8X10_REDUN_SEL_SHIFT;
+	pr_debug("calib_redun_sel:%x\n", calib_redun_sel);
+
+	if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) {
+		calib_data[0] = readl_relaxed(
+			TSENS_EEPROM_8X10_SPARE_1(tmdev->tsens_calib_addr));
+		calib_data[1] = readl_relaxed(
+			TSENS_EEPROM_8X10_SPARE_2(tmdev->tsens_calib_addr));
+	} else {
+		calib_data[0] = readl_relaxed(
 			TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr));
-	calib_data[1] = readl_relaxed(
-		(TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) +
+		calib_data[1] = readl_relaxed(
+			(TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) +
 					TSENS_EEPROM_8X10_1_OFFSET));
+	}
 
 	tsens_calibration_mode = (calib_data[0] & TSENS_8X10_TSENS_CAL_SEL)
 			>> TSENS_8X10_CAL_SEL_SHIFT;
@@ -1325,7 +1346,7 @@
 
 static int get_device_tree_data(struct platform_device *pdev)
 {
-	const struct device_node *of_node = pdev->dev.of_node;
+	struct device_node *of_node = pdev->dev.of_node;
 	struct resource *res_mem = NULL;
 	u32 *tsens_slope_data;
 	u32 *sensor_id;
@@ -1353,8 +1374,13 @@
 		return rc;
 	};
 
-	tsens_calib_mode = of_get_property(of_node,
-			"qcom,calib-mode", NULL);
+	rc = of_property_read_string(of_node,
+				"qcom,calib-mode", &tsens_calib_mode);
+	if (rc) {
+		dev_err(&pdev->dev, "missing calib-mode\n");
+		return -ENODEV;
+	}
+
 	if (!strncmp(tsens_calib_mode, "fuse_map1", 9))
 		calib_type = TSENS_CALIB_FUSE_MAP_8974;
 	else if (!strncmp(tsens_calib_mode, "fuse_map2", 9))
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 03c58a2..974cadc 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -1514,7 +1514,7 @@
 				goto read_node_fail;
 		}
 
-		rails[i].curr_level = 0;
+		rails[i].curr_level = -1;
 		rails[i].reg = NULL;
 		i++;
 	}
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index f3b29c9..3b0ef8c 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -1315,7 +1315,7 @@
 		return -ENODEV;
 
 	if (param->threshold_notification == NULL) {
-		pr_err("No notification for high/low temp??\n");
+		pr_debug("No notification for high/low temp??\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index 3794aa9..e36806f 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -297,6 +297,8 @@
 	[SMUX_HIGH_WM_HIT] = "HIGH_WM_HIT",
 	[SMUX_RX_RETRY_HIGH_WM_HIT] = "RX_RETRY_HIGH_WM_HIT",
 	[SMUX_RX_RETRY_LOW_WM_HIT] = "RX_RETRY_LOW_WM_HIT",
+	[SMUX_LOCAL_CLOSED] = "LOCAL_CLOSED",
+	[SMUX_REMOTE_CLOSED] = "REMOTE_CLOSED",
 };
 
 static const char * const smux_local_state[] = {
@@ -553,6 +555,8 @@
 
 	/* Close all ports */
 	for (i = 0 ; i < SMUX_NUM_LOGICAL_CHANNELS; i++) {
+		union notifier_metadata meta;
+		int send_disconnect = 0;
 		ch = &smux_lch[i];
 		SMUX_DBG("smux: %s: cleaning up lcid %d\n", __func__, i);
 
@@ -563,14 +567,19 @@
 		smux_purge_ch_tx_queue(ch, 1);
 		spin_unlock(&ch->tx_lock_lhb2);
 
+		meta.disconnected.is_ssr = smux.in_reset;
 		/* Notify user of disconnect and reset channel state */
 		if (ch->local_state == SMUX_LCH_LOCAL_OPENED ||
 			ch->local_state == SMUX_LCH_LOCAL_CLOSING) {
-			union notifier_metadata meta;
-
-			meta.disconnected.is_ssr = smux.in_reset;
-			schedule_notify(ch->lcid, SMUX_DISCONNECTED, &meta);
+			schedule_notify(ch->lcid, SMUX_LOCAL_CLOSED, &meta);
+			send_disconnect = 1;
 		}
+		if (ch->remote_state != SMUX_LCH_REMOTE_CLOSED) {
+			schedule_notify(ch->lcid, SMUX_REMOTE_CLOSED, &meta);
+			send_disconnect = 1;
+		}
+		if (send_disconnect)
+			schedule_notify(ch->lcid, SMUX_DISCONNECTED, &meta);
 
 		ch->local_state = SMUX_LCH_LOCAL_CLOSED;
 		ch->remote_state = SMUX_LCH_REMOTE_CLOSED;
@@ -857,6 +866,10 @@
 
 	IPC_LOG_STR("smux: %s ch:%d\n", event_to_str(event), lcid);
 	ch = &smux_lch[lcid];
+	if (!ch->notify) {
+		SMUX_DBG("%s: [%d]lcid notify fn is NULL\n", __func__, lcid);
+		return ret;
+	}
 	notify_handle = kzalloc(sizeof(struct smux_notify_handle),
 						GFP_ATOMIC);
 	if (!notify_handle) {
@@ -1173,6 +1186,7 @@
 	int ret;
 	struct smux_lch_t *ch;
 	int enable_powerdown = 0;
+	int tx_ready = 0;
 
 	lcid = pkt->hdr.lcid;
 	ch = &smux_lch[lcid];
@@ -1190,7 +1204,7 @@
 		if (ch->remote_state == SMUX_LCH_REMOTE_OPENED) {
 			schedule_notify(lcid, SMUX_CONNECTED, NULL);
 			if (!(list_empty(&ch->tx_queue)))
-				list_channel(ch);
+				tx_ready = 1;
 		}
 		ret = 0;
 	} else if (ch->remote_mode == SMUX_LCH_MODE_REMOTE_LOOPBACK) {
@@ -1213,6 +1227,9 @@
 		spin_unlock(&smux.tx_lock_lha2);
 	}
 
+	if (tx_ready)
+		list_channel(ch);
+
 	return ret;
 }
 
@@ -1235,6 +1252,7 @@
 				SMUX_LCH_LOCAL_CLOSING,
 				SMUX_LCH_LOCAL_CLOSED);
 		ch->local_state = SMUX_LCH_LOCAL_CLOSED;
+		schedule_notify(lcid, SMUX_LOCAL_CLOSED, &meta_disconnected);
 		if (ch->remote_state == SMUX_LCH_REMOTE_CLOSED)
 			schedule_notify(lcid, SMUX_DISCONNECTED,
 				&meta_disconnected);
@@ -1422,6 +1440,7 @@
 			}
 		}
 
+		schedule_notify(lcid, SMUX_REMOTE_CLOSED, &meta_disconnected);
 		if (ch->local_state == SMUX_LCH_LOCAL_CLOSED)
 			schedule_notify(lcid, SMUX_DISCONNECTED,
 				&meta_disconnected);
@@ -2360,8 +2379,11 @@
 		union notifier_metadata meta_disconnected;
 
 		meta_disconnected.disconnected.is_ssr = smux.in_reset;
-		schedule_notify(ch->lcid, SMUX_DISCONNECTED,
+		schedule_notify(ch->lcid, SMUX_LOCAL_CLOSED,
 			&meta_disconnected);
+		if (ch->remote_state == SMUX_LCH_REMOTE_CLOSED)
+			schedule_notify(ch->lcid, SMUX_DISCONNECTED,
+				&meta_disconnected);
 	}
 }
 
@@ -3089,11 +3111,15 @@
  *
  * @returns 0 for success, <0 otherwise
  *
- * A channel must be fully closed (either not previously opened or
- * msm_smux_close() has been called and the SMUX_DISCONNECTED has been
- * received.
+ * The local channel state must be closed (either not previously
+ * opened or msm_smux_close() has been called and the SMUX_LOCAL_CLOSED
+ * notification has been received).
  *
- * One the remote side is opened, the client will receive a SMUX_CONNECTED
+ * If open is called before the SMUX_LOCAL_CLOSED has been received,
+ * then the function will return -EAGAIN and the client will need to
+ * retry the open later.
+ *
+ * Once the remote side is opened, the client will receive a SMUX_CONNECTED
  * event.
  */
 int msm_smux_open(uint8_t lcid, void *priv,
@@ -3170,7 +3196,8 @@
  * @returns 0 for success, <0 otherwise
  *
  * Once the close event has been acknowledge by the remote side, the client
- * will receive a SMUX_DISCONNECTED notification.
+ * will receive an SMUX_LOCAL_CLOSED notification.  If the remote side is also
+ * closed, then an SMUX_DISCONNECTED notification will also be sent.
  */
 int msm_smux_close(uint8_t lcid)
 {
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index cab7c12..a243a05 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -192,7 +192,7 @@
 	ktime_t clk_off_delay;
 	enum msm_hs_clk_states_e clk_state;
 	enum msm_hs_clk_req_off_state_e clk_req_off_state;
-
+	atomic_t clk_count;
 	struct msm_hs_wakeup wakeup;
 	struct wake_lock dma_wake_lock;  /* held while any DMA active */
 
@@ -219,8 +219,67 @@
 	struct msm_bus_scale_pdata *bus_scale_table;
 	bool rx_discard_flush_issued;
 	int rx_count_callback;
+	unsigned int *reg_ptr;
 };
 
+unsigned int regmap_nonblsp[UART_DM_LAST] = {
+		[UART_DM_MR1] = UARTDM_MR1_ADDR,
+		[UART_DM_MR2] = UARTDM_MR2_ADDR,
+		[UART_DM_IMR] = UARTDM_IMR_ADDR,
+		[UART_DM_SR] = UARTDM_SR_ADDR,
+		[UART_DM_CR] = UARTDM_CR_ADDR,
+		[UART_DM_CSR] = UARTDM_CSR_ADDR,
+		[UART_DM_IPR] = UARTDM_IPR_ADDR,
+		[UART_DM_ISR] = UARTDM_ISR_ADDR,
+		[UART_DM_RX_TOTAL_SNAP] = UARTDM_RX_TOTAL_SNAP_ADDR,
+		[UART_DM_TFWR] = UARTDM_TFWR_ADDR,
+		[UART_DM_RFWR] = UARTDM_RFWR_ADDR,
+		[UART_DM_RF] = UARTDM_RF_ADDR,
+		[UART_DM_TF] = UARTDM_TF_ADDR,
+		[UART_DM_MISR] = UARTDM_MISR_ADDR,
+		[UART_DM_DMRX] = UARTDM_DMRX_ADDR,
+		[UART_DM_NCF_TX] = UARTDM_NCF_TX_ADDR,
+		[UART_DM_DMEN] = UARTDM_DMEN_ADDR,
+		[UART_DM_TXFS] = UARTDM_TXFS_ADDR,
+		[UART_DM_RXFS] = UARTDM_RXFS_ADDR,
+		[UART_DM_RX_TRANS_CTRL] = UARTDM_RX_TRANS_CTRL_ADDR,
+};
+
+unsigned int regmap_blsp[UART_DM_LAST] = {
+		[UART_DM_MR1] = 0x0,
+		[UART_DM_MR2] = 0x4,
+		[UART_DM_IMR] = 0xb0,
+		[UART_DM_SR] = 0xa4,
+		[UART_DM_CR] = 0xa8,
+		[UART_DM_CSR] = 0xa0,
+		[UART_DM_IPR] = 0x18,
+		[UART_DM_ISR] = 0xb4,
+		[UART_DM_RX_TOTAL_SNAP] = 0xbc,
+		[UART_DM_TFWR] = 0x1c,
+		[UART_DM_RFWR] = 0x20,
+		[UART_DM_RF] = 0x140,
+		[UART_DM_TF] = 0x100,
+		[UART_DM_MISR] = 0xac,
+		[UART_DM_DMRX] = 0x34,
+		[UART_DM_NCF_TX] = 0x40,
+		[UART_DM_DMEN] = 0x3c,
+		[UART_DM_TXFS] = 0x4c,
+		[UART_DM_RXFS] = 0x50,
+		[UART_DM_RX_TRANS_CTRL] = 0xcc,
+};
+
+static struct of_device_id msm_hs_match_table[] = {
+	{ .compatible = "qcom,msm-hsuart-v14",
+	  .data = regmap_blsp
+	},
+	{
+	  .compatible = "qcom,msm-hsuart-v13",
+	  .data = regmap_nonblsp
+	},
+	{}
+};
+
+
 #define MSM_UARTDM_BURST_SIZE 16   /* DM burst size (in bytes) */
 #define UARTDM_TX_BUF_SIZE UART_XMIT_SIZE
 #define UARTDM_RX_BUF_SIZE 512
@@ -241,6 +300,7 @@
 static void msm_hs_start_rx_locked(struct uart_port *uport);
 static void msm_serial_hs_rx_tlet(unsigned long tlet_ptr);
 static void flip_insert_work(struct work_struct *work);
+static void msm_hs_bus_voting(struct msm_hs_port *msm_uport, unsigned int vote);
 
 #define UARTDM_TO_MSM(uart_port) \
 	container_of((uart_port), struct msm_hs_port, uport)
@@ -287,6 +347,61 @@
 	return ret;
 }
 
+static int msm_hs_clock_vote(struct msm_hs_port *msm_uport)
+{
+	int rc = 0;
+
+	if (1 == atomic_inc_return(&msm_uport->clk_count)) {
+		msm_hs_bus_voting(msm_uport, BUS_SCALING);
+		/* Turn on core clk and iface clk */
+		rc = clk_prepare_enable(msm_uport->clk);
+		if (rc) {
+			dev_err(msm_uport->uport.dev,
+				"%s: Could not turn on core clk [%d]\n",
+				__func__, rc);
+			return rc;
+		}
+
+		if (msm_uport->pclk) {
+			rc = clk_prepare_enable(msm_uport->pclk);
+			if (rc) {
+				clk_disable_unprepare(msm_uport->clk);
+				dev_err(msm_uport->uport.dev,
+					"%s: Could not turn on pclk [%d]\n",
+					__func__, rc);
+				return rc;
+			}
+		}
+		msm_uport->clk_state = MSM_HS_CLK_ON;
+	}
+
+
+	return rc;
+}
+
+static void msm_hs_clock_unvote(struct msm_hs_port *msm_uport)
+{
+	int rc = atomic_dec_return(&msm_uport->clk_count);
+
+	if (rc < 0) {
+		msm_hs_bus_voting(msm_uport, BUS_RESET);
+		WARN(rc, "msm_uport->clk_count < 0!");
+		dev_err(msm_uport->uport.dev,
+			"%s: Clocks count invalid  [%d]\n", __func__,
+			atomic_read(&msm_uport->clk_count));
+		return;
+	}
+
+	if (0 == rc) {
+		msm_hs_bus_voting(msm_uport, BUS_RESET);
+		/* Turn off the core clk and iface clk*/
+		clk_disable_unprepare(msm_uport->clk);
+		if (msm_uport->pclk)
+			clk_disable_unprepare(msm_uport->pclk);
+		msm_uport->clk_state = MSM_HS_CLK_OFF;
+	}
+}
+
 static ssize_t show_clock(struct device *dev, struct device_attribute *attr,
 			  char *buf)
 {
@@ -365,14 +480,23 @@
 }
 
 static inline unsigned int msm_hs_read(struct uart_port *uport,
-				       unsigned int offset)
+				       unsigned int index)
 {
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+	unsigned int offset;
+
+	offset = *(msm_uport->reg_ptr + index);
+
 	return readl_relaxed(uport->membase + offset);
 }
 
-static inline void msm_hs_write(struct uart_port *uport, unsigned int offset,
+static inline void msm_hs_write(struct uart_port *uport, unsigned int index,
 				 unsigned int value)
 {
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+	unsigned int offset;
+
+	offset = *(msm_uport->reg_ptr + index);
 	writel_relaxed(value, uport->membase + offset);
 }
 
@@ -432,40 +556,33 @@
 	unsigned long flags;
 	int ret = 0;
 
-	msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
-	clk_prepare_enable(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_prepare_enable(msm_uport->pclk);
+	msm_hs_clock_vote(msm_uport);
 
 	if (val) {
 		spin_lock_irqsave(&uport->lock, flags);
-		ret = msm_hs_read(uport, UARTDM_MR2_ADDR);
+		ret = msm_hs_read(uport, UART_DM_MR2);
 		if (is_blsp_uart(msm_uport))
 			ret |= (UARTDM_MR2_LOOP_MODE_BMSK |
 				UARTDM_MR2_RFR_CTS_LOOP_MODE_BMSK);
 		else
 			ret |= UARTDM_MR2_LOOP_MODE_BMSK;
-		msm_hs_write(uport, UARTDM_MR2_ADDR, ret);
+		msm_hs_write(uport, UART_DM_MR2, ret);
 		spin_unlock_irqrestore(&uport->lock, flags);
 	} else {
 		spin_lock_irqsave(&uport->lock, flags);
-		ret = msm_hs_read(uport, UARTDM_MR2_ADDR);
+		ret = msm_hs_read(uport, UART_DM_MR2);
 		if (is_blsp_uart(msm_uport))
 			ret &= ~(UARTDM_MR2_LOOP_MODE_BMSK |
 				UARTDM_MR2_RFR_CTS_LOOP_MODE_BMSK);
 		else
 			ret &= ~UARTDM_MR2_LOOP_MODE_BMSK;
-		msm_hs_write(uport, UARTDM_MR2_ADDR, ret);
+		msm_hs_write(uport, UART_DM_MR2, ret);
 		spin_unlock_irqrestore(&uport->lock, flags);
 	}
 	/* Calling CLOCK API. Hence mb() requires here. */
 	mb();
-	clk_disable_unprepare(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_disable_unprepare(msm_uport->pclk);
 
-	msm_hs_bus_voting(msm_uport, BUS_RESET);
+	msm_hs_clock_unvote(msm_uport);
 	return 0;
 }
 
@@ -476,23 +593,16 @@
 	unsigned long flags;
 	int ret = 0;
 
-	msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
-	clk_prepare_enable(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_prepare_enable(msm_uport->pclk);
+	msm_hs_clock_vote(msm_uport);
 
 	spin_lock_irqsave(&uport->lock, flags);
-	ret = msm_hs_read(&msm_uport->uport, UARTDM_MR2_ADDR);
+	ret = msm_hs_read(&msm_uport->uport, UART_DM_MR2);
 	spin_unlock_irqrestore(&uport->lock, flags);
 
-	clk_disable_unprepare(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_disable_unprepare(msm_uport->pclk);
+	msm_hs_clock_unvote(msm_uport);
 
 	*val = (ret & UARTDM_MR2_LOOP_MODE_BMSK) ? 1 : 0;
 
-	msm_hs_bus_voting(msm_uport, BUS_RESET);
 	return 0;
 }
 DEFINE_SIMPLE_ATTRIBUTE(loopback_enable_fops, msm_serial_loopback_enable_get,
@@ -585,22 +695,12 @@
 		return ret;
 	}
 
-	ret = clk_prepare_enable(msm_uport->clk);
+	ret = msm_hs_clock_vote(msm_uport);
 	if (ret) {
 		printk(KERN_ERR "Error could not turn on UART clk\n");
 		return ret;
 	}
-	if (msm_uport->pclk) {
-		ret = clk_prepare_enable(msm_uport->pclk);
-		if (ret) {
-			clk_disable_unprepare(msm_uport->clk);
-			dev_err(uport->dev,
-				"Error could not turn on UART pclk\n");
-			return ret;
-		}
-	}
 
-	msm_uport->clk_state = MSM_HS_CLK_ON;
 	return 0;
 }
 
@@ -705,63 +805,63 @@
 
 	switch (bps) {
 	case 300:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x00);
+		msm_hs_write(uport, UART_DM_CSR, 0x00);
 		rxstale = 1;
 		break;
 	case 600:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x11);
+		msm_hs_write(uport, UART_DM_CSR, 0x11);
 		rxstale = 1;
 		break;
 	case 1200:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x22);
+		msm_hs_write(uport, UART_DM_CSR, 0x22);
 		rxstale = 1;
 		break;
 	case 2400:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x33);
+		msm_hs_write(uport, UART_DM_CSR, 0x33);
 		rxstale = 1;
 		break;
 	case 4800:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x44);
+		msm_hs_write(uport, UART_DM_CSR, 0x44);
 		rxstale = 1;
 		break;
 	case 9600:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x55);
+		msm_hs_write(uport, UART_DM_CSR, 0x55);
 		rxstale = 2;
 		break;
 	case 14400:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x66);
+		msm_hs_write(uport, UART_DM_CSR, 0x66);
 		rxstale = 3;
 		break;
 	case 19200:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x77);
+		msm_hs_write(uport, UART_DM_CSR, 0x77);
 		rxstale = 4;
 		break;
 	case 28800:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x88);
+		msm_hs_write(uport, UART_DM_CSR, 0x88);
 		rxstale = 6;
 		break;
 	case 38400:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x99);
+		msm_hs_write(uport, UART_DM_CSR, 0x99);
 		rxstale = 8;
 		break;
 	case 57600:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xaa);
+		msm_hs_write(uport, UART_DM_CSR, 0xaa);
 		rxstale = 16;
 		break;
 	case 76800:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xbb);
+		msm_hs_write(uport, UART_DM_CSR, 0xbb);
 		rxstale = 16;
 		break;
 	case 115200:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xcc);
+		msm_hs_write(uport, UART_DM_CSR, 0xcc);
 		rxstale = 31;
 		break;
 	case 230400:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xee);
+		msm_hs_write(uport, UART_DM_CSR, 0xee);
 		rxstale = 31;
 		break;
 	case 460800:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xff);
+		msm_hs_write(uport, UART_DM_CSR, 0xff);
 		rxstale = 31;
 		break;
 	case 4000000:
@@ -774,11 +874,11 @@
 	case 1152000:
 	case 1000000:
 	case 921600:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xff);
+		msm_hs_write(uport, UART_DM_CSR, 0xff);
 		rxstale = 31;
 		break;
 	default:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xff);
+		msm_hs_write(uport, UART_DM_CSR, 0xff);
 		/* default to 9600 */
 		bps = 9600;
 		rxstale = 2;
@@ -816,14 +916,14 @@
 	data = rxstale & UARTDM_IPR_STALE_LSB_BMSK;
 	data |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2);
 
-	msm_hs_write(uport, UARTDM_IPR_ADDR, data);
+	msm_hs_write(uport, UART_DM_IPR, data);
 	/*
 	 * It is suggested to do reset of transmitter and receiver after
 	 * changing any protocol configuration. Here Baud rate and stale
 	 * timeout are getting updated. Hence reset transmitter and receiver.
 	 */
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
+	msm_hs_write(uport, UART_DM_CR, RESET_TX);
+	msm_hs_write(uport, UART_DM_CR, RESET_RX);
 }
 
 
@@ -835,35 +935,35 @@
 
 	switch (bps) {
 	case 9600:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x99);
+		msm_hs_write(uport, UART_DM_CSR, 0x99);
 		rxstale = 2;
 		break;
 	case 14400:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xaa);
+		msm_hs_write(uport, UART_DM_CSR, 0xaa);
 		rxstale = 3;
 		break;
 	case 19200:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xbb);
+		msm_hs_write(uport, UART_DM_CSR, 0xbb);
 		rxstale = 4;
 		break;
 	case 28800:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xcc);
+		msm_hs_write(uport, UART_DM_CSR, 0xcc);
 		rxstale = 6;
 		break;
 	case 38400:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xdd);
+		msm_hs_write(uport, UART_DM_CSR, 0xdd);
 		rxstale = 8;
 		break;
 	case 57600:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xee);
+		msm_hs_write(uport, UART_DM_CSR, 0xee);
 		rxstale = 16;
 		break;
 	case 115200:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0xff);
+		msm_hs_write(uport, UART_DM_CSR, 0xff);
 		rxstale = 31;
 		break;
 	default:
-		msm_hs_write(uport, UARTDM_CSR_ADDR, 0x99);
+		msm_hs_write(uport, UART_DM_CSR, 0x99);
 		/* default to 9600 */
 		bps = 9600;
 		rxstale = 2;
@@ -873,7 +973,7 @@
 	data = rxstale & UARTDM_IPR_STALE_LSB_BMSK;
 	data |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2);
 
-	msm_hs_write(uport, UARTDM_IPR_ADDR, data);
+	msm_hs_write(uport, UART_DM_IPR, data);
 }
 
 
@@ -896,7 +996,7 @@
 	struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
 
 	mutex_lock(&msm_uport->clk_mutex);
-	msm_hs_write(uport, UARTDM_IMR_ADDR, 0);
+	msm_hs_write(uport, UART_DM_IMR, 0);
 
 	/*
 	 * Disable Rx channel of UARTDM
@@ -907,7 +1007,7 @@
 	 * Note: should not reset the receiver here immediately as it is not
 	 * suggested to do disable/reset or reset/disable at the same time.
 	 */
-	data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
+	data = msm_hs_read(uport, UART_DM_DMEN);
 	if (is_blsp_uart(msm_uport)) {
 		/* Disable UARTDM RX BAM Interface */
 		data &= ~UARTDM_RX_BAM_ENABLE_BMSK;
@@ -915,7 +1015,7 @@
 		data &= ~UARTDM_RX_DM_EN_BMSK;
 	}
 
-	msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
+	msm_hs_write(uport, UART_DM_DMEN, data);
 
 	/* 300 is the minimum baud support by the driver  */
 	bps = uart_get_baud_rate(uport, termios, oldtermios, 200, 4000000);
@@ -930,7 +1030,7 @@
 	else
 		msm_hs_set_bps_locked(uport, bps);
 
-	data = msm_hs_read(uport, UARTDM_MR2_ADDR);
+	data = msm_hs_read(uport, UART_DM_MR2);
 	data &= ~UARTDM_MR2_PARITY_MODE_BMSK;
 	/* set parity */
 	if (PARENB == (c_cflag & PARENB)) {
@@ -969,10 +1069,10 @@
 	}
 	data |= UARTDM_MR2_ERROR_MODE_BMSK;
 	/* write parity/bits per char/stop bit configuration */
-	msm_hs_write(uport, UARTDM_MR2_ADDR, data);
+	msm_hs_write(uport, UART_DM_MR2, data);
 
 	/* Configure HW flow control */
-	data = msm_hs_read(uport, UARTDM_MR1_ADDR);
+	data = msm_hs_read(uport, UART_DM_MR1);
 
 	data &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
 
@@ -981,7 +1081,7 @@
 		data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
 	}
 
-	msm_hs_write(uport, UARTDM_MR1_ADDR, data);
+	msm_hs_write(uport, UART_DM_MR1, data);
 
 	uport->ignore_status_mask = termios->c_iflag & INPCK;
 	uport->ignore_status_mask |= termios->c_iflag & IGNPAR;
@@ -993,8 +1093,8 @@
 	/* Set Transmit software time out */
 	uart_update_timeout(uport, c_cflag, bps);
 
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
+	msm_hs_write(uport, UART_DM_CR, RESET_RX);
+	msm_hs_write(uport, UART_DM_CR, RESET_TX);
 
 	if (msm_uport->rx.flush == FLUSH_NONE) {
 		wake_lock(&msm_uport->rx.wake_lock);
@@ -1027,7 +1127,7 @@
 		}
 	}
 
-	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+	msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
 	mb();
 	mutex_unlock(&msm_uport->clk_mutex);
 }
@@ -1040,8 +1140,12 @@
 {
 	unsigned int data;
 	unsigned int ret = 0;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 
+	msm_hs_clock_vote(msm_uport);
 	data = msm_hs_read(uport, UARTDM_SR_ADDR);
+	msm_hs_clock_unvote(msm_uport);
+
 	if (data & UARTDM_SR_TXEMT_BMSK)
 		ret = TIOCSER_TEMT;
 
@@ -1093,12 +1197,12 @@
 	unsigned int data;
 
 	/* disable dlink */
-	data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
+	data = msm_hs_read(uport, UART_DM_DMEN);
 	if (is_blsp_uart(msm_uport))
 		data &= ~UARTDM_RX_BAM_ENABLE_BMSK;
 	else
 		data &= ~UARTDM_RX_DM_EN_BMSK;
-	msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
+	msm_hs_write(uport, UART_DM_DMEN, data);
 
 	/* calling DMOV or CLOCK API. Hence mb() */
 	mb();
@@ -1162,7 +1266,7 @@
 
 	if (is_blsp_uart(msm_uport)) {
 		/* Issue TX BAM Start IFC command */
-		msm_hs_write(uport, UARTDM_CR_ADDR, START_TX_BAM_IFC);
+		msm_hs_write(uport, UART_DM_CR, START_TX_BAM_IFC);
 	} else {
 		tx->command_ptr->num_rows =
 				(((tx_count + 15) >> 4) << 16) |
@@ -1178,11 +1282,11 @@
 
 	/* Save tx_count to use in Callback */
 	tx->tx_count = tx_count;
-	msm_hs_write(uport, UARTDM_NCF_TX_ADDR, tx_count);
+	msm_hs_write(uport, UART_DM_NCF_TX, tx_count);
 
 	/* Disable the tx_ready interrupt */
 	msm_uport->imr_reg &= ~UARTDM_ISR_TX_READY_BMSK;
-	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+	msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
 	/* Calling next DMOV API. Hence mb() here. */
 	mb();
 
@@ -1216,16 +1320,16 @@
 		printk(KERN_ERR "Error: rx started in buffer state = %x",
 		       buffer_pending);
 
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
-	msm_hs_write(uport, UARTDM_DMRX_ADDR, UARTDM_RX_BUF_SIZE);
-	msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_ENABLE);
+	msm_hs_write(uport, UART_DM_CR, RESET_STALE_INT);
+	msm_hs_write(uport, UART_DM_DMRX, UARTDM_RX_BUF_SIZE);
+	msm_hs_write(uport, UART_DM_CR, STALE_EVENT_ENABLE);
 	msm_uport->imr_reg |= UARTDM_ISR_RXLEV_BMSK;
 
 	/*
 	 * Enable UARTDM Rx Interface as previously it has been
 	 * disable in set_termios before configuring baud rate.
 	 */
-	data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
+	data = msm_hs_read(uport, UART_DM_DMEN);
 	if (is_blsp_uart(msm_uport)) {
 		/* Enable UARTDM Rx BAM Interface */
 		data |= UARTDM_RX_BAM_ENABLE_BMSK;
@@ -1233,8 +1337,8 @@
 		data |= UARTDM_RX_DM_EN_BMSK;
 	}
 
-	msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
-	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+	msm_hs_write(uport, UART_DM_DMEN, data);
+	msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
 	/* Calling next DMOV API. Hence mb() here. */
 	mb();
 
@@ -1245,9 +1349,9 @@
 		 */
 		data = (RX_STALE_AUTO_RE_EN | RX_TRANS_AUTO_RE_ACTIVATE |
 					RX_DMRX_CYCLIC_EN);
-		msm_hs_write(uport, UARTDM_RX_TRANS_CTRL_ADDR, data);
+		msm_hs_write(uport, UART_DM_RX_TRANS_CTRL, data);
 		/* Issue RX BAM Start IFC command */
-		msm_hs_write(uport, UARTDM_CR_ADDR, START_RX_BAM_IFC);
+		msm_hs_write(uport, UART_DM_CR, START_RX_BAM_IFC);
 		mb();
 	}
 
@@ -1342,12 +1446,12 @@
 	notify = &msm_uport->notify;
 	rx = &msm_uport->rx;
 
-	status = msm_hs_read(uport, UARTDM_SR_ADDR);
+	status = msm_hs_read(uport, UART_DM_SR);
 
 	spin_lock_irqsave(&uport->lock, flags);
 
 	if (!is_blsp_uart(msm_uport))
-		msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
+		msm_hs_write(uport, UART_DM_CR, STALE_EVENT_DISABLE);
 
 	/* overflow is not connect to data in a FIFO */
 	if (unlikely((status & UARTDM_SR_OVERRUN_BMSK) &&
@@ -1388,7 +1492,7 @@
 	}
 
 	if (error_f)
-		msm_hs_write(uport, UARTDM_CR_ADDR, RESET_ERROR_STATUS);
+		msm_hs_write(uport, UART_DM_CR, RESET_ERROR_STATUS);
 
 	if (msm_uport->clk_req_off_state == CLK_REQ_OFF_FLUSH_ISSUED)
 		msm_uport->clk_req_off_state = CLK_REQ_OFF_RXSTALE_FLUSHED;
@@ -1407,7 +1511,7 @@
 	if (is_blsp_uart(msm_uport)) {
 		rx_count = msm_uport->rx_count_callback;
 	} else {
-		rx_count = msm_hs_read(uport, UARTDM_RX_TOTAL_SNAP_ADDR);
+		rx_count = msm_hs_read(uport, UART_DM_RX_TOTAL_SNAP);
 		/* order the read of rx.buffer */
 		rmb();
 	}
@@ -1530,7 +1634,7 @@
 	}
 
 	msm_uport->imr_reg |= UARTDM_ISR_TX_READY_BMSK;
-	msm_hs_write(&(msm_uport->uport), UARTDM_IMR_ADDR, msm_uport->imr_reg);
+	msm_hs_write(&(msm_uport->uport), UART_DM_IMR, msm_uport->imr_reg);
 	/* Calling clk API. Hence mb() requires. */
 	mb();
 
@@ -1639,17 +1743,17 @@
 	/* RTS is active low */
 	set_rts = TIOCM_RTS & mctrl ? 0 : 1;
 
-	data = msm_hs_read(uport, UARTDM_MR1_ADDR);
+	data = msm_hs_read(uport, UART_DM_MR1);
 	if (set_rts) {
 		/*disable auto ready-for-receiving */
 		data &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
-		msm_hs_write(uport, UARTDM_MR1_ADDR, data);
+		msm_hs_write(uport, UART_DM_MR1, data);
 		/* set RFR_N to high */
-		msm_hs_write(uport, UARTDM_CR_ADDR, RFR_HIGH);
+		msm_hs_write(uport, UART_DM_CR, RFR_HIGH);
 	} else {
 		/* Enable auto ready-for-receiving */
 		data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
-		msm_hs_write(uport, UARTDM_MR1_ADDR, data);
+		msm_hs_write(uport, UART_DM_MR1, data);
 	}
 	mb();
 }
@@ -1658,10 +1762,13 @@
 				    unsigned int mctrl)
 {
 	unsigned long flags;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 
+	msm_hs_clock_vote(msm_uport);
 	spin_lock_irqsave(&uport->lock, flags);
 	msm_hs_set_mctrl_locked(uport, mctrl);
 	spin_unlock_irqrestore(&uport->lock, flags);
+	msm_hs_clock_unvote(msm_uport);
 }
 EXPORT_SYMBOL(msm_hs_set_mctrl);
 
@@ -1672,7 +1779,7 @@
 
 	/* Enable DELTA_CTS Interrupt */
 	msm_uport->imr_reg |= UARTDM_ISR_DELTA_CTS_BMSK;
-	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+	msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
 	mb();
 
 }
@@ -1696,7 +1803,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&uport->lock, flags);
-	msm_hs_write(uport, UARTDM_CR_ADDR, ctl ? START_BREAK : STOP_BREAK);
+	msm_hs_write(uport, UART_DM_CR, ctl ? START_BREAK : STOP_BREAK);
 	mb();
 	spin_unlock_irqrestore(&uport->lock, flags);
 }
@@ -1727,7 +1834,7 @@
 static void msm_hs_handle_delta_cts_locked(struct uart_port *uport)
 {
 	/* clear interrupt */
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS);
+	msm_hs_write(uport, UART_DM_CR, RESET_CTS);
 	/* Calling CLOCK API. Hence mb() requires here. */
 	mb();
 	uport->icount.cts++;
@@ -1763,7 +1870,7 @@
 	}
 
 	/* Make sure the uart is finished with the last byte */
-	sr_status = msm_hs_read(uport, UARTDM_SR_ADDR);
+	sr_status = msm_hs_read(uport, UARTDM_SR);
 	if (!(sr_status & UARTDM_SR_TXEMT_BMSK)) {
 		spin_unlock_irqrestore(&uport->lock, flags);
 		mutex_unlock(&msm_uport->clk_mutex);
@@ -1776,7 +1883,7 @@
 		msm_uport->clk_req_off_state = CLK_REQ_OFF_RXSTALE_ISSUED;
 
 		if (!is_blsp_uart(msm_uport)) {
-			msm_hs_write(uport, UARTDM_CR_ADDR, FORCE_STALE_EVENT);
+			msm_hs_write(uport, UART_DM_CR, FORCE_STALE_EVENT);
 			/*
 			* Before returning make sure that device writel
 			* completed. Hence mb() requires here.
@@ -1825,11 +1932,7 @@
 	spin_unlock_irqrestore(&uport->lock, flags);
 
 	/* we really want to clock off */
-	clk_disable_unprepare(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_disable_unprepare(msm_uport->pclk);
-
-	msm_uport->clk_state = MSM_HS_CLK_OFF;
+	msm_hs_clock_unvote(msm_uport);
 
 	spin_lock_irqsave(&uport->lock, flags);
 	if (use_low_power_wakeup(msm_uport)) {
@@ -1881,20 +1984,20 @@
 
 	spin_lock_irqsave(&uport->lock, flags);
 
-	isr_status = msm_hs_read(uport, UARTDM_MISR_ADDR);
+	isr_status = msm_hs_read(uport, UART_DM_MISR);
 
 	/* Uart RX starting */
 	if (isr_status & UARTDM_ISR_RXLEV_BMSK) {
 		wake_lock(&rx->wake_lock);  /* hold wakelock while rx dma */
 		msm_uport->imr_reg &= ~UARTDM_ISR_RXLEV_BMSK;
-		msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+		msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
 		/* Complete device write for IMR. Hence mb() requires. */
 		mb();
 	}
 	/* Stale rx interrupt */
 	if (isr_status & UARTDM_ISR_RXSTALE_BMSK) {
-		msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
-		msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
+		msm_hs_write(uport, UART_DM_CR, STALE_EVENT_DISABLE);
+		msm_hs_write(uport, UART_DM_CR, RESET_STALE_INT);
 		/*
 		 * Complete device write before calling DMOV API. Hence
 		 * mb() requires here.
@@ -1914,12 +2017,11 @@
 	/* tx ready interrupt */
 	if (isr_status & UARTDM_ISR_TX_READY_BMSK) {
 		/* Clear  TX Ready */
-		msm_hs_write(uport, UARTDM_CR_ADDR, CLEAR_TX_READY);
+		msm_hs_write(uport, UART_DM_CR, CLEAR_TX_READY);
 
 		if (msm_uport->clk_state == MSM_HS_CLK_REQUEST_OFF) {
 			msm_uport->imr_reg |= UARTDM_ISR_TXLEV_BMSK;
-			msm_hs_write(uport, UARTDM_IMR_ADDR,
-				     msm_uport->imr_reg);
+			msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
 		}
 		/*
 		 * Complete both writes before starting new TX.
@@ -1948,7 +2050,7 @@
 	if (isr_status & UARTDM_ISR_TXLEV_BMSK) {
 		/* TX FIFO is empty */
 		msm_uport->imr_reg &= ~UARTDM_ISR_TXLEV_BMSK;
-		msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+		msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
 		/*
 		 * Complete device write before starting clock_off request.
 		 * Hence mb() requires here.
@@ -1992,7 +2094,7 @@
 		msm_uport->clk_state = MSM_HS_CLK_REQUEST_OFF;
 		msm_uport->clk_req_off_state = CLK_REQ_OFF_START;
 		msm_uport->imr_reg |= UARTDM_ISR_TXLEV_BMSK;
-		msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+		msm_hs_write(uport, UARTDM_IMR, msm_uport->imr_reg);
 		/*
 		 * Complete device write before retuning back.
 		 * Hence mb() requires here.
@@ -2020,37 +2122,25 @@
 			disable_irq_nosync(msm_uport->wakeup.irq);
 		spin_unlock_irqrestore(&uport->lock, flags);
 
-		/* Vote for PNOC BUS Scaling */
-		msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
-		ret = clk_prepare_enable(msm_uport->clk);
+		ret = msm_hs_clock_vote(msm_uport);
 		if (ret) {
 			dev_err(uport->dev, "Clock ON Failure"
 			"For UART CLK Stalling HSUART\n");
 			break;
 		}
 
-		if (msm_uport->pclk) {
-			ret = clk_prepare_enable(msm_uport->pclk);
-			if (unlikely(ret)) {
-				clk_disable_unprepare(msm_uport->clk);
-				dev_err(uport->dev, "Clock ON Failure"
-				"For UART Pclk Stalling HSUART\n");
-				break;
-			}
-		}
 		spin_lock_irqsave(&uport->lock, flags);
 		/* else fall-through */
 	case MSM_HS_CLK_REQUEST_OFF:
 		if (msm_uport->rx.flush == FLUSH_STOP ||
 		    msm_uport->rx.flush == FLUSH_SHUTDOWN) {
-			msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
-			data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
+			msm_hs_write(uport, UART_DM_CR, RESET_RX);
+			data = msm_hs_read(uport, UART_DM_DMEN);
 			if (is_blsp_uart(msm_uport))
 				data |= UARTDM_RX_BAM_ENABLE_BMSK;
 			else
 				data |= UARTDM_RX_DM_EN_BMSK;
-			msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
+			msm_hs_write(uport, UART_DM_DMEN, data);
 			/* Complete above device write. Hence mb() here. */
 			mb();
 		}
@@ -2279,18 +2369,18 @@
 	}
 
 	/* Set auto RFR Level */
-	data = msm_hs_read(uport, UARTDM_MR1_ADDR);
+	data = msm_hs_read(uport, UART_DM_MR1);
 	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
 	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK;
 	data |= (UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2));
 	data |= (UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level);
-	msm_hs_write(uport, UARTDM_MR1_ADDR, data);
+	msm_hs_write(uport, UART_DM_MR1, data);
 
 	/* Make sure RXSTALE count is non-zero */
-	data = msm_hs_read(uport, UARTDM_IPR_ADDR);
+	data = msm_hs_read(uport, UART_DM_IPR);
 	if (!data) {
 		data |= 0x1f & UARTDM_IPR_STALE_LSB_BMSK;
-		msm_hs_write(uport, UARTDM_IPR_ADDR, data);
+		msm_hs_write(uport, UART_DM_IPR, data);
 	}
 
 	if (is_blsp_uart(msm_uport)) {
@@ -2300,21 +2390,21 @@
 		/* Enable Data Mover Mode */
 		data = UARTDM_TX_DM_EN_BMSK | UARTDM_RX_DM_EN_BMSK;
 	}
-	msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
+	msm_hs_write(uport, UART_DM_DMEN, data);
 
 	/* Reset TX */
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_ERROR_STATUS);
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_BREAK_INT);
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
-	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS);
-	msm_hs_write(uport, UARTDM_CR_ADDR, RFR_LOW);
+	msm_hs_write(uport, UART_DM_CR, RESET_TX);
+	msm_hs_write(uport, UART_DM_CR, RESET_RX);
+	msm_hs_write(uport, UART_DM_CR, RESET_ERROR_STATUS);
+	msm_hs_write(uport, UART_DM_CR, RESET_BREAK_INT);
+	msm_hs_write(uport, UART_DM_CR, RESET_STALE_INT);
+	msm_hs_write(uport, UART_DM_CR, RESET_CTS);
+	msm_hs_write(uport, UART_DM_CR, RFR_LOW);
 	/* Turn on Uart Receiver */
-	msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_RX_EN_BMSK);
+	msm_hs_write(uport, UART_DM_CR, UARTDM_CR_RX_EN_BMSK);
 
 	/* Turn on Uart Transmitter */
-	msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_EN_BMSK);
+	msm_hs_write(uport, UART_DM_CR, UARTDM_CR_TX_EN_BMSK);
 
 	/* Initialize the tx */
 	tx->tx_ready_int_en = 0;
@@ -2340,7 +2430,8 @@
 	/* Enable reading the current CTS, no harm even if CTS is ignored */
 	msm_uport->imr_reg |= UARTDM_ISR_CURRENT_CTS_BMSK;
 
-	msm_hs_write(uport, UARTDM_TFWR_ADDR, 0);  /* TXLEV on empty TX fifo */
+	/* TXLEV on empty TX fifo */
+	msm_hs_write(uport, UART_DM_TFWR, 0);
 	/*
 	 * Complete all device write related configuration before
 	 * queuing RX request. Hence mb() requires here.
@@ -2375,8 +2466,7 @@
 		disable_irq(msm_uport->wakeup.irq);
 	}
 
-	/* Vote for PNOC BUS Scaling */
-	msm_hs_bus_voting(msm_uport, BUS_SCALING);
+	msm_hs_clock_vote(msm_uport);
 
 	spin_lock_irqsave(&uport->lock, flags);
 
@@ -2384,6 +2474,8 @@
 
 	spin_unlock_irqrestore(&uport->lock, flags);
 
+	msm_hs_clock_unvote(msm_uport);
+
 	pm_runtime_enable(uport->dev);
 
 	return 0;
@@ -2403,9 +2495,7 @@
 	if (is_blsp_uart(msm_uport))
 		msm_hs_unconfig_uart_gpios(uport);
 deinit_uart_clk:
-	clk_disable_unprepare(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_disable_unprepare(msm_uport->pclk);
+	msm_hs_clock_unvote(msm_uport);
 	wake_unlock(&msm_uport->dma_wake_lock);
 
 	return ret;
@@ -2447,9 +2537,9 @@
 
 	/* Set up Uart Receive */
 	if (is_blsp_uart(msm_uport))
-		msm_hs_write(uport, UARTDM_RFWR_ADDR, 32);
+		msm_hs_write(uport, UART_DM_RFWR, 32);
 	else
-		msm_hs_write(uport, UARTDM_RFWR_ADDR, 0);
+		msm_hs_write(uport, UART_DM_RFWR, 0);
 
 	INIT_DELAYED_WORK(&rx->flip_insert_work, flip_insert_work);
 
@@ -2837,6 +2927,7 @@
 	struct resource *resource;
 	int core_irqres, bam_irqres, wakeup_irqres;
 	struct msm_serial_hs_platform_data *pdata = pdev->dev.platform_data;
+	const struct of_device_id *match;
 
 	if (pdev->dev.of_node) {
 		dev_dbg(&pdev->dev, "device tree enabled\n");
@@ -2883,6 +2974,12 @@
 	uport = &msm_uport->uport;
 	uport->dev = &pdev->dev;
 
+	match = of_match_device(msm_hs_match_table, &pdev->dev);
+	if (match)
+		msm_uport->reg_ptr = (unsigned int *)match->data;
+	else if (is_gsbi_uart(msm_uport))
+		msm_uport->reg_ptr = regmap_nonblsp;
+
 	if (pdev->dev.of_node)
 		msm_uport->uart_type = BLSP_HSUART;
 
@@ -3057,6 +3154,8 @@
 	INIT_WORK(&msm_uport->disconnect_rx_endpoint,
 				hsuart_disconnect_rx_endpoint_work);
 	mutex_init(&msm_uport->clk_mutex);
+	atomic_set(&msm_uport->clk_count, 0);
+
 
 	/* Initialize SPS HW connected with UART core */
 	if (is_blsp_uart(msm_uport)) {
@@ -3067,11 +3166,7 @@
 		}
 	}
 
-	msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
-	clk_prepare_enable(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_prepare_enable(msm_uport->pclk);
+	msm_hs_clock_vote(msm_uport);
 
 	ret = uartdm_init_port(uport);
 	if (unlikely(ret)) {
@@ -3079,8 +3174,7 @@
 	}
 
 	/* configure the CR Protection to Enable */
-	msm_hs_write(uport, UARTDM_CR_ADDR, CR_PROTECTION_EN);
-
+	msm_hs_write(uport, UART_DM_CR, CR_PROTECTION_EN);
 
 	/*
 	 * Enable Command register protection before going ahead as this hw
@@ -3106,19 +3200,12 @@
 		uport->line = pdata->userid;
 	ret = uart_add_one_port(&msm_hs_driver, uport);
 	if (!ret) {
-		msm_hs_bus_voting(msm_uport, BUS_RESET);
-		clk_disable_unprepare(msm_uport->clk);
-		if (msm_uport->pclk)
-			clk_disable_unprepare(msm_uport->pclk);
+		msm_hs_clock_unvote(msm_uport);
 		return ret;
 	}
 
 err_clock:
-
-	msm_hs_bus_voting(msm_uport, BUS_RESET);
-	clk_disable_unprepare(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_disable_unprepare(msm_uport->pclk);
+	msm_hs_clock_unvote(msm_uport);
 
 destroy_mutex:
 	mutex_destroy(&msm_uport->clk_mutex);
@@ -3189,20 +3276,21 @@
 	struct msm_hs_tx *tx = &msm_uport->tx;
 	struct sps_pipe *sps_pipe_handle = tx->cons.pipe_handle;
 
+	msm_hs_clock_vote(msm_uport);
 	if (msm_uport->tx.dma_in_flight) {
 		if (!is_blsp_uart(msm_uport)) {
 			spin_lock_irqsave(&uport->lock, flags);
 			/* disable UART TX interface to DM */
-			data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
+			data = msm_hs_read(uport, UART_DM_DMEN);
 			data &= ~UARTDM_TX_DM_EN_BMSK;
-			msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
+			msm_hs_write(uport, UART_DM_DMEN, data);
 			/* turn OFF UART Transmitter */
-			msm_hs_write(uport, UARTDM_CR_ADDR,
-					UARTDM_CR_TX_DISABLE_BMSK);
+			msm_hs_write(uport, UART_DM_CR,
+				UARTDM_CR_TX_DISABLE_BMSK);
 			/* reset UART TX */
-			msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
+			msm_hs_write(uport, UART_DM_CR, RESET_TX);
 			/* reset UART TX Error */
-			msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX_ERROR);
+			msm_hs_write(uport, UART_DM_CR, RESET_TX_ERROR);
 			msm_uport->tx.flush = FLUSH_STOP;
 			spin_unlock_irqrestore(&uport->lock, flags);
 			/* discard flush */
@@ -3228,28 +3316,24 @@
 	pm_runtime_disable(uport->dev);
 
 	/* Disable the transmitter */
-	msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_DISABLE_BMSK);
+	msm_hs_write(uport, UART_DM_CR, UARTDM_CR_TX_DISABLE_BMSK);
 	/* Disable the receiver */
-	msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_RX_DISABLE_BMSK);
+	msm_hs_write(uport, UART_DM_CR, UARTDM_CR_RX_DISABLE_BMSK);
 
 	msm_uport->imr_reg = 0;
-	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+	msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
 	/*
 	 * Complete all device write before actually disabling uartclk.
 	 * Hence mb() requires here.
 	 */
 	mb();
 
-	/* Reset PNOC Bus Scaling */
-	msm_hs_bus_voting(msm_uport, BUS_RESET);
-
 	if (msm_uport->clk_state != MSM_HS_CLK_OFF) {
 		/* to balance clk_state */
-		clk_disable_unprepare(msm_uport->clk);
-		if (msm_uport->pclk)
-			clk_disable_unprepare(msm_uport->pclk);
+		msm_hs_clock_unvote(msm_uport);
 		wake_unlock(&msm_uport->dma_wake_lock);
 	}
+	msm_hs_clock_unvote(msm_uport);
 
 	msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
 	dma_unmap_single(uport->dev, msm_uport->tx.dma_base,
@@ -3313,10 +3397,6 @@
 	.runtime_idle    = msm_hs_runtime_idle,
 };
 
-static struct of_device_id msm_hs_match_table[] = {
-	{ .compatible = "qcom,msm-hsuart-v14" },
-	{}
-};
 
 static struct platform_driver msm_serial_hs_platform_driver = {
 	.probe	= msm_hs_probe,
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index cd24f23..d912b9f 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -60,6 +60,30 @@
 	UARTDM_LAST,
 };
 
+enum msm_hs_regs {
+	UART_DM_MR1,
+	UART_DM_MR2,
+	UART_DM_IMR,
+	UART_DM_SR,
+	UART_DM_CR,
+	UART_DM_CSR,
+	UART_DM_IPR,
+	UART_DM_ISR,
+	UART_DM_RX_TOTAL_SNAP,
+	UART_DM_RFWR,
+	UART_DM_TFWR,
+	UART_DM_RF,
+	UART_DM_TF,
+	UART_DM_MISR,
+	UART_DM_DMRX,
+	UART_DM_NCF_TX,
+	UART_DM_DMEN,
+	UART_DM_TXFS,
+	UART_DM_RXFS,
+	UART_DM_RX_TRANS_CTRL,
+	UART_DM_LAST,
+};
+
 #define UARTDM_MR1_ADDR 0x0
 #define UARTDM_MR2_ADDR 0x4
 
@@ -219,70 +243,6 @@
 #define UARTDM_TX_BAM_ENABLE_BMSK 0x4
 #define UARTDM_RX_BAM_ENABLE_BMSK 0x8
 
-/*
- * Some of the BLSP Based UART Core(v14) existing register offsets
- * are different compare to GSBI based UART Core(v13)
- * Hence add the changed register offsets for UART Core v14
- */
-#ifdef CONFIG_MSM_UARTDM_Core_v14
-
-/* write only register */
-#define UARTDM_CSR_ADDR    0xa0
-
-/* write only register */
-#define UARTDM_TF_ADDR   0x100
-#define UARTDM_TF2_ADDR  0x104
-#define UARTDM_TF3_ADDR  0x108
-#define UARTDM_TF4_ADDR  0x10c
-#define UARTDM_TF5_ADDR  0x110
-#define UARTDM_TF6_ADDR  0x114
-#define UARTDM_TF7_ADDR  0x118
-#define UARTDM_TF8_ADDR  0x11c
-#define UARTDM_TF9_ADDR  0x120
-#define UARTDM_TF10_ADDR 0x124
-#define UARTDM_TF11_ADDR 0x128
-#define UARTDM_TF12_ADDR 0x12c
-#define UARTDM_TF13_ADDR 0x130
-#define UARTDM_TF14_ADDR 0x134
-#define UARTDM_TF15_ADDR 0x138
-#define UARTDM_TF16_ADDR 0x13c
-
-/* write only register */
-#define UARTDM_CR_ADDR 0xa8
-/* write only register */
-#define UARTDM_IMR_ADDR 0xb0
-#define UARTDM_IRDA_ADDR 0xb8
-
-/* Read Only register */
-#define UARTDM_SR_ADDR 0xa4
-
-/* Read Only register */
-#define UARTDM_RF_ADDR   0x140
-#define UARTDM_RF2_ADDR  0x144
-#define UARTDM_RF3_ADDR  0x148
-#define UARTDM_RF4_ADDR  0x14c
-#define UARTDM_RF5_ADDR  0x150
-#define UARTDM_RF6_ADDR  0x154
-#define UARTDM_RF7_ADDR  0x158
-#define UARTDM_RF8_ADDR  0x15c
-#define UARTDM_RF9_ADDR  0x160
-#define UARTDM_RF10_ADDR 0x164
-#define UARTDM_RF11_ADDR 0x168
-#define UARTDM_RF12_ADDR 0x16c
-#define UARTDM_RF13_ADDR 0x170
-#define UARTDM_RF14_ADDR 0x174
-#define UARTDM_RF15_ADDR 0x178
-#define UARTDM_RF16_ADDR 0x17c
-
-/* Read Only register */
-#define UARTDM_MISR_ADDR 0xac
-
-/* Read Only register */
-#define UARTDM_ISR_ADDR 0xb4
-#define UARTDM_RX_TOTAL_SNAP_ADDR 0xbc
-
-#else
-
 /* Register offsets for UART Core v13 */
 
 /* write only register */
@@ -316,6 +276,4 @@
 #define UARTDM_ISR_ADDR 0x14
 #define UARTDM_RX_TOTAL_SNAP_ADDR 0x38
 
-#endif
-
 #endif /* MSM_SERIAL_HS_HWREG_H */
diff --git a/drivers/tty/smux_test.c b/drivers/tty/smux_test.c
index 8d17674..130b65e 100644
--- a/drivers/tty/smux_test.c
+++ b/drivers/tty/smux_test.c
@@ -194,6 +194,8 @@
 	int event_high_wm;
 	int event_rx_retry_high_wm;
 	int event_rx_retry_low_wm;
+	int event_local_closed;
+	int event_remote_closed;
 
 	/* TIOCM changes */
 	int event_tiocm;
@@ -249,6 +251,8 @@
 	cb->event_high_wm = 0;
 	cb->event_rx_retry_high_wm = 0;
 	cb->event_rx_retry_low_wm = 0;
+	cb->event_local_closed = 0;
+	cb->event_remote_closed = 0;
 	cb->event_tiocm = 0;
 	cb->tiocm_meta.tiocm_old = 0;
 	cb->tiocm_meta.tiocm_new = 0;
@@ -311,6 +315,8 @@
 		"\tevent_high_wm=%d\n"
 		"\tevent_rx_retry_high_wm=%d\n"
 		"\tevent_rx_retry_low_wm=%d\n"
+		"\tevent_local_closed=%d\n"
+		"\tevent_remote_closed=%d\n"
 		"\tevent_tiocm=%d\n"
 		"\tevent_read_done=%d\n"
 		"\tevent_read_failed=%d\n"
@@ -329,6 +335,8 @@
 		cb->event_high_wm,
 		cb->event_rx_retry_high_wm,
 		cb->event_rx_retry_low_wm,
+		cb->event_local_closed,
+		cb->event_remote_closed,
 		cb->event_tiocm,
 		cb->event_read_done,
 		cb->event_read_failed,
@@ -467,6 +475,22 @@
 		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
 		break;
 
+	case SMUX_LOCAL_CLOSED:
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
+		++cb_data_ptr->event_local_closed;
+		cb_data_ptr->event_disconnected_ssr =
+			((struct smux_meta_disconnected *)metadata)->is_ssr;
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
+		break;
+
+	case SMUX_REMOTE_CLOSED:
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
+		++cb_data_ptr->event_remote_closed;
+		cb_data_ptr->event_disconnected_ssr =
+			((struct smux_meta_disconnected *)metadata)->is_ssr;
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
+		break;
+
 	default:
 		pr_err("%s: unknown event %d\n", __func__, event);
 	};
@@ -609,13 +633,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -783,13 +812,18 @@
 
 		/* verify SSR events */
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, 5*HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, 10*HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		mock_cb_data_reset(&cb_data);
 
 		/* close port */
@@ -894,6 +928,8 @@
 			break;
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		mock_cb_data_reset(&cb_data);
 
 		/* close port */
@@ -1272,13 +1308,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -1442,13 +1483,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -1552,13 +1598,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -1884,13 +1935,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -2010,13 +2066,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -2139,13 +2200,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index bb2879b..db6fec9 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -264,7 +264,7 @@
  *
  * Returns 0 on success otherwise negative errno.
  */
-static int dwc3_event_buffers_setup(struct dwc3 *dwc)
+int dwc3_event_buffers_setup(struct dwc3 *dwc)
 {
 	struct dwc3_event_buffer	*evt;
 	int				n;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 5db7420..2064c13 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -920,6 +920,7 @@
 
 void dwc3_gadget_restart(struct dwc3 *dwc);
 void dwc3_post_host_reset_core_init(struct dwc3 *dwc);
+int dwc3_event_buffers_setup(struct dwc3 *dwc);
 
 extern int dwc3_get_device_id(void);
 extern void dwc3_put_device_id(int id);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 2487e3f..c89f6d8 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -36,6 +36,7 @@
 #include <linux/usb/msm_hsusb.h>
 #include <linux/usb/msm_ext_chg.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_wakeup.h>
 #include <linux/power_supply.h>
 #include <linux/qpnp/qpnp-adc.h>
 #include <linux/cdev.h>
@@ -196,7 +197,6 @@
 	bool			lpm_irq_seen;
 	struct delayed_work	resume_work;
 	struct work_struct	restart_usb_work;
-	struct wake_lock	wlock;
 	struct dwc3_charger	charger;
 	struct usb_phy		*otg_xceiv;
 	struct delayed_work	chg_work;
@@ -213,6 +213,7 @@
 	struct power_supply	*ext_vbus_psy;
 	unsigned int		online;
 	unsigned int		host_mode;
+	unsigned int		voltage_max;
 	unsigned int		current_max;
 	unsigned int		vdd_no_vol_level;
 	unsigned int		vdd_low_vol_level;
@@ -246,8 +247,6 @@
 #define USB_SSPHY_1P8_VOL_MAX		1800000 /* uV */
 #define USB_SSPHY_1P8_HPM_LOAD		23000	/* uA */
 
-static struct dwc3_msm *context;
-
 static struct usb_ext_notification *usb_ext;
 
 /**
@@ -343,8 +342,8 @@
 	tmp &= mask;		/* clear other bits */
 
 	if (tmp != val)
-		dev_err(context->dev, "%s: write: %x to QSCRATCH: %x FAILED\n",
-						__func__, val, offset);
+		pr_err("%s: write: %x to QSCRATCH: %x FAILED\n",
+			__func__, val, offset);
 }
 
 /**
@@ -413,12 +412,12 @@
  * Return DBM EP number according to usb endpoint number.
  *
  */
-static int dwc3_msm_find_matching_dbm_ep(u8 usb_ep)
+static int dwc3_msm_find_matching_dbm_ep(struct dwc3_msm *mdwc, u8 usb_ep)
 {
 	int i;
 
-	for (i = 0; i < context->dbm_num_eps; i++)
-		if (context->ep_num_mapping[i] == usb_ep)
+	for (i = 0; i < mdwc->dbm_num_eps; i++)
+		if (mdwc->ep_num_mapping[i] == usb_ep)
 			return i;
 
 	return -ENODEV; /* Not found */
@@ -428,13 +427,13 @@
  * Return number of configured DBM endpoints.
  *
  */
-static int dwc3_msm_configured_dbm_ep_num(void)
+static int dwc3_msm_configured_dbm_ep_num(struct dwc3_msm *mdwc)
 {
 	int i;
 	int count = 0;
 
-	for (i = 0; i < context->dbm_num_eps; i++)
-		if (context->ep_num_mapping[i])
+	for (i = 0; i < mdwc->dbm_num_eps; i++)
+		if (mdwc->ep_num_mapping[i])
 			count++;
 
 	return count;
@@ -448,12 +447,13 @@
  * @size - size of the event buffer.
  *
  */
-static int dwc3_msm_event_buffer_config(u32 addr, u16 size)
+static int dwc3_msm_event_buffer_config(struct dwc3_msm *mdwc,
+					u32 addr, u16 size)
 {
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 
-	dwc3_msm_write_reg(context->base, DBM_GEVNTADR, addr);
-	dwc3_msm_write_reg_field(context->base, DBM_GEVNTSIZ,
+	dwc3_msm_write_reg(mdwc->base, DBM_GEVNTADR, addr);
+	dwc3_msm_write_reg_field(mdwc->base, DBM_GEVNTSIZ,
 		DBM_GEVNTSIZ_MASK, size);
 
 	return 0;
@@ -463,19 +463,19 @@
  * Reset the DBM registers upon initialization.
  *
  */
-static int dwc3_msm_dbm_soft_reset(int enter_reset)
+static int dwc3_msm_dbm_soft_reset(struct dwc3_msm *mdwc, int enter_reset)
 {
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 	if (enter_reset) {
-		dev_dbg(context->dev, "enter DBM reset\n");
-		dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+		dev_dbg(mdwc->dev, "enter DBM reset\n");
+		dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
 			DBM_SFT_RST_MASK, 1);
 	} else {
-		dev_dbg(context->dev, "exit DBM reset\n");
-		dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+		dev_dbg(mdwc->dev, "exit DBM reset\n");
+		dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
 			DBM_SFT_RST_MASK, 0);
 		/*enable DBM*/
-		dwc3_msm_write_reg_field(context->base, QSCRATCH_GENERAL_CFG,
+		dwc3_msm_write_reg_field(mdwc->base, QSCRATCH_GENERAL_CFG,
 			DBM_EN_MASK, 0x1);
 	}
 
@@ -492,21 +492,21 @@
  * @enter_reset - should we enter a reset state or get out of it.
  *
  */
-static int dwc3_msm_dbm_ep_soft_reset(u8 dbm_ep, bool enter_reset)
+static int dwc3_msm_dbm_ep_soft_reset(struct dwc3_msm *mdwc,
+					u8 dbm_ep, bool enter_reset)
 {
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 
-	if (dbm_ep >= context->dbm_num_eps) {
-		dev_err(context->dev,
-				"%s: Invalid DBM ep index\n", __func__);
+	if (dbm_ep >= mdwc->dbm_num_eps) {
+		dev_err(mdwc->dev, "%s: Invalid DBM ep index\n", __func__);
 		return -ENODEV;
 	}
 
 	if (enter_reset) {
-		dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+		dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
 			DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 1);
 	} else {
-		dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+		dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
 			DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 0);
 	}
 
@@ -525,43 +525,43 @@
  *
  * @return int - DBM ep number.
  */
-static int dwc3_msm_dbm_ep_config(u8 usb_ep, u8 bam_pipe,
+static int dwc3_msm_dbm_ep_config(struct dwc3_msm *mdwc, u8 usb_ep, u8 bam_pipe,
 				  bool producer, bool disable_wb,
 				  bool internal_mem, bool ioc)
 {
 	u8 dbm_ep;
 	u32 ep_cfg;
 
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 
-	dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
+	dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
 
 	if (dbm_ep < 0) {
-		dev_err(context->dev,
+		dev_err(mdwc->dev,
 				"%s: Invalid usb ep index\n", __func__);
 		return -ENODEV;
 	}
 	/* First, reset the dbm endpoint */
-	dwc3_msm_dbm_ep_soft_reset(dbm_ep, 0);
+	dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, 0);
 
 	/* Set ioc bit for dbm_ep if needed */
-	dwc3_msm_write_reg_field(context->base, DBM_DBG_CNFG,
+	dwc3_msm_write_reg_field(mdwc->base, DBM_DBG_CNFG,
 		DBM_ENABLE_IOC_MASK & 1 << dbm_ep, ioc ? 1 : 0);
 
 	ep_cfg = (producer ? DBM_PRODUCER : 0) |
 		(disable_wb ? DBM_DISABLE_WB : 0) |
 		(internal_mem ? DBM_INT_RAM_ACC : 0);
 
-	dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+	dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
 		DBM_PRODUCER | DBM_DISABLE_WB | DBM_INT_RAM_ACC, ep_cfg >> 8);
 
-	dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
+	dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
 		usb_ep);
-	dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+	dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
 		DBM_BAM_PIPE_NUM, bam_pipe);
-	dwc3_msm_write_reg_field(context->base, DBM_PIPE_CFG, 0x000000ff,
+	dwc3_msm_write_reg_field(mdwc->base, DBM_PIPE_CFG, 0x000000ff,
 		0xe4);
-	dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
+	dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
 		1);
 
 	return dbm_ep;
@@ -573,35 +573,34 @@
  * @usb_ep - USB ep number.
  *
  */
-static int dwc3_msm_dbm_ep_unconfig(u8 usb_ep)
+static int dwc3_msm_dbm_ep_unconfig(struct dwc3_msm *mdwc, u8 usb_ep)
 {
 	u8 dbm_ep;
 	u32 data;
 
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 
-	dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
+	dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
 
 	if (dbm_ep < 0) {
-		dev_err(context->dev,
-				"%s: Invalid usb ep index\n", __func__);
+		dev_err(mdwc->dev, "%s: Invalid usb ep index\n", __func__);
 		return -ENODEV;
 	}
 
-	context->ep_num_mapping[dbm_ep] = 0;
+	mdwc->ep_num_mapping[dbm_ep] = 0;
 
-	data = dwc3_msm_read_reg(context->base, DBM_EP_CFG(dbm_ep));
+	data = dwc3_msm_read_reg(mdwc->base, DBM_EP_CFG(dbm_ep));
 	data &= (~0x1);
-	dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep), data);
+	dwc3_msm_write_reg(mdwc->base, DBM_EP_CFG(dbm_ep), data);
 
 	/* Reset the dbm endpoint */
-	dwc3_msm_dbm_ep_soft_reset(dbm_ep, true);
+	dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, true);
 	/*
 	 * 10 usec delay is required before deasserting DBM endpoint reset
 	 * according to hardware programming guide.
 	 */
 	udelay(10);
-	dwc3_msm_dbm_ep_soft_reset(dbm_ep, false);
+	dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, false);
 
 	return 0;
 }
@@ -620,15 +619,17 @@
 {
 	u8 dbm_ep;
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	u8 bam_pipe = dst_pipe_idx;
 
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 
 	dbm_ep = bam_pipe;
-	context->ep_num_mapping[dbm_ep] = dep->number;
+	mdwc->ep_num_mapping[dbm_ep] = dep->number;
 
-	dwc3_msm_write_reg(context->base, DBM_DATA_FIFO(dbm_ep), addr);
-	dwc3_msm_write_reg_field(context->base, DBM_DATA_FIFO_SIZE(dbm_ep),
+	dwc3_msm_write_reg(mdwc->base, DBM_DATA_FIFO(dbm_ep), addr);
+	dwc3_msm_write_reg_field(mdwc->base, DBM_DATA_FIFO_SIZE(dbm_ep),
 		DBM_DATA_FIFO_SIZE_MASK, size);
 
 	return 0;
@@ -648,12 +649,12 @@
 				       struct usb_request *request)
 {
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	struct dwc3_msm_req_complete *req_complete = NULL;
 
 	/* Find original request complete function and remove it from list */
-	list_for_each_entry(req_complete,
-				&context->req_complete_list,
-				list_item) {
+	list_for_each_entry(req_complete, &mdwc->req_complete_list, list_item) {
 		if (req_complete->req == request)
 			break;
 	}
@@ -672,14 +673,14 @@
 	dep->busy_slot++;
 
 	/* Unconfigure dbm ep */
-	dwc3_msm_dbm_ep_unconfig(dep->number);
+	dwc3_msm_dbm_ep_unconfig(mdwc, dep->number);
 
 	/*
 	 * If this is the last endpoint we unconfigured, than reset also
 	 * the event buffers.
 	 */
-	if (0 == dwc3_msm_configured_dbm_ep_num())
-		dwc3_msm_event_buffer_config(0, 0);
+	if (0 == dwc3_msm_configured_dbm_ep_num(mdwc))
+		dwc3_msm_event_buffer_config(mdwc, 0, 0);
 
 	/*
 	 * Call original complete function, notice that dwc->lock is already
@@ -792,6 +793,7 @@
 	struct dwc3_request *req = to_dwc3_request(request);
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
 	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	struct dwc3_msm_req_complete *req_complete;
 	unsigned long flags;
 	int ret = 0;
@@ -804,23 +806,23 @@
 
 	if (!(request->udc_priv & MSM_SPS_MODE)) {
 		/* Not SPS mode, call original queue */
-		dev_vdbg(dwc->dev, "%s: not sps mode, use regular queue\n",
+		dev_vdbg(mdwc->dev, "%s: not sps mode, use regular queue\n",
 					__func__);
 
-		return (context->original_ep_ops[dep->number])->queue(ep,
+		return (mdwc->original_ep_ops[dep->number])->queue(ep,
 								request,
 								gfp_flags);
 	}
 
 	if (!dep->endpoint.desc) {
-		dev_err(dwc->dev,
+		dev_err(mdwc->dev,
 			"%s: trying to queue request %p to disabled ep %s\n",
 			__func__, request, ep->name);
 		return -EPERM;
 	}
 
 	if (dep->number == 0 || dep->number == 1) {
-		dev_err(dwc->dev,
+		dev_err(mdwc->dev,
 			"%s: trying to queue dbm request %p to control ep %s\n",
 			__func__, request, ep->name);
 		return -EPERM;
@@ -829,7 +831,7 @@
 
 	if (dep->busy_slot != dep->free_slot || !list_empty(&dep->request_list)
 					 || !list_empty(&dep->req_queued)) {
-		dev_err(dwc->dev,
+		dev_err(mdwc->dev,
 			"%s: trying to queue dbm request %p tp ep %s\n",
 			__func__, request, ep->name);
 		return -EPERM;
@@ -844,12 +846,12 @@
 	 */
 	req_complete = kzalloc(sizeof(*req_complete), GFP_KERNEL);
 	if (!req_complete) {
-		dev_err(dep->dwc->dev, "%s: not enough memory\n", __func__);
+		dev_err(mdwc->dev, "%s: not enough memory\n", __func__);
 		return -ENOMEM;
 	}
 	req_complete->req = request;
 	req_complete->orig_complete = request->complete;
-	list_add_tail(&req_complete->list_item, &context->req_complete_list);
+	list_add_tail(&req_complete->list_item, &mdwc->req_complete_list);
 	request->complete = dwc3_msm_req_complete_func;
 
 	/*
@@ -861,11 +863,11 @@
 	internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
 	ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
 
-	ret = dwc3_msm_dbm_ep_config(dep->number,
+	ret = dwc3_msm_dbm_ep_config(mdwc, dep->number,
 					bam_pipe, producer,
 					disable_wb, internal_mem, ioc);
 	if (ret < 0) {
-		dev_err(context->dev,
+		dev_err(mdwc->dev,
 			"error %d after calling dwc3_msm_dbm_ep_config\n",
 			ret);
 		return ret;
@@ -885,13 +887,13 @@
 	ret = __dwc3_msm_ep_queue(dep, req);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 	if (ret < 0) {
-		dev_err(context->dev,
+		dev_err(mdwc->dev,
 			"error %d after calling __dwc3_msm_ep_queue\n", ret);
 		return ret;
 	}
 
 	speed = dwc3_readl(dwc->regs, DWC3_DSTS) & DWC3_DSTS_CONNECTSPD;
-	dwc3_msm_write_reg(context->base, DBM_GEN_CFG, speed >> 2);
+	dwc3_msm_write_reg(mdwc->base, DBM_GEN_CFG, speed >> 2);
 
 	return 0;
 }
@@ -913,25 +915,27 @@
 int msm_ep_config(struct usb_ep *ep)
 {
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	struct usb_ep_ops *new_ep_ops;
 
-	dwc3_msm_event_buffer_config(dwc3_msm_read_reg(context->base,
-			DWC3_GEVNTADRLO(0)),
-			dwc3_msm_read_reg(context->base, DWC3_GEVNTSIZ(0)));
+	dwc3_msm_event_buffer_config(mdwc,
+			dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRLO(0)),
+			dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0)));
 
 	/* Save original ep ops for future restore*/
-	if (context->original_ep_ops[dep->number]) {
-		dev_err(context->dev,
+	if (mdwc->original_ep_ops[dep->number]) {
+		dev_err(mdwc->dev,
 			"ep [%s,%d] already configured as msm endpoint\n",
 			ep->name, dep->number);
 		return -EPERM;
 	}
-	context->original_ep_ops[dep->number] = ep->ops;
+	mdwc->original_ep_ops[dep->number] = ep->ops;
 
 	/* Set new usb ops as we like */
 	new_ep_ops = kzalloc(sizeof(struct usb_ep_ops), GFP_KERNEL);
 	if (!new_ep_ops) {
-		dev_err(context->dev,
+		dev_err(mdwc->dev,
 			"%s: unable to allocate mem for new usb ep ops\n",
 			__func__);
 		return -ENOMEM;
@@ -963,18 +967,20 @@
 int msm_ep_unconfig(struct usb_ep *ep)
 {
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	struct usb_ep_ops *old_ep_ops;
 
 	/* Restore original ep ops */
-	if (!context->original_ep_ops[dep->number]) {
-		dev_err(context->dev,
+	if (!mdwc->original_ep_ops[dep->number]) {
+		dev_err(mdwc->dev,
 			"ep [%s,%d] was not configured as msm endpoint\n",
 			ep->name, dep->number);
 		return -EINVAL;
 	}
 	old_ep_ops = (struct usb_ep_ops	*)ep->ops;
-	ep->ops = context->original_ep_ops[dep->number];
-	context->original_ep_ops[dep->number] = NULL;
+	ep->ops = mdwc->original_ep_ops[dep->number];
+	mdwc->original_ep_ops[dep->number] = NULL;
 	kfree(old_ep_ops);
 
 	/*
@@ -1019,14 +1025,16 @@
  * This performs full hardware reset and re-initialization which
  * might be required by some DBM client driver during uninit/cleanup.
  */
-void msm_dwc3_restart_usb_session(void)
+void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3 *dwc = container_of(gadget, struct dwc3, gadget);
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+	if (mdwc)
+		return;
 
 	dev_dbg(mdwc->dev, "%s\n", __func__);
 	queue_work(system_nrt_wq, &mdwc->restart_usb_work);
-
-	return;
 }
 EXPORT_SYMBOL(msm_dwc3_restart_usb_session);
 
@@ -1058,10 +1066,9 @@
 EXPORT_SYMBOL(msm_register_usb_ext_notification);
 
 /* HSPHY */
-static int dwc3_hsusb_config_vddcx(int high)
+static int dwc3_hsusb_config_vddcx(struct dwc3_msm *dwc, int high)
 {
 	int min_vol, max_vol, ret;
-	struct dwc3_msm *dwc = context;
 
 	max_vol = dwc->vdd_high_vol_level;
 	min_vol = high ? dwc->vdd_low_vol_level : dwc->vdd_no_vol_level;
@@ -1077,10 +1084,9 @@
 	return ret;
 }
 
-static int dwc3_hsusb_ldo_init(int init)
+static int dwc3_hsusb_ldo_init(struct dwc3_msm *dwc, int init)
 {
 	int rc = 0;
-	struct dwc3_msm *dwc = context;
 
 	if (!init) {
 		regulator_set_voltage(dwc->hsusb_1p8, 0, USB_HSPHY_1P8_VOL_MAX);
@@ -1121,10 +1127,9 @@
 	return rc;
 }
 
-static int dwc3_hsusb_ldo_enable(int on)
+static int dwc3_hsusb_ldo_enable(struct dwc3_msm *dwc, int on)
 {
 	int rc = 0;
-	struct dwc3_msm *dwc = context;
 
 	dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
 
@@ -1182,10 +1187,9 @@
 }
 
 /* SSPHY */
-static int dwc3_ssusb_config_vddcx(int high)
+static int dwc3_ssusb_config_vddcx(struct dwc3_msm *dwc, int high)
 {
 	int min_vol, max_vol, ret;
-	struct dwc3_msm *dwc = context;
 
 	max_vol = dwc->vdd_high_vol_level;
 	min_vol = high ? dwc->vdd_low_vol_level : dwc->vdd_no_vol_level;
@@ -1201,10 +1205,9 @@
 }
 
 /* 3.3v supply not needed for SS PHY */
-static int dwc3_ssusb_ldo_init(int init)
+static int dwc3_ssusb_ldo_init(struct dwc3_msm *dwc, int init)
 {
 	int rc = 0;
-	struct dwc3_msm *dwc = context;
 
 	if (!init) {
 		regulator_set_voltage(dwc->ssusb_1p8, 0, USB_SSPHY_1P8_VOL_MAX);
@@ -1224,12 +1227,11 @@
 	return rc;
 }
 
-static int dwc3_ssusb_ldo_enable(int on)
+static int dwc3_ssusb_ldo_enable(struct dwc3_msm *dwc, int on)
 {
 	int rc = 0;
-	struct dwc3_msm *dwc = context;
 
-	dev_dbg(context->dev, "reg (%s)\n", on ? "HPM" : "LPM");
+	dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
 
 	if (!on)
 		goto disable_regulators;
@@ -1266,37 +1268,36 @@
  * Config Global Distributed Switch Controller (GDSC)
  * to support controller power collapse
  */
-static int dwc3_msm_config_gdsc(struct dwc3_msm *msm, int on)
+static int dwc3_msm_config_gdsc(struct dwc3_msm *mdwc, int on)
 {
 	int ret = 0;
 
-	if (IS_ERR(msm->dwc3_gdsc))
+	if (IS_ERR(mdwc->dwc3_gdsc))
 		return 0;
 
-	if (!msm->dwc3_gdsc) {
-		msm->dwc3_gdsc = devm_regulator_get(msm->dev,
+	if (!mdwc->dwc3_gdsc) {
+		mdwc->dwc3_gdsc = devm_regulator_get(mdwc->dev,
 			"USB3_GDSC");
-		if (IS_ERR(msm->dwc3_gdsc))
+		if (IS_ERR(mdwc->dwc3_gdsc))
 			return 0;
 	}
 
 	if (on) {
-		ret = regulator_enable(msm->dwc3_gdsc);
+		ret = regulator_enable(mdwc->dwc3_gdsc);
 		if (ret) {
-			dev_err(msm->dev, "unable to enable usb3 gdsc\n");
+			dev_err(mdwc->dev, "unable to enable usb3 gdsc\n");
 			return ret;
 		}
 	} else {
-		regulator_disable(msm->dwc3_gdsc);
+		regulator_disable(mdwc->dwc3_gdsc);
 	}
 
 	return 0;
 }
 
-static int dwc3_msm_link_clk_reset(bool assert)
+static int dwc3_msm_link_clk_reset(struct dwc3_msm *mdwc, bool assert)
 {
 	int ret = 0;
-	struct dwc3_msm *mdwc = context;
 
 	if (assert) {
 		/* Using asynchronous block reset to the hardware */
@@ -1322,7 +1323,7 @@
 }
 
 /* Reinitialize SSPHY parameters by overriding using QSCRATCH CR interface */
-static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *msm)
+static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *mdwc)
 {
 	u32 data = 0;
 
@@ -1331,14 +1332,14 @@
 	 * in HS mode instead of SS mode. Workaround it by asserting
 	 * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode
 	 */
-	data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x102D);
+	data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x102D);
 	data |= (1 << 7);
-	dwc3_msm_ssusb_write_phycreg(msm->base, 0x102D, data);
+	dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x102D, data);
 
-	data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1010);
+	data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1010);
 	data &= ~0xFF0;
 	data |= 0x20;
-	dwc3_msm_ssusb_write_phycreg(msm->base, 0x1010, data);
+	dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1010, data);
 
 	/*
 	 * Fix RX Equalization setting as follows
@@ -1347,13 +1348,13 @@
 	 * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3
 	 * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1
 	 */
-	data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1006);
+	data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1006);
 	data &= ~(1 << 6);
 	data |= (1 << 7);
 	data &= ~(0x7 << 8);
 	data |= (0x3 << 8);
 	data |= (0x1 << 11);
-	dwc3_msm_ssusb_write_phycreg(msm->base, 0x1006, data);
+	dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1006, data);
 
 	/*
 	 * Set EQ and TX launch amplitudes as follows
@@ -1361,12 +1362,12 @@
 	 * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127
 	 * LANE0.TX_OVRD_DRV_LO.EN set to 1.
 	 */
-	data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1002);
+	data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1002);
 	data &= ~0x3F80;
 	data |= (0x16 << 7);
 	data &= ~0x7F;
 	data |= (0x7F | (1 << 14));
-	dwc3_msm_ssusb_write_phycreg(msm->base, 0x1002, data);
+	dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1002, data);
 
 	/*
 	 * Set the QSCRATCH SS_PHY_PARAM_CTRL1 parameters as follows
@@ -1374,73 +1375,73 @@
 	 * TX_DEEMPH_3_5DB [13:8] to 22
 	 * LOS_BIAS [2:0] to 0x5
 	 */
-	dwc3_msm_write_readback(msm->base, SS_PHY_PARAM_CTRL_1,
+	dwc3_msm_write_readback(mdwc->base, SS_PHY_PARAM_CTRL_1,
 				0x07f03f07, 0x07f01605);
 }
 
 /* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
-static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *msm)
+static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc)
 {
 	/* SSPHY Initialization: Use ref_clk from pads and set its parameters */
-	dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+	dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
 	msleep(30);
 	/* Assert SSPHY reset */
-	dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210082);
+	dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210082);
 	usleep_range(2000, 2200);
 	/* De-assert SSPHY reset - power and ref_clock must be ON */
-	dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+	dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
 	usleep_range(2000, 2200);
 	/* Ref clock must be stable now, enable ref clock for HS mode */
-	dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210102);
+	dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210102);
 	usleep_range(2000, 2200);
 	/*
 	 * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
 	 * and disable RETENTION (power-on default is ENABLED)
 	 */
-	dwc3_msm_write_reg(msm->base, HS_PHY_CTRL_REG, 0x5220bb2);
+	dwc3_msm_write_reg(mdwc->base, HS_PHY_CTRL_REG, 0x5220bb2);
 	usleep_range(2000, 2200);
 	/* Disable (bypass) VBUS and ID filters */
-	dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
+	dwc3_msm_write_reg(mdwc->base, QSCRATCH_GENERAL_CFG, 0x78);
 	/*
 	 * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
 	 * VBUS valid threshold, disconnect valid threshold, DC voltage level,
 	 * preempasis and rise/fall time.
 	 */
 	if (override_phy_init)
-		msm->hsphy_init_seq = override_phy_init;
-	if (msm->hsphy_init_seq)
-		dwc3_msm_write_readback(msm->base,
+		mdwc->hsphy_init_seq = override_phy_init;
+	if (mdwc->hsphy_init_seq)
+		dwc3_msm_write_readback(mdwc->base,
 					PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
-					msm->hsphy_init_seq & 0x03FFFFFF);
+					mdwc->hsphy_init_seq & 0x03FFFFFF);
 
 	/* Enable master clock for RAMs to allow BAM to access RAMs when
 	 * RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
 	 * are seen where RAM clocks get turned OFF in SS mode
 	 */
-	dwc3_msm_write_reg(msm->base, CGCTL_REG,
-		dwc3_msm_read_reg(msm->base, CGCTL_REG) | 0x18);
+	dwc3_msm_write_reg(mdwc->base, CGCTL_REG,
+		dwc3_msm_read_reg(mdwc->base, CGCTL_REG) | 0x18);
 
-	dwc3_msm_ss_phy_reg_init(msm);
+	dwc3_msm_ss_phy_reg_init(mdwc);
 	/*
 	 * This is required to restore the POR value after userspace
 	 * is done with charger detection.
 	 */
-	msm->qscratch_ctl_val = dwc3_msm_read_reg(msm->base, QSCRATCH_CTRL_REG);
+	mdwc->qscratch_ctl_val =
+		dwc3_msm_read_reg(mdwc->base, QSCRATCH_CTRL_REG);
 }
 
-static void dwc3_msm_block_reset(bool core_reset)
+static void dwc3_msm_block_reset(struct dwc3_ext_xceiv *xceiv, bool core_reset)
 {
-
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = container_of(xceiv, struct dwc3_msm, ext_xceiv);
 	int ret  = 0;
 
 	if (core_reset) {
-		ret = dwc3_msm_link_clk_reset(1);
+		ret = dwc3_msm_link_clk_reset(mdwc, 1);
 		if (ret)
 			return;
 
 		usleep_range(1000, 1200);
-		ret = dwc3_msm_link_clk_reset(0);
+		ret = dwc3_msm_link_clk_reset(mdwc, 0);
 		if (ret)
 			return;
 
@@ -1451,9 +1452,9 @@
 	}
 
 	/* Reset the DBM */
-	dwc3_msm_dbm_soft_reset(1);
+	dwc3_msm_dbm_soft_reset(mdwc, 1);
 	usleep_range(1000, 1200);
-	dwc3_msm_dbm_soft_reset(0);
+	dwc3_msm_dbm_soft_reset(mdwc, 0);
 }
 
 static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc)
@@ -1664,7 +1665,7 @@
 
 static void dwc3_start_chg_det(struct dwc3_charger *charger, bool start)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = container_of(charger, struct dwc3_msm, charger);
 
 	if (start == false) {
 		dev_dbg(mdwc->dev, "canceling charging detection work\n");
@@ -1796,13 +1797,13 @@
 
 	if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
 							!host_bus_suspend)
-		dwc3_hsusb_ldo_enable(0);
+		dwc3_hsusb_ldo_enable(mdwc, 0);
 
-	dwc3_ssusb_ldo_enable(0);
-	dwc3_ssusb_config_vddcx(0);
+	dwc3_ssusb_ldo_enable(mdwc, 0);
+	dwc3_ssusb_config_vddcx(mdwc, 0);
 	if (!host_bus_suspend && !dcp)
-		dwc3_hsusb_config_vddcx(0);
-	wake_unlock(&mdwc->wlock);
+		dwc3_hsusb_config_vddcx(mdwc, 0);
+	pm_relax(mdwc->dev);
 	atomic_set(&mdwc->in_lpm, 1);
 
 	dev_info(mdwc->dev, "DWC3 in low power mode\n");
@@ -1830,7 +1831,7 @@
 		return 0;
 	}
 
-	wake_lock(&mdwc->wlock);
+	pm_stay_awake(mdwc->dev);
 
 	if (mdwc->bus_perf_client) {
 		ret = msm_bus_scale_client_update_request(
@@ -1861,13 +1862,13 @@
 
 	if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
 							!host_bus_suspend)
-		dwc3_hsusb_ldo_enable(1);
+		dwc3_hsusb_ldo_enable(mdwc, 1);
 
-	dwc3_ssusb_ldo_enable(1);
-	dwc3_ssusb_config_vddcx(1);
+	dwc3_ssusb_ldo_enable(mdwc, 1);
+	dwc3_ssusb_config_vddcx(mdwc, 1);
 
 	if (!host_bus_suspend && !dcp)
-		dwc3_hsusb_config_vddcx(1);
+		dwc3_hsusb_config_vddcx(mdwc, 1);
 
 	clk_prepare_enable(mdwc->ref_clk);
 	usleep_range(1000, 1200);
@@ -2119,6 +2120,9 @@
 	case POWER_SUPPLY_PROP_SCOPE:
 		val->intval = mdwc->host_mode;
 		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		val->intval = mdwc->voltage_max;
+		break;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 		val->intval = mdwc->current_max;
 		break;
@@ -2166,6 +2170,9 @@
 	case POWER_SUPPLY_PROP_ONLINE:
 		mdwc->online = val->intval;
 		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		mdwc->voltage_max = val->intval;
+		break;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 		mdwc->current_max = val->intval;
 		break;
@@ -2206,6 +2213,20 @@
 	power_supply_changed(&mdwc->usb_psy);
 }
 
+static int
+dwc3_msm_property_is_writeable(struct power_supply *psy,
+				enum power_supply_property psp)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 
 static char *dwc3_msm_pm_power_supplied_to[] = {
 	"battery",
@@ -2214,6 +2235,7 @@
 static enum power_supply_property dwc3_msm_pm_power_props_usb[] = {
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX,
 	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_TYPE,
 	POWER_SUPPLY_PROP_SCOPE,
@@ -2221,9 +2243,9 @@
 
 static void dwc3_init_adc_work(struct work_struct *w);
 
-static void dwc3_ext_notify_online(int on)
+static void dwc3_ext_notify_online(void *ctx, int on)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = ctx;
 	bool notify_otg = false;
 
 	if (!mdwc) {
@@ -2271,7 +2293,7 @@
 			disable_irq(mdwc->pmic_id_irq);
 
 		ret = usb_ext->notify(usb_ext->ctxt, mdwc->id_state,
-				      dwc3_ext_notify_online);
+				      dwc3_ext_notify_online, mdwc);
 		dev_dbg(mdwc->dev, "%s: external handler returned %d\n",
 			__func__, ret);
 
@@ -2367,7 +2389,12 @@
 static ssize_t adc_enable_show(struct device *dev,
 			       struct device_attribute *attr, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%s\n", context->id_adc_detect ?
+	struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+	if (!mdwc)
+		return -EINVAL;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", mdwc->id_adc_detect ?
 						"enabled" : "disabled");
 }
 
@@ -2375,13 +2402,18 @@
 		struct device_attribute *attr, const char
 		*buf, size_t size)
 {
+	struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+	if (!mdwc)
+		return -EINVAL;
+
 	if (!strnicmp(buf, "enable", 6)) {
-		if (!context->id_adc_detect)
-			dwc3_init_adc_work(&context->init_adc_work.work);
+		if (!mdwc->id_adc_detect)
+			dwc3_init_adc_work(&mdwc->init_adc_work.work);
 		return size;
 	} else if (!strnicmp(buf, "disable", 7)) {
 		qpnp_adc_tm_usbid_end();
-		context->id_adc_detect = false;
+		mdwc->id_adc_detect = false;
 		return size;
 	}
 
@@ -2393,25 +2425,27 @@
 
 static int dwc3_msm_ext_chg_open(struct inode *inode, struct file *file)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc =
+		container_of(inode->i_cdev, struct dwc3_msm, ext_chg_cdev);
 
 	pr_debug("dwc3-msm ext chg open\n");
-
+	file->private_data = mdwc;
 	mdwc->ext_chg_opened = true;
+
 	return 0;
 }
 
 static long
 dwc3_msm_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = file->private_data;
 	struct msm_usb_chg_info info = {0};
 	int ret = 0, val;
 
 	switch (cmd) {
 	case MSM_USB_EXT_CHG_INFO:
 		info.chg_block_type = USB_CHG_BLOCK_QSCRATCH;
-		info.page_offset = (context->io_res->start +
+		info.page_offset = (mdwc->io_res->start +
 				QSCRATCH_REG_OFFSET) & ~PAGE_MASK;
 		/*
 		 * The charger block register address space is only
@@ -2454,7 +2488,7 @@
 
 static int dwc3_msm_ext_chg_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = file->private_data;
 	unsigned long vsize = vma->vm_end - vma->vm_start;
 	int ret;
 
@@ -2475,7 +2509,7 @@
 
 static int dwc3_msm_ext_chg_release(struct inode *inode, struct file *file)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = file->private_data;
 
 	pr_debug("dwc3-msm ext chg release\n");
 
@@ -2540,7 +2574,7 @@
 static int __devinit dwc3_msm_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
-	struct dwc3_msm *msm;
+	struct dwc3_msm *mdwc;
 	struct resource *res;
 	void __iomem *tcsr;
 	unsigned long flags;
@@ -2548,39 +2582,38 @@
 	int len = 0;
 	u32 tmp[3];
 
-	msm = devm_kzalloc(&pdev->dev, sizeof(*msm), GFP_KERNEL);
-	if (!msm) {
+	mdwc = devm_kzalloc(&pdev->dev, sizeof(*mdwc), GFP_KERNEL);
+	if (!mdwc) {
 		dev_err(&pdev->dev, "not enough memory\n");
 		return -ENOMEM;
 	}
 
-	platform_set_drvdata(pdev, msm);
-	context = msm;
-	msm->dev = &pdev->dev;
+	platform_set_drvdata(pdev, mdwc);
+	mdwc->dev = &pdev->dev;
 
-	INIT_LIST_HEAD(&msm->req_complete_list);
-	INIT_DELAYED_WORK(&msm->chg_work, dwc3_chg_detect_work);
-	INIT_DELAYED_WORK(&msm->resume_work, dwc3_resume_work);
-	INIT_WORK(&msm->restart_usb_work, dwc3_restart_usb_work);
-	INIT_WORK(&msm->id_work, dwc3_id_work);
-	INIT_DELAYED_WORK(&msm->init_adc_work, dwc3_init_adc_work);
-	init_completion(&msm->ext_chg_wait);
+	INIT_LIST_HEAD(&mdwc->req_complete_list);
+	INIT_DELAYED_WORK(&mdwc->chg_work, dwc3_chg_detect_work);
+	INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work);
+	INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work);
+	INIT_WORK(&mdwc->id_work, dwc3_id_work);
+	INIT_DELAYED_WORK(&mdwc->init_adc_work, dwc3_init_adc_work);
+	init_completion(&mdwc->ext_chg_wait);
 
-	ret = dwc3_msm_config_gdsc(msm, 1);
+	ret = dwc3_msm_config_gdsc(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to configure usb3 gdsc\n");
 		return ret;
 	}
 
-	msm->xo_clk = clk_get(&pdev->dev, "xo");
-	if (IS_ERR(msm->xo_clk)) {
+	mdwc->xo_clk = clk_get(&pdev->dev, "xo");
+	if (IS_ERR(mdwc->xo_clk)) {
 		dev_err(&pdev->dev, "%s unable to get TCXO buffer handle\n",
 								__func__);
-		ret = PTR_ERR(msm->xo_clk);
+		ret = PTR_ERR(mdwc->xo_clk);
 		goto disable_dwc3_gdsc;
 	}
 
-	ret = clk_prepare_enable(msm->xo_clk);
+	ret = clk_prepare_enable(mdwc->xo_clk);
 	if (ret) {
 		dev_err(&pdev->dev, "%s failed to vote for TCXO buffer%d\n",
 						__func__, ret);
@@ -2591,62 +2624,62 @@
 	 * DWC3 Core requires its CORE CLK (aka master / bus clk) to
 	 * run at 125Mhz in SSUSB mode and >60MHZ for HSUSB mode.
 	 */
-	msm->core_clk = devm_clk_get(&pdev->dev, "core_clk");
-	if (IS_ERR(msm->core_clk)) {
+	mdwc->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+	if (IS_ERR(mdwc->core_clk)) {
 		dev_err(&pdev->dev, "failed to get core_clk\n");
-		ret = PTR_ERR(msm->core_clk);
+		ret = PTR_ERR(mdwc->core_clk);
 		goto disable_xo;
 	}
-	clk_set_rate(msm->core_clk, 125000000);
-	clk_prepare_enable(msm->core_clk);
+	clk_set_rate(mdwc->core_clk, 125000000);
+	clk_prepare_enable(mdwc->core_clk);
 
-	msm->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
-	if (IS_ERR(msm->iface_clk)) {
+	mdwc->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
+	if (IS_ERR(mdwc->iface_clk)) {
 		dev_err(&pdev->dev, "failed to get iface_clk\n");
-		ret = PTR_ERR(msm->iface_clk);
+		ret = PTR_ERR(mdwc->iface_clk);
 		goto disable_core_clk;
 	}
-	clk_prepare_enable(msm->iface_clk);
+	clk_prepare_enable(mdwc->iface_clk);
 
-	msm->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
-	if (IS_ERR(msm->sleep_clk)) {
+	mdwc->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
+	if (IS_ERR(mdwc->sleep_clk)) {
 		dev_err(&pdev->dev, "failed to get sleep_clk\n");
-		ret = PTR_ERR(msm->sleep_clk);
+		ret = PTR_ERR(mdwc->sleep_clk);
 		goto disable_iface_clk;
 	}
-	clk_prepare_enable(msm->sleep_clk);
+	clk_prepare_enable(mdwc->sleep_clk);
 
-	msm->hsphy_sleep_clk = devm_clk_get(&pdev->dev, "sleep_a_clk");
-	if (IS_ERR(msm->hsphy_sleep_clk)) {
+	mdwc->hsphy_sleep_clk = devm_clk_get(&pdev->dev, "sleep_a_clk");
+	if (IS_ERR(mdwc->hsphy_sleep_clk)) {
 		dev_err(&pdev->dev, "failed to get sleep_a_clk\n");
-		ret = PTR_ERR(msm->hsphy_sleep_clk);
+		ret = PTR_ERR(mdwc->hsphy_sleep_clk);
 		goto disable_sleep_clk;
 	}
-	clk_prepare_enable(msm->hsphy_sleep_clk);
+	clk_prepare_enable(mdwc->hsphy_sleep_clk);
 
-	msm->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk");
-	if (IS_ERR(msm->utmi_clk)) {
+	mdwc->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk");
+	if (IS_ERR(mdwc->utmi_clk)) {
 		dev_err(&pdev->dev, "failed to get utmi_clk\n");
-		ret = PTR_ERR(msm->utmi_clk);
+		ret = PTR_ERR(mdwc->utmi_clk);
 		goto disable_sleep_a_clk;
 	}
-	clk_prepare_enable(msm->utmi_clk);
+	clk_prepare_enable(mdwc->utmi_clk);
 
-	msm->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
-	if (IS_ERR(msm->ref_clk)) {
+	mdwc->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
+	if (IS_ERR(mdwc->ref_clk)) {
 		dev_err(&pdev->dev, "failed to get ref_clk\n");
-		ret = PTR_ERR(msm->ref_clk);
+		ret = PTR_ERR(mdwc->ref_clk);
 		goto disable_utmi_clk;
 	}
-	clk_prepare_enable(msm->ref_clk);
+	clk_prepare_enable(mdwc->ref_clk);
 
 	of_get_property(node, "qcom,vdd-voltage-level", &len);
 	if (len == sizeof(tmp)) {
 		of_property_read_u32_array(node, "qcom,vdd-voltage-level",
 							tmp, len/sizeof(*tmp));
-		msm->vdd_no_vol_level = tmp[0];
-		msm->vdd_low_vol_level = tmp[1];
-		msm->vdd_high_vol_level = tmp[2];
+		mdwc->vdd_no_vol_level = tmp[0];
+		mdwc->vdd_low_vol_level = tmp[1];
+		mdwc->vdd_high_vol_level = tmp[2];
 	} else {
 		dev_err(&pdev->dev, "no qcom,vdd-voltage-level property\n");
 		ret = -EINVAL;
@@ -2654,99 +2687,100 @@
 	}
 
 	/* SS PHY */
-	msm->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
-	if (IS_ERR(msm->ssusb_vddcx)) {
+	mdwc->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
+	if (IS_ERR(mdwc->ssusb_vddcx)) {
 		dev_err(&pdev->dev, "unable to get ssusb vddcx\n");
-		ret = PTR_ERR(msm->ssusb_vddcx);
+		ret = PTR_ERR(mdwc->ssusb_vddcx);
 		goto disable_ref_clk;
 	}
 
-	ret = dwc3_ssusb_config_vddcx(1);
+	ret = dwc3_ssusb_config_vddcx(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "ssusb vddcx configuration failed\n");
 		goto disable_ref_clk;
 	}
 
-	ret = regulator_enable(context->ssusb_vddcx);
+	ret = regulator_enable(mdwc->ssusb_vddcx);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to enable the ssusb vddcx\n");
 		goto unconfig_ss_vddcx;
 	}
 
-	ret = dwc3_ssusb_ldo_init(1);
+	ret = dwc3_ssusb_ldo_init(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "ssusb vreg configuration failed\n");
 		goto disable_ss_vddcx;
 	}
 
-	ret = dwc3_ssusb_ldo_enable(1);
+	ret = dwc3_ssusb_ldo_enable(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "ssusb vreg enable failed\n");
 		goto free_ss_ldo_init;
 	}
 
 	/* HS PHY */
-	msm->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
-	if (IS_ERR(msm->hsusb_vddcx)) {
+	mdwc->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
+	if (IS_ERR(mdwc->hsusb_vddcx)) {
 		dev_err(&pdev->dev, "unable to get hsusb vddcx\n");
-		ret = PTR_ERR(msm->hsusb_vddcx);
+		ret = PTR_ERR(mdwc->hsusb_vddcx);
 		goto disable_ss_ldo;
 	}
 
-	ret = dwc3_hsusb_config_vddcx(1);
+	ret = dwc3_hsusb_config_vddcx(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
 		goto disable_ss_ldo;
 	}
 
-	ret = regulator_enable(context->hsusb_vddcx);
+	ret = regulator_enable(mdwc->hsusb_vddcx);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
 		goto unconfig_hs_vddcx;
 	}
 
-	ret = dwc3_hsusb_ldo_init(1);
+	ret = dwc3_hsusb_ldo_init(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
 		goto disable_hs_vddcx;
 	}
 
-	ret = dwc3_hsusb_ldo_enable(1);
+	ret = dwc3_hsusb_ldo_enable(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
 		goto free_hs_ldo_init;
 	}
 
-	msm->id_state = msm->ext_xceiv.id = DWC3_ID_FLOAT;
-	msm->ext_xceiv.otg_capability = of_property_read_bool(node,
+	mdwc->id_state = mdwc->ext_xceiv.id = DWC3_ID_FLOAT;
+	mdwc->ext_xceiv.otg_capability = of_property_read_bool(node,
 				"qcom,otg-capability");
-	msm->charger.charging_disabled = of_property_read_bool(node,
+	mdwc->charger.charging_disabled = of_property_read_bool(node,
 				"qcom,charging-disabled");
 
-	msm->charger.skip_chg_detect = of_property_read_bool(node,
+	mdwc->charger.skip_chg_detect = of_property_read_bool(node,
 				"qcom,skip-charger-detection");
 	/*
 	 * DWC3 has separate IRQ line for OTG events (ID/BSV) and for
 	 * DP and DM linestate transitions during low power mode.
 	 */
-	msm->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
-	if (msm->hs_phy_irq < 0) {
+	mdwc->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
+	if (mdwc->hs_phy_irq < 0) {
 		dev_dbg(&pdev->dev, "pget_irq for hs_phy_irq failed\n");
-		msm->hs_phy_irq = 0;
+		mdwc->hs_phy_irq = 0;
 	} else {
-		ret = devm_request_irq(&pdev->dev, msm->hs_phy_irq,
+		ret = devm_request_irq(&pdev->dev, mdwc->hs_phy_irq,
 				msm_dwc3_irq, IRQF_TRIGGER_RISING,
-			       "msm_dwc3", msm);
+			       "msm_dwc3", mdwc);
 		if (ret) {
 			dev_err(&pdev->dev, "irqreq HSPHYINT failed\n");
 			goto disable_hs_ldo;
 		}
-		enable_irq_wake(msm->hs_phy_irq);
+		enable_irq_wake(mdwc->hs_phy_irq);
 	}
 
-	if (msm->ext_xceiv.otg_capability) {
-		msm->pmic_id_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
-		if (msm->pmic_id_irq > 0) {
+	if (mdwc->ext_xceiv.otg_capability) {
+		mdwc->pmic_id_irq =
+			platform_get_irq_byname(pdev, "pmic_id_irq");
+		if (mdwc->pmic_id_irq > 0) {
 			/* check if PMIC ID IRQ is supported */
 			ret = qpnp_misc_irqs_available(&pdev->dev);
 
@@ -2754,14 +2788,15 @@
 				/* qpnp hasn't probed yet; defer dwc probe */
 				goto disable_hs_ldo;
 			} else if (ret == 0) {
-				msm->pmic_id_irq = 0;
+				mdwc->pmic_id_irq = 0;
 			} else {
 				ret = devm_request_irq(&pdev->dev,
-						       msm->pmic_id_irq,
+						       mdwc->pmic_id_irq,
 						       dwc3_pmic_id_irq,
 						       IRQF_TRIGGER_RISING |
 						       IRQF_TRIGGER_FALLING,
-						       "dwc3_msm_pmic_id", msm);
+						       "dwc3_msm_pmic_id",
+						       mdwc);
 				if (ret) {
 					dev_err(&pdev->dev, "irqreq IDINT failed\n");
 					goto disable_hs_ldo;
@@ -2769,21 +2804,21 @@
 
 				local_irq_save(flags);
 				/* Update initial ID state */
-				msm->id_state =
-					!!irq_read_line(msm->pmic_id_irq);
-				if (msm->id_state == DWC3_ID_GROUND)
+				mdwc->id_state =
+					!!irq_read_line(mdwc->pmic_id_irq);
+				if (mdwc->id_state == DWC3_ID_GROUND)
 					queue_work(system_nrt_wq,
-							&msm->id_work);
+							&mdwc->id_work);
 				local_irq_restore(flags);
-				enable_irq_wake(msm->pmic_id_irq);
+				enable_irq_wake(mdwc->pmic_id_irq);
 			}
 		}
 
-		if (msm->pmic_id_irq <= 0) {
+		if (mdwc->pmic_id_irq <= 0) {
 			/* If no PMIC ID IRQ, use ADC for ID pin detection */
-			queue_work(system_nrt_wq, &msm->init_adc_work.work);
+			queue_work(system_nrt_wq, &mdwc->init_adc_work.work);
 			device_create_file(&pdev->dev, &dev_attr_adc_enable);
-			msm->pmic_id_irq = 0;
+			mdwc->pmic_id_irq = 0;
 		}
 	}
 
@@ -2813,59 +2848,62 @@
 		goto disable_hs_ldo;
 	}
 
-	msm->base = devm_ioremap_nocache(&pdev->dev, res->start,
+	mdwc->base = devm_ioremap_nocache(&pdev->dev, res->start,
 		resource_size(res));
-	if (!msm->base) {
+	if (!mdwc->base) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		ret = -ENODEV;
 		goto disable_hs_ldo;
 	}
 
-	msm->io_res = res; /* used to calculate chg block offset */
+	mdwc->io_res = res; /* used to calculate chg block offset */
 
 	if (of_property_read_u32(node, "qcom,dwc-hsphy-init",
-						&msm->hsphy_init_seq))
+						&mdwc->hsphy_init_seq))
 		dev_dbg(&pdev->dev, "unable to read hsphy init seq\n");
-	else if (!msm->hsphy_init_seq)
+	else if (!mdwc->hsphy_init_seq)
 		dev_warn(&pdev->dev, "incorrect hsphyinitseq.Using PORvalue\n");
 
-	dwc3_msm_qscratch_reg_init(msm);
+	dwc3_msm_qscratch_reg_init(mdwc);
 
-	pm_runtime_set_active(msm->dev);
-	pm_runtime_enable(msm->dev);
+	pm_runtime_set_active(mdwc->dev);
+	pm_runtime_enable(mdwc->dev);
 
 	if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
-				 &msm->dbm_num_eps)) {
+				 &mdwc->dbm_num_eps)) {
 		dev_err(&pdev->dev,
 			"unable to read platform data num of dbm eps\n");
-		msm->dbm_num_eps = DBM_MAX_EPS;
+		mdwc->dbm_num_eps = DBM_MAX_EPS;
 	}
 
-	if (msm->dbm_num_eps > DBM_MAX_EPS) {
+	if (mdwc->dbm_num_eps > DBM_MAX_EPS) {
 		dev_err(&pdev->dev,
 			"Driver doesn't support number of DBM EPs. "
 			"max: %d, dbm_num_eps: %d\n",
-			DBM_MAX_EPS, msm->dbm_num_eps);
+			DBM_MAX_EPS, mdwc->dbm_num_eps);
 		ret = -ENODEV;
 		goto disable_hs_ldo;
 	}
 
 	/* usb_psy required only for vbus_notifications or charging support */
-	if (msm->ext_xceiv.otg_capability || !msm->charger.charging_disabled) {
-		msm->usb_psy.name = "usb";
-		msm->usb_psy.type = POWER_SUPPLY_TYPE_USB;
-		msm->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
-		msm->usb_psy.num_supplicants = ARRAY_SIZE(
+	if (mdwc->ext_xceiv.otg_capability ||
+			!mdwc->charger.charging_disabled) {
+		mdwc->usb_psy.name = "usb";
+		mdwc->usb_psy.type = POWER_SUPPLY_TYPE_USB;
+		mdwc->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
+		mdwc->usb_psy.num_supplicants = ARRAY_SIZE(
 						dwc3_msm_pm_power_supplied_to);
-		msm->usb_psy.properties = dwc3_msm_pm_power_props_usb;
-		msm->usb_psy.num_properties =
+		mdwc->usb_psy.properties = dwc3_msm_pm_power_props_usb;
+		mdwc->usb_psy.num_properties =
 					ARRAY_SIZE(dwc3_msm_pm_power_props_usb);
-		msm->usb_psy.get_property = dwc3_msm_power_get_property_usb;
-		msm->usb_psy.set_property = dwc3_msm_power_set_property_usb;
-		msm->usb_psy.external_power_changed =
+		mdwc->usb_psy.get_property = dwc3_msm_power_get_property_usb;
+		mdwc->usb_psy.set_property = dwc3_msm_power_set_property_usb;
+		mdwc->usb_psy.external_power_changed =
 					dwc3_msm_external_power_changed;
+		mdwc->usb_psy.property_is_writeable =
+				dwc3_msm_property_is_writeable;
 
-		ret = power_supply_register(&pdev->dev, &msm->usb_psy);
+		ret = power_supply_register(&pdev->dev, &mdwc->usb_psy);
 		if (ret < 0) {
 			dev_err(&pdev->dev,
 					"%s:power_supply_register usb failed\n",
@@ -2883,27 +2921,28 @@
 		}
 	}
 
-	msm->bus_scale_table = msm_bus_cl_get_pdata(pdev);
-	if (!msm->bus_scale_table) {
+	mdwc->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+	if (!mdwc->bus_scale_table) {
 		dev_err(&pdev->dev, "bus scaling is disabled\n");
 	} else {
-		msm->bus_perf_client =
-			msm_bus_scale_register_client(msm->bus_scale_table);
+		mdwc->bus_perf_client =
+			msm_bus_scale_register_client(mdwc->bus_scale_table);
 		ret = msm_bus_scale_client_update_request(
-						msm->bus_perf_client, 1);
+						mdwc->bus_perf_client, 1);
 		if (ret)
 			dev_err(&pdev->dev, "Failed to vote for bus scaling\n");
 	}
 
-	msm->otg_xceiv = usb_get_transceiver();
+	mdwc->otg_xceiv = usb_get_transceiver();
 	/* Register with OTG if present, ignore USB2 OTG using other PHY */
-	if (msm->otg_xceiv && !(msm->otg_xceiv->flags & ENABLE_SECONDARY_PHY)) {
+	if (mdwc->otg_xceiv &&
+			!(mdwc->otg_xceiv->flags & ENABLE_SECONDARY_PHY)) {
 		/* Skip charger detection for simulator targets */
-		if (!msm->charger.skip_chg_detect) {
-			msm->charger.start_detection = dwc3_start_chg_det;
-			ret = dwc3_set_charger(msm->otg_xceiv->otg,
-					&msm->charger);
-			if (ret || !msm->charger.notify_detection_complete) {
+		if (!mdwc->charger.skip_chg_detect) {
+			mdwc->charger.start_detection = dwc3_start_chg_det;
+			ret = dwc3_set_charger(mdwc->otg_xceiv->otg,
+					&mdwc->charger);
+			if (ret || !mdwc->charger.notify_detection_complete) {
 				dev_err(&pdev->dev,
 					"failed to register charger: %d\n",
 					ret);
@@ -2911,129 +2950,130 @@
 			}
 		}
 
-		if (msm->ext_xceiv.otg_capability)
-			msm->ext_xceiv.ext_block_reset = dwc3_msm_block_reset;
-		ret = dwc3_set_ext_xceiv(msm->otg_xceiv->otg, &msm->ext_xceiv);
-		if (ret || !msm->ext_xceiv.notify_ext_events) {
+		if (mdwc->ext_xceiv.otg_capability)
+			mdwc->ext_xceiv.ext_block_reset = dwc3_msm_block_reset;
+		ret = dwc3_set_ext_xceiv(mdwc->otg_xceiv->otg,
+						&mdwc->ext_xceiv);
+		if (ret || !mdwc->ext_xceiv.notify_ext_events) {
 			dev_err(&pdev->dev, "failed to register xceiver: %d\n",
 									ret);
 			goto put_xcvr;
 		}
 	} else {
 		dev_dbg(&pdev->dev, "No OTG, DWC3 running in host only mode\n");
-		msm->host_mode = 1;
-		msm->vbus_otg = devm_regulator_get(&pdev->dev, "vbus_dwc3");
-		if (IS_ERR(msm->vbus_otg)) {
+		mdwc->host_mode = 1;
+		mdwc->vbus_otg = devm_regulator_get(&pdev->dev, "vbus_dwc3");
+		if (IS_ERR(mdwc->vbus_otg)) {
 			dev_dbg(&pdev->dev, "Failed to get vbus regulator\n");
-			msm->vbus_otg = 0;
+			mdwc->vbus_otg = 0;
 		} else {
-			ret = regulator_enable(msm->vbus_otg);
+			ret = regulator_enable(mdwc->vbus_otg);
 			if (ret) {
-				msm->vbus_otg = 0;
+				mdwc->vbus_otg = 0;
 				dev_err(&pdev->dev, "Failed to enable vbus_otg\n");
 			}
 		}
-		msm->otg_xceiv = NULL;
+		mdwc->otg_xceiv = NULL;
 	}
-	if (msm->ext_xceiv.otg_capability && msm->charger.start_detection) {
-		ret = dwc3_msm_setup_cdev(msm);
+	if (mdwc->ext_xceiv.otg_capability && mdwc->charger.start_detection) {
+		ret = dwc3_msm_setup_cdev(mdwc);
 		if (ret)
 			dev_err(&pdev->dev, "Fail to setup dwc3 setup cdev\n");
 	}
 
-	wake_lock_init(&msm->wlock, WAKE_LOCK_SUSPEND, "msm_dwc3");
-	wake_lock(&msm->wlock);
-	dwc3_debugfs_init(msm);
+	device_init_wakeup(mdwc->dev, 1);
+	pm_stay_awake(mdwc->dev);
+	dwc3_debugfs_init(mdwc);
 
 	return 0;
 
 put_xcvr:
-	usb_put_transceiver(msm->otg_xceiv);
+	usb_put_transceiver(mdwc->otg_xceiv);
 put_psupply:
-	if (msm->usb_psy.dev)
-		power_supply_unregister(&msm->usb_psy);
+	if (mdwc->usb_psy.dev)
+		power_supply_unregister(&mdwc->usb_psy);
 disable_hs_ldo:
-	dwc3_hsusb_ldo_enable(0);
+	dwc3_hsusb_ldo_enable(mdwc, 0);
 free_hs_ldo_init:
-	dwc3_hsusb_ldo_init(0);
+	dwc3_hsusb_ldo_init(mdwc, 0);
 disable_hs_vddcx:
-	regulator_disable(context->hsusb_vddcx);
+	regulator_disable(mdwc->hsusb_vddcx);
 unconfig_hs_vddcx:
-	dwc3_hsusb_config_vddcx(0);
+	dwc3_hsusb_config_vddcx(mdwc, 0);
 disable_ss_ldo:
-	dwc3_ssusb_ldo_enable(0);
+	dwc3_ssusb_ldo_enable(mdwc, 0);
 free_ss_ldo_init:
-	dwc3_ssusb_ldo_init(0);
+	dwc3_ssusb_ldo_init(mdwc, 0);
 disable_ss_vddcx:
-	regulator_disable(context->ssusb_vddcx);
+	regulator_disable(mdwc->ssusb_vddcx);
 unconfig_ss_vddcx:
-	dwc3_ssusb_config_vddcx(0);
+	dwc3_ssusb_config_vddcx(mdwc, 0);
 disable_ref_clk:
-	clk_disable_unprepare(msm->ref_clk);
+	clk_disable_unprepare(mdwc->ref_clk);
 disable_utmi_clk:
-	clk_disable_unprepare(msm->utmi_clk);
+	clk_disable_unprepare(mdwc->utmi_clk);
 disable_sleep_a_clk:
-	clk_disable_unprepare(msm->hsphy_sleep_clk);
+	clk_disable_unprepare(mdwc->hsphy_sleep_clk);
 disable_sleep_clk:
-	clk_disable_unprepare(msm->sleep_clk);
+	clk_disable_unprepare(mdwc->sleep_clk);
 disable_iface_clk:
-	clk_disable_unprepare(msm->iface_clk);
+	clk_disable_unprepare(mdwc->iface_clk);
 disable_core_clk:
-	clk_disable_unprepare(msm->core_clk);
+	clk_disable_unprepare(mdwc->core_clk);
 disable_xo:
-	clk_disable_unprepare(msm->xo_clk);
+	clk_disable_unprepare(mdwc->xo_clk);
 put_xo:
-	clk_put(msm->xo_clk);
+	clk_put(mdwc->xo_clk);
 disable_dwc3_gdsc:
-	dwc3_msm_config_gdsc(msm, 0);
+	dwc3_msm_config_gdsc(mdwc, 0);
 
 	return ret;
 }
 
 static int __devexit dwc3_msm_remove(struct platform_device *pdev)
 {
-	struct dwc3_msm	*msm = platform_get_drvdata(pdev);
+	struct dwc3_msm	*mdwc = platform_get_drvdata(pdev);
 
-	if (!msm->ext_chg_device) {
-		device_destroy(msm->ext_chg_class, msm->ext_chg_dev);
-		cdev_del(&msm->ext_chg_cdev);
-		class_destroy(msm->ext_chg_class);
-		unregister_chrdev_region(msm->ext_chg_dev, 1);
+	if (!mdwc->ext_chg_device) {
+		device_destroy(mdwc->ext_chg_class, mdwc->ext_chg_dev);
+		cdev_del(&mdwc->ext_chg_cdev);
+		class_destroy(mdwc->ext_chg_class);
+		unregister_chrdev_region(mdwc->ext_chg_dev, 1);
 	}
 
-	if (msm->id_adc_detect)
+	if (mdwc->id_adc_detect)
 		qpnp_adc_tm_usbid_end();
 	if (dwc3_debugfs_root)
 		debugfs_remove_recursive(dwc3_debugfs_root);
-	if (msm->otg_xceiv) {
-		dwc3_start_chg_det(&msm->charger, false);
-		usb_put_transceiver(msm->otg_xceiv);
+	if (mdwc->otg_xceiv) {
+		dwc3_start_chg_det(&mdwc->charger, false);
+		usb_put_transceiver(mdwc->otg_xceiv);
 	}
-	if (msm->usb_psy.dev)
-		power_supply_unregister(&msm->usb_psy);
-	if (msm->vbus_otg)
-		regulator_disable(msm->vbus_otg);
+	if (mdwc->usb_psy.dev)
+		power_supply_unregister(&mdwc->usb_psy);
+	if (mdwc->vbus_otg)
+		regulator_disable(mdwc->vbus_otg);
 
-	pm_runtime_disable(msm->dev);
-	wake_lock_destroy(&msm->wlock);
+	pm_runtime_disable(mdwc->dev);
+	device_init_wakeup(mdwc->dev, 0);
 
-	dwc3_hsusb_ldo_enable(0);
-	dwc3_hsusb_ldo_init(0);
-	regulator_disable(msm->hsusb_vddcx);
-	dwc3_hsusb_config_vddcx(0);
-	dwc3_ssusb_ldo_enable(0);
-	dwc3_ssusb_ldo_init(0);
-	regulator_disable(msm->ssusb_vddcx);
-	dwc3_ssusb_config_vddcx(0);
-	clk_disable_unprepare(msm->core_clk);
-	clk_disable_unprepare(msm->iface_clk);
-	clk_disable_unprepare(msm->sleep_clk);
-	clk_disable_unprepare(msm->hsphy_sleep_clk);
-	clk_disable_unprepare(msm->ref_clk);
-	clk_disable_unprepare(msm->xo_clk);
-	clk_put(msm->xo_clk);
+	dwc3_hsusb_ldo_enable(mdwc, 0);
+	dwc3_hsusb_ldo_init(mdwc, 0);
+	regulator_disable(mdwc->hsusb_vddcx);
+	dwc3_hsusb_config_vddcx(mdwc, 0);
+	dwc3_ssusb_ldo_enable(mdwc, 0);
+	dwc3_ssusb_ldo_init(mdwc, 0);
+	regulator_disable(mdwc->ssusb_vddcx);
+	dwc3_ssusb_config_vddcx(mdwc, 0);
+	clk_disable_unprepare(mdwc->core_clk);
+	clk_disable_unprepare(mdwc->iface_clk);
+	clk_disable_unprepare(mdwc->sleep_clk);
+	clk_disable_unprepare(mdwc->hsphy_sleep_clk);
+	clk_disable_unprepare(mdwc->ref_clk);
+	clk_disable_unprepare(mdwc->xo_clk);
+	clk_put(mdwc->xo_clk);
 
-	dwc3_msm_config_gdsc(msm, 0);
+	dwc3_msm_config_gdsc(mdwc, 0);
 
 	return 0;
 }
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 1bc7757..0d4d580 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -218,7 +218,7 @@
 		 */
 		if (ext_xceiv && ext_xceiv->otg_capability &&
 						ext_xceiv->ext_block_reset)
-			ext_xceiv->ext_block_reset(true);
+			ext_xceiv->ext_block_reset(ext_xceiv, true);
 
 		dwc3_otg_set_peripheral_regs(dotg);
 
@@ -285,7 +285,7 @@
 		 * DBM reset is required, hence perform only DBM reset here */
 		if (ext_xceiv && ext_xceiv->otg_capability &&
 						ext_xceiv->ext_block_reset)
-			ext_xceiv->ext_block_reset(false);
+			ext_xceiv->ext_block_reset(ext_xceiv, false);
 
 		dwc3_otg_set_peripheral_regs(dotg);
 		usb_gadget_vbus_connect(otg->gadget);
@@ -804,7 +804,7 @@
 				 */
 				dev_dbg(phy->dev, "enter lpm as\n"
 					"unable to start A-device\n");
-				phy->state = OTG_STATE_UNDEFINED;
+				phy->state = OTG_STATE_A_IDLE;
 				pm_runtime_put_sync(phy->dev);
 				return;
 			}
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index 28573a1..7adf874 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -114,7 +114,8 @@
 	void	(*notify_ext_events)(struct usb_otg *otg,
 					enum dwc3_ext_events ext_event);
 	/* for block reset USB core */
-	void	(*ext_block_reset)(bool core_reset);
+	void	(*ext_block_reset)(struct dwc3_ext_xceiv *ext_xceiv,
+					bool core_reset);
 };
 
 /* for external transceiver driver */
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 63698de..acda980 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -43,6 +43,7 @@
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/ratelimit.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/list.h>
@@ -1487,10 +1488,12 @@
 	return 0;
 }
 
+#define DWC3_SOFT_RESET_TIMEOUT	10  /* 10 msec */
 static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
 {
 	u32			reg;
 	u32			timeout = 500;
+	ktime_t start, diff;
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	if (is_on) {
@@ -1501,6 +1504,29 @@
 
 		if (dwc->revision >= DWC3_REVISION_194A)
 			reg &= ~DWC3_DCTL_KEEP_CONNECT;
+
+		start = ktime_get();
+		/* issue device SoftReset */
+		dwc3_writel(dwc->regs, DWC3_DCTL, reg | DWC3_DCTL_CSFTRST);
+		do {
+			reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+			if (!(reg & DWC3_DCTL_CSFTRST))
+				break;
+
+			diff = ktime_sub(ktime_get(), start);
+			/* poll for max. 10ms */
+			if (ktime_to_ms(diff) > DWC3_SOFT_RESET_TIMEOUT) {
+				printk_ratelimited(KERN_ERR
+					"%s:core Reset Timed Out\n", __func__);
+				break;
+			}
+			cpu_relax();
+		} while (true);
+
+
+		dwc3_event_buffers_setup(dwc);
+		dwc3_gadget_restart(dwc);
+		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 		reg |= DWC3_DCTL_RUN_STOP;
 	} else {
 		reg &= ~DWC3_DCTL_RUN_STOP;
@@ -1754,6 +1780,7 @@
 	dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 
 	dep = dwc->eps[0];
+	dep->endpoint.maxburst = 1;
 	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
 	if (ret) {
 		dev_err(dwc->dev, "failed to enable %s\n", dep->name);
@@ -1761,6 +1788,7 @@
 	}
 
 	dep = dwc->eps[1];
+	dep->endpoint.maxburst = 1;
 	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
 	if (ret) {
 		dev_err(dwc->dev, "failed to enable %s\n", dep->name);
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index e7074a2..3f8d924 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1853,6 +1853,14 @@
 
 
 	spin_lock_irqsave(mep->lock, flags);
+
+	if (_udc && (!_udc->vbus_active || _udc->suspended)) {
+		pr_debug("ep%d%s prime timer when vbus_active=%d,suspend=%d\n",
+			mep->num, mep->dir ? "IN" : "OUT",
+			_udc->vbus_active, _udc->suspended);
+		goto out;
+	}
+
 	if (!hw_cread(CAP_ENDPTPRIME, BIT(n)))
 		goto out;
 
@@ -2197,6 +2205,9 @@
 	if (mEp == NULL)
 		return -EINVAL;
 
+	del_timer(&mEp->prime_timer);
+	mEp->prime_timer_count = 0;
+
 	hw_ep_flush(mEp->num, mEp->dir);
 
 	while (!list_empty(&mEp->qh.queue)) {
@@ -2926,8 +2937,6 @@
 
 	/* only internal SW should disable ctrl endpts */
 
-	del_timer(&mEp->prime_timer);
-	mEp->prime_timer_count = 0;
 	direction = mEp->dir;
 	do {
 		dbg_event(_usb_addr(mEp), "DISABLE", 0);
@@ -3282,8 +3291,6 @@
 
 	spin_lock_irqsave(mEp->lock, flags);
 
-	del_timer(&mEp->prime_timer);
-	mEp->prime_timer_count = 0;
 	dbg_event(_usb_addr(mEp), "FFLUSH", 0);
 	/*
 	 * _ep_nuke() takes care of flushing the endpoint.
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index 3355e19..d1b911a 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -642,6 +642,8 @@
 	if (ctxt->ch && ctxt->ch->priv_usb == ctxt)
 		ctxt->ch->priv_usb = NULL;
 	list_del(&ctxt->list_item);
+	/* Free any pending USB requests from last session */
+	free_reqs(ctxt);
 	kfree(ctxt);
 }
 
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index cece500..f90967f 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -790,6 +790,7 @@
 void usb_qdss_close(struct usb_qdss_ch *ch)
 {
 	struct f_qdss *qdss = ch->priv_usb;
+	struct usb_gadget *gadget = qdss->cdev->gadget;
 	unsigned long flags;
 
 	pr_debug("usb_qdss_close\n");
@@ -801,7 +802,7 @@
 	ch->app_conn = 0;
 	spin_unlock_irqrestore(&d_lock, flags);
 
-	msm_dwc3_restart_usb_session();
+	msm_dwc3_restart_usb_session(gadget);
 }
 EXPORT_SYMBOL(usb_qdss_close);
 
diff --git a/drivers/usb/gadget/u_ctrl_hsuart.c b/drivers/usb/gadget/u_ctrl_hsuart.c
index a9bd53e..3443d12 100644
--- a/drivers/usb/gadget/u_ctrl_hsuart.c
+++ b/drivers/usb/gadget/u_ctrl_hsuart.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
@@ -18,11 +18,13 @@
 #include <linux/termios.h>
 #include <linux/debugfs.h>
 #include <linux/smux.h>
+#include <linux/completion.h>
 
 #include <mach/usb_gadget_xport.h>
 
 #define CH_OPENED 0
 #define CH_READY 1
+#define CH_CONNECTED 2
 
 static unsigned int num_ctrl_ports;
 
@@ -37,6 +39,7 @@
 	enum gadget_type gtype;
 	spinlock_t port_lock;
 	void *port_usb;
+	struct completion close_complete;
 	/* work queue*/
 	struct workqueue_struct	*wq;
 	struct work_struct connect_w;
@@ -74,6 +77,10 @@
 	size_t			len;
 
 	switch (event_type) {
+	case SMUX_LOCAL_CLOSED:
+		clear_bit(CH_OPENED, &port->channel_sts);
+		complete(&port->close_complete);
+		break;
 	case SMUX_CONNECTED:
 		spin_lock_irqsave(&port->port_lock, flags);
 		if (!port->port_usb) {
@@ -81,7 +88,7 @@
 			return;
 		}
 		spin_unlock_irqrestore(&port->port_lock, flags);
-		set_bit(CH_OPENED, &port->channel_sts);
+		set_bit(CH_CONNECTED, &port->channel_sts);
 		if (port->gtype == USB_GADGET_RMNET) {
 			gr = port->port_usb;
 			if (gr && gr->connect)
@@ -89,7 +96,7 @@
 		}
 		break;
 	case SMUX_DISCONNECTED:
-		clear_bit(CH_OPENED, &port->channel_sts);
+		clear_bit(CH_CONNECTED, &port->channel_sts);
 		break;
 	case SMUX_READ_DONE:
 		len = ((struct smux_meta_read *)metadata)->len;
@@ -163,7 +170,7 @@
 		return -ENODEV;
 	}
 	/* drop cpkt if ch is not open */
-	if (!test_bit(CH_OPENED, &port->channel_sts)) {
+	if (!test_bit(CH_CONNECTED, &port->channel_sts)) {
 		port->drp_cpkt_cnt++;
 		return 0;
 	}
@@ -209,7 +216,7 @@
 
 	port->cbits_tomodem = cbits;
 
-	if (!test_bit(CH_OPENED, &port->channel_sts))
+	if (!test_bit(CH_CONNECTED, &port->channel_sts))
 		return;
 
 	pr_debug("%s: ctrl_tomodem:%d\n", __func__, cbits);
@@ -228,12 +235,21 @@
 
 	pr_debug("%s: port:%p\n", __func__, port);
 
+	if (test_bit(CH_OPENED, &port->channel_sts)) {
+		retval = wait_for_completion_timeout(
+				&port->close_complete, 3 * HZ);
+		if (retval == 0) {
+			pr_err("%s: smux close timedout\n", __func__);
+			return;
+		}
+	}
 	retval = msm_smux_open(port->ch_id, port->ctxt, smux_control_event,
 				rx_control_buffer);
 	if (retval < 0) {
 		pr_err(" %s smux_open failed\n", __func__);
 		return;
 	}
+	set_bit(CH_OPENED, &port->channel_sts);
 
 }
 
@@ -283,8 +299,9 @@
 	if (!test_bit(CH_OPENED, &port->channel_sts))
 		return;
 
+	INIT_COMPLETION(port->close_complete);
 	msm_smux_close(port->ch_id);
-	clear_bit(CH_OPENED, &port->channel_sts);
+	clear_bit(CH_CONNECTED, &port->channel_sts);
 }
 
 void ghsuart_ctrl_disconnect(void *gptr, int port_num)
@@ -363,6 +380,7 @@
 		gr->disconnect(gr);
 
 	clear_bit(CH_OPENED, &port->channel_sts);
+	clear_bit(CH_CONNECTED, &port->channel_sts);
 not_ready:
 	clear_bit(CH_READY, &port->channel_sts);
 
@@ -403,6 +421,7 @@
 
 	spin_lock_init(&port->port_lock);
 
+	init_completion(&port->close_complete);
 	INIT_WORK(&port->connect_w, ghsuart_ctrl_connect_w);
 	INIT_WORK(&port->disconnect_w, ghsuart_ctrl_disconnect_w);
 
diff --git a/drivers/usb/gadget/u_data_hsuart.c b/drivers/usb/gadget/u_data_hsuart.c
index 8005a4a..c342437 100644
--- a/drivers/usb/gadget/u_data_hsuart.c
+++ b/drivers/usb/gadget/u_data_hsuart.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
@@ -20,6 +20,7 @@
 #include <linux/debugfs.h>
 #include <linux/bitops.h>
 #include <linux/smux.h>
+#include <linux/completion.h>
 
 #include <mach/usb_gadget_xport.h>
 
@@ -72,6 +73,7 @@
 
 #define CH_OPENED 0
 #define CH_READY 1
+#define CH_CONNECTED 2
 
 struct ghsuart_data_port {
 	/* port */
@@ -86,6 +88,7 @@
 	spinlock_t		port_lock;
 	void *port_usb;
 
+	struct completion	close_complete;
 	/* data transfer queues */
 	unsigned int		tx_q_size;
 	struct list_head	tx_idle;
@@ -502,8 +505,12 @@
 
 	pr_debug("%s: event type: %s ", __func__, event_string(event_type));
 	switch (event_type) {
+	case SMUX_LOCAL_CLOSED:
+		clear_bit(CH_OPENED, &port->channel_sts);
+		complete(&port->close_complete);
+		break;
 	case SMUX_CONNECTED:
-		set_bit(CH_OPENED, &port->channel_sts);
+		set_bit(CH_CONNECTED, &port->channel_sts);
 		if (port->gtype == USB_GADGET_SERIAL) {
 			cbits = msm_smux_tiocm_get(port->ch_id);
 			if (cbits & ACM_CTRL_DCD) {
@@ -515,7 +522,7 @@
 		ghsuart_data_start_io(port);
 		break;
 	case SMUX_DISCONNECTED:
-		clear_bit(CH_OPENED, &port->channel_sts);
+		clear_bit(CH_CONNECTED, &port->channel_sts);
 		break;
 	case SMUX_READ_DONE:
 		skb = meta_read->pkt_priv;
@@ -589,6 +596,14 @@
 
 	pr_debug("%s: port:%p\n", __func__, port);
 
+	if (test_bit(CH_OPENED, &port->channel_sts)) {
+		ret = wait_for_completion_timeout(
+				&port->close_complete, 3 * HZ);
+		if (ret == 0) {
+			pr_err("%s: smux close timedout\n", __func__);
+			return;
+		}
+	}
 	ret = msm_smux_open(port->ch_id, port, &ghsuart_notify_event,
 				&ghsuart_get_rx_buffer);
 	if (ret) {
@@ -596,6 +611,7 @@
 				__func__, port->ch_id, ret);
 		return;
 	}
+	set_bit(CH_OPENED, &port->channel_sts);
 }
 
 static void ghsuart_data_disconnect_w(struct work_struct *w)
@@ -606,8 +622,9 @@
 	if (!test_bit(CH_OPENED, &port->channel_sts))
 		return;
 
+	INIT_COMPLETION(port->close_complete);
 	msm_smux_close(port->ch_id);
-	clear_bit(CH_OPENED, &port->channel_sts);
+	clear_bit(CH_CONNECTED, &port->channel_sts);
 }
 
 static void ghsuart_data_free_buffers(struct ghsuart_data_port *port)
@@ -710,6 +727,7 @@
 
 	clear_bit(CH_READY, &port->channel_sts);
 	clear_bit(CH_OPENED, &port->channel_sts);
+	clear_bit(CH_CONNECTED, &port->channel_sts);
 
 	return 0;
 }
@@ -747,7 +765,7 @@
 
 	port->cbits_tomodem = cbits;
 
-	if (!test_bit(CH_OPENED, &port->channel_sts))
+	if (!test_bit(CH_CONNECTED, &port->channel_sts))
 		return;
 
 	/* if DTR is high, update latest modem info to Host */
@@ -786,6 +804,7 @@
 	spin_lock_init(&port->rx_lock);
 	spin_lock_init(&port->tx_lock);
 
+	init_completion(&port->close_complete);
 	INIT_WORK(&port->connect_w, ghsuart_data_connect_w);
 	INIT_WORK(&port->disconnect_w, ghsuart_data_disconnect_w);
 	INIT_WORK(&port->write_tohost_w, ghsuart_data_write_tohost);
@@ -994,6 +1013,7 @@
 				"#PORT:%d port#:   %p\n"
 				"data_ch_open:	   %d\n"
 				"data_ch_ready:    %d\n"
+				"data_ch_connected: %d\n"
 				"\n******UL INFO*****\n\n"
 				"dpkts_to_modem:   %lu\n"
 				"tomodem_drp_cnt:  %u\n"
@@ -1003,6 +1023,7 @@
 				i, port,
 				test_bit(CH_OPENED, &port->channel_sts),
 				test_bit(CH_READY, &port->channel_sts),
+				test_bit(CH_CONNECTED, &port->channel_sts),
 				port->to_modem,
 				port->tomodem_drp_cnt,
 				port->rx_skb_q.qlen,
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index a09b1ab..20425e2d 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -1229,6 +1229,12 @@
 			} else {
 				ehci_writel(ehci, temp, status_reg);
 			}
+
+			if (ehci->reset_delay) {
+				spin_unlock_irqrestore(&ehci->lock, flags);
+				msleep(ehci->reset_delay);
+				spin_lock_irqsave(&ehci->lock, flags);
+			}
 			break;
 
 		/* For downstream facing ports (these):  one hub port is put
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index ef45d49..253658e 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1878,6 +1878,8 @@
 					&pdata->strobe_pad_offset);
 	of_property_read_u32(node, "hsic,data-pad-offset",
 					&pdata->data_pad_offset);
+	of_property_read_u32(node, "hsic,reset-delay",
+					&pdata->reset_delay);
 	of_property_read_u32(node, "hsic,log2-itc",
 					&pdata->log2_irq_thresh);
 	if (pdata->log2_irq_thresh > 6)
@@ -1981,6 +1983,9 @@
 		mehci->ehci.resume_sof_bug = 1;
 	}
 
+	if (pdata->reset_delay)
+		mehci->ehci.reset_delay = pdata->reset_delay;
+
 	mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
 	mehci->enable_hbm = pdata->enable_hbm;
 
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 823229b..8b1f3a8 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -48,7 +48,7 @@
 		return retval;
 
 	/* bursts of unspecified length. */
-	writel(0, USB_AHBBURST);
+	writel_relaxed(0, USB_AHBBURST);
 	/* Use the AHB transactor */
 	writel_relaxed(0x08, USB_AHBMODE);
 	/* Disable streaming mode and select host mode */
@@ -60,6 +60,10 @@
 							USB_PHY_CTRL2);
 	}
 
+	/* Disable ULPI_TX_PKT_EN_CLR_FIX which is valid only for HSIC */
+	writel_relaxed(readl_relaxed(USB_GENCONFIG2) & ~(1<<19),
+					USB_GENCONFIG2);
+
 	ehci_port_power(ehci, 1);
 	return 0;
 }
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 0498a6a..7cd945a 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -155,6 +155,7 @@
 	unsigned		resume_sof_bug:1;/*Chip Idea HC*/
 	unsigned		reset_sof_bug:1; /*Chip Idea HC*/
 	bool			disable_cerr;
+	u32			reset_delay;
 
 	/* required for usb32 quirk */
 	#define OHCI_CTRL_HCFS          (3 << 6)
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 1b6d15e..bec0356 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -541,7 +541,7 @@
  */
 static int xhci_ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
 {
-	int retval;
+	int retval = -ENOMEM;
 	struct usb_ctrlrequest *dr;
 	struct urb *urb;
 	struct usb_device *udev;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index eb65509..de7fc02 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -36,6 +36,7 @@
 #include <linux/usb/quirks.h>
 #include <linux/usb/msm_hsusb.h>
 #include <linux/usb/msm_hsusb_hw.h>
+#include <linux/usb/msm_ext_chg.h>
 #include <linux/regulator/consumer.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/misc.h>
@@ -888,7 +889,7 @@
 	bool floated_charger;
 	u32 phy_ctrl_val = 0, cmd_val;
 	unsigned ret;
-	u32 portsc;
+	u32 portsc, config2;
 
 	if (atomic_read(&motg->in_lpm))
 		return 0;
@@ -906,6 +907,17 @@
 	prop_charger = motg->chg_type == USB_PROPRIETARY_CHARGER;
 	floated_charger = motg->chg_type == USB_FLOATED_CHARGER;
 
+	/* Enable line state difference wakeup fix for only device and host
+	 * bus suspend scenarios.  Otherwise PHY can not be suspended when
+	 * a charger that pulls DP/DM high is connected.
+	 */
+	config2 = readl_relaxed(USB_GENCONFIG2);
+	if (device_bus_suspend)
+		config2 |= GENCFG2_LINESTATE_DIFF_WAKEUP_EN;
+	else
+		config2 &= ~GENCFG2_LINESTATE_DIFF_WAKEUP_EN;
+	writel_relaxed(config2, USB_GENCONFIG2);
+
 	/*
 	 * Abort suspend when,
 	 * 1. charging detection in progress due to cable plug-in
@@ -993,7 +1005,8 @@
 	 * PHY retention and collapse can not happen with VDP_SRC enabled.
 	 */
 	if (motg->caps & ALLOW_PHY_RETENTION && !device_bus_suspend && !dcp &&
-		 (!host_bus_suspend || motg->caps & ALLOW_HOST_PHY_RETENTION)) {
+		 (!host_bus_suspend || ((motg->caps & ALLOW_HOST_PHY_RETENTION)
+		&& (pdata->dpdm_pulldown_added || !(portsc & PORTSC_CCS))))) {
 		phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
 		if (motg->pdata->otg_control == OTG_PHY_CONTROL) {
 			/* Enable PHY HV interrupts to wake MPM/Link */
@@ -1022,7 +1035,8 @@
 	}
 
 	/* usb phy no more require TCXO clock, hence vote for TCXO disable */
-	if (!host_bus_suspend || (motg->caps & ALLOW_HOST_PHY_RETENTION)) {
+	if (!host_bus_suspend || ((motg->caps & ALLOW_HOST_PHY_RETENTION) &&
+		(pdata->dpdm_pulldown_added || !(portsc & PORTSC_CCS)))) {
 		if (!IS_ERR(motg->xo_clk)) {
 			clk_disable_unprepare(motg->xo_clk);
 			motg->lpm_flags |= XO_SHUTDOWN;
@@ -1099,6 +1113,9 @@
 	if (!atomic_read(&motg->in_lpm))
 		return 0;
 
+	if (motg->pdata->delay_lpm_hndshk_on_disconnect)
+		msm_bam_notify_lpm_resume();
+
 	disable_irq(motg->irq);
 	wake_lock(&motg->wlock);
 
@@ -2207,6 +2224,8 @@
 		/* Clear alt interrupt latch and enable bits */
 		ulpi_write(phy, 0x1F, 0x92);
 		ulpi_write(phy, 0x1F, 0x95);
+		/* re-enable DP and DM pull down resistors */
+		ulpi_write(phy, 0x6, 0xB);
 		break;
 	default:
 		break;
@@ -2448,11 +2467,46 @@
 	}
 }
 
+static void msm_otg_wait_for_ext_chg_done(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	unsigned long t;
+
+	/*
+	 * Defer next cable connect event till external charger
+	 * detection is completed.
+	 */
+
+	if (motg->ext_chg_active) {
+
+		pr_debug("before msm_otg ext chg wait\n");
+
+		t = wait_for_completion_timeout(&motg->ext_chg_wait,
+				msecs_to_jiffies(3000));
+		if (!t)
+			pr_err("msm_otg ext chg wait timeout\n");
+		else
+			pr_debug("msm_otg ext chg wait done\n");
+	}
+
+	if (motg->ext_chg_opened) {
+		if (phy->flags & ENABLE_DP_MANUAL_PULLUP) {
+			ulpi_write(phy, ULPI_MISC_A_VBUSVLDEXT |
+					ULPI_MISC_A_VBUSVLDEXTSEL,
+					ULPI_CLR(ULPI_MISC_A));
+		}
+		/* clear charging register bits */
+		ulpi_write(phy, 0x3F, 0x86);
+		/* re-enable DP and DM pull-down resistors*/
+		ulpi_write(phy, 0x6, 0xB);
+	}
+}
+
 static void msm_otg_sm_work(struct work_struct *w)
 {
 	struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
 	struct usb_otg *otg = motg->phy.otg;
-	bool work = 0, srp_reqd;
+	bool work = 0, srp_reqd, dcp;
 
 	pm_runtime_resume(otg->phy->dev);
 	pr_debug("%s work\n", otg_state_string(otg->phy->state));
@@ -2502,12 +2556,16 @@
 				case USB_DCP_CHARGER:
 					/* Enable VDP_SRC */
 					ulpi_write(otg->phy, 0x2, 0x85);
+					if (motg->ext_chg_opened) {
+						init_completion(
+							&motg->ext_chg_wait);
+						motg->ext_chg_active = true;
+					}
 					/* fall through */
 				case USB_PROPRIETARY_CHARGER:
 					msm_otg_notify_charger(motg,
 							IDEV_CHG_MAX);
-					pm_runtime_put_noidle(otg->phy->dev);
-					pm_runtime_suspend(otg->phy->dev);
+					pm_runtime_put_sync(otg->phy->dev);
 					break;
 				case USB_FLOATED_CHARGER:
 					msm_otg_notify_charger(motg,
@@ -2567,9 +2625,12 @@
 			clear_bit(B_FALSE_SDP, &motg->inputs);
 			clear_bit(A_BUS_REQ, &motg->inputs);
 			cancel_delayed_work_sync(&motg->chg_work);
+			dcp = (motg->chg_type == USB_DCP_CHARGER);
 			motg->chg_state = USB_CHG_STATE_UNDEFINED;
 			motg->chg_type = USB_INVALID_CHARGER;
 			msm_otg_notify_charger(motg, 0);
+			if (dcp)
+				msm_otg_wait_for_ext_chg_done(motg);
 			msm_otg_reset(otg->phy);
 			/*
 			 * There is a small window where ID interrupt
@@ -3544,14 +3605,20 @@
 		else
 			val->intval = POWER_SUPPLY_SCOPE_DEVICE;
 		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		val->intval = motg->voltage_max;
+		break;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
-			val->intval = motg->current_max;
+		val->intval = motg->current_max;
 		break;
 	/* Reflect USB enumeration */
 	case POWER_SUPPLY_PROP_PRESENT:
 	case POWER_SUPPLY_PROP_ONLINE:
 		val->intval = motg->online;
 		break;
+	case POWER_SUPPLY_PROP_TYPE:
+		val->intval = psy->type;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -3573,9 +3640,15 @@
 	case POWER_SUPPLY_PROP_ONLINE:
 		motg->online = val->intval;
 		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		motg->voltage_max = val->intval;
+		break;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 		motg->current_max = val->intval;
 		break;
+	case POWER_SUPPLY_PROP_TYPE:
+		psy->type = val->intval;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -3590,6 +3663,7 @@
 	switch (psp) {
 	case POWER_SUPPLY_PROP_PRESENT:
 	case POWER_SUPPLY_PROP_ONLINE:
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 		return 1;
 	default:
@@ -3606,8 +3680,10 @@
 static enum power_supply_property otg_pm_power_props_usb[] = {
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX,
 	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_SCOPE,
+	POWER_SUPPLY_PROP_TYPE,
 };
 
 const struct file_operations msm_otg_bus_fops = {
@@ -3828,6 +3904,199 @@
 	return 0;
 }
 
+static int msm_otg_ext_chg_open(struct inode *inode, struct file *file)
+{
+	struct msm_otg *motg = the_msm_otg;
+
+	pr_debug("msm_otg ext chg open\n");
+
+	motg->ext_chg_opened = true;
+	file->private_data = (void *)motg;
+	return 0;
+}
+
+static long
+msm_otg_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct msm_otg *motg = file->private_data;
+	struct msm_usb_chg_info info = {0};
+	int ret = 0, val;
+
+	switch (cmd) {
+	case MSM_USB_EXT_CHG_INFO:
+		info.chg_block_type = USB_CHG_BLOCK_ULPI;
+		info.page_offset = motg->io_res->start & ~PAGE_MASK;
+		/* mmap() works on PAGE granularity */
+		info.length = PAGE_SIZE;
+
+		if (copy_to_user((void __user *)arg, &info, sizeof(info))) {
+			pr_err("%s: copy to user failed\n\n", __func__);
+			ret = -EFAULT;
+		}
+		break;
+	case MSM_USB_EXT_CHG_BLOCK_LPM:
+		if (get_user(val, (int __user *)arg)) {
+			pr_err("%s: get_user failed\n\n", __func__);
+			ret = -EFAULT;
+			break;
+		}
+		pr_debug("%s: LPM block request %d\n", __func__, val);
+		if (val) { /* block LPM */
+			if (motg->chg_type == USB_DCP_CHARGER) {
+				/*
+				 * If device is already suspended, resume it.
+				 * The PM usage counter is incremented in
+				 * runtime resume method.  if device is not
+				 * suspended, cancel the scheduled suspend
+				 * and increment the PM usage counter.
+				 */
+				if (pm_runtime_suspended(motg->phy.dev))
+					pm_runtime_resume(motg->phy.dev);
+				else
+					pm_runtime_get_sync(motg->phy.dev);
+			} else {
+				motg->ext_chg_active = false;
+				complete(&motg->ext_chg_wait);
+				ret = -ENODEV;
+			}
+		} else {
+			motg->ext_chg_active = false;
+			complete(&motg->ext_chg_wait);
+			pm_runtime_put(motg->phy.dev);
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int msm_otg_ext_chg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct msm_otg *motg = file->private_data;
+	unsigned long vsize = vma->vm_end - vma->vm_start;
+	int ret;
+
+	if (vma->vm_pgoff || vsize > PAGE_SIZE)
+		return -EINVAL;
+
+	vma->vm_pgoff = __phys_to_pfn(motg->io_res->start);
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+				 vsize, vma->vm_page_prot);
+	if (ret < 0) {
+		pr_err("%s: failed with return val %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int msm_otg_ext_chg_release(struct inode *inode, struct file *file)
+{
+	struct msm_otg *motg = file->private_data;
+
+	pr_debug("msm_otg ext chg release\n");
+
+	motg->ext_chg_opened = false;
+
+	return 0;
+}
+
+static const struct file_operations msm_otg_ext_chg_fops = {
+	.owner = THIS_MODULE,
+	.open = msm_otg_ext_chg_open,
+	.unlocked_ioctl = msm_otg_ext_chg_ioctl,
+	.mmap = msm_otg_ext_chg_mmap,
+	.release = msm_otg_ext_chg_release,
+};
+
+static int msm_otg_setup_ext_chg_cdev(struct msm_otg *motg)
+{
+	int ret;
+
+	if (motg->pdata->enable_sec_phy || motg->pdata->mode == USB_HOST ||
+			motg->pdata->otg_control != OTG_PMIC_CONTROL ||
+			psy != &motg->usb_psy) {
+		pr_debug("usb ext chg is not supported by msm otg\n");
+		return -ENODEV;
+	}
+
+	ret = alloc_chrdev_region(&motg->ext_chg_dev, 0, 1, "usb_ext_chg");
+	if (ret < 0) {
+		pr_err("Fail to allocate usb ext char dev region\n");
+		return ret;
+	}
+	motg->ext_chg_class = class_create(THIS_MODULE, "msm_ext_chg");
+	if (ret < 0) {
+		pr_err("Fail to create usb ext chg class\n");
+		goto unreg_chrdev;
+	}
+	cdev_init(&motg->ext_chg_cdev, &msm_otg_ext_chg_fops);
+	motg->ext_chg_cdev.owner = THIS_MODULE;
+
+	ret = cdev_add(&motg->ext_chg_cdev, motg->ext_chg_dev, 1);
+	if (ret < 0) {
+		pr_err("Fail to add usb ext chg cdev\n");
+		goto destroy_class;
+	}
+	motg->ext_chg_device = device_create(motg->ext_chg_class,
+					NULL, motg->ext_chg_dev, NULL,
+					"usb_ext_chg");
+	if (IS_ERR(motg->ext_chg_device)) {
+		pr_err("Fail to create usb ext chg device\n");
+		ret = PTR_ERR(motg->ext_chg_device);
+		motg->ext_chg_device = NULL;
+		goto del_cdev;
+	}
+
+	init_completion(&motg->ext_chg_wait);
+	pr_debug("msm otg ext chg cdev setup success\n");
+	return 0;
+
+del_cdev:
+	cdev_del(&motg->ext_chg_cdev);
+destroy_class:
+	class_destroy(motg->ext_chg_class);
+unreg_chrdev:
+	unregister_chrdev_region(motg->ext_chg_dev, 1);
+
+	return ret;
+}
+
+static ssize_t dpdm_pulldown_enable_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct msm_otg *motg = the_msm_otg;
+	struct msm_otg_platform_data *pdata = motg->pdata;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", pdata->dpdm_pulldown_added ?
+							"enabled" : "disabled");
+}
+
+static ssize_t dpdm_pulldown_enable_store(struct device *dev,
+		struct device_attribute *attr, const char
+		*buf, size_t size)
+{
+	struct msm_otg *motg = the_msm_otg;
+	struct msm_otg_platform_data *pdata = motg->pdata;
+
+	if (!strnicmp(buf, "enable", 6)) {
+		pdata->dpdm_pulldown_added = true;
+		return size;
+	} else if (!strnicmp(buf, "disable", 7)) {
+		pdata->dpdm_pulldown_added = false;
+		return size;
+	}
+
+	return -EINVAL;
+}
+
+static DEVICE_ATTR(dpdm_pulldown_enable, S_IRUGO | S_IWUSR,
+		dpdm_pulldown_enable_show, dpdm_pulldown_enable_store);
+
 struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
@@ -4029,6 +4298,7 @@
 		goto put_pclk;
 	}
 
+	motg->io_res = res;
 	motg->regs = ioremap(res->start, resource_size(res));
 	if (!motg->regs) {
 		dev_err(&pdev->dev, "ioremap failed\n");
@@ -4253,6 +4523,8 @@
 
 		if (motg->pdata->mpm_dpshv_int || motg->pdata->mpm_dmshv_int)
 			motg->caps |= ALLOW_HOST_PHY_RETENTION;
+			device_create_file(&pdev->dev,
+					&dev_attr_dpdm_pulldown_enable);
 	}
 
 	if (motg->pdata->enable_lpm_on_dev_suspend)
@@ -4292,6 +4564,10 @@
 	if (legacy_power_supply && pdata->otg_control == OTG_PMIC_CONTROL)
 		pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
 
+	ret = msm_otg_setup_ext_chg_cdev(motg);
+	if (ret)
+		dev_dbg(&pdev->dev, "fail to setup cdev\n");
+
 	return 0;
 
 remove_phy:
@@ -4353,6 +4629,13 @@
 	if (phy->otg->host || phy->otg->gadget)
 		return -EBUSY;
 
+	if (!motg->ext_chg_device) {
+		device_destroy(motg->ext_chg_class, motg->ext_chg_dev);
+		cdev_del(&motg->ext_chg_cdev);
+		class_destroy(motg->ext_chg_class);
+		unregister_chrdev_region(motg->ext_chg_dev, 1);
+	}
+
 	if (pdev->dev.of_node)
 		msm_otg_setup_devices(pdev, motg->pdata->mode, false);
 	if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
@@ -4376,6 +4659,10 @@
 	usb_set_transceiver(NULL);
 	free_irq(motg->irq, motg);
 
+	if ((motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) &&
+		(motg->pdata->mpm_dpshv_int || motg->pdata->mpm_dmshv_int))
+			device_remove_file(&pdev->dev,
+					&dev_attr_dpdm_pulldown_enable);
 	if (motg->pdata->otg_control == OTG_PHY_CONTROL &&
 		motg->pdata->mpm_otgsessvld_int)
 		msm_mpm_enable_pin(motg->pdata->mpm_otgsessvld_int, 0);
@@ -4444,8 +4731,25 @@
 
 	if (phy->state == OTG_STATE_UNDEFINED)
 		return -EAGAIN;
-	else
-		return 0;
+
+	if (motg->ext_chg_active) {
+		dev_dbg(dev, "Deferring LPM\n");
+		/*
+		 * Charger detection may happen in user space.
+		 * Delay entering LPM by 3 sec.  Otherwise we
+		 * have to exit LPM when user space begins
+		 * charger detection.
+		 *
+		 * This timer will be canceled when user space
+		 * votes against LPM by incrementing PM usage
+		 * counter.  We enter low power mode when
+		 * PM usage counter is decremented.
+		 */
+		pm_schedule_suspend(dev, 3000);
+		return -EAGAIN;
+	}
+
+	return 0;
 }
 
 static int msm_otg_runtime_suspend(struct device *dev)
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 43eda51..017fa8e 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -24,6 +24,7 @@
 mdss-dsi-objs += msm_mdss_io_8974.o
 obj-$(CONFIG_FB_MSM_MDSS) += mdss-dsi.o
 obj-$(CONFIG_FB_MSM_MDSS) += mdss_edp.o
+obj-$(CONFIG_FB_MSM_MDSS) += mdss_edp_aux.o
 
 obj-$(CONFIG_FB_MSM_MDSS) += mdss_io_util.o
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_tx.o
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 96f0f8c..f2de17d 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -857,6 +857,26 @@
 	return ret;
 }
 
+static int msm_dsi_cont_on(struct mdss_panel_data *pdata)
+{
+	struct mdss_panel_info *pinfo;
+	int ret = 0;
+
+	pr_debug("%s:\n", __func__);
+
+	pinfo = &pdata->panel_info;
+	ret = msm_dsi_regulator_enable();
+	if (ret) {
+		pr_err("%s: DSI power on failed\n", __func__);
+		return ret;
+	}
+
+	msm_dsi_ahb_ctrl(1);
+	msm_dsi_prepare_clocks();
+	msm_dsi_clk_enable();
+	return 0;
+}
+
 static int __devinit msm_dsi_probe(struct platform_device *pdev)
 {
 	struct dsi_interface intf;
@@ -925,6 +945,7 @@
 	dsi_host_private->dis_dev = pdev->dev;
 	intf.on = msm_dsi_on;
 	intf.off = msm_dsi_off;
+	intf.cont_on = msm_dsi_cont_on;
 	intf.op_mode_config = msm_dsi_op_mode_config;
 	intf.tx = msm_dsi_cmds_tx;
 	intf.rx = msm_dsi_cmds_rx;
diff --git a/drivers/video/msm/mdss/dsi_io_v2.c b/drivers/video/msm/mdss/dsi_io_v2.c
index 273fb54..f0ad511 100644
--- a/drivers/video/msm/mdss/dsi_io_v2.c
+++ b/drivers/video/msm/mdss/dsi_io_v2.c
@@ -320,7 +320,7 @@
 static void msm_dsi_phy_regulator_init(unsigned char *ctrl_base,
 					struct mdss_dsi_phy_ctrl *pd)
 {
-	MIPI_OUTP(ctrl_base + DSI_DSIPHY_LDO_CNTRL, 0x04);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_LDO_CNTRL, 0x25);
 	MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_0, pd->regulator[0]);
 	MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_1, pd->regulator[1]);
 	MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_2, pd->regulator[2]);
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
index 5c164e4..022d911 100644
--- a/drivers/video/msm/mdss/dsi_panel_v2.c
+++ b/drivers/video/msm/mdss/dsi_panel_v2.c
@@ -163,7 +163,20 @@
 
 	pr_debug("%s: enable = %d\n", __func__, enable);
 
-	if (enable) {
+	if (enable == 2) {
+		dsi_panel_power(1);
+		gpio_request(panel_private->rst_gpio, "panel_reset");
+		if (gpio_is_valid(panel_private->disp_en_gpio)) {
+			gpio_request(panel_private->disp_en_gpio,
+					"panel_enable");
+		}
+		if (gpio_is_valid(panel_private->video_mode_gpio)) {
+			gpio_request(panel_private->video_mode_gpio,
+					"panel_video_mdoe");
+		}
+		if (gpio_is_valid(panel_private->te_gpio))
+			gpio_request(panel_private->te_gpio, "panel_te");
+	} else if (enable == 1) {
 		dsi_panel_power(1);
 		gpio_request(panel_private->rst_gpio, "panel_reset");
 		gpio_set_value(panel_private->rst_gpio, 1);
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index 5833796..686ec01 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -26,15 +26,6 @@
 static int dsi_off(struct mdss_panel_data *pdata)
 {
 	int rc = 0;
-	if (!panel_common_data || !pdata)
-		return -ENODEV;
-
-	if (dsi_intf.op_mode_config)
-		dsi_intf.op_mode_config(DSI_CMD_MODE, pdata);
-
-	pr_debug("panel off commands\n");
-	if (panel_common_data->off)
-		panel_common_data->off(pdata);
 
 	pr_debug("turn off dsi controller\n");
 	if (dsi_intf.off)
@@ -44,11 +35,6 @@
 		pr_err("mdss_dsi_off DSI failed %d\n", rc);
 		return rc;
 	}
-
-	pr_debug("turn off panel power\n");
-	if (panel_common_data->reset)
-		panel_common_data->reset(pdata, 0);
-
 	return rc;
 }
 
@@ -56,13 +42,7 @@
 {
 	int rc = 0;
 
-	pr_debug("dsi_on\n");
-
-	if (!panel_common_data || !pdata)
-		return -ENODEV;
-
-
-	pr_debug("dsi_on DSI controller ont\n");
+	pr_debug("dsi_on DSI controller on\n");
 	if (dsi_intf.on)
 		rc = dsi_intf.on(pdata);
 
@@ -70,16 +50,52 @@
 		pr_err("mdss_dsi_on DSI failed %d\n", rc);
 		return rc;
 	}
-	pr_debug("dsi_on power on panel\n");
-	if (panel_common_data->reset)
-		panel_common_data->reset(pdata, 1);
+	return rc;
+}
+static int dsi_panel_handler(struct mdss_panel_data *pdata, int enable)
+{
+	int rc = 0;
 
-	pr_debug("dsi_on DSI panel ont\n");
-	if (panel_common_data->on)
-		rc = panel_common_data->on(pdata);
+	pr_debug("dsi_panel_handler enable=%d\n", enable);
+	if (!panel_common_data || !pdata)
+		return -ENODEV;
+
+	if (enable) {
+		if (panel_common_data->reset)
+			panel_common_data->reset(pdata, 1);
+
+		if (panel_common_data->on)
+			rc = panel_common_data->on(pdata);
+
+		if (rc)
+			pr_err("dsi_panel_handler panel on failed %d\n", rc);
+	} else {
+		if (dsi_intf.op_mode_config)
+			dsi_intf.op_mode_config(DSI_CMD_MODE, pdata);
+
+		if (panel_common_data->off)
+			panel_common_data->off(pdata);
+
+		if (panel_common_data->reset)
+			panel_common_data->reset(pdata, 0);
+	}
+	return rc;
+}
+
+static int dsi_splash_on(struct mdss_panel_data *pdata)
+{
+	int rc = 0;
+
+	pr_debug("%s:\n", __func__);
+
+	if (panel_common_data->reset)
+		panel_common_data->reset(pdata, 2);
+
+	if (dsi_intf.cont_on)
+		rc = dsi_intf.cont_on(pdata);
 
 	if (rc) {
-		pr_err("mdss_dsi_on panel failed %d\n", rc);
+		pr_err("mdss_dsi_on DSI failed %d\n", rc);
 		return rc;
 	}
 	return rc;
@@ -96,12 +112,21 @@
 	}
 
 	switch (event) {
-	case MDSS_EVENT_PANEL_ON:
+	case MDSS_EVENT_UNBLANK:
 		rc = dsi_on(pdata);
 		break;
-	case MDSS_EVENT_PANEL_OFF:
+	case MDSS_EVENT_BLANK:
 		rc = dsi_off(pdata);
 		break;
+	case MDSS_EVENT_PANEL_ON:
+		rc = dsi_panel_handler(pdata, 1);
+		break;
+	case MDSS_EVENT_PANEL_OFF:
+		rc = dsi_panel_handler(pdata, 0);
+		break;
+	case MDSS_EVENT_CONT_SPLASH_BEGIN:
+		rc = dsi_splash_on(pdata);
+		break;
 	default:
 		pr_debug("%s: unhandled event=%d\n", __func__, event);
 		break;
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
index 54b772b..96dd390 100644
--- a/drivers/video/msm/mdss/dsi_v2.h
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -198,6 +198,7 @@
 struct dsi_interface {
 	int (*on)(struct mdss_panel_data *pdata);
 	int (*off)(struct mdss_panel_data *pdata);
+	int (*cont_on)(struct mdss_panel_data *pdata);
 	void (*op_mode_config)(int mode, struct mdss_panel_data *pdata);
 	int (*tx)(struct mdss_panel_data *pdata,
 		struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt);
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index bbf9b60..f6f722e 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -959,6 +959,21 @@
 	return rc;
 }
 
+int mdp3_iommu_is_attached(int client)
+{
+	struct mdp3_iommu_ctx_map *context_map;
+	int context = MDP3_IOMMU_CTX_DMA_0;
+
+	if (!mdp3_res->iommu_contexts)
+		return 0;
+
+	if (client == MDP3_CLIENT_PPP)
+		context = MDP3_IOMMU_CTX_PPP_0;
+
+	context_map = mdp3_res->iommu_contexts + context;
+	return context_map->attached;
+}
+
 static int mdp3_init(struct msm_fb_data_type *mfd)
 {
 	int rc;
@@ -982,6 +997,139 @@
 		return xres * bpp;
 }
 
+void mdp3_fbmem_clear(void)
+{
+	if (mdp3_res->ion_handle && mdp3_res->virt) {
+		pr_debug("mdp3_fbmem_clear\n");
+		memset(mdp3_res->virt, 0, mdp3_res->size);
+	}
+}
+
+static int mdp3_alloc(size_t size, void **virt, unsigned long *phys)
+{
+	int ret = 0;
+
+	if (mdp3_res->ion_handle) {
+		pr_debug("memory already alloc\n");
+		*virt = mdp3_res->virt;
+		*phys = mdp3_res->phys;
+		return 0;
+	}
+
+	mdp3_res->ion_handle = ion_alloc(mdp3_res->ion_client, size,
+					SZ_1M,
+					ION_HEAP(ION_QSECOM_HEAP_ID), 0);
+
+	if (!IS_ERR_OR_NULL(mdp3_res->ion_handle)) {
+		*virt = ion_map_kernel(mdp3_res->ion_client,
+					mdp3_res->ion_handle);
+		if (IS_ERR(*virt)) {
+			pr_err("map kernel error\n");
+			goto ion_map_kernel_err;
+		}
+
+		ret = ion_phys(mdp3_res->ion_client, mdp3_res->ion_handle,
+				phys, &size);
+		if (ret) {
+			pr_err("%s ion_phys error\n", __func__);
+			goto ion_map_phys_err;
+		}
+
+		mdp3_res->virt = *virt;
+		mdp3_res->phys = *phys;
+		mdp3_res->size = size;
+	} else {
+		pr_err("%s ion alloc fail\n", __func__);
+		mdp3_res->ion_handle = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+
+ion_map_phys_err:
+	ion_unmap_kernel(mdp3_res->ion_client, mdp3_res->ion_handle);
+ion_map_kernel_err:
+	ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
+	mdp3_res->ion_handle = NULL;
+	mdp3_res->virt = NULL;
+	mdp3_res->phys = 0;
+	mdp3_res->size = 0;
+	return -ENOMEM;
+}
+
+static int mdp3_fbmem_alloc(struct msm_fb_data_type *mfd)
+{
+	int ret = -ENOMEM, dom;
+	void *virt = NULL;
+	unsigned long phys = 0;
+	size_t size;
+	u32 yres = mfd->fbi->var.yres_virtual;
+
+	size = PAGE_ALIGN(mfd->fbi->fix.line_length * yres);
+
+	if (mfd->index != 0) {
+		mfd->fbi->screen_base = virt;
+		mfd->fbi->fix.smem_start = phys;
+		mfd->fbi->fix.smem_len = 0;
+		return 0;
+	}
+
+	ret = mdp3_alloc(size, &virt, &phys);
+	if (ret) {
+		pr_err("fail to allocate fb memory\n");
+		return ret;
+	}
+
+	dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+	ret = ion_map_iommu(mdp3_res->ion_client, mdp3_res->ion_handle,
+			dom, 0, SZ_4K, 0, &mfd->iova,
+			(unsigned long *)&size, 0, 0);
+
+	if (ret) {
+		pr_err("%s map IOMMU error\n", __func__);
+		goto ion_map_iommu_err;
+	}
+
+	pr_debug("allocating %u bytes at %p (%lx phys) for fb %d\n",
+			size, virt, phys, mfd->index);
+
+	mfd->fbi->screen_base = virt;
+	mfd->fbi->fix.smem_start = phys;
+	mfd->fbi->fix.smem_len = size;
+	return 0;
+
+ion_map_iommu_err:
+	ion_unmap_kernel(mdp3_res->ion_client, mdp3_res->ion_handle);
+	ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
+	mdp3_res->ion_handle = NULL;
+	mdp3_res->virt = NULL;
+	mdp3_res->phys = 0;
+	mdp3_res->size = 0;
+	return -ENOMEM;
+}
+
+void mdp3_fbmem_free(struct msm_fb_data_type *mfd)
+{
+	pr_debug("mdp3_fbmem_free\n");
+	if (mdp3_res->ion_handle) {
+		int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+		ion_unmap_kernel(mdp3_res->ion_client, mdp3_res->ion_handle);
+		ion_unmap_iommu(mdp3_res->ion_client,  mdp3_res->ion_handle,
+				dom, 0);
+		ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
+		mdp3_res->ion_handle = NULL;
+		mdp3_res->virt = NULL;
+		mdp3_res->phys = 0;
+		mdp3_res->size = 0;
+		mfd->fbi->screen_base = 0;
+		mfd->fbi->fix.smem_start = 0;
+		mfd->fbi->fix.smem_len = 0;
+		mfd->iova = 0;
+	}
+}
+
 struct mdp3_dma *mdp3_get_dma_pipe(int capability)
 {
 	int i;
@@ -1017,12 +1165,138 @@
 	return mdp3_res->domains[MDP3_IOMMU_DOMAIN].domain_idx;
 }
 
+int mdp3_continuous_splash_copy(struct mdss_panel_data *pdata)
+{
+	unsigned long splash_phys, phys;
+	void *splash_virt, *virt;
+	u32 height, width, rgb_size, stride;
+	size_t size;
+	int rc;
+
+	rgb_size = MDP3_REG_READ(MDP3_REG_DMA_P_SIZE);
+	stride = MDP3_REG_READ(MDP3_REG_DMA_P_IBUF_Y_STRIDE);
+	stride = stride & 0x3FFF;
+	splash_phys = MDP3_REG_READ(MDP3_REG_DMA_P_IBUF_ADDR);
+
+	height = (rgb_size >> 16) & 0xffff;
+	width  = rgb_size & 0xffff;
+	size = PAGE_ALIGN(height * stride * 2);
+	pr_debug("splash_height=%d splash_width=%d Buffer size=%d\n",
+		height, width, size);
+
+	rc = mdp3_alloc(size, &virt, &phys);
+	if (rc) {
+		pr_err("fail to allocate memory for continuous splash image\n");
+		return rc;
+	}
+
+	splash_virt = ioremap(splash_phys, stride * height);
+	memcpy(virt, splash_virt, stride * height);
+	iounmap(splash_virt);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, phys);
+
+	return 0;
+}
+
+static int mdp3_is_display_on(struct mdss_panel_data *pdata)
+{
+	int rc = 0;
+	u32 status;
+
+	mdp3_clk_update(MDP3_CLK_AHB, 1);
+	mdp3_clk_update(MDP3_CLK_CORE, 1);
+
+	if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
+		status = MDP3_REG_READ(MDP3_REG_DSI_VIDEO_EN);
+		rc = status & 0x1;
+	} else {
+		status = MDP3_REG_READ(MDP3_REG_DMA_P_START);
+		rc = status & 01;
+	}
+
+	mdp3_clk_update(MDP3_CLK_AHB, 0);
+	mdp3_clk_update(MDP3_CLK_CORE, 0);
+	return rc;
+}
+
+static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata)
+{
+	struct mdss_panel_info *panel_info = &pdata->panel_info;
+	int ab, ib, rc;
+
+	pr_debug("mdp3__continuous_splash_on\n");
+
+	rc = mdp3_clk_enable(1);
+	if (rc) {
+		pr_err("fail to enable clk\n");
+		return rc;
+	}
+
+	ab = panel_info->xres * panel_info->yres * 4;
+	ab *= panel_info->mipi.frame_rate;
+	ib = (ab * 3) / 2;
+	rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib);
+	if (rc) {
+		pr_err("fail to request bus bandwidth\n");
+		goto splash_on_err;
+	}
+
+	rc = mdp3_ppp_init();
+	if (rc) {
+		pr_err("ppp init failed\n");
+		goto splash_on_err;
+	}
+
+	rc = mdp3_continuous_splash_copy(pdata);
+	if (rc) {
+		pr_err("fail to copy continuous splash image\n");
+		goto splash_on_err;
+	}
+
+	mdp3_irq_register();
+
+	if (pdata->event_handler) {
+		rc = pdata->event_handler(pdata, MDSS_EVENT_CONT_SPLASH_BEGIN,
+					NULL);
+		if (rc) {
+			pr_err("MDSS_EVENT_CONT_SPLASH_BEGIN event fail\n");
+			goto splash_on_err;
+		}
+	}
+
+	if (panel_info->type == MIPI_VIDEO_PANEL)
+		mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_DSI_VIDEO].active = 1;
+	else
+		mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_DSI_CMD].active = 1;
+	return 0;
+
+splash_on_err:
+	mdp3_clk_enable(0);
+	return rc;
+}
+
+static int mdp3_panel_register_done(struct mdss_panel_data *pdata)
+{
+	int rc = 0;
+
+	if (pdata->panel_info.cont_splash_enabled) {
+		if (!mdp3_is_display_on(pdata)) {
+			pr_err("continuous splash, but bootloader is not\n");
+			return 0;
+		}
+		rc = mdp3_continuous_splash_on(pdata);
+	}
+	return rc;
+}
+
 static int mdp3_probe(struct platform_device *pdev)
 {
 	int rc;
 	static struct msm_mdp_interface mdp3_interface = {
 	.init_fnc = mdp3_init,
 	.fb_mem_get_iommu_domain = mdp3_fb_mem_get_iommu_domain,
+	.fb_mem_alloc_fnc = mdp3_fbmem_alloc,
+	.panel_register_done = mdp3_panel_register_done,
 	.fb_stride = mdp3_fb_stride,
 	};
 
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 0482844..03416c7 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -110,6 +110,10 @@
 	struct ion_client *ion_client;
 	struct mdp3_iommu_domain_map *domains;
 	struct mdp3_iommu_ctx_map *iommu_contexts;
+	struct ion_handle *ion_handle;
+	void *virt;
+	unsigned long phys;
+	size_t size;
 
 	struct mdp3_dma dma[MDP3_DMA_MAX];
 	struct mdp3_intf intf[MDP3_DMA_OUTPUT_SEL_MAX];
@@ -150,6 +154,10 @@
 int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data);
 int mdp3_iommu_enable(int client);
 int mdp3_iommu_disable(int client);
+int mdp3_iommu_is_attached(int client);
+void mdp3_fbmem_free(struct msm_fb_data_type *mfd);
+void mdp3_fbmem_clear(void);
+
 
 #define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
 #define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index a875f21..f77a2b3 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -351,7 +351,11 @@
 		cfg.dsi_cmd.dsi_cmd_tg_intf_sel = 0;
 	} else
 		return -EINVAL;
-	rc = mdp3_intf_init(intf, &cfg);
+
+	if (intf->config)
+		rc = intf->config(intf, &cfg);
+	else
+		rc = -EINVAL;
 	return rc;
 }
 
@@ -390,7 +394,10 @@
 					(MDP3_DMA_OUTPUT_COMP_BITS_8 << 2)|
 					MDP3_DMA_OUTPUT_COMP_BITS_8;
 
-	rc = mdp3_dma_init(dma, &sourceConfig, &outputConfig);
+	if (dma->dma_config)
+		rc = dma->dma_config(dma, &sourceConfig, &outputConfig);
+	else
+		rc = -EINVAL;
 	return rc;
 }
 
@@ -413,6 +420,11 @@
 		goto on_error;
 	}
 
+	if (mdp3_session->intf->active) {
+		pr_debug("continuous splash screen, initialized already\n");
+		goto on_error;
+	}
+
 	rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
 	if (rc) {
 		pr_err("fail to attach MDP DMA SMMU\n");
@@ -427,8 +439,10 @@
 	}
 
 	panel = mdp3_session->panel;
-	if (panel->event_handler)
-		rc = panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
+	if (panel->event_handler) {
+		rc = panel->event_handler(panel, MDSS_EVENT_UNBLANK, NULL);
+		rc |= panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
+	}
 	if (rc) {
 		pr_err("fail to turn on the panel\n");
 		goto on_error;
@@ -459,6 +473,12 @@
 		goto on_error;
 	}
 
+	mdp3_fbmem_clear();
+
+	if (panel->set_backlight)
+		panel->set_backlight(panel, panel->panel_info.bl_max);
+
+	pr_debug("mdp3_ctrl_on dma start\n");
 	if (mfd->fbi->screen_base) {
 		rc = mdp3_session->dma->start(mdp3_session->dma,
 						mdp3_session->intf);
@@ -490,6 +510,7 @@
 		return -ENODEV;
 	}
 
+	panel = mdp3_session->panel;
 	mutex_lock(&mdp3_session->lock);
 
 	if (!mdp3_session->status) {
@@ -497,32 +518,39 @@
 		goto off_error;
 	}
 
-	pr_debug("mdp3_ctrl_off stop mdp3 dma engine\n");
-
 	mdp3_histogram_stop(mdp3_session, MDP_BLOCK_DMA_P);
 
-	rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
+	pr_debug("mdp3_ctrl_off turn panel off\n");
+	if (panel->set_backlight)
+		panel->set_backlight(panel, 0);
 
-	if (rc)
-		pr_err("fail to stop the MDP3 dma\n");
-
-	mdp3_irq_deregister();
-
-	pr_debug("mdp3_ctrl_off stop dsi panel and controller\n");
-	panel = mdp3_session->panel;
 	if (panel->event_handler)
 		rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
 	if (rc)
 		pr_err("fail to turn off the panel\n");
 
-	pr_debug("mdp3_ctrl_off release bus and clock\n");
-	rc = mdp3_ctrl_res_req_bus(mfd, 0);
+	rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
 	if (rc)
-		pr_err("mdp bus resource release failed\n");
+		pr_err("fail to stop the MDP3 dma\n");
+
+	mdp3_irq_deregister();
+
+	pr_debug("mdp3_ctrl_off stop clock\n");
 	rc = mdp3_ctrl_res_req_clk(mfd, 0);
 	if (rc)
 		pr_err("mdp clock resource release failed\n");
 
+	pr_debug("mdp3_ctrl_off stop dsi controller\n");
+	if (panel->event_handler)
+		rc = panel->event_handler(panel, MDSS_EVENT_BLANK, NULL);
+	if (rc)
+		pr_err("fail to turn off the panel\n");
+
+	pr_debug("mdp3_ctrl_off release bus\n");
+	rc = mdp3_ctrl_res_req_bus(mfd, 0);
+	if (rc)
+		pr_err("mdp bus resource release failed\n");
+
 	rc = mdp3_iommu_disable(MDP3_CLIENT_DMA_P);
 	if (rc)
 		pr_err("fail to dettach MDP DMA SMMU\n");
@@ -657,6 +685,12 @@
 		return -EPERM;
 	}
 
+	if (!mdp3_iommu_is_attached(MDP3_CLIENT_DMA_P)) {
+		pr_debug("continuous splash screen, IOMMU not attached\n");
+		mdp3_ctrl_off(mfd);
+		mdp3_ctrl_on(mfd);
+	}
+
 	mutex_lock(&mdp3_session->lock);
 
 	data = mdp3_bufq_pop(&mdp3_session->bufq_in);
@@ -670,6 +704,9 @@
 	if (mdp3_bufq_count(&mdp3_session->bufq_out) > 2) {
 		data = mdp3_bufq_pop(&mdp3_session->bufq_out);
 		mdp3_put_img(data);
+
+		if (mfd->fbi->screen_base)
+			mdp3_fbmem_free(mfd);
 	}
 	mutex_unlock(&mdp3_session->lock);
 
@@ -698,6 +735,12 @@
 		return;
 	}
 
+	if (!mdp3_iommu_is_attached(MDP3_CLIENT_DMA_P)) {
+		pr_debug("continuous splash screen, IOMMU not attached\n");
+		mdp3_ctrl_off(mfd);
+		mdp3_ctrl_on(mfd);
+	}
+
 	mutex_lock(&mdp3_session->lock);
 	fbi = mfd->fbi;
 
@@ -854,7 +897,7 @@
 
 	ret = session->dma->get_histo(session->dma);
 	if (ret) {
-		pr_err("mdp3_histogram_collect error = %d\n", ret);
+		pr_debug("mdp3_histogram_collect error = %d\n", ret);
 		return ret;
 	}
 
@@ -903,11 +946,53 @@
 	return ret;
 }
 
+static int mdp3_csc_config(struct mdp3_session_data *session,
+					struct mdp_csc_cfg_data *data)
+{
+	struct mdp3_dma_color_correct_config config;
+	struct mdp3_dma_ccs ccs;
+	int ret = -EINVAL;
+
+	if (!data->csc_data.csc_mv || !data->csc_data.csc_pre_bv ||
+		!data->csc_data.csc_post_bv || !data->csc_data.csc_pre_lv ||
+			!data->csc_data.csc_post_lv) {
+		pr_err("%s : Invalid csc vectors", __func__);
+		return -EINVAL;
+	}
+
+	session->cc_vect_sel = (session->cc_vect_sel + 1) % 2;
+
+	config.ccs_enable = 1;
+	config.ccs_sel = session->cc_vect_sel;
+	config.pre_limit_sel = session->cc_vect_sel;
+	config.post_limit_sel = session->cc_vect_sel;
+	config.pre_bias_sel = session->cc_vect_sel;
+	config.post_bias_sel = session->cc_vect_sel;
+	config.ccs_dirty = true;
+
+	ccs.mv = data->csc_data.csc_mv;
+	ccs.pre_bv = data->csc_data.csc_pre_bv;
+	ccs.post_bv = data->csc_data.csc_post_bv;
+	ccs.pre_lv = data->csc_data.csc_pre_lv;
+	ccs.post_lv = data->csc_data.csc_post_lv;
+
+	mutex_lock(&session->lock);
+	ret = session->dma->config_ccs(session->dma, &config, &ccs);
+	mutex_unlock(&session->lock);
+	return ret;
+}
+
 static int mdp3_pp_ioctl(struct msm_fb_data_type *mfd,
 					void __user *argp)
 {
 	int ret = -EINVAL;
 	struct msmfb_mdp_pp mdp_pp;
+	struct mdp3_session_data *mdp3_session;
+
+	if (!mfd || !mfd->mdp.private1)
+		return -EINVAL;
+
+	mdp3_session = mfd->mdp.private1;
 
 	ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
 	if (ret)
@@ -918,6 +1003,11 @@
 		ret = mdp3_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
 						&mdp_pp.data.bl_scale_data);
 		break;
+	case mdp_op_csc_cfg:
+		ret = mdp3_csc_config(mdp3_session,
+						&(mdp_pp.data.csc_cfg_data));
+		break;
+
 	default:
 		pr_err("Unsupported request to MDP_PP IOCTL.\n");
 		ret = -EINVAL;
@@ -1005,6 +1095,7 @@
 	lut_config.lut_enable = 7;
 	lut_config.lut_sel = mdp3_session->lut_sel;
 	lut_config.lut_position = 0;
+	lut_config.lut_dirty = true;
 	lut.color0_lut = r;
 	lut.color1_lut = g;
 	lut.color2_lut = b;
@@ -1152,12 +1243,23 @@
 		goto init_done;
 	}
 
+	rc = mdp3_dma_init(mdp3_session->dma);
+	if (rc) {
+		pr_err("fail to init dma\n");
+		goto init_done;
+	}
+
 	intf_type = mdp3_ctrl_get_intf_type(mfd);
 	mdp3_session->intf = mdp3_get_display_intf(intf_type);
 	if (!mdp3_session->intf) {
 		rc = -ENODEV;
 		goto init_done;
 	}
+	rc = mdp3_intf_init(mdp3_session->intf);
+	if (rc) {
+		pr_err("fail to init interface\n");
+		goto init_done;
+	}
 
 	mdp3_session->mfd = mfd;
 	mdp3_session->panel = dev_get_platdata(&mfd->pdev->dev);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index 0bbc2ac..9ea1c91 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -50,6 +50,7 @@
 	int histo_status;
 	struct mutex histo_lock;
 	int lut_sel;
+	int cc_vect_sel;
 };
 
 int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 3b65405..88eedb9 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -219,6 +219,25 @@
 	}
 }
 
+static void mdp3_dma_clk_auto_gating(struct mdp3_dma *dma, int enable)
+{
+	u32 cgc;
+	int clock_bit = 10;
+
+	clock_bit += dma->dma_sel;
+
+	if (enable) {
+		cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
+		cgc |= BIT(clock_bit);
+		MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+
+	} else {
+		cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
+		cgc &= ~BIT(clock_bit);
+		MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+	}
+}
+
 static int mdp3_dma_sync_config(struct mdp3_dma *dma,
 			struct mdp3_dma_source *source_config)
 {
@@ -347,11 +366,109 @@
 	return 0;
 }
 
+static void mdp3_ccs_update(struct mdp3_dma *dma)
+{
+	u32 cc_config;
+	int updated = 0;
+
+	cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
+
+	if (dma->ccs_config.ccs_dirty) {
+		cc_config &= DMA_CCS_CONFIG_MASK;
+		if (dma->ccs_config.ccs_enable)
+			cc_config |= BIT(3);
+		else
+			cc_config &= ~BIT(3);
+		cc_config |= dma->ccs_config.ccs_sel << 5;
+		cc_config |= dma->ccs_config.pre_bias_sel << 6;
+		cc_config |= dma->ccs_config.post_bias_sel << 7;
+		cc_config |= dma->ccs_config.pre_limit_sel << 8;
+		cc_config |= dma->ccs_config.post_limit_sel << 9;
+		dma->ccs_config.ccs_dirty = false;
+		updated = 1;
+	}
+
+	if (dma->lut_config.lut_dirty) {
+		cc_config &= DMA_LUT_CONFIG_MASK;
+		cc_config |= dma->lut_config.lut_enable;
+		cc_config |= dma->lut_config.lut_position << 4;
+		cc_config |= dma->lut_config.lut_sel << 10;
+		dma->lut_config.lut_dirty = false;
+		updated = 1;
+	}
+	if (updated) {
+		MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
+
+		/* Make sure ccs configuration update is done before continuing
+		with the DMA transfer */
+		wmb();
+	}
+}
+
+static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
+			struct mdp3_dma_color_correct_config *config,
+			struct mdp3_dma_ccs *ccs)
+{
+	int i;
+	u32 addr;
+
+	if (!ccs)
+		return -EINVAL;
+
+	if (config->ccs_enable) {
+		addr = MDP3_REG_DMA_P_CSC_MV1;
+		if (config->ccs_sel)
+			addr = MDP3_REG_DMA_P_CSC_MV2;
+		for (i = 0; i < 9; i++) {
+			MDP3_REG_WRITE(addr, ccs->mv[i]);
+			addr += 4;
+		}
+
+		addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
+		if (config->pre_bias_sel)
+			addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
+		for (i = 0; i < 3; i++) {
+			MDP3_REG_WRITE(addr, ccs->pre_bv[i]);
+			addr += 4;
+		}
+
+		addr = MDP3_REG_DMA_P_CSC_POST_BV1;
+		if (config->post_bias_sel)
+			addr = MDP3_REG_DMA_P_CSC_POST_BV2;
+		for (i = 0; i < 3; i++) {
+			MDP3_REG_WRITE(addr, ccs->post_bv[i]);
+			addr += 4;
+		}
+
+		addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
+		if (config->pre_limit_sel)
+			addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
+		for (i = 0; i < 6; i++) {
+			MDP3_REG_WRITE(addr, ccs->pre_lv[i]);
+			addr += 4;
+		}
+
+		addr = MDP3_REG_DMA_P_CSC_POST_LV1;
+		if (config->post_limit_sel)
+			addr = MDP3_REG_DMA_P_CSC_POST_LV2;
+		for (i = 0; i < 6; i++) {
+			MDP3_REG_WRITE(addr, ccs->post_lv[i]);
+			addr += 4;
+		}
+	}
+	dma->ccs_config = *config;
+
+	if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+		mdp3_ccs_update(dma);
+
+	return 0;
+}
+
 static int mdp3_dmap_lut_config(struct mdp3_dma *dma,
 			struct mdp3_dma_lut_config *config,
 			struct mdp3_dma_lut *lut)
 {
-	u32 cc_config, addr, color;
+	u32 addr, color;
 	int i;
 
 	if (config->lut_enable && lut) {
@@ -368,119 +485,11 @@
 		}
 	}
 
-	cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
-	cc_config &= DMA_LUT_CONFIG_MASK;
-	cc_config |= config->lut_enable;
-	cc_config |= config->lut_position << 4;
-	cc_config |= config->lut_sel << 10;
-	MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
-	wmb();
-
 	dma->lut_config = *config;
-	return 0;
-}
 
-static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
-			struct mdp3_dma_color_correct_config *config,
-			struct mdp3_dma_ccs *ccs)
-{
-	int i;
-	u32 cc_config, addr;
+	if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+		mdp3_ccs_update(dma);
 
-	cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
-	cc_config &= DMA_CCS_CONFIG_MASK;
-	cc_config |= BIT(3);
-	cc_config |= config->ccs_sel << 5;
-	cc_config |= config->pre_bias_sel << 6;
-	cc_config |= config->post_bias_sel << 7;
-	cc_config |= config->pre_limit_sel << 8;
-	cc_config |= config->post_limit_sel << 9;
-
-	MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
-
-	if (config->ccs_enable && ccs) {
-		if (ccs->mv1) {
-			addr = MDP3_REG_DMA_P_CSC_MV1;
-			for (i = 0; i < 9; i++) {
-				MDP3_REG_WRITE(addr, ccs->mv1[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->mv2) {
-			addr = MDP3_REG_DMA_P_CSC_MV2;
-			for (i = 0; i < 9; i++) {
-				MDP3_REG_WRITE(addr, ccs->mv2[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->pre_bv1) {
-			addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
-			for (i = 0; i < 3; i++) {
-				MDP3_REG_WRITE(addr, ccs->pre_bv1[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->pre_bv2) {
-			addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
-			for (i = 0; i < 3; i++) {
-				MDP3_REG_WRITE(addr, ccs->pre_bv2[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->post_bv1) {
-			addr = MDP3_REG_DMA_P_CSC_POST_BV1;
-			for (i = 0; i < 3; i++) {
-				MDP3_REG_WRITE(addr, ccs->post_bv1[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->post_bv2) {
-			addr = MDP3_REG_DMA_P_CSC_POST_BV2;
-			for (i = 0; i < 3; i++) {
-				MDP3_REG_WRITE(addr, ccs->post_bv2[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->pre_lv1) {
-			addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
-			for (i = 0; i < 6; i++) {
-				MDP3_REG_WRITE(addr, ccs->pre_lv1[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->pre_lv2) {
-			addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
-			for (i = 0; i < 6; i++) {
-				MDP3_REG_WRITE(addr, ccs->pre_lv2[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->post_lv1) {
-			addr = MDP3_REG_DMA_P_CSC_POST_LV1;
-			for (i = 0; i < 6; i++) {
-				MDP3_REG_WRITE(addr, ccs->post_lv1[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->post_lv2) {
-			addr = MDP3_REG_DMA_P_CSC_POST_LV2;
-			for (i = 0; i < 6; i++) {
-				MDP3_REG_WRITE(addr, ccs->post_lv2[i]);
-				addr += 4;
-			}
-		}
-	}
-
-	dma->ccs_config = *config;
 	return 0;
 }
 
@@ -528,8 +537,10 @@
 	spin_lock_irqsave(&dma->dma_lock, flag);
 	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
 	dma->source_config.buf = buf;
-	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		mdp3_ccs_update(dma);
 		MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
+	}
 
 	if (!intf->active) {
 		pr_debug("mdp3_dmap_update start interface\n");
@@ -610,7 +621,7 @@
 	ret = wait_for_completion_killable_timeout(&dma->histo_comp, timeout);
 
 	if (ret == 0) {
-		pr_err("mdp3_dmap_histo_get time out\n");
+		pr_debug("mdp3_dmap_histo_get time out\n");
 		ret = -ETIMEDOUT;
 	} else if (ret < 0) {
 		pr_err("mdp3_dmap_histo_get interrupted\n");
@@ -682,7 +693,6 @@
 {
 	unsigned long flag;
 	int ret;
-	u32 cgc;
 
 	if (dma->histo_state == MDP3_DMA_HISTO_STATE_START)
 		return -EINVAL;
@@ -690,9 +700,8 @@
 	spin_lock_irqsave(&dma->histo_lock, flag);
 
 	init_completion(&dma->histo_comp);
-	cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
-	cgc &= ~BIT(10);
-	MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+
+	mdp3_dma_clk_auto_gating(dma, 0);
 
 	MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, BIT(0)|BIT(1));
 	MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_RESET_SEQ_START, 1);
@@ -714,8 +723,7 @@
 		ret = 0;
 	}
 	mdp3_dma_callback_disable(dma, MDP3_DMA_CALLBACK_TYPE_HIST_RESET_DONE);
-	cgc |= BIT(10);
-	MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+	mdp3_dma_clk_auto_gating(dma, 1);
 
 	return ret;
 }
@@ -732,6 +740,7 @@
 	MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, 0);
 	wmb();
 	dma->histo_state = MDP3_DMA_HISTO_STATE_IDLE;
+	complete(&dma->histo_comp);
 
 	spin_unlock_irqrestore(&dma->histo_lock, flag);
 
@@ -820,19 +829,14 @@
 	return ret;
 }
 
-int mdp3_dma_init(struct mdp3_dma *dma,
-		struct mdp3_dma_source *source_config,
-		struct mdp3_dma_output_config *output_config)
+int mdp3_dma_init(struct mdp3_dma *dma)
 {
 	int ret = 0;
 
 	pr_debug("mdp3_dma_init\n");
 	switch (dma->dma_sel) {
 	case MDP3_DMA_P:
-		ret = mdp3_dmap_config(dma, source_config, output_config);
-		if (ret < 0)
-			return ret;
-
+		dma->dma_config = mdp3_dmap_config;
 		dma->config_cursor = mdp3_dmap_cursor_config;
 		dma->config_ccs = mdp3_dmap_ccs_config;
 		dma->config_histo = mdp3_dmap_histo_config;
@@ -846,10 +850,7 @@
 		dma->stop = mdp3_dma_stop;
 		break;
 	case MDP3_DMA_S:
-		ret = mdp3_dmas_config(dma, source_config, output_config);
-		if (ret < 0)
-			return ret;
-
+		dma->dma_config = mdp3_dmas_config;
 		dma->config_cursor = NULL;
 		dma->config_ccs = NULL;
 		dma->config_histo = NULL;
@@ -1020,10 +1021,9 @@
 	return 0;
 }
 
-int mdp3_intf_init(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+int mdp3_intf_init(struct mdp3_intf *intf)
 {
-	int ret = 0;
-	switch (cfg->type) {
+	switch (intf->cfg.type) {
 	case MDP3_DMA_OUTPUT_SEL_LCDC:
 		intf->config = lcdc_config;
 		intf->start = lcdc_start;
@@ -1043,16 +1043,5 @@
 	default:
 		return -EINVAL;
 	}
-
-	intf->active = false;
-	if (intf->config)
-		ret = intf->config(intf, cfg);
-
-	if (ret) {
-		pr_err("MDP interface initialization failed\n");
-		return ret;
-	}
-
-	intf->cfg = *cfg;
 	return 0;
 }
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 518bd58..e4a28dc 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -176,16 +176,11 @@
 };
 
 struct mdp3_dma_ccs {
-	u32 *mv1; /*set1 matrix vector, 3x3 */
-	u32 *mv2;
-	u32 *pre_bv1; /*pre-bias vector for set1, 1x3*/
-	u32 *pre_bv2;
-	u32 *post_bv1; /*post-bias vecotr for set1,  */
-	u32 *post_bv2;
-	u32 *pre_lv1; /*pre-limit vector for set 1, 1x6*/
-	u32 *pre_lv2;
-	u32 *post_lv1;
-	u32 *post_lv2;
+	u32 *mv; /*set1 matrix vector, 3x3 */
+	u32 *pre_bv; /*pre-bias vector for set1, 1x3*/
+	u32 *post_bv; /*post-bias vecotr for set1,  */
+	u32 *pre_lv; /*pre-limit vector for set 1, 1x6*/
+	u32 *post_lv;
 };
 
 struct mdp3_dma_lut {
@@ -198,6 +193,7 @@
 	int lut_enable;
 	u32 lut_sel;
 	u32 lut_position;
+	bool lut_dirty;
 };
 
 struct mdp3_dma_color_correct_config {
@@ -207,6 +203,7 @@
 	u32 post_bias_sel;
 	u32 pre_bias_sel;
 	u32 ccs_sel;
+	bool ccs_dirty;
 };
 
 struct mdp3_dma_histogram_config {
@@ -253,6 +250,10 @@
 	int histo_state;
 	struct mdp3_dma_histogram_data histo_data;
 
+	int (*dma_config)(struct mdp3_dma *dma,
+			struct mdp3_dma_source *source_config,
+			struct mdp3_dma_output_config *output_config);
+
 	int (*start)(struct mdp3_dma *dma, struct mdp3_intf *intf);
 
 	int (*stop)(struct mdp3_dma *dma, struct mdp3_intf *intf);
@@ -326,11 +327,9 @@
 	int (*stop)(struct mdp3_intf *intf);
 };
 
-int mdp3_dma_init(struct mdp3_dma *dma,
-		struct mdp3_dma_source *source_config,
-		struct mdp3_dma_output_config *output_config);
+int mdp3_dma_init(struct mdp3_dma *dma);
 
-int mdp3_intf_init(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg);
+int mdp3_intf_init(struct mdp3_intf *intf);
 
 void mdp3_dma_callback_enable(struct mdp3_dma *dma, int type);
 
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index 48ffb72..924ec5a 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -23,6 +23,7 @@
 #include <linux/sync.h>
 #include <linux/sw_sync.h>
 #include "linux/proc_fs.h"
+#include <linux/delay.h>
 
 #include "mdss_fb.h"
 #include "mdp3_ppp.h"
@@ -30,6 +31,7 @@
 #include "mdp3.h"
 
 #define MDP_IS_IMGTYPE_BAD(x) ((x) >= MDP_IMGTYPE_LIMIT)
+#define MDP_RELEASE_BW_TIMEOUT 50
 #define MDP_BLIT_CLK_RATE	200000000
 #define MDP_PPP_MAX_BPP 4
 #define MDP_PPP_DYNAMIC_FACTOR 3
@@ -48,6 +50,7 @@
 	[MDP_Y_CRCB_H2V2] = true,
 	[MDP_Y_CBCR_H2V2] = true,
 	[MDP_Y_CBCR_H2V2_ADRENO] = true,
+	[MDP_Y_CBCR_H2V2_VENUS] = true,
 	[MDP_YCRYCB_H2V1] = true,
 	[MDP_Y_CBCR_H2V1] = true,
 	[MDP_Y_CRCB_H2V1] = true,
@@ -92,6 +95,9 @@
 	struct sw_sync_timeline *timeline;
 	int timeline_value;
 
+	struct timer_list free_bw_timer;
+	struct work_struct free_bw_work;
+	bool bw_on;
 };
 
 static struct ppp_status *ppp_stat;
@@ -353,6 +359,7 @@
 	mdp3_clk_set_rate(MDP3_CLK_CORE, rate, MDP3_CLIENT_PPP);
 	mdp3_clk_enable(on_off);
 	mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
+	ppp_stat->bw_on = on_off;
 	return 0;
 }
 
@@ -403,6 +410,11 @@
 			(void *) ((uint32_t) blit_op->src.p0 +
 				ALIGN((ALIGN(req->src.width, 32) *
 				ALIGN(req->src.height, 32)), 4096));
+	else if (blit_op->src.color_fmt == MDP_Y_CBCR_H2V2_VENUS)
+		blit_op->src.p1 =
+			(void *) ((uint32_t) blit_op->src.p0 +
+				ALIGN((ALIGN(req->src.width, 128) *
+				ALIGN(req->src.height, 32)), 4096));
 	else
 		blit_op->src.p1 = (void *) ((uint32_t) blit_op->src.p0 +
 			req->src.width * req->src.height);
@@ -754,9 +766,6 @@
 				src_data, dst_data);
 	else
 		ret = mdp3_ppp_blit(mfd, req, src_data, dst_data);
-
-	mdp3_put_img(src_data);
-	mdp3_put_img(dst_data);
 	return ret;
 }
 
@@ -892,28 +901,52 @@
 	req_q->pop_idx = (req_q->pop_idx + 1) % MDP3_PPP_MAX_LIST_REQ;
 }
 
+void mdp3_free_fw_timer_func(unsigned long arg)
+{
+	schedule_work(&ppp_stat->free_bw_work);
+}
+
+static void mdp3_free_bw_wq_handler(struct work_struct *work)
+{
+	struct msm_fb_data_type *mfd = ppp_stat->mfd;
+	mutex_lock(&ppp_stat->config_ppp_mutex);
+	if (ppp_stat->bw_on) {
+		mdp3_ppp_turnon(mfd, 0);
+		mdp3_iommu_disable(MDP3_CLIENT_PPP);
+	}
+	mutex_unlock(&ppp_stat->config_ppp_mutex);
+}
+
 static void mdp3_ppp_blit_wq_handler(struct work_struct *work)
 {
 	struct msm_fb_data_type *mfd = ppp_stat->mfd;
 	struct blit_req_list *req;
-	int i, rc;
+	int i, rc = 0;
 
-	req = mdp3_ppp_next_req(&ppp_stat->req_q);
 	mutex_lock(&ppp_stat->config_ppp_mutex);
+	req = mdp3_ppp_next_req(&ppp_stat->req_q);
+	if (!req) {
+		mutex_unlock(&ppp_stat->config_ppp_mutex);
+		return;
+	}
 
-	mdp3_iommu_enable(MDP3_CLIENT_PPP);
-	mdp3_ppp_turnon(mfd, 1);
+	if (!ppp_stat->bw_on) {
+		mdp3_iommu_enable(MDP3_CLIENT_PPP);
+		mdp3_ppp_turnon(mfd, 1);
+	}
 	while (req) {
 		mdp3_ppp_wait_for_fence(req);
 		for (i = 0; i < req->count; i++) {
 			if (!(req->req_list[i].flags & MDP_NO_BLIT)) {
 				/* Do the actual blit. */
-				rc = mdp3_ppp_start_blit(mfd,
+				if (!rc) {
+					rc = mdp3_ppp_start_blit(mfd,
 						&(req->req_list[i]),
 						&req->src_data[i],
 						&req->dst_data[i]);
-				if (rc)
-					break;
+				}
+				mdp3_put_img(&req->src_data[i]);
+				mdp3_put_img(&req->dst_data[i]);
 			}
 		}
 		/* Signal to release fence */
@@ -925,8 +958,8 @@
 			complete(&ppp_stat->pop_q_comp);
 		mutex_unlock(&ppp_stat->req_mutex);
 	}
-	mdp3_ppp_turnon(mfd, 0);
-	mdp3_iommu_disable(MDP3_CLIENT_PPP);
+	mod_timer(&ppp_stat->free_bw_timer, jiffies +
+		msecs_to_jiffies(MDP_RELEASE_BW_TIMEOUT));
 	mutex_unlock(&ppp_stat->config_ppp_mutex);
 }
 
@@ -995,14 +1028,14 @@
 		if (req->cur_rel_fen_fd < 0) {
 			pr_err("%s: get_unused_fd_flags failed\n", __func__);
 			rc  = -ENOMEM;
-			goto parse_err_2;
+			goto parse_err_1;
 		}
 		sync_fence_install(req->cur_rel_fence, req->cur_rel_fen_fd);
 		rc = copy_to_user(req_list_header->sync.rel_fen_fd,
 			&req->cur_rel_fen_fd, sizeof(int));
 		if (rc) {
 			pr_err("%s:copy_to_user failed\n", __func__);
-			goto parse_err_3;
+			goto parse_err_2;
 		}
 	} else {
 		fence = req->cur_rel_fence;
@@ -1023,12 +1056,8 @@
 	}
 	return 0;
 
-parse_err_3:
-	put_unused_fd(req->cur_rel_fen_fd);
 parse_err_2:
-	sync_fence_put(req->cur_rel_fence);
-	req->cur_rel_fence = NULL;
-	req->cur_rel_fen_fd = 0;
+	put_unused_fd(req->cur_rel_fen_fd);
 parse_err_1:
 	for (i--; i >= 0; i--) {
 		mdp3_put_img(&req->src_data[i]);
@@ -1058,10 +1087,14 @@
 	}
 
 	INIT_WORK(&ppp_stat->blit_work, mdp3_ppp_blit_wq_handler);
+	INIT_WORK(&ppp_stat->free_bw_work, mdp3_free_bw_wq_handler);
 	init_completion(&ppp_stat->pop_q_comp);
 	spin_lock_init(&ppp_stat->ppp_lock);
 	mutex_init(&ppp_stat->req_mutex);
 	mutex_init(&ppp_stat->config_ppp_mutex);
+	init_timer(&ppp_stat->free_bw_timer);
+	ppp_stat->free_bw_timer.function = mdp3_free_fw_timer_func;
+	ppp_stat->free_bw_timer.data = 0;
 	ppp_stat->busy = false;
 	ppp_stat->mfd = mfd;
 	mdp3_ppp_callback_setup();
diff --git a/drivers/video/msm/mdss/mdp3_ppp_data.c b/drivers/video/msm/mdss/mdp3_ppp_data.c
index d68faad..e1c0f27 100644
--- a/drivers/video/msm/mdss/mdp3_ppp_data.c
+++ b/drivers/video/msm/mdss/mdp3_ppp_data.c
@@ -30,6 +30,7 @@
 	[MDP_Y_CRCB_H2V2] = MDP_Y_CBCR_H2V2_SRC_REG,
 	[MDP_Y_CBCR_H2V2] = MDP_Y_CBCR_H2V2_SRC_REG,
 	[MDP_Y_CBCR_H2V2_ADRENO] = MDP_Y_CBCR_H2V2_SRC_REG,
+	[MDP_Y_CBCR_H2V2_VENUS] = MDP_Y_CBCR_H2V2_SRC_REG,
 	[MDP_YCRYCB_H2V1] = MDP_YCRYCB_H2V1_SRC_REG,
 	[MDP_Y_CBCR_H2V1] = MDP_Y_CRCB_H2V1_SRC_REG,
 	[MDP_Y_CRCB_H2V1] = MDP_Y_CRCB_H2V1_SRC_REG,
@@ -48,6 +49,7 @@
 	[MDP_Y_CRCB_H2V2] = MDP_Y_CBCR_H2V2_DST_REG,
 	[MDP_Y_CBCR_H2V2] = MDP_Y_CBCR_H2V2_DST_REG,
 	[MDP_Y_CBCR_H2V2_ADRENO] = MDP_Y_CBCR_H2V2_DST_REG,
+	[MDP_Y_CBCR_H2V2_VENUS] = MDP_Y_CBCR_H2V2_DST_REG,
 	[MDP_YCRYCB_H2V1] = MDP_YCRYCB_H2V1_DST_REG,
 	[MDP_Y_CBCR_H2V1] = MDP_Y_CRCB_H2V1_DST_REG,
 	[MDP_Y_CRCB_H2V1] = MDP_Y_CRCB_H2V1_DST_REG,
@@ -72,6 +74,8 @@
 	[MDP_Y_CBCR_H2V2] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8),
 	[MDP_Y_CBCR_H2V2_ADRENO] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB,
 		CLR_CR, 8),
+	[MDP_Y_CBCR_H2V2_VENUS] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB,
+		CLR_CR, 8),
 	[MDP_YCRYCB_H2V1] = PPP_GET_PACK_PATTERN(CLR_Y,
 		CLR_CR, CLR_Y, CLR_CB, 8),
 	[MDP_Y_CBCR_H2V1] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8),
@@ -91,6 +95,8 @@
 	[MDP_Y_CBCR_H2V2] = PPP_OP_SRC_CHROMA_420 | PPP_OP_COLOR_SPACE_YCBCR,
 	[MDP_Y_CBCR_H2V2_ADRENO] = PPP_OP_SRC_CHROMA_420 |
 			PPP_OP_COLOR_SPACE_YCBCR,
+	[MDP_Y_CBCR_H2V2_VENUS] = PPP_OP_SRC_CHROMA_420 |
+			PPP_OP_COLOR_SPACE_YCBCR,
 	[MDP_Y_CBCR_H2V1] = PPP_OP_SRC_CHROMA_H2V1,
 	[MDP_Y_CRCB_H2V1] = PPP_OP_SRC_CHROMA_H2V1,
 	[MDP_YCRYCB_H2V1] = PPP_OP_SRC_CHROMA_H2V1,
@@ -109,6 +115,7 @@
 	[MDP_Y_CBCR_H2V1] = 1,
 	[MDP_Y_CBCR_H2V2] = 1,
 	[MDP_Y_CBCR_H2V2_ADRENO] = 1,
+	[MDP_Y_CBCR_H2V2_VENUS] = 1,
 	[MDP_Y_CRCB_H2V1] = 1,
 	[MDP_Y_CRCB_H2V2] = 1,
 	[MDP_YCRYCB_H2V1] = 2,
diff --git a/drivers/video/msm/mdss/mdp3_ppp_hwio.c b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
index 309effc..199387f 100644
--- a/drivers/video/msm/mdss/mdp3_ppp_hwio.c
+++ b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
@@ -57,6 +57,8 @@
 	int64_t Od;
 	int64_t Odprime;
 	int64_t Oreq;
+	int64_t init_phase_temp;
+	int64_t delta;
 	uint32_t mult;
 
 	/*
@@ -149,7 +151,24 @@
 				Oreq = (Osprime & int_mask) - one;
 
 				/* calculate initial phase */
-				init_phase = (int)((Osprime - Oreq) >> 4);
+				init_phase_temp = Osprime - Oreq;
+				delta = ((int64_t) (org) << PQF_PLUS_4) - Oreq;
+				init_phase_temp -= delta;
+
+				/* limit to valid range before the left shift */
+				delta = (init_phase_temp & (1LL << 63)) ?
+						4 : -4;
+				delta <<= PQF_PLUS_4;
+				while (abs((int)(init_phase_temp >>
+							PQF_PLUS_4)) > 4)
+					init_phase_temp += delta;
+
+				/*
+				 * right shift to account for extra bits of
+				 * precision
+				 */
+				init_phase = (int)(init_phase_temp >> 4);
+
 			}
 		} else {
 			/*
@@ -181,7 +200,18 @@
 			Oreq = (Osprime & int_mask) - one;
 
 			/* calculate initial phase */
-			init_phase = (int)((Osprime - Oreq) >> 4);
+			init_phase_temp = Osprime - Oreq;
+			delta = ((int64_t) (org) << PQF_PLUS_4) - Oreq;
+			init_phase_temp -= delta;
+
+			/* limit to valid range before the left shift */
+			delta = (init_phase_temp & (1LL << 63)) ? 4 : -4;
+			delta <<= PQF_PLUS_4;
+			while (abs((int)(init_phase_temp >> PQF_PLUS_4)) > 4)
+				init_phase_temp += delta;
+
+			/* right shift to account for extra bits of precision */
+			init_phase = (int)(init_phase_temp >> 4);
 		}
 	}
 
@@ -331,13 +361,43 @@
 	return rgb;
 }
 
-static uint8_t *mdp_adjust_rot_addr(struct ppp_blit_op *iBuf,
+uint8_t *mdp_bg_adjust_rot_addr(struct ppp_blit_op *iBuf,
+	uint8_t *addr, uint32_t bpp, uint32_t uv)
+{
+	uint32_t dest_ystride = iBuf->bg.prop.width * bpp;
+	uint32_t h_slice = 1, min_val;
+
+	if (uv && ((iBuf->bg.color_fmt == MDP_Y_CBCR_H2V2) ||
+		(iBuf->bg.color_fmt == MDP_Y_CRCB_H2V2)))
+		h_slice = 2;
+
+	if (((iBuf->mdp_op & MDPOP_ROT90) == MDPOP_ROT90) ^
+		((iBuf->mdp_op & MDPOP_LR) == MDPOP_LR)) {
+		min_val = (iBuf->bg.roi.width + iBuf->bg.roi.x) % 16;
+		if (!min_val)
+			min_val = 16;
+		addr +=
+		    (iBuf->bg.roi.width -
+			    MIN(min_val, iBuf->bg.roi.width)) * bpp;
+	}
+	if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) {
+		min_val = (iBuf->bg.roi.height + iBuf->bg.roi.y) % 16;
+		if (!min_val)
+			min_val = 16;
+		addr +=
+			((iBuf->bg.roi.height -
+			MIN(min_val, iBuf->bg.roi.height))/h_slice) *
+			dest_ystride;
+	}
+
+	return addr;
+}
+
+uint8_t *mdp_dst_adjust_rot_addr(struct ppp_blit_op *iBuf,
 	uint8_t *addr, uint32_t bpp, uint32_t uv)
 {
 	uint32_t dest_ystride = iBuf->dst.prop.width * bpp;
 	uint32_t h_slice = 1;
-	if (0)
-		return 0;
 
 	if (uv && ((iBuf->dst.color_fmt == MDP_Y_CBCR_H2V2) ||
 		(iBuf->dst.color_fmt == MDP_Y_CRCB_H2V2)))
@@ -350,16 +410,10 @@
 			    MIN(16, iBuf->dst.roi.width)) * bpp;
 	}
 	if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) {
-		if (1) {
-			addr +=
-				((iBuf->dst.roi.height -
-				MIN(16, iBuf->dst.roi.height))/h_slice) *
-				dest_ystride;
-		} else {
-			addr +=
-			(iBuf->dst.roi.width -
-				MIN(16, iBuf->dst.roi.width)) * bpp;
-		}
+		addr +=
+			((iBuf->dst.roi.height -
+			MIN(16, iBuf->dst.roi.height))/h_slice) *
+			dest_ystride;
 	}
 
 	return addr;
@@ -376,17 +430,22 @@
 
 	if (img->color_fmt == MDP_Y_CBCR_H2V2_ADRENO && layer == 0)
 		img->p0 += (x + y * ALIGN(width, 32)) * bpp;
+	else if (img->color_fmt == MDP_Y_CBCR_H2V2_VENUS && layer == 0)
+		img->p0 += (x + y * ALIGN(width, 128)) * bpp;
 	else
 		img->p0 += (x + y * width) * bpp;
-	if (layer != 0)
-		img->p0 = mdp_adjust_rot_addr(blit_op, img->p0, bpp, 0);
+	if (layer == 1)
+		img->p0 = mdp_bg_adjust_rot_addr(blit_op, img->p0, bpp, 0);
+	else if (layer == 2)
+		img->p0 = mdp_dst_adjust_rot_addr(blit_op, img->p0, bpp, 0);
 
 	if (img->p1) {
 		/*
 		 * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now
 		 * we need to shift x direction same as y dir for offsite
 		 */
-		if (img->color_fmt == MDP_Y_CBCR_H2V2_ADRENO
+		if ((img->color_fmt == MDP_Y_CBCR_H2V2_ADRENO ||
+				img->color_fmt == MDP_Y_CBCR_H2V2_VENUS)
 							&& layer == 0)
 			img->p1 += ((x / h_slice) * h_slice + ((y == 0) ? 0 :
 			(((y + 1) / v_slice - 1) * (ALIGN(width/2, 32) * 2))))
@@ -394,8 +453,14 @@
 		else
 			img->p1 += ((x / h_slice) * h_slice +
 			((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
-		if (layer != 0)
-			img->p1 = mdp_adjust_rot_addr(blit_op, img->p1, bpp, 1);
+
+		if (layer == 1) {
+			img->p0 = mdp_bg_adjust_rot_addr(blit_op,
+					img->p0, bpp, 0);
+		} else if (layer == 2) {
+			img->p0 = mdp_dst_adjust_rot_addr(blit_op,
+					img->p0, bpp, 0);
+		}
 	}
 }
 
@@ -678,6 +743,7 @@
 
 	case MDP_Y_CBCR_H2V2:
 	case MDP_Y_CBCR_H2V2_ADRENO:
+	case MDP_Y_CBCR_H2V2_VENUS:
 	case MDP_Y_CRCB_H2V2:
 		er->chroma_interp_point_left = er->luma_interp_point_left >> 1;
 		er->chroma_interp_point_right =
@@ -716,6 +782,7 @@
 			break;
 		case MDP_Y_CBCR_H2V2:
 		case MDP_Y_CBCR_H2V2_ADRENO:
+		case MDP_Y_CBCR_H2V2_VENUS:
 		case MDP_Y_CRCB_H2V2:
 			/*
 			 * cosite in horizontal dir, and offsite in vertical dir
@@ -1044,7 +1111,6 @@
 	}
 
 	if (*pppop_reg_ptr & PPP_OP_BLEND_ON) {
-		blit_op->bg = blit_op->dst;
 		config_ppp_background(&blit_op->bg);
 
 		if (blit_op->dst.color_fmt == MDP_YCRYCB_H2V1) {
@@ -1107,6 +1173,7 @@
 	switch (blit_op->src.color_fmt) {
 	case MDP_Y_CBCR_H2V2:
 	case MDP_Y_CBCR_H2V2_ADRENO:
+	case MDP_Y_CBCR_H2V2_VENUS:
 	case MDP_Y_CRCB_H2V2:
 		sh_slice = sv_slice = 2;
 		break;
@@ -1134,6 +1201,10 @@
 		blit_op->src.stride0 = ALIGN(blit_op->src.prop.width, 32) *
 			ppp_bpp(blit_op->src.color_fmt);
 		blit_op->src.stride1 = 2 * ALIGN(blit_op->src.prop.width/2, 32);
+	} else if (blit_op->src.color_fmt == MDP_Y_CBCR_H2V2_VENUS) {
+		blit_op->src.stride0 = ALIGN(blit_op->src.prop.width, 128)  *
+			ppp_bpp(blit_op->src.color_fmt);
+		blit_op->src.stride1 = blit_op->src.stride0;
 	} else {
 		blit_op->src.stride0 = blit_op->src.prop.width *
 			ppp_bpp(blit_op->src.color_fmt);
@@ -1152,9 +1223,11 @@
 		blit_op->dst.p1 = NULL;
 	}
 
+	blit_op->bg = blit_op->dst;
 	/* Jumping from Y-Plane to Chroma Plane */
 	/* first pixel addr calculation */
 	mdp_adjust_start_addr(blit_op, &blit_op->src, sv_slice, sh_slice, 0);
+	mdp_adjust_start_addr(blit_op, &blit_op->bg, dv_slice, dh_slice, 1);
 	mdp_adjust_start_addr(blit_op, &blit_op->dst, dv_slice, dh_slice, 2);
 
 	config_ppp_scale(blit_op, &ppp_operation_reg);
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 078960b..840af17 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -89,6 +89,7 @@
 
 	u32 smp_mb_cnt;
 	u32 smp_mb_size;
+	u32 smp_mb_per_pipe;
 
 	u32 rot_block_size;
 
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index fb0e8ba..3b0cd20 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -31,9 +31,7 @@
 
 static int mdss_dsi_regulator_init(struct platform_device *pdev)
 {
-	int ret = 0;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
-	struct dsi_drv_cm_data *dsi_drv = NULL;
 
 	if (!pdev) {
 		pr_err("%s: invalid input\n", __func__);
@@ -46,59 +44,9 @@
 		return -EINVAL;
 	}
 
-	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->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;
+	return msm_dss_config_vreg(&pdev->dev,
+			ctrl_pdata->power_data.vreg_config,
+			ctrl_pdata->power_data.num_vreg, 1);
 }
 
 static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata, int enable)
@@ -108,7 +56,8 @@
 
 	if (pdata == NULL) {
 		pr_err("%s: Invalid input data\n", __func__);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto error;
 	}
 
 	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
@@ -116,71 +65,13 @@
 	pr_debug("%s: enable=%d\n", __func__, enable);
 
 	if (enable) {
-		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 = 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 vregs.rc=%d\n",
+				__func__, ret);
+			goto error;
 		}
 
 		if (pdata->panel_info.panel_power_on == 0)
@@ -190,65 +81,16 @@
 
 		mdss_dsi_panel_reset(pdata, 0);
 
-		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).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_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 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;
-			}
+		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 vregs.rc=%d\n",
+				__func__, ret);
 		}
 	}
-	return 0;
+error:
+	return ret;
 }
 
 static void mdss_dsi_put_dt_vreg_data(struct device *dev,
@@ -269,10 +111,9 @@
 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;
+	int i = 0, rc = 0;
+	u32 tmp = 0;
+	struct device_node *of_node = NULL, *supply_node = NULL;
 
 	if (!dev || !mp) {
 		pr_err("%s: invalid input\n", __func__);
@@ -283,94 +124,131 @@
 	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);
+	for_each_child_of_node(of_node, supply_node) {
+		if (!strncmp(supply_node->name, "qcom,platform-supply-entry",
+						26))
+			++mp->num_vreg;
 	}
-
-	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 {
+	if (mp->num_vreg == 0) {
 		pr_debug("%s: no vreg\n", __func__);
-		return 0;
+		goto novreg;
+	} else {
+		pr_debug("%s: vreg found. count=%d\n", __func__, mp->num_vreg);
 	}
 
-	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__);
+	mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) *
+		mp->num_vreg, GFP_KERNEL);
+	if (!mp->vreg_config) {
+		pr_err("%s: can't alloc vreg 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);
+	for_each_child_of_node(of_node, supply_node) {
+		if (!strncmp(supply_node->name, "qcom,platform-supply-entry",
+						26)) {
+			const char *st = NULL;
+			/* vreg-name */
+			rc = of_property_read_string(supply_node,
+				"qcom,supply-name", &st);
+			if (rc) {
+				pr_err("%s: error reading name. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			snprintf(mp->vreg_config[i].vreg_name,
+				ARRAY_SIZE((mp->vreg_config[i].vreg_name)),
+				"%s", st);
+			/* vreg-min-voltage */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-min-voltage", &tmp);
+			if (rc) {
+				pr_err("%s: error reading min volt. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].min_voltage = tmp;
 
-		/* 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 */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-max-voltage", &tmp);
+			if (rc) {
+				pr_err("%s: error reading max volt. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].max_voltage = tmp;
 
-		/* 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];
+			/* enable-load */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-enable-load", &tmp);
+			if (rc) {
+				pr_err("%s: error reading enable load. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].enable_load = tmp;
 
-		/* 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].peak_current = val_array[i];
+			/* disable-load */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-disable-load", &tmp);
+			if (rc) {
+				pr_err("%s: error reading disable load. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].disable_load = tmp;
 
-		pr_debug("%s: %s min=%d, max=%d, pc=%d\n", __func__,
-			mp->vreg_config[i].vreg_name,
-			mp->vreg_config[i].min_voltage,
-			mp->vreg_config[i].max_voltage,
-			mp->vreg_config[i].peak_current);
+			/* pre-sleep */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-pre-on-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error reading supply pre sleep value. rc=%d\n",
+					__func__, rc);
+			}
+			mp->vreg_config[i].pre_on_sleep = (!rc ? tmp : 0);
+
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-pre-off-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error reading supply pre sleep value. rc=%d\n",
+					__func__, rc);
+			}
+			mp->vreg_config[i].pre_off_sleep = (!rc ? tmp : 0);
+
+			/* post-sleep */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-post-on-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error reading supply post sleep value. rc=%d\n",
+					__func__, rc);
+			}
+			mp->vreg_config[i].post_on_sleep = (!rc ? tmp : 0);
+
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-post-off-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error reading supply post sleep value. rc=%d\n",
+					__func__, rc);
+			}
+			mp->vreg_config[i].post_off_sleep = (!rc ? tmp : 0);
+
+			pr_debug("%s: %s min=%d, max=%d, enable=%d, disable=%d, preonsleep=%d, postonsleep=%d, preoffsleep=%d, postoffsleep=%d\n",
+				__func__,
+				mp->vreg_config[i].vreg_name,
+				mp->vreg_config[i].min_voltage,
+				mp->vreg_config[i].max_voltage,
+				mp->vreg_config[i].enable_load,
+				mp->vreg_config[i].disable_load,
+				mp->vreg_config[i].pre_on_sleep,
+				mp->vreg_config[i].post_on_sleep,
+				mp->vreg_config[i].pre_off_sleep,
+				mp->vreg_config[i].post_off_sleep
+				);
+			++i;
+		}
 	}
 
-	devm_kfree(dev, val_array);
-
 	return rc;
 
 error:
@@ -378,10 +256,9 @@
 		devm_kfree(dev, mp->vreg_config);
 		mp->vreg_config = NULL;
 	}
+novreg:
 	mp->num_vreg = 0;
 
-	if (val_array)
-		devm_kfree(dev, val_array);
 	return rc;
 }
 
@@ -937,14 +814,14 @@
 			      struct mdss_panel_common_pdata *panel_data)
 {
 	struct mipi_panel_info *mipi;
-	int rc;
+	int rc, i, len;
 	u8 lanes = 0, bpp;
-	u32 h_period, v_period, dsi_pclk_rate;
+	u32 h_period, v_period, dsi_pclk_rate, tmp[9];
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata;
 	struct device_node *dsi_ctrl_np = NULL;
 	struct platform_device *ctrl_pdev = NULL;
-	bool broadcast;
 	bool cont_splash_enabled = false;
+	const char *data;
 
 	h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
 			+ (panel_data->panel_info.lcdc.h_back_porch)
@@ -1010,7 +887,7 @@
 	mipi->dsi_pclk_rate = dsi_pclk_rate;
 
 	dsi_ctrl_np = of_parse_phandle(pdev->dev.of_node,
-				       "qcom,dsi-ctrl-phandle", 0);
+				"qcom,mdss-dsi-panel-controller", 0);
 	if (!dsi_ctrl_np) {
 		pr_err("%s: Dsi controller node not initialized\n", __func__);
 		return -EPROBE_DEFER;
@@ -1031,13 +908,57 @@
 		return rc;
 	}
 
-	broadcast = of_property_read_bool(pdev->dev.of_node,
-					  "qcom,mdss-pan-broadcast-mode");
-	if (broadcast)
-		ctrl_pdata->shared_pdata.broadcast_enable = 1;
+	data = of_get_property(ctrl_pdev->dev.of_node,
+		"qcom,platform-strength-ctrl", &len);
+	if ((!data) || (len != 2)) {
+		pr_err("%s:%d, Unable to read Phy Strength ctrl settings",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+	(panel_data->panel_info.mipi.dsi_phy_db)->strength[0] = data[0];
+	(panel_data->panel_info.mipi.dsi_phy_db)->strength[1] = data[1];
 
-	ctrl_pdata->disp_en_gpio = of_get_named_gpio(pdev->dev.of_node,
-						     "qcom,enable-gpio", 0);
+	data = of_get_property(ctrl_pdev->dev.of_node,
+		"qcom,platform-regulator-settings", &len);
+	if ((!data) || (len != 7)) {
+		pr_err("%s:%d, Unable to read Phy regulator settings",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+	for (i = 0; i < len; i++) {
+		(panel_data->panel_info.mipi.dsi_phy_db)->regulator[i]
+			= data[i];
+	}
+
+	data = of_get_property(ctrl_pdev->dev.of_node,
+		"qcom,platform-bist-ctrl", &len);
+	if ((!data) || (len != 6)) {
+		pr_err("%s:%d, Unable to read Phy Bist Ctrl settings",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+	for (i = 0; i < len; i++) {
+		(panel_data->panel_info.mipi.dsi_phy_db)->bistCtrl[i]
+			= data[i];
+	}
+
+	data = of_get_property(ctrl_pdev->dev.of_node,
+		"qcom,platform-lane-config", &len);
+	if ((!data) || (len != 45)) {
+		pr_err("%s:%d, Unable to read Phy lane configure settings",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+	for (i = 0; i < len; i++) {
+		(panel_data->panel_info.mipi.dsi_phy_db)->laneCfg[i] =
+			data[i];
+	}
+
+	ctrl_pdata->shared_pdata.broadcast_enable = of_property_read_bool(
+		pdev->dev.of_node, "qcom,mdss-dsi-panel-broadcast-mode");
+
+	ctrl_pdata->disp_en_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+		"qcom,platform-enable-gpio", 0);
 	if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
 		pr_err("%s:%d, Disp_en gpio not specified\n",
 						__func__, __LINE__);
@@ -1051,8 +972,8 @@
 		}
 	}
 
-	ctrl_pdata->disp_te_gpio = of_get_named_gpio(pdev->dev.of_node,
-						     "qcom,te-gpio", 0);
+	ctrl_pdata->disp_te_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+						"qcom,platform-te-gpio", 0);
 	if (!gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
 		pr_err("%s:%d, Disp_te gpio not specified\n",
 						__func__, __LINE__);
@@ -1089,9 +1010,17 @@
 					ctrl_pdata->disp_te_gpio);
 	}
 
+	rc = of_property_read_u32_array(ctrl_pdev->dev.of_node,
+		"qcom,platform-reset-sequence", tmp, MDSS_DSI_RST_SEQ_LEN);
+	if (rc)
+		pr_err("%s:%d, unable to read gpio reset sequence\n",
+						__func__, __LINE__);
+	else
+		for (i = 0; i < MDSS_DSI_RST_SEQ_LEN; ++i)
+			ctrl_pdata->rst_seq[i] = tmp[i];
 
-	ctrl_pdata->rst_gpio = of_get_named_gpio(pdev->dev.of_node,
-						 "qcom,rst-gpio", 0);
+	ctrl_pdata->rst_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+			 "qcom,platform-reset-gpio", 0);
 	if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
 		pr_err("%s:%d, reset gpio not specified\n",
 						__func__, __LINE__);
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 8a8e4ca..2603648 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -194,6 +194,8 @@
 
 #define MDSS_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align  */
 
+#define MDSS_DSI_RST_SEQ_LEN 6
+
 struct dsi_buf {
 	u32 *hdr;	/* dsi host header */
 	char *start;	/* buffer start addr */
@@ -346,6 +348,7 @@
 	u32 pclk_rate;
 	u32 byte_clk_rate;
 	struct dss_module_power power_data;
+	int rst_seq[MDSS_DSI_RST_SEQ_LEN];
 	u32 dsi_irq_mask;
 	struct mdss_hw *dsi_hw;
 
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 2f29b3d..5f5084d 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -44,6 +44,14 @@
 
 void mdss_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl)
 {
+	if (ctrl->shared_pdata.broadcast_enable)
+		if (ctrl->panel_data.panel_info.pdest
+					== DISPLAY_1) {
+			pr_debug("%s: Broadcast mode enabled.\n",
+				 __func__);
+			left_ctrl_pdata = ctrl;
+		}
+
 	if (ctrl->panel_data.panel_info.pdest == DISPLAY_1) {
 		mdss_dsi0_hw.ptr = (void *)(ctrl);
 		ctrl->dsi_hw = &mdss_dsi0_hw;
@@ -861,13 +869,6 @@
 	else
 		MIPI_OUTP(ctrl_pdata->ctrl_base + 0x3C, 0x14000000);
 
-	if (ctrl_pdata->shared_pdata.broadcast_enable)
-		if (pdata->panel_info.pdest == DISPLAY_1) {
-			pr_debug("%s: Broadcast mode enabled.\n",
-				 __func__);
-			left_ctrl_pdata = ctrl_pdata;
-		}
-
 	data = 0;
 	if (pinfo->te_sel)
 		data |= BIT(31);
@@ -1209,6 +1210,8 @@
 {
 	u32 dsi_ctrl, data;
 	int video_mode;
+	u32 left_dsi_ctrl = 0;
+	bool left_ctrl_restore = false;
 
 	if (ctrl->shared_pdata.broadcast_enable) {
 		if (ctrl->ndx == DSI_CTRL_0) {
@@ -1221,13 +1224,15 @@
 	if (ctrl->shared_pdata.broadcast_enable) {
 		if ((ctrl->ndx == DSI_CTRL_1)
 		  && (left_ctrl_pdata != NULL)) {
-			dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
+			left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
 								+ 0x0004);
-			video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+			video_mode =
+				left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
 			if (video_mode) {
-				data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+				data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */
 				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
 						data);
+				left_ctrl_restore = true;
 			}
 		}
 	}
@@ -1246,6 +1251,10 @@
 
 	mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt);
 
+	if (left_ctrl_restore)
+		MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
+					left_dsi_ctrl); /*restore */
+
 	if (video_mode)
 		MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
 					dsi_ctrl); /* restore */
@@ -1280,6 +1289,45 @@
 	struct dsi_buf *tp, *rp;
 	int no_max_pkt_size;
 	char cmd;
+	u32 dsi_ctrl, data;
+	int video_mode;
+	u32 left_dsi_ctrl = 0;
+	bool left_ctrl_restore = false;
+
+	if (ctrl->shared_pdata.broadcast_enable) {
+		if (ctrl->ndx == DSI_CTRL_0) {
+			pr_debug("%s: Broadcast mode. 1st ctrl\n",
+				 __func__);
+			return 0;
+		}
+	}
+
+	if (ctrl->shared_pdata.broadcast_enable) {
+		if ((ctrl->ndx == DSI_CTRL_1)
+		  && (left_ctrl_pdata != NULL)) {
+			left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
+								+ 0x0004);
+			video_mode = left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+			if (video_mode) {
+				data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */
+				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
+						data);
+				left_ctrl_restore = true;
+			}
+		}
+	}
+
+	/* turn on cmd mode
+	* for video mode, do not send cmds more than
+	* one pixel line, since it only transmit it
+	* during BLLP.
+	*/
+	dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
+	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+	if (video_mode) {
+		data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+		MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
+	}
 
 	no_max_pkt_size = rx_flags & CMD_REQ_NO_MAX_PKT_SIZE;
 	if (no_max_pkt_size)
@@ -1378,6 +1426,13 @@
 		break;
 	}
 
+	if (left_ctrl_restore)
+		MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
+					left_dsi_ctrl); /*restore */
+	if (video_mode)
+		MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
+					dsi_ctrl); /* restore */
+
 	return rp->len;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 05a84e3..9a019f9 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -158,6 +158,7 @@
 void mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
 {
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+	int i;
 
 	if (pdata == NULL) {
 		pr_err("%s: Invalid input data\n", __func__);
@@ -181,12 +182,11 @@
 	pr_debug("%s: enable = %d\n", __func__, enable);
 
 	if (enable) {
-		gpio_set_value((ctrl_pdata->rst_gpio), 1);
-		msleep(20);
-		gpio_set_value((ctrl_pdata->rst_gpio), 0);
-		udelay(200);
-		gpio_set_value((ctrl_pdata->rst_gpio), 1);
-		msleep(20);
+		for (i = 0; i < MDSS_DSI_RST_SEQ_LEN; ++i) {
+			gpio_set_value((ctrl_pdata->rst_gpio),
+				ctrl_pdata->rst_seq[i]);
+			msleep(ctrl_pdata->rst_seq[++i]);
+		}
 		if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
 			gpio_set_value((ctrl_pdata->disp_en_gpio), 1);
 		if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
@@ -348,11 +348,11 @@
 		len -= dchdr->dlen;
 	}
 
-	pcmds->link_state = DSI_LP_MODE; /* default */
-
 	data = of_get_property(np, link_key, NULL);
-	if (!strncmp(data, "DSI_HS_MODE", 11))
+	if (!strncmp(data, "dsi_hs_mode", 11))
 		pcmds->link_state = DSI_HS_MODE;
+	else
+		pcmds->link_state = DSI_LP_MODE;
 
 	pr_debug("%s: dcs_cmd=%x len=%d, cmd_cnt=%d link_state=%d\n", __func__,
 		pcmds->buf[0], pcmds->blen, pcmds->cmd_cnt, pcmds->link_state);
@@ -361,44 +361,188 @@
 }
 
 
+static int mdss_panel_dt_get_dst_fmt(u32 bpp, char mipi_mode, u32 pixel_packing,
+				char *dst_format)
+{
+	int rc = 0;
+	switch (bpp) {
+	case 3:
+		*dst_format = DSI_CMD_DST_FORMAT_RGB111;
+		break;
+	case 8:
+		*dst_format = DSI_CMD_DST_FORMAT_RGB332;
+		break;
+	case 12:
+		*dst_format = DSI_CMD_DST_FORMAT_RGB444;
+		break;
+	case 16:
+		switch (mipi_mode) {
+		case DSI_VIDEO_MODE:
+			*dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
+			break;
+		case DSI_CMD_MODE:
+			*dst_format = DSI_CMD_DST_FORMAT_RGB565;
+			break;
+		default:
+			*dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
+			break;
+		}
+		break;
+	case 18:
+		switch (mipi_mode) {
+		case DSI_VIDEO_MODE:
+			if (pixel_packing == 0)
+				*dst_format = DSI_VIDEO_DST_FORMAT_RGB666;
+			else
+				*dst_format = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE;
+			break;
+		case DSI_CMD_MODE:
+			*dst_format = DSI_CMD_DST_FORMAT_RGB666;
+			break;
+		default:
+			if (pixel_packing == 0)
+				*dst_format = DSI_VIDEO_DST_FORMAT_RGB666;
+			else
+				*dst_format = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE;
+			break;
+		}
+		break;
+	case 24:
+		switch (mipi_mode) {
+		case DSI_VIDEO_MODE:
+			*dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+			break;
+		case DSI_CMD_MODE:
+			*dst_format = DSI_CMD_DST_FORMAT_RGB888;
+			break;
+		default:
+			*dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+			break;
+		}
+		break;
+	default:
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
+
+static int mdss_dsi_parse_fbc_params(struct device_node *np,
+				struct mdss_panel_info *panel_info)
+{
+	int rc, fbc_enabled = 0;
+	u32 tmp;
+
+	fbc_enabled = of_property_read_bool(np,	"qcom,mdss-dsi-fbc-enable");
+	if (fbc_enabled) {
+		pr_debug("%s:%d FBC panel enabled.\n", __func__, __LINE__);
+		panel_info->fbc.enabled = 1;
+		rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bpp", &tmp);
+		panel_info->fbc.target_bpp =	(!rc ? tmp : panel_info->bpp);
+		rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-packing",
+				&tmp);
+		panel_info->fbc.comp_mode = (!rc ? tmp : 0);
+		panel_info->fbc.qerr_enable = of_property_read_bool(np,
+			"qcom,mdss-dsi-fbc-quant-error");
+		rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bias", &tmp);
+		panel_info->fbc.cd_bias = (!rc ? tmp : 0);
+		panel_info->fbc.pat_enable = of_property_read_bool(np,
+				"qcom,mdss-dsi-fbc-pat-mode");
+		panel_info->fbc.vlc_enable = of_property_read_bool(np,
+				"qcom,mdss-dsi-fbc-vlc-mode");
+		panel_info->fbc.bflc_enable = of_property_read_bool(np,
+				"qcom,mdss-dsi-fbc-bflc-mode");
+		rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-h-line-budget",
+				&tmp);
+		panel_info->fbc.line_x_budget = (!rc ? tmp : 0);
+		rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-budget-ctrl",
+				&tmp);
+		panel_info->fbc.block_x_budget = (!rc ? tmp : 0);
+		rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-block-budget",
+				&tmp);
+		panel_info->fbc.block_budget = (!rc ? tmp : 0);
+		rc = of_property_read_u32(np,
+				"qcom,mdss-dsi-fbc-lossless-threshold", &tmp);
+		panel_info->fbc.lossless_mode_thd = (!rc ? tmp : 0);
+		rc = of_property_read_u32(np,
+				"qcom,mdss-dsi-fbc-lossy-threshold", &tmp);
+		panel_info->fbc.lossy_mode_thd = (!rc ? tmp : 0);
+		rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-rgb-threshold",
+				&tmp);
+		panel_info->fbc.lossy_rgb_thd = (!rc ? tmp : 0);
+		rc = of_property_read_u32(np,
+				"qcom,mdss-dsi-fbc-lossy-mode-idx", &tmp);
+		panel_info->fbc.lossy_mode_idx = (!rc ? tmp : 0);
+	} else {
+		pr_debug("%s:%d Panel does not support FBC.\n",
+				__func__, __LINE__);
+		panel_info->fbc.enabled = 0;
+		panel_info->fbc.target_bpp =
+			panel_info->bpp;
+	}
+	return 0;
+}
+
+
 static int mdss_panel_parse_dt(struct platform_device *pdev,
-			       struct mdss_panel_common_pdata *panel_data)
+			      struct mdss_panel_common_pdata *panel_data)
 {
 	struct device_node *np = pdev->dev.of_node;
-	u32 res[6], tmp;
-	u32 fbc_res[7];
+	u32 tmp;
 	int rc, i, len;
 	const char *data;
-	static const char *bl_ctrl_type, *pdest;
-	bool fbc_enabled = false;
+	static const char *pdest;
 
-	rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-width", &tmp);
 	if (rc) {
-		pr_err("%s:%d, panel resolution not specified\n",
+		pr_err("%s:%d, panel width not specified\n",
 						__func__, __LINE__);
 		return -EINVAL;
 	}
-	panel_data->panel_info.xres = (!rc ? res[0] : 640);
-	panel_data->panel_info.yres = (!rc ? res[1] : 480);
+	panel_data->panel_info.xres = (!rc ? tmp : 640);
 
-	rc = of_property_read_u32_array(np, "qcom,mdss-pan-active-res", res, 2);
-	if (rc == 0) {
-		panel_data->panel_info.lcdc.xres_pad =
-			panel_data->panel_info.xres - res[0];
-		panel_data->panel_info.lcdc.yres_pad =
-			panel_data->panel_info.yres - res[1];
-	}
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-bpp", &tmp);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-height", &tmp);
 	if (rc) {
-		pr_err("%s:%d, panel bpp not specified\n",
+		pr_err("%s:%d, panel height not specified\n",
 						__func__, __LINE__);
 		return -EINVAL;
 	}
+	panel_data->panel_info.yres = (!rc ? tmp : 480);
+
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-left-border", &tmp);
+	panel_data->panel_info.lcdc.xres_pad = (!rc ? tmp : 0);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-right-border", &tmp);
+	if (!rc)
+		panel_data->panel_info.lcdc.xres_pad += tmp;
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-v-top-border", &tmp);
+	panel_data->panel_info.lcdc.yres_pad = (!rc ? tmp : 0);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-v-bottom-border", &tmp);
+	if (!rc)
+		panel_data->panel_info.lcdc.yres_pad += tmp;
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-bpp", &tmp);
+	if (rc) {
+		pr_err("%s:%d, bpp not specified\n", __func__, __LINE__);
+		return -EINVAL;
+	}
 	panel_data->panel_info.bpp = (!rc ? tmp : 24);
-
+	panel_data->panel_info.mipi.mode = DSI_VIDEO_MODE;
+	data = of_get_property(np, "qcom,mdss-dsi-panel-type", NULL);
+	if (data && !strncmp(data, "dsi_cmd_mode", 12))
+		panel_data->panel_info.mipi.mode = DSI_CMD_MODE;
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-pixel-packing", &tmp);
+	tmp = (!rc ? tmp : 0);
+	rc = mdss_panel_dt_get_dst_fmt(panel_data->panel_info.bpp,
+		panel_data->panel_info.mipi.mode, tmp,
+		&(panel_data->panel_info.mipi.dst_format));
+	if (rc) {
+		pr_debug("%s: problem determining dst format. Set Default\n",
+			__func__);
+		panel_data->panel_info.mipi.dst_format =
+			DSI_VIDEO_DST_FORMAT_RGB888;
+	}
 	pdest = of_get_property(pdev->dev.of_node,
-				"qcom,mdss-pan-dest", NULL);
+		"qcom,mdss-dsi-panel-destination", NULL);
 	if (strlen(pdest) != 9) {
 		pr_err("%s: Unknown pdest specified\n", __func__);
 		return -EINVAL;
@@ -412,141 +556,132 @@
 							__func__);
 		panel_data->panel_info.pdest = DISPLAY_1;
 	}
-
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-porch-values", res, 6);
-	panel_data->panel_info.lcdc.h_back_porch = (!rc ? res[0] : 6);
-	panel_data->panel_info.lcdc.h_pulse_width = (!rc ? res[1] : 2);
-	panel_data->panel_info.lcdc.h_front_porch = (!rc ? res[2] : 6);
-	panel_data->panel_info.lcdc.v_back_porch = (!rc ? res[3] : 6);
-	panel_data->panel_info.lcdc.v_pulse_width = (!rc ? res[4] : 2);
-	panel_data->panel_info.lcdc.v_front_porch = (!rc ? res[5] : 6);
-
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-front-porch", &tmp);
+	panel_data->panel_info.lcdc.h_front_porch = (!rc ? tmp : 6);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-back-porch", &tmp);
+	panel_data->panel_info.lcdc.h_back_porch = (!rc ? tmp : 6);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-pulse-width", &tmp);
+	panel_data->panel_info.lcdc.h_pulse_width = (!rc ? tmp : 2);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-sync-skew", &tmp);
+	panel_data->panel_info.lcdc.hsync_skew = (!rc ? tmp : 0);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-v-back-porch", &tmp);
+	panel_data->panel_info.lcdc.v_back_porch = (!rc ? tmp : 6);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-v-front-porch", &tmp);
+	panel_data->panel_info.lcdc.v_front_porch = (!rc ? tmp : 6);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-v-pulse-width", &tmp);
+	panel_data->panel_info.lcdc.v_pulse_width = (!rc ? tmp : 2);
 	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-underflow-clr", &tmp);
+		"qcom,mdss-dsi-underflow-color", &tmp);
 	panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
-
-	bl_ctrl_type = of_get_property(pdev->dev.of_node,
-				  "qcom,mdss-pan-bl-ctrl", NULL);
-	if ((bl_ctrl_type) && (!strncmp(bl_ctrl_type, "bl_ctrl_wled", 12))) {
-		led_trigger_register_simple("bkl-trigger", &bl_led_trigger);
-		pr_debug("%s: SUCCESS-> WLED TRIGGER register\n", __func__);
-
-		panel_data->panel_info.bklt_ctrl = BL_WLED;
-	} else if (!strncmp(bl_ctrl_type, "bl_ctrl_pwm", 11)) {
-		panel_data->panel_info.bklt_ctrl = BL_PWM;
-
-		rc = of_property_read_u32(np, "qcom,pwm-period", &tmp);
-		if (rc) {
-			pr_err("%s:%d, Error, panel pwm_period\n",
+	rc = of_property_read_u32(np,
+		"qcom,mdss-dsi-border-color", &tmp);
+	panel_data->panel_info.lcdc.border_clr = (!rc ? tmp : 0);
+	panel_data->panel_info.bklt_ctrl = UNKNOWN_CTRL;
+	data = of_get_property(np, "qcom,mdss-dsi-bl-pmic-control-type", NULL);
+	if (data) {
+		if (!strncmp(data, "bl_ctrl_wled", 12)) {
+			led_trigger_register_simple("bkl-trigger",
+				&bl_led_trigger);
+			pr_debug("%s: SUCCESS-> WLED TRIGGER register\n",
+				__func__);
+			panel_data->panel_info.bklt_ctrl = BL_WLED;
+		} else if (!strncmp(data, "bl_ctrl_pwm", 11)) {
+			panel_data->panel_info.bklt_ctrl = BL_PWM;
+			rc = of_property_read_u32(np,
+				"qcom,mdss-dsi-bl-pmic-pwm-frequency", &tmp);
+			if (rc) {
+				pr_err("%s:%d, Error, panel pwm_period\n",
 						__func__, __LINE__);
-			return -EINVAL;
-		}
-		panel_data->panel_info.pwm_period = tmp;
-
-		rc = of_property_read_u32(np, "qcom,pwm-lpg-channel", &tmp);
-		if (rc) {
-			pr_err("%s:%d, Error, dsi lpg channel\n",
+				return -EINVAL;
+			}
+			panel_data->panel_info.pwm_period = tmp;
+			rc = of_property_read_u32(np,
+				"qcom,mdss-dsi-bl-pmic-bank-select", &tmp);
+			if (rc) {
+				pr_err("%s:%d, Error, dsi lpg channel\n",
 						__func__, __LINE__);
-			return -EINVAL;
+				return -EINVAL;
+			}
+			panel_data->panel_info.pwm_lpg_chan = tmp;
+			tmp = of_get_named_gpio(np,
+				"qcom,mdss-dsi-pwm-gpio", 0);
+			panel_data->panel_info.pwm_pmic_gpio = tmp;
+		} else if (!strncmp(data, "bl_ctrl_dcs", 11)) {
+			panel_data->panel_info.bklt_ctrl = BL_DCS_CMD;
 		}
-		panel_data->panel_info.pwm_lpg_chan = tmp;
-
-		tmp = of_get_named_gpio(np, "qcom,pwm-pmic-gpio", 0);
-		panel_data->panel_info.pwm_pmic_gpio =  tmp;
-	} else if (!strncmp(bl_ctrl_type, "bl_ctrl_dcs", 11)) {
-		panel_data->panel_info.bklt_ctrl = BL_DCS_CMD;
-	} else {
-		pr_debug("%s: Unknown backlight control\n", __func__);
-		panel_data->panel_info.bklt_ctrl = UNKNOWN_CTRL;
 	}
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-min-level", &tmp);
+	panel_data->panel_info.bl_min = (!rc ? tmp : 0);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-max-level", &tmp);
+	panel_data->panel_info.bl_max = (!rc ? tmp : 255);
 
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-bl-levels", res, 2);
-	panel_data->panel_info.bl_min = (!rc ? res[0] : 0);
-	panel_data->panel_info.bl_max = (!rc ? res[1] : 255);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-interleave-mode", &tmp);
+	panel_data->panel_info.mipi.interleave_mode = (!rc ? tmp : 0);
 
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mode", &tmp);
-	panel_data->panel_info.mipi.mode = (!rc ? tmp : DSI_VIDEO_MODE);
-
-	rc = of_property_read_u32(np, "qcom,mdss-vsync-enable", &tmp);
-	panel_data->panel_info.mipi.vsync_enable = (!rc ? tmp : 0);
-
-	rc = of_property_read_u32(np, "qcom,mdss-hw-vsync-mode", &tmp);
-	panel_data->panel_info.mipi.hw_vsync_mode = (!rc ? tmp : 0);
-
+	panel_data->panel_info.mipi.vsync_enable = of_property_read_bool(np,
+		"qcom,mdss-dsi-te-check-enable");
+	panel_data->panel_info.mipi.hw_vsync_mode = of_property_read_bool(np,
+		"qcom,mdss-dsi-te-using-te-pin");
 
 	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
+		"qcom,mdss-dsi-h-sync-pulse", &tmp);
 	panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
 
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-dsi-h-power-stop", res, 3);
-	panel_data->panel_info.mipi.hbp_power_stop = (!rc ? res[0] : false);
-	panel_data->panel_info.mipi.hsa_power_stop = (!rc ? res[1] : false);
-	panel_data->panel_info.mipi.hfp_power_stop = (!rc ? res[2] : false);
-
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-dsi-bllp-power-stop", res, 2);
-	panel_data->panel_info.mipi.bllp_power_stop =
-					(!rc ? res[0] : false);
-	panel_data->panel_info.mipi.eof_bllp_power_stop =
-					(!rc ? res[1] : false);
-
+	panel_data->panel_info.mipi.hfp_power_stop = of_property_read_bool(np,
+		"qcom,mdss-dsi-hfp-power-mode");
+	panel_data->panel_info.mipi.hsa_power_stop = of_property_read_bool(np,
+		"qcom,mdss-dsi-hsa-power-mode");
+	panel_data->panel_info.mipi.hbp_power_stop = of_property_read_bool(np,
+		"qcom,mdss-dsi-hbp-power-mode");
+	panel_data->panel_info.mipi.bllp_power_stop = of_property_read_bool(np,
+		"qcom,mdss-dsi-bllp-power-mode");
+	panel_data->panel_info.mipi.eof_bllp_power_stop = of_property_read_bool(
+		np, "qcom,mdss-dsi-bllp-eof-power-mode");
 	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-dsi-traffic-mode", &tmp);
+		"qcom,mdss-dsi-traffic-mode", &tmp);
 	panel_data->panel_info.mipi.traffic_mode =
 			(!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
-
 	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-insert-dcs-cmd", &tmp);
+		"qcom,mdss-dsi-te-dcs-command", &tmp);
 	panel_data->panel_info.mipi.insert_dcs_cmd =
 			(!rc ? tmp : 1);
-
 	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-wr-mem-continue", &tmp);
+		"qcom,mdss-dsi-te-v-sync-continue-lines", &tmp);
 	panel_data->panel_info.mipi.wr_mem_continue =
 			(!rc ? tmp : 0x3c);
-
 	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-wr-mem-start", &tmp);
+		"qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line", &tmp);
 	panel_data->panel_info.mipi.wr_mem_start =
 			(!rc ? tmp : 0x2c);
-
 	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-te-sel", &tmp);
+		"qcom,mdss-dsi-te-pin-select", &tmp);
 	panel_data->panel_info.mipi.te_sel =
 			(!rc ? tmp : 1);
-
-	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-dsi-dst-format", &tmp);
-	panel_data->panel_info.mipi.dst_format =
-			(!rc ? tmp : DSI_VIDEO_DST_FORMAT_RGB888);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-vc", &tmp);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-virtual-channel-id", &tmp);
 	panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-rgb-swap", &tmp);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-color-order", &tmp);
 	panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
+	panel_data->panel_info.mipi.data_lane0 = of_property_read_bool(np,
+		"qcom,mdss-dsi-lane-0-state");
+	panel_data->panel_info.mipi.data_lane1 = of_property_read_bool(np,
+		"qcom,mdss-dsi-lane-1-state");
+	panel_data->panel_info.mipi.data_lane2 = of_property_read_bool(np,
+		"qcom,mdss-dsi-lane-2-state");
+	panel_data->panel_info.mipi.data_lane3 = of_property_read_bool(np,
+		"qcom,mdss-dsi-lane-3-state");
 
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-dsi-data-lanes", res, 4);
-	panel_data->panel_info.mipi.data_lane0 = (!rc ? res[0] : true);
-	panel_data->panel_info.mipi.data_lane1 = (!rc ? res[1] : false);
-	panel_data->panel_info.mipi.data_lane2 = (!rc ? res[2] : false);
-	panel_data->panel_info.mipi.data_lane3 = (!rc ? res[3] : false);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dlane-swap", &tmp);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-lane-map", &tmp);
 	panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
 
-	rc = of_property_read_u32_array(np, "qcom,mdss-pan-dsi-t-clk", res, 2);
-	panel_data->panel_info.mipi.t_clk_pre = (!rc ? res[0] : 0x24);
-	panel_data->panel_info.mipi.t_clk_post = (!rc ? res[1] : 0x03);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-pre", &tmp);
+	panel_data->panel_info.mipi.t_clk_pre = (!rc ? tmp : 0x24);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-post", &tmp);
+	panel_data->panel_info.mipi.t_clk_post = (!rc ? tmp : 0x03);
 
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-stream", &tmp);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-stream", &tmp);
 	panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
 
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mdp-tr", &tmp);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-mdp-trigger", &tmp);
 	panel_data->panel_info.mipi.mdp_trigger =
 			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
 	if (panel_data->panel_info.mipi.mdp_trigger > 6) {
@@ -556,7 +691,7 @@
 					DSI_CMD_TRIGGER_SW;
 	}
 
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dma-tr", &tmp);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-dma-trigger", &tmp);
 	panel_data->panel_info.mipi.dma_trigger =
 			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
 	if (panel_data->panel_info.mipi.dma_trigger > 6) {
@@ -565,23 +700,11 @@
 		panel_data->panel_info.mipi.dma_trigger =
 					DSI_CMD_TRIGGER_SW;
 	}
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-frame-rate", &tmp);
 	panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-clk-rate", &tmp);
+	rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-clock-rate", &tmp);
 	panel_data->panel_info.clk_rate = (!rc ? tmp : 0);
-
-	data = of_get_property(np, "qcom,panel-phy-regulatorSettings", &len);
-	if ((!data) || (len != 7)) {
-		pr_err("%s:%d, Unable to read Phy regulator settings",
-		       __func__, __LINE__);
-		goto error;
-	}
-	for (i = 0; i < len; i++)
-		phy_params.regulator[i] = data[i];
-
-	data = of_get_property(np, "qcom,panel-phy-timingSettings", &len);
+	data = of_get_property(np, "qcom,mdss-dsi-panel-timings", &len);
 	if ((!data) || (len != 12)) {
 		pr_err("%s:%d, Unable to read Phy timing settings",
 		       __func__, __LINE__);
@@ -590,87 +713,15 @@
 	for (i = 0; i < len; i++)
 		phy_params.timing[i] = data[i];
 
-	data = of_get_property(np, "qcom,panel-phy-strengthCtrl", &len);
-	if ((!data) || (len != 2)) {
-		pr_err("%s:%d, Unable to read Phy Strength ctrl settings",
-		       __func__, __LINE__);
-		goto error;
-	}
-	phy_params.strength[0] = data[0];
-	phy_params.strength[1] = data[1];
-
-	data = of_get_property(np, "qcom,panel-phy-bistCtrl", &len);
-	if ((!data) || (len != 6)) {
-		pr_err("%s:%d, Unable to read Phy Bist Ctrl settings",
-		       __func__, __LINE__);
-		goto error;
-	}
-	for (i = 0; i < len; i++)
-		phy_params.bistCtrl[i] = data[i];
-
-	data = of_get_property(np, "qcom,panel-phy-laneConfig", &len);
-	if ((!data) || (len != 45)) {
-		pr_err("%s:%d, Unable to read Phy lane configure settings",
-		       __func__, __LINE__);
-		goto error;
-	}
-	for (i = 0; i < len; i++)
-		phy_params.laneCfg[i] = data[i];
-
 	panel_data->panel_info.mipi.dsi_phy_db = &phy_params;
 
-	fbc_enabled = of_property_read_bool(np,
-			"qcom,fbc-enabled");
-	if (fbc_enabled) {
-		pr_debug("%s:%d FBC panel enabled.\n", __func__, __LINE__);
-		panel_data->panel_info.fbc.enabled = 1;
-
-		rc = of_property_read_u32_array(np,
-				"qcom,fbc-mode", fbc_res, 7);
-		panel_data->panel_info.fbc.target_bpp =
-			(!rc ?	fbc_res[0] : panel_data->panel_info.bpp);
-		panel_data->panel_info.fbc.comp_mode = (!rc ? fbc_res[1] : 0);
-		panel_data->panel_info.fbc.qerr_enable =
-			(!rc ? fbc_res[2] : 0);
-		panel_data->panel_info.fbc.cd_bias = (!rc ? fbc_res[3] : 0);
-		panel_data->panel_info.fbc.pat_enable = (!rc ? fbc_res[4] : 0);
-		panel_data->panel_info.fbc.vlc_enable = (!rc ? fbc_res[5] : 0);
-		panel_data->panel_info.fbc.bflc_enable =
-			(!rc ? fbc_res[6] : 0);
-
-		rc = of_property_read_u32_array(np,
-				"qcom,fbc-budget-ctl", fbc_res, 3);
-		panel_data->panel_info.fbc.line_x_budget =
-			(!rc ? fbc_res[0] : 0);
-		panel_data->panel_info.fbc.block_x_budget =
-			(!rc ? fbc_res[1] : 0);
-		panel_data->panel_info.fbc.block_budget =
-			(!rc ? fbc_res[2] : 0);
-
-		rc = of_property_read_u32_array(np,
-				"qcom,fbc-lossy-mode", fbc_res, 4);
-		panel_data->panel_info.fbc.lossless_mode_thd =
-			(!rc ? fbc_res[0] : 0);
-		panel_data->panel_info.fbc.lossy_mode_thd =
-			(!rc ? fbc_res[1] : 0);
-		panel_data->panel_info.fbc.lossy_rgb_thd =
-			(!rc ? fbc_res[2] : 0);
-		panel_data->panel_info.fbc.lossy_mode_idx =
-			(!rc ? fbc_res[3] : 0);
-
-	} else {
-		pr_debug("%s:%d Panel does not support FBC.\n",
-				__func__, __LINE__);
-		panel_data->panel_info.fbc.enabled = 0;
-		panel_data->panel_info.fbc.target_bpp =
-			panel_data->panel_info.bpp;
-	}
+	mdss_dsi_parse_fbc_params(np, &panel_data->panel_info);
 
 	mdss_dsi_parse_dcs_cmds(np, &panel_data->on_cmds,
-		"qcom,panel-on-cmds", "qcom,on-cmds-dsi-state");
+		"qcom,mdss-dsi-on-command", "qcom,mdss-dsi-on-command-state");
 
 	mdss_dsi_parse_dcs_cmds(np, &panel_data->off_cmds,
-		"qcom,panel-off-cmds", "qcom,off-cmds-dsi-state");
+		"qcom,mdss-dsi-off-command", "qcom,mdss-dsi-off-command-state");
 
 	return 0;
 
@@ -683,12 +734,12 @@
 	int rc = 0;
 	static struct mdss_panel_common_pdata vendor_pdata;
 	static const char *panel_name;
-
 	pr_debug("%s:%d, debug info id=%d", __func__, __LINE__, pdev->id);
 	if (!pdev->dev.of_node)
 		return -ENODEV;
 
-	panel_name = of_get_property(pdev->dev.of_node, "label", NULL);
+	panel_name = of_get_property(pdev->dev.of_node,
+		"qcom,mdss-dsi-panel-name", NULL);
 	if (!panel_name)
 		pr_info("%s:%d, panel name not specified\n",
 						__func__, __LINE__);
diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c
index aea2de0..3e0bc6d 100644
--- a/drivers/video/msm/mdss/mdss_edp.c
+++ b/drivers/video/msm/mdss/mdss_edp.c
@@ -24,14 +24,19 @@
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pwm.h>
-
+#include <linux/clk.h>
+#include <linux/spinlock_types.h>
+#include <linux/kthread.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
-
 #include <mach/hardware.h>
 #include <mach/dma.h>
 
+#include "mdss.h"
+#include "mdss_panel.h"
+#include "mdss_mdp.h"
 #include "mdss_edp.h"
+#include "mdss_debug.h"
 
 #define RGB_COMPONENTS		3
 #define VDDA_MIN_UV			1800000	/* uV units */
@@ -39,26 +44,7 @@
 #define VDDA_UA_ON_LOAD		100000	/* uA units */
 #define VDDA_UA_OFF_LOAD	100		/* uA units */
 
-static int mdss_edp_get_base_address(struct mdss_edp_drv_pdata *edp_drv);
-static int mdss_edp_get_mmss_cc_base_address(struct mdss_edp_drv_pdata
-		*edp_drv);
-static int mdss_edp_regulator_init(struct mdss_edp_drv_pdata *edp_drv);
 static int mdss_edp_regulator_on(struct mdss_edp_drv_pdata *edp_drv);
-static int mdss_edp_regulator_off(struct mdss_edp_drv_pdata *edp_drv);
-static int mdss_edp_gpio_panel_en(struct mdss_edp_drv_pdata *edp_drv);
-static int mdss_edp_pwm_config(struct mdss_edp_drv_pdata *edp_drv);
-
-static void mdss_edp_edid2pinfo(struct mdss_edp_drv_pdata *edp_drv);
-static void mdss_edp_fill_edid_data(struct mdss_edp_drv_pdata *edp_drv);
-static void mdss_edp_fill_dpcd_data(struct mdss_edp_drv_pdata *edp_drv);
-
-static int mdss_edp_device_register(struct mdss_edp_drv_pdata *edp_drv);
-
-static void mdss_edp_config_sync(unsigned char *edp_base);
-static void mdss_edp_config_sw_div(unsigned char *edp_base);
-static void mdss_edp_config_static_mdiv(unsigned char *edp_base);
-static void mdss_edp_enable(unsigned char *edp_base, int enable);
-
 /*
  * Init regulator needed for edp, 8974_l12
  */
@@ -256,79 +242,130 @@
 	}
 }
 
-void mdss_edp_config_sync(unsigned char *edp_base)
+void mdss_edp_config_sync(unsigned char *base)
 {
 	int ret = 0;
 
-	ret = edp_read(edp_base + 0xc); /* EDP_CONFIGURATION_CTRL */
+	ret = edp_read(base + 0xc); /* EDP_CONFIGURATION_CTRL */
 	ret &= ~0x733;
 	ret |= (0x55 & 0x733);
-	edp_write(edp_base + 0xc, ret);
-	edp_write(edp_base + 0xc, 0x55); /* EDP_CONFIGURATION_CTRL */
+	edp_write(base + 0xc, ret);
+	edp_write(base + 0xc, 0x55); /* EDP_CONFIGURATION_CTRL */
 }
 
-static void mdss_edp_config_sw_div(unsigned char *edp_base)
+static void mdss_edp_config_sw_div(unsigned char *base)
 {
-	edp_write(edp_base + 0x14, 0x13b); /* EDP_SOFTWARE_MVID */
-	edp_write(edp_base + 0x18, 0x266); /* EDP_SOFTWARE_NVID */
+	edp_write(base + 0x14, 0x13b); /* EDP_SOFTWARE_MVID */
+	edp_write(base + 0x18, 0x266); /* EDP_SOFTWARE_NVID */
 }
 
-static void mdss_edp_config_static_mdiv(unsigned char *edp_base)
+static void mdss_edp_config_static_mdiv(unsigned char *base)
 {
 	int ret = 0;
 
-	ret = edp_read(edp_base + 0xc); /* EDP_CONFIGURATION_CTRL */
-	edp_write(edp_base + 0xc, ret | 0x2); /* EDP_CONFIGURATION_CTRL */
-	edp_write(edp_base + 0xc, 0x57); /* EDP_CONFIGURATION_CTRL */
+	ret = edp_read(base + 0xc); /* EDP_CONFIGURATION_CTRL */
+	edp_write(base + 0xc, ret | 0x2); /* EDP_CONFIGURATION_CTRL */
+	edp_write(base + 0xc, 0x57); /* EDP_CONFIGURATION_CTRL */
 }
 
-static void mdss_edp_enable(unsigned char *edp_base, int enable)
+static void mdss_edp_enable(unsigned char *base, int enable)
 {
-	edp_write(edp_base + 0x8, 0x0); /* EDP_STATE_CTRL */
-	edp_write(edp_base + 0x8, 0x40); /* EDP_STATE_CTRL */
-	edp_write(edp_base + 0x94, enable); /* EDP_TIMING_ENGINE_EN */
-	edp_write(edp_base + 0x4, enable); /* EDP_MAINLINK_CTRL */
+	edp_write(base + 0x8, 0x0); /* EDP_STATE_CTRL */
+	edp_write(base + 0x8, 0x40); /* EDP_STATE_CTRL */
+	edp_write(base + 0x94, enable); /* EDP_TIMING_ENGINE_EN */
+	edp_write(base + 0x4, enable); /* EDP_MAINLINK_CTRL */
 }
 
+static void mdss_edp_irq_enable(struct mdss_edp_drv_pdata *edp_drv);
+static void mdss_edp_irq_disable(struct mdss_edp_drv_pdata *edp_drv);
+
 int mdss_edp_on(struct mdss_panel_data *pdata)
 {
 	struct mdss_edp_drv_pdata *edp_drv = NULL;
-	int i;
+	int ret = 0;
 
-	edp_drv = container_of(pdata, struct mdss_edp_drv_pdata,
-			panel_data);
-	if (!edp_drv) {
+	if (!pdata) {
 		pr_err("%s: Invalid input data\n", __func__);
 		return -EINVAL;
 	}
 
-	mdss_edp_prepare_clocks(edp_drv);
-	mdss_edp_phy_sw_reset(edp_drv->edp_base);
-	mdss_edp_hw_powerup(edp_drv->edp_base, 1);
-	mdss_edp_pll_configure(edp_drv->edp_base, edp_drv->edid.timing[0].pclk);
-	mdss_edp_clk_enable(edp_drv);
+	edp_drv = container_of(pdata, struct mdss_edp_drv_pdata,
+			panel_data);
 
-	for (i = 0; i < edp_drv->dpcd.max_lane_count; ++i)
-		mdss_edp_enable_lane_bist(edp_drv->edp_base, i, 1);
+	pr_debug("%s:+\n", __func__);
+	if (edp_drv->train_start == 0)
+		edp_drv->train_start++;
 
-	mdss_edp_enable_mainlink(edp_drv->edp_base, 1);
-	mdss_edp_config_clk(edp_drv->edp_base, edp_drv->mmss_cc_base);
+	mdss_edp_phy_pll_reset(edp_drv->base);
+	mdss_edp_aux_reset(edp_drv->base);
+	mdss_edp_mainlink_reset(edp_drv->base);
 
-	mdss_edp_phy_misc_cfg(edp_drv->edp_base);
-	mdss_edp_config_sync(edp_drv->edp_base);
-	mdss_edp_config_sw_div(edp_drv->edp_base);
-	mdss_edp_config_static_mdiv(edp_drv->edp_base);
-	mdss_edp_enable(edp_drv->edp_base, 1);
+	ret = mdss_edp_prepare_clocks(edp_drv);
+	if (ret)
+		return ret;
+	mdss_edp_phy_powerup(edp_drv->base, 1);
+
+	mdss_edp_pll_configure(edp_drv->base, edp_drv->edid.timing[0].pclk);
+	mdss_edp_phy_pll_ready(edp_drv->base);
+
+	ret = mdss_edp_clk_enable(edp_drv);
+	if (ret) {
+		mdss_edp_unprepare_clocks(edp_drv);
+		return ret;
+	}
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+	mdss_edp_aux_ctrl(edp_drv->base, 1);
+
+	mdss_edp_lane_power_ctrl(edp_drv->base,
+				edp_drv->dpcd.max_lane_count, 1);
+	mdss_edp_enable_mainlink(edp_drv->base, 1);
+	mdss_edp_config_clk(edp_drv->base, edp_drv->mmss_cc_base);
+
+	mdss_edp_clock_synchrous(edp_drv->base, 1);
+	mdss_edp_phy_vm_pe_init(edp_drv->base);
+	mdss_edp_config_sync(edp_drv->base);
+	mdss_edp_config_sw_div(edp_drv->base);
+	mdss_edp_config_static_mdiv(edp_drv->base);
 	gpio_set_value(edp_drv->gpio_panel_en, 1);
+	mdss_edp_irq_enable(edp_drv);
 
+	pr_debug("%s:-\n", __func__);
 	return 0;
 }
 
+int mdss_edp_wait4train(struct mdss_panel_data *pdata)
+{
+	struct mdss_edp_drv_pdata *edp_drv = NULL;
+	int ret = 0;
+
+	if (!pdata) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
+
+	edp_drv = container_of(pdata, struct mdss_edp_drv_pdata,
+			panel_data);
+
+	ret = wait_for_completion_timeout(&edp_drv->train_comp, 100);
+	if (ret <= 0) {
+		pr_err("%s: Link Train timedout\n", __func__);
+		ret = -EINVAL;
+	} else {
+		ret = 0;
+	}
+
+	mdss_edp_enable(edp_drv->base, 1);
+
+	pr_debug("%s:\n", __func__);
+
+	return ret;
+}
+
 int mdss_edp_off(struct mdss_panel_data *pdata)
 {
 	struct mdss_edp_drv_pdata *edp_drv = NULL;
 	int ret = 0;
-	int i;
 
 	edp_drv = container_of(pdata, struct mdss_edp_drv_pdata,
 				panel_data);
@@ -336,20 +373,26 @@
 		pr_err("%s: Invalid input data\n", __func__);
 		return -EINVAL;
 	}
+	pr_debug("%s:+\n", __func__);
+
+	mdss_edp_irq_disable(edp_drv);
 
 	gpio_set_value(edp_drv->gpio_panel_en, 0);
 	pwm_disable(edp_drv->bl_pwm);
-	mdss_edp_enable(edp_drv->edp_base, 0);
-	mdss_edp_unconfig_clk(edp_drv->edp_base, edp_drv->mmss_cc_base);
-	mdss_edp_enable_mainlink(edp_drv->edp_base, 0);
+	mdss_edp_enable(edp_drv->base, 0);
+	mdss_edp_unconfig_clk(edp_drv->base, edp_drv->mmss_cc_base);
+	mdss_edp_enable_mainlink(edp_drv->base, 0);
 
-	for (i = 0; i < edp_drv->dpcd.max_lane_count; ++i)
-		mdss_edp_enable_lane_bist(edp_drv->edp_base, i, 0);
-
+	mdss_edp_lane_power_ctrl(edp_drv->base,
+				edp_drv->dpcd.max_lane_count, 0);
 	mdss_edp_clk_disable(edp_drv);
-	mdss_edp_hw_powerup(edp_drv->edp_base, 0);
+	mdss_edp_phy_powerup(edp_drv->base, 0);
 	mdss_edp_unprepare_clocks(edp_drv);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
+	mdss_edp_aux_ctrl(edp_drv->base, 0);
+
+	pr_debug("%s:-\n", __func__);
 	return ret;
 }
 
@@ -363,6 +406,9 @@
 	case MDSS_EVENT_UNBLANK:
 		rc = mdss_edp_on(pdata);
 		break;
+	case MDSS_EVENT_PANEL_ON:
+		rc = mdss_edp_wait4train(pdata);
+		break;
 	case MDSS_EVENT_PANEL_OFF:
 		rc = mdss_edp_off(pdata);
 		break;
@@ -382,20 +428,31 @@
 	pinfo = &edp_drv->panel_data.panel_info;
 
 	pinfo->clk_rate = dp->pclk;
+	pr_debug("%s: pclk=%d\n", __func__, pinfo->clk_rate);
 
 	pinfo->xres = dp->h_addressable + dp->h_border * 2;
 	pinfo->yres = dp->v_addressable + dp->v_border * 2;
 
+	pr_debug("%s: x=%d y=%d\n", __func__, pinfo->xres, pinfo->yres);
+
 	pinfo->lcdc.h_back_porch = dp->h_blank - dp->h_fporch \
 		- dp->h_sync_pulse;
 	pinfo->lcdc.h_front_porch = dp->h_fporch;
 	pinfo->lcdc.h_pulse_width = dp->h_sync_pulse;
 
+	pr_debug("%s: hporch= %d %d %d\n", __func__,
+		pinfo->lcdc.h_back_porch, pinfo->lcdc.h_front_porch,
+		pinfo->lcdc.h_pulse_width);
+
 	pinfo->lcdc.v_back_porch = dp->v_blank - dp->v_fporch \
 		- dp->v_sync_pulse;
 	pinfo->lcdc.v_front_porch = dp->v_fporch;
 	pinfo->lcdc.v_pulse_width = dp->v_sync_pulse;
 
+	pr_debug("%s: vporch= %d %d %d\n", __func__,
+		pinfo->lcdc.v_back_porch, pinfo->lcdc.v_front_porch,
+		pinfo->lcdc.v_pulse_width);
+
 	pinfo->type = EDP_PANEL;
 	pinfo->pdest = DISPLAY_1;
 	pinfo->wait_cycle = 0;
@@ -415,9 +472,9 @@
 
 	gpio_free(edp_drv->gpio_panel_en);
 	mdss_edp_regulator_off(edp_drv);
-	iounmap(edp_drv->edp_base);
+	iounmap(edp_drv->base);
 	iounmap(edp_drv->mmss_cc_base);
-	edp_drv->edp_base = NULL;
+	edp_drv->base = NULL;
 
 	return 0;
 }
@@ -458,12 +515,19 @@
 		return -ENOMEM;
 	}
 
-	edp_drv->edp_base = ioremap(res->start, resource_size(res));
-	if (!edp_drv->edp_base) {
+	edp_drv->base_size = resource_size(res);
+	edp_drv->base = ioremap(res->start, resource_size(res));
+	if (!edp_drv->base) {
 		pr_err("%s: Unable to remap EDP resources",  __func__);
 		return -ENOMEM;
 	}
 
+	pr_debug("%s: drv=%x base=%x size=%x\n", __func__,
+		(int)edp_drv, (int)edp_drv->base, edp_drv->base_size);
+
+	mdss_debug_register_base("edp",
+			edp_drv->base, edp_drv->base_size);
+
 	return 0;
 }
 
@@ -488,52 +552,202 @@
 	return 0;
 }
 
-static void mdss_edp_fill_edid_data(struct mdss_edp_drv_pdata *edp_drv)
+static void mdss_edp_video_ready(struct mdss_edp_drv_pdata *edp_drv)
 {
-	struct edp_edid *edid = &edp_drv->edid;
-
-	edid->id_name[0] = 'A';
-	edid->id_name[0] = 'U';
-	edid->id_name[0] = 'O';
-	edid->id_name[0] = 0;
-	edid->id_product = 0x305D;
-	edid->version = 1;
-	edid->revision = 4;
-	edid->ext_block_cnt = 0;
-	edid->video_digital = 0x5;
-	edid->color_depth = 6;
-	edid->dpm = 0;
-	edid->color_format = 0;
-	edid->timing[0].pclk = 138500000;
-	edid->timing[0].h_addressable = 1920;
-	edid->timing[0].h_blank = 160;
-	edid->timing[0].v_addressable = 1080;
-	edid->timing[0].v_blank = 30;
-	edid->timing[0].h_fporch = 48;
-	edid->timing[0].h_sync_pulse = 32;
-	edid->timing[0].v_sync_pulse = 14;
-	edid->timing[0].v_fporch = 8;
-	edid->timing[0].width_mm =  256;
-	edid->timing[0].height_mm = 144;
-	edid->timing[0].h_border = 0;
-	edid->timing[0].v_border = 0;
-	edid->timing[0].interlaced = 0;
-	edid->timing[0].stereo = 0;
-	edid->timing[0].sync_type = 1;
-	edid->timing[0].sync_separate = 1;
-	edid->timing[0].vsync_pol = 0;
-	edid->timing[0].hsync_pol = 0;
+	pr_debug("%s: edp_video_ready\n", __func__);
 
 }
 
-static void mdss_edp_fill_dpcd_data(struct mdss_edp_drv_pdata *edp_drv)
+static int edp_event_thread(void *data)
 {
-	struct dpcd_cap *cap = &edp_drv->dpcd;
+	struct mdss_edp_drv_pdata *ep;
+	unsigned long flag;
+	u32 todo = 0;
 
-	cap->max_lane_count = 2;
-	cap->max_link_clk = 270;
+	ep = (struct mdss_edp_drv_pdata *)data;
+
+	while (1) {
+		wait_event(ep->event_q, (ep->event_pndx != ep->event_gndx));
+		spin_lock_irqsave(&ep->event_lock, flag);
+		if (ep->event_pndx == ep->event_gndx) {
+			spin_unlock_irqrestore(&ep->event_lock, flag);
+			break;
+		}
+		todo = ep->event_todo_list[ep->event_gndx];
+		ep->event_todo_list[ep->event_gndx++] = 0;
+		ep->event_gndx %= HPD_EVENT_MAX;
+		spin_unlock_irqrestore(&ep->event_lock, flag);
+
+		pr_debug("%s: todo=%x\n", __func__, todo);
+
+		if (todo == 0)
+			continue;
+
+		if (todo & EV_EDID_READ)
+			mdss_edp_edid_read(ep, 0);
+
+		if (todo & EV_DPCD_CAP_READ)
+			mdss_edp_dpcd_cap_read(ep);
+
+		if (todo & EV_DPCD_STATUS_READ)
+			mdss_edp_dpcd_status_read(ep);
+
+		if (todo & EV_LINK_TRAIN) {
+			INIT_COMPLETION(ep->train_comp);
+			mdss_edp_link_train(ep);
+		}
+
+		if (todo & EV_VIDEO_READY)
+			mdss_edp_video_ready(ep);
+	}
+
+	return 0;
 }
 
+static void edp_send_events(struct mdss_edp_drv_pdata *ep, u32 events)
+{
+	spin_lock(&ep->event_lock);
+	ep->event_todo_list[ep->event_pndx++] = events;
+	ep->event_pndx %= HPD_EVENT_MAX;
+	wake_up(&ep->event_q);
+	spin_unlock(&ep->event_lock);
+}
+
+irqreturn_t edp_isr(int irq, void *ptr)
+{
+	struct mdss_edp_drv_pdata *ep = (struct mdss_edp_drv_pdata *)ptr;
+	unsigned char *base = ep->base;
+	u32 isr1, isr2, mask1, mask2;
+	u32 ack;
+
+	isr1 = edp_read(base + 0x308);
+	isr2 = edp_read(base + 0x30c);
+
+	mask1 = isr1 & EDP_INTR_MASK1;
+	mask2 = isr2 & EDP_INTR_MASK2;
+
+	isr1 &= ~mask1;	/* remove masks bit */
+	isr2 &= ~mask2;
+
+	pr_debug("%s: isr=%x mask=%x isr2=%x mask2=%x\n",
+			__func__, isr1, mask1, isr2, mask2);
+
+	ack = isr1 & EDP_INTR_STATUS1;
+	ack <<= 1;	/* ack bits */
+	ack |= mask1;
+	edp_write(base + 0x308, ack);
+
+	ack = isr2 & EDP_INTR_STATUS2;
+	ack <<= 1;	/* ack bits */
+	ack |= mask2;
+	edp_write(base + 0x30c, ack);
+
+	if (isr1 & EDP_INTR_HPD) {
+		isr1 &= ~EDP_INTR_HPD;	/* clear */
+		if (ep->train_start)
+			edp_send_events(ep, EV_LINK_TRAIN);
+	}
+
+	if (isr2 & EDP_INTR_READY_FOR_VIDEO)
+		edp_send_events(ep, EV_VIDEO_READY);
+
+	if (isr1 && ep->aux_cmd_busy) {
+		/* clear EDP_AUX_TRANS_CTRL */
+		edp_write(base + 0x318, 0);
+		/* read EDP_INTERRUPT_TRANS_NUM */
+		ep->aux_trans_num = edp_read(base + 0x310);
+
+		if (ep->aux_cmd_i2c)
+			edp_aux_i2c_handler(ep, isr1);
+		else
+			edp_aux_native_handler(ep, isr1);
+	}
+
+	return IRQ_HANDLED;
+}
+
+struct mdss_hw mdss_edp_hw = {
+	.hw_ndx = MDSS_HW_EDP,
+	.ptr = NULL,
+	.irq_handler = edp_isr,
+};
+
+static void mdss_edp_irq_enable(struct mdss_edp_drv_pdata *edp_drv)
+{
+	edp_write(edp_drv->base + 0x308, EDP_INTR_MASK1);
+	edp_write(edp_drv->base + 0x30c, EDP_INTR_MASK2);
+
+	mdss_enable_irq(&mdss_edp_hw);
+}
+
+static void mdss_edp_irq_disable(struct mdss_edp_drv_pdata *edp_drv)
+{
+	edp_write(edp_drv->base + 0x308, 0x0);
+	edp_write(edp_drv->base + 0x30c, 0x0);
+
+	mdss_disable_irq(&mdss_edp_hw);
+}
+
+static int mdss_edp_irq_setup(struct mdss_edp_drv_pdata *edp_drv)
+{
+	int ret = 0;
+
+
+	edp_drv->gpio_panel_hpd = of_get_named_gpio_flags(
+			edp_drv->pdev->dev.of_node, "gpio-panel-hpd", 0,
+			&edp_drv->hpd_flags);
+
+	if (!gpio_is_valid(edp_drv->gpio_panel_hpd)) {
+		pr_err("%s gpio_panel_hpd %d is not valid ", __func__,
+				edp_drv->gpio_panel_hpd);
+		return -ENODEV;
+	}
+
+	ret = gpio_request(edp_drv->gpio_panel_hpd, "edp_hpd_irq_gpio");
+	if (ret) {
+		pr_err("%s unable to request gpio_panel_hpd %d", __func__,
+				edp_drv->gpio_panel_hpd);
+		return -ENODEV;
+	}
+
+	ret = gpio_tlmm_config(GPIO_CFG(
+					edp_drv->gpio_panel_hpd,
+					1,
+					GPIO_CFG_INPUT,
+					GPIO_CFG_NO_PULL,
+					GPIO_CFG_2MA),
+					GPIO_CFG_ENABLE);
+	if (ret) {
+		pr_err("%s: unable to config tlmm = %d\n", __func__,
+				edp_drv->gpio_panel_hpd);
+		gpio_free(edp_drv->gpio_panel_hpd);
+		return -ENODEV;
+	}
+
+	ret = gpio_direction_input(edp_drv->gpio_panel_hpd);
+	if (ret) {
+		pr_err("%s unable to set direction for gpio_panel_hpd %d",
+				__func__, edp_drv->gpio_panel_hpd);
+		return -ENODEV;
+	}
+
+	mdss_edp_hw.ptr = (void *)(edp_drv);
+
+	if (mdss_register_irq(&mdss_edp_hw))
+		pr_err("%s: mdss_register_irq failed.\n", __func__);
+
+
+	return 0;
+}
+
+
+static void mdss_edp_event_setup(struct mdss_edp_drv_pdata *ep)
+{
+	init_waitqueue_head(&ep->event_q);
+	spin_lock_init(&ep->event_lock);
+
+	kthread_run(edp_event_thread, (void *)ep, "mdss_edp_hpd");
+}
 
 static int __devinit mdss_edp_probe(struct platform_device *pdev)
 {
@@ -554,6 +768,7 @@
 	edp_drv->pdev = pdev;
 	edp_drv->pdev->id = 1;
 	edp_drv->clk_on = 0;
+	edp_drv->train_start = 0; /* no link train yet */
 
 	ret = mdss_edp_get_base_address(edp_drv);
 	if (ret)
@@ -579,8 +794,38 @@
 	if (ret)
 		goto edp_free_gpio_panel_en;
 
-	mdss_edp_fill_edid_data(edp_drv);
-	mdss_edp_fill_dpcd_data(edp_drv);
+	mdss_edp_irq_setup(edp_drv);
+
+	mdss_edp_aux_init(edp_drv);
+
+	mdss_edp_event_setup(edp_drv);
+
+	/* need mdss clock to receive irq */
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+	/* only need aux and ahb clock for aux channel */
+	mdss_edp_prepare_aux_clocks(edp_drv);
+	mdss_edp_aux_clk_enable(edp_drv);
+	mdss_edp_phy_pll_reset(edp_drv->base);
+	mdss_edp_aux_reset(edp_drv->base);
+	mdss_edp_mainlink_reset(edp_drv->base);
+	mdss_edp_phy_powerup(edp_drv->base, 1);
+	mdss_edp_aux_ctrl(edp_drv->base, 1);
+
+	mdss_edp_irq_enable(edp_drv);
+
+	mdss_edp_edid_read(edp_drv, 0);
+	mdss_edp_dpcd_cap_read(edp_drv);
+
+	mdss_edp_irq_disable(edp_drv);
+
+	mdss_edp_aux_ctrl(edp_drv->base, 0);
+	mdss_edp_aux_clk_disable(edp_drv);
+	mdss_edp_phy_powerup(edp_drv->base, 0);
+	mdss_edp_unprepare_aux_clocks(edp_drv);
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
 	mdss_edp_device_register(edp_drv);
 
 	return 0;
@@ -594,7 +839,7 @@
 mmss_cc_base_unmap:
 	iounmap(edp_drv->mmss_cc_base);
 edp_base_unmap:
-	iounmap(edp_drv->edp_base);
+	iounmap(edp_drv->base);
 probe_err:
 	return ret;
 
diff --git a/drivers/video/msm/mdss/mdss_edp.h b/drivers/video/msm/mdss/mdss_edp.h
index 00ef206..c3f7d0d 100644
--- a/drivers/video/msm/mdss/mdss_edp.h
+++ b/drivers/video/msm/mdss/mdss_edp.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
@@ -14,15 +14,157 @@
 #ifndef MDSS_EDP_H
 #define MDSS_EDP_H
 
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/clk.h>
-
-#include "mdss_panel.h"
+#include <linux/of_gpio.h>
 
 #define edp_read(offset) readl_relaxed((offset))
 #define edp_write(offset, data) writel_relaxed((data), (offset))
 
+#define AUX_CMD_FIFO_LEN	144
+#define AUX_CMD_MAX		16
+#define AUX_CMD_I2C_MAX		128
+
+#define EDP_PORT_MAX		1
+#define EDP_SINK_CAP_LEN	16
+
+#define EDP_AUX_ERR_NONE	0
+#define EDP_AUX_ERR_ADDR	-1
+#define EDP_AUX_ERR_TOUT	-2
+#define EDP_AUX_ERR_NACK	-3
+
+/* 4 bits of aux command */
+#define EDP_CMD_AUX_WRITE	0x8
+#define EDP_CMD_AUX_READ	0x9
+
+/* 4 bits of i2c command */
+#define EDP_CMD_I2C_MOT		0x4	/* i2c middle of transaction */
+#define EDP_CMD_I2C_WRITE	0x0
+#define EDP_CMD_I2C_READ	0x1
+#define EDP_CMD_I2C_STATUS	0x2	/* i2c write status request */
+
+/* cmd reply: bit 0, 1 for aux */
+#define EDP_AUX_ACK		0x0
+#define EDP_AUX_NACK	0x1
+#define EDP_AUX_DEFER	0x2
+
+/* cmd reply: bit 2, 3 for i2c */
+#define EDP_I2C_ACK		0x0
+#define EDP_I2C_NACK	0x4
+#define EDP_I2C_DEFER	0x8
+
+#define EDP_CMD_TIMEOUT	400	/* us */
+#define EDP_CMD_LEN		16
+
+#define EDP_INTR_ACK_SHIFT	1
+#define EDP_INTR_MASK_SHIFT	2
+
+/* isr */
+#define EDP_INTR_HPD		BIT(0)
+#define EDP_INTR_AUX_I2C_DONE	BIT(3)
+#define EDP_INTR_WRONG_ADDR	BIT(6)
+#define EDP_INTR_TIMEOUT	BIT(9)
+#define EDP_INTR_NACK_DEFER	BIT(12)
+#define EDP_INTR_WRONG_DATA_CNT	BIT(15)
+#define EDP_INTR_I2C_NACK	BIT(18)
+#define EDP_INTR_I2C_DEFER	BIT(21)
+#define EDP_INTR_PLL_UNLOCKED	BIT(24)
+#define EDP_INTR_AUX_ERROR	BIT(27)
+
+
+#define EDP_INTR_STATUS1 \
+	(EDP_INTR_HPD | EDP_INTR_AUX_I2C_DONE| \
+	EDP_INTR_WRONG_ADDR | EDP_INTR_TIMEOUT | \
+	EDP_INTR_NACK_DEFER | EDP_INTR_WRONG_DATA_CNT | \
+	EDP_INTR_I2C_NACK | EDP_INTR_I2C_DEFER | \
+	EDP_INTR_PLL_UNLOCKED | EDP_INTR_AUX_ERROR)
+
+#define EDP_INTR_MASK1		(EDP_INTR_STATUS1 << 2)
+
+
+#define EDP_INTR_READY_FOR_VIDEO	BIT(0)
+#define EDP_INTR_IDLE_PATTERNs_SENT	BIT(3)
+#define EDP_INTR_FRAME_END		BIT(6)
+#define EDP_INTR_CRC_UPDATED		BIT(9)
+
+#define EDP_INTR_STATUS2 \
+	(EDP_INTR_READY_FOR_VIDEO | EDP_INTR_IDLE_PATTERNs_SENT | \
+	EDP_INTR_FRAME_END | EDP_INTR_CRC_UPDATED)
+
+#define EDP_INTR_MASK2		(EDP_INTR_STATUS2 << 2)
+
+
+#define EDP_MAINLINK_CTRL	0x004
+#define EDP_STATE_CTRL		0x008
+#define EDP_MAINLINK_READY	0x084
+
+#define EDP_AUX_CTRL		0x300
+#define EDP_INTERRUPT_STATUS	0x308
+#define EDP_INTERRUPT_STATUS_2	0x30c
+#define EDP_AUX_DATA		0x314
+#define EDP_AUX_TRANS_CTRL	0x318
+#define EDP_AUX_STATUS		0x324
+
+#define EDP_PHY_EDPPHY_GLB_VM_CFG0	0x510
+#define EDP_PHY_EDPPHY_GLB_VM_CFG1	0x514
+
+struct edp_cmd {
+	char read;	/* 1 == read, 0 == write */
+	char i2c;	/* 1 == i2c cmd, 0 == native cmd */
+	u32 addr;	/* 20 bits */
+	char *datap;
+	int len;	/* len to be tx OR len to be rx for read */
+	char next;	/* next command */
+};
+
+struct edp_buf {
+	char *start;	/* buffer start addr */
+	char *end;	/* buffer end addr */
+	int size;	/* size of buffer */
+	char *data;	/* data pointer */
+	int len;	/* dara length */
+	char trans_num;	/* transaction number */
+	char i2c;	/* 1 == i2c cmd, 0 == native cmd */
+};
+
+#define DPCD_ENHANCED_FRAME	BIT(0)
+#define DPCD_TPS3	BIT(1)
+#define DPCD_MAX_DOWNSPREAD_0_5	BIT(2)
+#define DPCD_NO_AUX_HANDSHAKE	BIT(3)
+#define DPCD_PORT_0_EDID_PRESENTED	BIT(4)
+
+/* event */
+#define EV_EDP_AUX_SETUP		BIT(0)
+#define EV_EDID_READ			BIT(1)
+#define EV_DPCD_CAP_READ		BIT(2)
+#define EV_DPCD_STATUS_READ		BIT(3)
+#define EV_LINK_TRAIN			BIT(4)
+#define EV_VIDEO_READY			BIT(31)
+
+struct dpcd_cap {
+	char major;
+	char minor;
+	char max_lane_count;
+	char num_rx_port;
+	char i2c_speed_ctrl;
+	char scrambler_reset;
+	char enhanced_frame;
+	u32 max_link_rate;  /* 162, 270 and 540 Mb, divided by 10 */
+	u32 flags;
+	u32 rx_port0_buf_size;
+	u32 training_read_interval;/* us */
+};
+
+struct dpcd_link_status {
+	char lane_01_status;
+	char lane_23_status;
+	char interlane_align_done;
+	char downstream_port_status_changed;
+	char link_status_updated;
+	char port_0_in_sync;
+	char port_1_in_sync;
+	char req_voltage_swing[4];
+	char req_pre_emphasis[4];
+};
+
 struct display_timing_desc {
 	u32 pclk;
 	u32 h_addressable; /* addressable + boder = active */
@@ -45,12 +187,14 @@
 	u32 hsync_pol;
 };
 
+#define EDID_DISPLAY_PORT_SUPPORT 0x05
+
 struct edp_edid {
 	char id_name[4];
 	short id_product;
 	char version;
 	char revision;
-	char video_digital;
+	char video_intf;	/* edp == 0x5 */
 	char color_depth;	/* 6, 8, 10, 12 and 14 bits */
 	char color_format;	/* RGB 4:4:4, YCrCb 4:4:4, Ycrcb 4:2:2 */
 	char dpm;		/* display power management */
@@ -62,11 +206,32 @@
 	struct display_timing_desc timing[4];
 };
 
-struct dpcd_cap {
-	char max_lane_count;
-	u32 max_link_clk;  /* 162, 270 and 540 Mb, divided by 10 */
+struct edp_statistic {
+	u32 intr_hpd;
+	u32 intr_aux_i2c_done;
+	u32 intr_wrong_addr;
+	u32 intr_tout;
+	u32 intr_nack_defer;
+	u32 intr_wrong_data_cnt;
+	u32 intr_i2c_nack;
+	u32 intr_i2c_defer;
+	u32 intr_pll_unlock;
+	u32 intr_crc_update;
+	u32 intr_frame_end;
+	u32 intr_idle_pattern_sent;
+	u32 intr_ready_for_video;
+	u32 aux_i2c_tx;
+	u32 aux_i2c_rx;
+	u32 aux_native_tx;
+	u32 aux_native_rx;
 };
 
+
+#define DPCD_LINK_VOLTAGE_MAX	4
+#define DPCD_LINK_PRE_EMPHASIS_MAX	4
+
+#define HPD_EVENT_MAX   8
+
 struct mdss_edp_drv_pdata {
 	/* device driver */
 	int (*on) (struct mdss_panel_data *pdata);
@@ -74,11 +239,15 @@
 	struct platform_device *pdev;
 
 	/* edp specific */
-	struct mdss_panel_data panel_data;
-	unsigned char *edp_base;
+	unsigned char *base;
+	int base_size;
 	unsigned char *mmss_cc_base;
+
+	struct mdss_panel_data panel_data;
+
 	struct edp_edid edid;
 	struct dpcd_cap dpcd;
+	int train_start;
 
 	/* regulators */
 	struct regulator *vdda_vreg;
@@ -98,22 +267,82 @@
 	struct pwm_device *bl_pwm;
 	int lpg_channel;
 	int pwm_period;
+
+	/* hpd */
+	int gpio_panel_hpd;
+	enum of_gpio_flags hpd_flags;
+	int hpd_irq;
+
+	/* aux */
+	struct completion aux_comp;
+	struct completion train_comp;
+	struct mutex aux_mutex;
+	u32 aux_cmd_busy;
+	u32 aux_cmd_i2c;
+	int aux_trans_num;
+	int aux_error_num;
+	u32 aux_ctrl_reg;
+	struct edp_buf txp;
+	struct edp_buf rxp;
+	char txbuf[256];
+	char rxbuf[256];
+	struct dpcd_link_status link_status;
+	char link_rate;
+	char lane_cnt;
+	char v_level;
+	char p_level;
+	/* transfer unit */
+	char tu_desired;
+	char valid_boundary;
+	char delay_start;
+	u32 bpp;
+	struct edp_statistic edp_stat;
+
+	/* event */
+	wait_queue_head_t event_q;
+	u32 event_pndx;
+	u32 event_gndx;
+	u32 event_todo_list[HPD_EVENT_MAX];
+	spinlock_t event_lock;
 };
 
-void mdss_edp_phy_sw_reset(unsigned char *edp_base);
-void mdss_edp_pll_configure(unsigned char *edp_base, int rate);
-void mdss_edp_enable_lane_bist(unsigned char *edp_base, int lane, int enable);
-void mdss_edp_enable_mainlink(unsigned char *edp_base, int enable);
-void mdss_edp_hw_powerup(unsigned char *edp_base, int enable);
-void mdss_edp_clk_enable(struct mdss_edp_drv_pdata *edp_drv);
+void mdss_edp_phy_sw_reset(unsigned char *base);
+void mdss_edp_pll_configure(unsigned char *base, int rate);
+void mdss_edp_enable_mainlink(unsigned char *base, int enable);
+void mdss_edp_phy_powerup(unsigned char *base, int enable);
+int mdss_edp_aux_clk_enable(struct mdss_edp_drv_pdata *edp_drv);
+void mdss_edp_aux_clk_disable(struct mdss_edp_drv_pdata *edp_drv);
+int mdss_edp_clk_enable(struct mdss_edp_drv_pdata *edp_drv);
 void mdss_edp_clk_disable(struct mdss_edp_drv_pdata *edp_drv);
 int mdss_edp_clk_init(struct mdss_edp_drv_pdata *edp_drv);
 void mdss_edp_clk_deinit(struct mdss_edp_drv_pdata *edp_drv);
-void mdss_edp_prepare_clocks(struct mdss_edp_drv_pdata *edp_drv);
+int mdss_edp_prepare_aux_clocks(struct mdss_edp_drv_pdata *edp_drv);
+void mdss_edp_unprepare_aux_clocks(struct mdss_edp_drv_pdata *edp_drv);
+int mdss_edp_prepare_clocks(struct mdss_edp_drv_pdata *edp_drv);
 void mdss_edp_unprepare_clocks(struct mdss_edp_drv_pdata *edp_drv);
-void mdss_edp_config_clk(unsigned char *edp_base, unsigned char *mmss_cc_base);
-void mdss_edp_unconfig_clk(unsigned char *edp_base,
+void mdss_edp_config_clk(unsigned char *base, unsigned char *mmss_cc_base);
+void mdss_edp_unconfig_clk(unsigned char *base,
 		unsigned char *mmss_cc_base);
-void mdss_edp_phy_misc_cfg(unsigned char *edp_base);
+
+void mdss_edp_dpcd_cap_read(struct mdss_edp_drv_pdata *edp);
+void mdss_edp_dpcd_status_read(struct mdss_edp_drv_pdata *edp);
+void mdss_edp_edid_read(struct mdss_edp_drv_pdata *edp, int block);
+int mdss_edp_link_train(struct mdss_edp_drv_pdata *edp);
+void edp_aux_i2c_handler(struct mdss_edp_drv_pdata *edp, u32 isr);
+void edp_aux_native_handler(struct mdss_edp_drv_pdata *edp, u32 isr);
+void mdss_edp_aux_init(struct mdss_edp_drv_pdata *ep);
+void mdss_edp_enable_aux(unsigned char *edp_base, int enable);
+
+void mdss_edp_timing_engine_ctrl(unsigned char *edp_base, int enable);
+void mdss_edp_mainlink_ctrl(unsigned char *edp_base, int enable);
+void mdss_edp_mainlink_reset(unsigned char *edp_base);
+void mdss_edp_aux_reset(unsigned char *edp_base);
+void mdss_edp_aux_ctrl(unsigned char *edp_base, int enable);
+void mdss_edp_phy_pll_reset(unsigned char *edp_base);
+int mdss_edp_phy_pll_ready(unsigned char *edp_base);
+int mdss_edp_phy_ready(unsigned char *edp_base);
+void mdss_edp_lane_power_ctrl(unsigned char *edp_base, int max_lane, int up);
+void mdss_edp_phy_vm_pe_init(unsigned char *edp_base);
+void mdss_edp_clock_synchrous(unsigned char *edp_base, int sync);
 
 #endif /* MDSS_EDP_H */
diff --git a/drivers/video/msm/mdss/mdss_edp_aux.c b/drivers/video/msm/mdss/mdss_edp_aux.c
new file mode 100644
index 0000000..6d8e2c2
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_edp_aux.c
@@ -0,0 +1,1260 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/bug.h>
+#include <linux/of_gpio.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/clk.h>
+#include <mach/dma.h>
+
+#include "mdss_panel.h"
+#include "mdss_edp.h"
+
+/*
+ * edp buffer operation
+ */
+static char *edp_buf_init(struct edp_buf *eb, char *buf, int size)
+{
+	eb->start = buf;
+	eb->size = size;
+	eb->data = eb->start;
+	eb->end = eb->start + eb->size;
+	eb->len = 0;
+	eb->trans_num = 0;
+	eb->i2c = 0;
+	return eb->data;
+}
+
+static char *edp_buf_reset(struct edp_buf *eb)
+{
+	eb->data = eb->start;
+	eb->len = 0;
+	eb->trans_num = 0;
+	eb->i2c = 0;
+	return eb->data;
+}
+
+static char *edp_buf_push(struct edp_buf *eb, int len)
+{
+	eb->data += len;
+	eb->len += len;
+	return eb->data;
+}
+
+static int edp_buf_trailing(struct edp_buf *eb)
+{
+	return (int)(eb->end - eb->data);
+}
+
+/*
+ * edp aux edp_buf_add_cmd:
+ * NO native and i2c command mix allowed
+ */
+static int edp_buf_add_cmd(struct edp_buf *eb, struct edp_cmd *cmd)
+{
+	char data;
+	char *bp, *cp;
+	int i, len;
+
+	if (cmd->read)	/* read */
+		len = 4;
+	else
+		len = cmd->len + 4;
+
+	if (edp_buf_trailing(eb) < len)
+		return 0;
+
+	/*
+	 * cmd fifo only has depth of 144 bytes
+	 * limit buf length to 128 bytes here
+	 */
+	if ((eb->len + len) > 128)
+		return 0;
+
+	bp = eb->data;
+	data = cmd->addr >> 16;
+	data &=  0x0f;	/* 4 addr bits */
+	if (cmd->read)
+		data |=  BIT(4);
+	*bp++ = data;
+	*bp++ = cmd->addr >> 8;
+	*bp++ = cmd->addr;
+	*bp++ = cmd->len - 1;
+
+	if (!cmd->read) { /* write */
+		cp = cmd->datap;
+		for (i = 0; i < cmd->len; i++)
+			*bp++ = *cp++;
+	}
+	edp_buf_push(eb, len);
+
+	if (cmd->i2c)
+		eb->i2c++;
+
+	eb->trans_num++;	/* Increase transaction number */
+
+	return cmd->len - 1;
+}
+
+static int edp_cmd_fifo_tx(struct edp_buf *tp, unsigned char *base)
+{
+	u32 data;
+	char *dp;
+	int len, cnt;
+
+	len = tp->len;	/* total byte to cmd fifo */
+	if (len == 0)
+		return 0;
+
+	cnt = 0;
+	dp = tp->start;
+
+	while (cnt < len) {
+		data = *dp; /* data byte */
+		data <<= 8;
+		data &= 0x00ff00; /* index = 0, write */
+		if (cnt == 0)
+			data |= BIT(31);  /* INDEX_WRITE */
+		pr_debug("%s: data=%x\n", __func__, data);
+		edp_write(base + EDP_AUX_DATA, data);
+		cnt++;
+		dp++;
+	}
+
+	data = (tp->trans_num - 1);
+	if (tp->i2c)
+		data |= BIT(8); /* I2C */
+
+	data |= BIT(9); /* GO */
+	pr_debug("%s: data=%x\n", __func__, data);
+	edp_write(base + EDP_AUX_TRANS_CTRL, data);
+
+	return tp->len;
+}
+
+static int edp_cmd_fifo_rx(struct edp_buf *rp, int len, unsigned char *base)
+{
+	u32 data;
+	char *dp;
+	int i;
+
+	data = 0; /* index = 0 */
+	data |= BIT(31);  /* INDEX_WRITE */
+	data |= BIT(0);	/* read */
+	edp_write(base + EDP_AUX_DATA, data);
+
+	dp = rp->data;
+
+	/* discard first byte */
+	data = edp_read(base + EDP_AUX_DATA);
+	for (i = 0; i < len; i++) {
+		data = edp_read(base + EDP_AUX_DATA);
+		pr_debug("%s: data=%x\n", __func__, data);
+		*dp++ = (char)((data >> 8) & 0xff);
+	}
+
+	rp->len = len;
+	return len;
+}
+
+static int edp_aux_write_cmds(struct mdss_edp_drv_pdata *ep,
+					struct edp_cmd *cmd)
+{
+	struct edp_cmd *cm;
+	struct edp_buf *tp;
+	int len, ret;
+
+	mutex_lock(&ep->aux_mutex);
+	ep->aux_cmd_busy = 1;
+
+	tp = &ep->txp;
+	edp_buf_reset(tp);
+
+	cm = cmd;
+	while (cm) {
+		pr_debug("%s: i2c=%d read=%d addr=%x len=%d next=%d\n",
+			__func__, cm->i2c, cm->read, cm->addr, cm->len,
+			cm->next);
+		ret = edp_buf_add_cmd(tp, cm);
+		if (ret <= 0)
+			break;
+		if (cm->next == 0)
+			break;
+		cm++;
+	}
+
+	if (tp->i2c)
+		ep->aux_cmd_i2c = 1;
+	else
+		ep->aux_cmd_i2c = 0;
+
+	INIT_COMPLETION(ep->aux_comp);
+
+	len = edp_cmd_fifo_tx(&ep->txp, ep->base);
+
+	wait_for_completion(&ep->aux_comp);
+
+	if (ep->aux_error_num == EDP_AUX_ERR_NONE)
+		ret = len;
+	else
+		ret = ep->aux_error_num;
+
+	ep->aux_cmd_busy = 0;
+	mutex_unlock(&ep->aux_mutex);
+	return  ret;
+}
+
+static int edp_aux_read_cmds(struct mdss_edp_drv_pdata *ep,
+				struct edp_cmd *cmds)
+{
+	struct edp_cmd *cm;
+	struct edp_buf *tp;
+	struct edp_buf *rp;
+	int len, ret;
+
+	mutex_lock(&ep->aux_mutex);
+	ep->aux_cmd_busy = 1;
+
+	tp = &ep->txp;
+	rp = &ep->rxp;
+	edp_buf_reset(tp);
+	edp_buf_reset(rp);
+
+	cm = cmds;
+	len = 0;
+	while (cm) {
+		pr_debug("%s: i2c=%d read=%d addr=%x len=%d next=%d\n",
+			__func__, cm->i2c, cm->read, cm->addr, cm->len,
+			cm->next);
+		ret = edp_buf_add_cmd(tp, cm);
+		len += cm->len;
+		if (ret <= 0)
+			break;
+		if (cm->next == 0)
+			break;
+		cm++;
+	}
+
+	if (tp->i2c)
+		ep->aux_cmd_i2c = 1;
+	else
+		ep->aux_cmd_i2c = 0;
+
+	INIT_COMPLETION(ep->aux_comp);
+
+	edp_cmd_fifo_tx(tp, ep->base);
+
+	wait_for_completion(&ep->aux_comp);
+
+	if (ep->aux_error_num == EDP_AUX_ERR_NONE)
+		ret = edp_cmd_fifo_rx(rp, len, ep->base);
+	else
+		ret = ep->aux_error_num;
+
+	ep->aux_cmd_busy = 0;
+	mutex_unlock(&ep->aux_mutex);
+
+	return ret;
+}
+
+void edp_aux_native_handler(struct mdss_edp_drv_pdata *ep, u32 isr)
+{
+
+	pr_debug("%s: isr=%x\n", __func__, isr);
+
+	if (isr & EDP_INTR_AUX_I2C_DONE)
+		ep->aux_error_num = EDP_AUX_ERR_NONE;
+	else if (isr & EDP_INTR_WRONG_ADDR)
+		ep->aux_error_num = EDP_AUX_ERR_ADDR;
+	else if (isr & EDP_INTR_TIMEOUT)
+		ep->aux_error_num = EDP_AUX_ERR_TOUT;
+	if (isr & EDP_INTR_NACK_DEFER)
+		ep->aux_error_num = EDP_AUX_ERR_NACK;
+
+	complete(&ep->aux_comp);
+}
+
+void edp_aux_i2c_handler(struct mdss_edp_drv_pdata *ep, u32 isr)
+{
+
+	pr_debug("%s: isr=%x\n", __func__, isr);
+
+	if (isr & EDP_INTR_AUX_I2C_DONE) {
+		if (isr & (EDP_INTR_I2C_NACK | EDP_INTR_I2C_DEFER))
+			ep->aux_error_num = EDP_AUX_ERR_NACK;
+		else
+			ep->aux_error_num = EDP_AUX_ERR_NONE;
+	} else {
+		if (isr & EDP_INTR_WRONG_ADDR)
+			ep->aux_error_num = EDP_AUX_ERR_ADDR;
+		else if (isr & EDP_INTR_TIMEOUT)
+			ep->aux_error_num = EDP_AUX_ERR_TOUT;
+		if (isr & EDP_INTR_NACK_DEFER)
+			ep->aux_error_num = EDP_AUX_ERR_NACK;
+		if (isr & EDP_INTR_I2C_NACK)
+			ep->aux_error_num = EDP_AUX_ERR_NACK;
+		if (isr & EDP_INTR_I2C_DEFER)
+			ep->aux_error_num = EDP_AUX_ERR_NACK;
+	}
+
+	complete(&ep->aux_comp);
+}
+
+static int edp_aux_write_buf(struct mdss_edp_drv_pdata *ep, u32 addr,
+				char *buf, int len, int i2c)
+{
+	struct edp_cmd	cmd;
+
+	cmd.read = 0;
+	cmd.i2c = i2c;
+	cmd.addr = addr;
+	cmd.datap = buf;
+	cmd.len = len & 0x0ff;
+	cmd.next = 0;
+
+	return edp_aux_write_cmds(ep, &cmd);
+}
+
+static int edp_aux_read_buf(struct mdss_edp_drv_pdata *ep, u32 addr,
+				int len, int i2c)
+{
+	struct edp_cmd cmd;
+
+	cmd.read = 1;
+	cmd.i2c = i2c;
+	cmd.addr = addr;
+	cmd.datap = NULL;
+	cmd.len = len & 0x0ff;
+	cmd.next = 0;
+
+	return edp_aux_read_cmds(ep, &cmd);
+}
+
+/*
+ * edid standard header bytes
+ */
+static char edid_hdr[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
+
+int edp_edid_buf_error(char *buf, int len)
+{
+	char *bp;
+	int i;
+	char csum = 0;
+	int ret = 0;
+
+	bp = buf;
+	if (len < 128) {
+		pr_err("%s: Error: len=%x\n", __func__, len);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < 128; i++)
+		csum += *bp++;
+
+	if (csum != 0) {
+		pr_err("%s: Error: csum=%x\n", __func__, csum);
+		return -EINVAL;
+	}
+
+	if (strncmp(buf, edid_hdr, strlen(edid_hdr))) {
+		pr_err("%s: Error: header\n", __func__);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+
+void edp_extract_edid_manufacturer(struct edp_edid *edid, char *buf)
+{
+	char *bp;
+	char data;
+
+	bp = &buf[8];
+	data = *bp & 0x7f;
+	data >>= 2;
+	edid->id_name[0] = 'A' + data - 1;
+	data = *bp & 0x03;
+	data <<= 3;
+	bp++;
+	data |= (*bp >> 5);
+	edid->id_name[1] = 'A' + data - 1;
+	data = *bp & 0x1f;
+	edid->id_name[2] = 'A' + data - 1;
+	edid->id_name[3] = 0;
+
+	pr_debug("%s: edid manufacturer = %s", __func__, edid->id_name);
+}
+
+void edp_extract_edid_product(struct edp_edid *edid, char *buf)
+{
+	char *bp;
+	u32 data;
+
+	bp = &buf[0x0a];
+	data =  *bp;
+	edid->id_product = *bp++;
+	edid->id_product &= 0x0ff;
+	data = *bp & 0x0ff;
+	data <<= 8;
+	edid->id_product |= data;
+
+	pr_debug("%s: edid product = 0x%x", __func__, edid->id_product);
+};
+
+void edp_extract_edid_version(struct edp_edid *edid, char *buf)
+{
+	edid->version = buf[0x12];
+	edid->revision = buf[0x13];
+	pr_debug("%s: edid version = %d.%d", __func__, edid->version,
+			edid->revision);
+};
+
+void edp_extract_edid_ext_block_cnt(struct edp_edid *edid, char *buf)
+{
+	edid->ext_block_cnt = buf[0x7e];
+	pr_debug("%s: edid extension = %d", __func__,
+			edid->ext_block_cnt);
+};
+
+void edp_extract_edid_video_support(struct edp_edid *edid, char *buf)
+{
+	char *bp;
+
+	bp = &buf[0x14];
+	if (*bp & 0x80) {
+		edid->video_intf = *bp & 0x0f;
+		/* 6, 8, 10, 12, 14 and 16 bit per component */
+		edid->color_depth = ((*bp & 0x70) >> 4); /* color bit depth */
+		if (edid->color_depth) {
+			edid->color_depth *= 2;
+			edid->color_depth += 4;
+		}
+		pr_debug("%s: Digital Video intf=%d color_depth=%d\n",
+			 __func__, edid->video_intf, edid->color_depth);
+	} else {
+		pr_err("%s: Error, Analog video interface", __func__);
+	}
+};
+
+void edp_extract_edid_feature(struct edp_edid *edid, char *buf)
+{
+	char *bp;
+	char data;
+
+	bp = &buf[0x18];
+	data = *bp;
+	data &= 0xe0;
+	data >>= 5;
+	if (data == 0x01)
+		edid->dpm = 1; /* display power management */
+
+	if (edid->video_intf) {
+		if (*bp & 0x80) {
+			/* RGB 4:4:4, YcrCb 4:4:4 and YCrCb 4:2:2 */
+			edid->color_format = *bp & 0x18;
+			edid->color_format >>= 3;
+		}
+	}
+
+	pr_debug("%s: edid dpm=%d color_format=%d", __func__,
+			edid->dpm, edid->color_format);
+};
+
+void edp_extract_edid_detailed_timing_description(struct edp_edid *edid,
+		char *buf)
+{
+	char *bp;
+	u32 data;
+	struct display_timing_desc *dp;
+
+	dp = &edid->timing[0];
+
+	bp = &buf[0x36];
+	dp->pclk = 0;
+	dp->pclk = *bp++; /* byte 0x36 */
+	dp->pclk |= (*bp++ << 8); /* byte 0x37 */
+
+	dp->h_addressable = *bp++; /* byte 0x38 */
+
+	if (dp->pclk == 0 && dp->h_addressable == 0)
+		return;	/* Not detailed timing definition */
+
+	dp->pclk *= 10000;
+
+	dp->h_blank = *bp++;/* byte 0x39 */
+	data = *bp & 0xf0; /* byte 0x3A */
+	data  <<= 4;
+	dp->h_addressable |= data;
+
+	data = *bp++ & 0x0f;
+	data <<= 8;
+	dp->h_blank |= data;
+
+	dp->v_addressable = *bp++; /* byte 0x3B */
+	dp->v_blank = *bp++; /* byte 0x3C */
+	data = *bp & 0xf0; /* byte 0x3D */
+	data  <<= 4;
+	dp->v_addressable |= data;
+
+	data = *bp++ & 0x0f;
+	data <<= 8;
+	dp->v_blank |= data;
+
+	dp->h_fporch = *bp++; /* byte 0x3E */
+	dp->h_sync_pulse = *bp++; /* byte 0x3F */
+
+	dp->v_fporch = *bp & 0x0f0; /* byte 0x40 */
+	dp->v_fporch  >>= 4;
+	dp->v_sync_pulse = *bp & 0x0f;
+
+	bp++;
+	data = *bp & 0xc0; /* byte 0x41 */
+	data <<= 2;
+	dp->h_fporch |= data;
+
+	data = *bp & 0x30;
+	data <<= 4;
+	dp->h_sync_pulse |= data;
+
+	data = *bp & 0x0c;
+	data <<= 2;
+	dp->v_fporch |= data;
+
+	data = *bp & 0x03;
+	data <<= 4;
+	dp->v_sync_pulse |= data;
+
+	bp++;
+	dp->width_mm = *bp++; /* byte 0x42 */
+	dp->height_mm = *bp++; /* byte 0x43 */
+	data = *bp & 0x0f0; /* byte 0x44 */
+	data <<= 4;
+	dp->width_mm |= data;
+	data = *bp & 0x0f;
+	data <<= 8;
+	dp->height_mm |= data;
+
+	bp++;
+	dp->h_border = *bp++; /* byte 0x45 */
+	dp->v_border = *bp++; /* byte 0x46 */
+
+	dp->interlaced = *bp & 0x80; /* byte 0x47 */
+
+	dp->stereo = *bp & 0x60;
+	dp->stereo >>= 5;
+
+	data = *bp & 0x1e; /* bit 4,3,2 1*/
+	data >>= 1;
+	dp->sync_type = data & 0x08;
+	dp->sync_type >>= 3;	/* analog or digital */
+	if (dp->sync_type) {
+		dp->sync_separate = data & 0x04;
+		dp->sync_separate >>= 2;
+		if (dp->sync_separate) {
+			if (data & 0x02)
+				dp->vsync_pol = 1; /* positive */
+			else
+				dp->vsync_pol = 0;/* negative */
+
+			if (data & 0x01)
+				dp->hsync_pol = 1; /* positive */
+			else
+				dp->hsync_pol = 0; /* negative */
+		}
+	}
+
+	pr_debug("%s: pixel_clock = %d\n", __func__, dp->pclk);
+
+	pr_debug("%s: horizontal=%d, blank=%d, porch=%d, sync=%d\n"
+			, __func__, dp->h_addressable, dp->h_blank,
+			dp->h_fporch, dp->h_sync_pulse);
+	pr_debug("%s: vertical=%d, blank=%d, porch=%d, vsync=%d\n"
+			, __func__, dp->v_addressable, dp->v_blank,
+			dp->v_fporch, dp->v_sync_pulse);
+	pr_debug("%s: panel size in mm, width=%d height=%d\n", __func__,
+			dp->width_mm, dp->height_mm);
+	pr_debug("%s: panel border horizontal=%d vertical=%d\n", __func__,
+				dp->h_border, dp->v_border);
+	pr_debug("%s: flags: interlaced=%d stereo=%d sync_type=%d sync_sep=%d\n"
+			, __func__, dp->interlaced, dp->stereo,
+			dp->sync_type, dp->sync_separate);
+	pr_debug("%s: polarity vsync=%d, hsync=%d", __func__,
+			dp->vsync_pol, dp->hsync_pol);
+}
+
+
+/*
+ * EDID structure can be found in VESA standart here:
+ * http://read.pudn.com/downloads110/ebook/456020/E-EDID%20Standard.pdf
+ *
+ * following table contains default edid
+ * static char edid_raw_data[128] = {
+ * 0, 255, 255, 255, 255, 255, 255, 0,
+ * 6, 175, 93, 48, 0, 0, 0, 0, 0, 22,
+ * 1, 4,
+ * 149, 26, 14, 120, 2,
+ * 164, 21,158, 85, 78, 155, 38, 15, 80, 84,
+ * 0, 0, 0,
+ * 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ * 29, 54, 128, 160, 112, 56, 30, 64, 48, 32, 142, 0, 0, 144, 16,0,0,24,
+ * 19, 36, 128, 160, 112, 56, 30, 64, 48, 32, 142, 0, 0, 144, 16,0,0,24,
+ * 0, 0, 0, 254, 0, 65, 85, 79, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ * 0, 0, 0, 254, 0, 66, 49, 49, 54, 72, 65, 78, 48, 51, 46, 48, 32, 10,
+ * 0, 75 };
+ */
+
+static int edp_aux_chan_ready(struct mdss_edp_drv_pdata *ep)
+{
+	int cnt, ret;
+	char data = 0;
+
+	for (cnt = 5; cnt; cnt--) {
+		ret = edp_aux_write_buf(ep, 0x50, &data, 1, 1);
+		pr_debug("%s: ret=%d\n", __func__, ret);
+		if (ret >= 0)
+			break;
+		pr_debug("%s: failed in write\n", __func__);
+		msleep(100);
+	}
+
+	if (cnt == 0)
+		return 0;
+
+	return 1;
+}
+
+static int edp_sink_edid_read(struct mdss_edp_drv_pdata *ep, int block)
+{
+	struct edp_buf *rp;
+	int cnt, rlen;
+	int ret = 0;
+
+	ret = edp_aux_chan_ready(ep);
+	if (ret == 0) {
+		pr_err("%s: aux chan NOT ready\n", __func__);
+		return ret;
+	}
+
+	for (cnt = 5; cnt; cnt--) {
+		rlen = edp_aux_read_buf(ep, 0x50, 128, 1);
+		if (rlen > 0) {
+			pr_debug("%s: rlen=%d\n", __func__, rlen);
+
+			rp = &ep->rxp;
+			if (!edp_edid_buf_error(rp->data, rp->len))
+				break;
+		}
+	}
+
+	if (cnt <= 0) {
+		pr_err("%s: Failed\n", __func__);
+		return -EINVAL;
+	}
+
+	edp_extract_edid_manufacturer(&ep->edid, rp->data);
+	edp_extract_edid_product(&ep->edid, rp->data);
+	edp_extract_edid_version(&ep->edid, rp->data);
+	edp_extract_edid_ext_block_cnt(&ep->edid, rp->data);
+	edp_extract_edid_video_support(&ep->edid, rp->data);
+	edp_extract_edid_feature(&ep->edid, rp->data);
+	edp_extract_edid_detailed_timing_description(&ep->edid, rp->data);
+
+	return 128;
+}
+
+static void edp_sink_capability_read(struct mdss_edp_drv_pdata *ep,
+				int len)
+{
+	char *bp;
+	char data;
+	struct dpcd_cap *cap;
+	struct edp_buf *rp;
+	int rlen;
+
+	rlen = edp_aux_read_buf(ep, 0, len, 0);
+	if (rlen <= 0) {
+		pr_err("%s: edp aux read failed\n", __func__);
+		return;
+	}
+	rp = &ep->rxp;
+	cap = &ep->dpcd;
+	bp = rp->data;
+
+	data = *bp++; /* byte 0 */
+	cap->major = (data >> 4) & 0x0f;
+	cap->minor = data & 0x0f;
+	if (--rlen <= 0)
+		return;
+	pr_debug("%s: version: %d.%d\n", __func__, cap->major, cap->minor);
+
+	data = *bp++; /* byte 1 */
+	/* 162, 270 and 540 MB, symbol rate, NOT bit rate */
+	cap->max_link_rate = data * 27;
+	if (--rlen <= 0)
+		return;
+	pr_debug("%s: link_rate=%d\n", __func__, cap->max_link_rate);
+
+	data = *bp++; /* byte 2 */
+	if (data & BIT(7))
+		cap->flags |=  DPCD_ENHANCED_FRAME;
+	if (data & 0x40)
+		cap->flags |=  DPCD_TPS3;
+	data &= 0x0f;
+	cap->max_lane_count = data;
+	if (--rlen <= 0)
+		return;
+	pr_debug("%s: lane_count=%d\n", __func__, cap->max_lane_count);
+
+	data = *bp++; /* byte 3 */
+	if (data & BIT(0)) {
+		cap->flags |= DPCD_MAX_DOWNSPREAD_0_5;
+		pr_debug("%s: max_downspread\n", __func__);
+	}
+
+	if (data & BIT(6)) {
+		cap->flags |= DPCD_NO_AUX_HANDSHAKE;
+		pr_debug("%s: NO Link Training\n", __func__);
+	}
+	if (--rlen <= 0)
+		return;
+
+	data = *bp++; /* byte 4 */
+	cap->num_rx_port = (data & BIT(0)) + 1;
+	pr_debug("%s: rx_ports=%d", __func__, cap->num_rx_port);
+	if (--rlen <= 0)
+		return;
+
+	bp += 3;	/* skip 5, 6 and 7 */
+	rlen -= 3;
+	if (rlen <= 0)
+		return;
+
+	data = *bp++; /* byte 8 */
+	if (data & BIT(1)) {
+		cap->flags |= DPCD_PORT_0_EDID_PRESENTED;
+		pr_debug("%s: edid presented\n", __func__);
+	}
+	if (--rlen <= 0)
+		return;
+
+	data = *bp++; /* byte 9 */
+	cap->rx_port0_buf_size = (data + 1) * 32;
+	pr_debug("%s: lane_buf_size=%d", __func__, cap->rx_port0_buf_size);
+	if (--rlen <= 0)
+		return;
+
+	bp += 2; /* skip 10, 11 port1 capability */
+	rlen -= 2;
+	if (rlen <= 0)
+		return;
+
+	data = *bp++;	/* byte 12 */
+	cap->i2c_speed_ctrl = data;
+	if (cap->i2c_speed_ctrl > 0)
+		pr_debug("%s: i2c_rate=%d", __func__, cap->i2c_speed_ctrl);
+	if (--rlen <= 0)
+		return;
+
+	data = *bp++;	/* byte 13 */
+	cap->scrambler_reset = data & BIT(0);
+	pr_debug("%s: scrambler_reset=%d\n", __func__,
+					cap->scrambler_reset);
+
+	cap->enhanced_frame = data & BIT(1);
+	pr_debug("%s: enhanced_framing=%d\n", __func__,
+					cap->enhanced_frame);
+	if (--rlen <= 0)
+		return;
+
+	data = *bp++; /* byte 14 */
+	if (data == 0)
+		cap->training_read_interval = 4000; /* us */
+	else
+		cap->training_read_interval = 4000 * data; /* us */
+	pr_debug("%s: training_interval=%d\n", __func__,
+			 cap->training_read_interval);
+}
+
+static void edp_link_status_read(struct mdss_edp_drv_pdata *ep, int len)
+{
+	char *bp;
+	char data;
+	struct dpcd_link_status *sp;
+	struct edp_buf *rp;
+	int rlen;
+
+	pr_debug("%s: len=%d", __func__, len);
+	/* skip byte 0x200 and 0x201 */
+	rlen = edp_aux_read_buf(ep, 0x202, len, 0);
+	if (rlen <= 0) {
+		pr_err("%s: edp aux read failed\n", __func__);
+		return;
+	}
+	rp = &ep->rxp;
+	bp = rp->data;
+	sp = &ep->link_status;
+
+	data = *bp++; /* byte 0x202 */
+	sp->lane_01_status = data; /* lane 0, 1 */
+	if (--rlen <= 0)
+		return;
+
+	data = *bp++; /* byte 0x203 */
+	sp->lane_23_status = data; /* lane 2, 3 */
+	if (--rlen <= 0)
+		return;
+
+	data = *bp++; /* byte 0x204 */
+	sp->interlane_align_done = (data & BIT(0));
+	sp->downstream_port_status_changed = (data & BIT(6));
+	sp->link_status_updated = (data & BIT(7));
+	if (--rlen <= 0)
+		return;
+
+	data = *bp++; /* byte 0x205 */
+	sp->port_0_in_sync = (data & BIT(0));
+	sp->port_1_in_sync = (data & BIT(1));
+	if (--rlen <= 0)
+		return;
+
+	data = *bp++; /* byte 0x206 */
+	sp->req_voltage_swing[0] = data & 0x03;
+	data >>= 2;
+	sp->req_pre_emphasis[0] = data & 0x03;
+	data >>= 2;
+	sp->req_voltage_swing[1] = data & 0x03;
+	data >>= 2;
+	sp->req_pre_emphasis[1] = data & 0x03;
+	if (--rlen <= 0)
+		return;
+
+	data = *bp++; /* byte 0x207 */
+	sp->req_voltage_swing[2] = data & 0x03;
+	data >>= 2;
+	sp->req_pre_emphasis[2] = data & 0x03;
+	data >>= 2;
+	sp->req_voltage_swing[3] = data & 0x03;
+	data >>= 2;
+	sp->req_pre_emphasis[3] = data & 0x03;
+}
+
+static int edp_cap_lane_rate_set(struct mdss_edp_drv_pdata *ep)
+{
+	char buf[4];
+	int len = 0;
+
+	pr_debug("%s: bw=%x lane=%d\n", __func__, ep->link_rate, ep->lane_cnt);
+	buf[0] = ep->link_rate;
+	buf[1] = ep->lane_cnt;
+	len = edp_aux_write_buf(ep, 0x100, buf, 2, 0);
+
+	return len;
+}
+
+static int edp_lane_set_write(struct mdss_edp_drv_pdata *ep, int voltage_level,
+		int pre_emphasis_level)
+{
+	int i;
+	char buf[4];
+
+	if (voltage_level >= DPCD_LINK_VOLTAGE_MAX)
+		voltage_level |= 0x04;
+
+	if (pre_emphasis_level >= DPCD_LINK_PRE_EMPHASIS_MAX)
+		pre_emphasis_level |= 0x04;
+
+	pre_emphasis_level <<= 3;
+
+	for (i = 0; i < 4; i++)
+		buf[i] = voltage_level | pre_emphasis_level;
+
+	pr_debug("%s: p|v=0x%x", __func__, voltage_level | pre_emphasis_level);
+	return edp_aux_write_buf(ep, 0x103, buf, 4, 0);
+}
+
+static int edp_powerstate_write(struct mdss_edp_drv_pdata *ep,
+					char powerstate)
+{
+	pr_debug("%s: state=%d\n", __func__, powerstate);
+	return edp_aux_write_buf(ep, 0x600, &powerstate, 1, 0);
+}
+
+static int edp_train_pattern_set_write(struct mdss_edp_drv_pdata *ep,
+						int pattern)
+{
+	char buf[4];
+
+	pr_debug("%s: pattern=%x\n", __func__, pattern);
+	buf[0] = pattern;
+	return edp_aux_write_buf(ep, 0x102, buf, 1, 0);
+}
+
+static int edp_sink_clock_recovery_done(struct mdss_edp_drv_pdata *ep)
+{
+	u32 mask;
+	u32 data;
+
+	pr_debug("%s:\n", __func__);
+
+	if (ep->lane_cnt == 1) {
+		mask = 0x01;	/* lane 0 */
+		data = ep->link_status.lane_01_status;
+	} else if (ep->lane_cnt == 2) {
+		mask = 0x011; /*B lane 0, 1 */
+		data = ep->link_status.lane_01_status;
+	} else {
+		mask = 0x01111; /*B lane 0, 1 */
+		data = ep->link_status.lane_23_status;
+		data <<= 8;
+		data |= ep->link_status.lane_01_status;
+	}
+
+	pr_debug("%s: data=%x mask=%x\n", __func__, data, mask);
+	data &= mask;
+	if (data == mask) /* all done */
+		return 1;
+
+	return 0;
+}
+
+static int edp_sink_channel_eq_done(struct mdss_edp_drv_pdata *ep)
+{
+	u32 mask;
+	u32 data;
+
+	pr_debug("%s:\n", __func__);
+
+	if (!ep->link_status.interlane_align_done) /* not align */
+		return 0;
+
+	if (ep->lane_cnt == 1) {
+		mask = 0x7;
+		data = ep->link_status.lane_01_status;
+	} else if (ep->lane_cnt == 2) {
+		mask = 0x77;
+		data = ep->link_status.lane_01_status;
+	} else {
+		mask = 0x7777;
+		data = ep->link_status.lane_23_status;
+		data <<= 8;
+		data |= ep->link_status.lane_01_status;
+	}
+
+	pr_debug("%s: data=%x mask=%x\n", __func__, data, mask);
+
+	data &= mask;
+	if (data == mask)/* all done */
+		return 1;
+
+	return 0;
+}
+
+void edp_sink_train_set_adjust(struct mdss_edp_drv_pdata *ep)
+{
+	int i;
+	int max = 0;
+
+
+	/* use the max level across lanes */
+	for (i = 0; i < ep->lane_cnt; i++) {
+		pr_debug("%s: lane=%d req_voltage_swing=%d",
+			__func__, i, ep->link_status.req_voltage_swing[i]);
+		if (max < ep->link_status.req_voltage_swing[i])
+			max = ep->link_status.req_voltage_swing[i];
+	}
+
+	ep->v_level = max;
+
+	/* use the max level across lanes */
+	max = 0;
+	for (i = 0; i < ep->lane_cnt; i++) {
+		pr_debug(" %s: lane=%d req_pre_emphasis=%d",
+			__func__, i, ep->link_status.req_pre_emphasis[i]);
+		if (max < ep->link_status.req_pre_emphasis[i])
+			max = ep->link_status.req_pre_emphasis[i];
+	}
+
+	ep->p_level = max;
+	pr_debug("%s: v_level=%d, p_level=%d", __func__,
+					ep->v_level, ep->p_level);
+}
+
+static void edp_host_train_set(struct mdss_edp_drv_pdata *ep, int train)
+{
+	int bit, cnt;
+	u32 data;
+
+
+	bit = 1;
+	bit  <<=  (train - 1);
+	pr_debug("%s: bit=%d train=%d\n", __func__, bit, train);
+	edp_write(ep->base + EDP_STATE_CTRL, bit);
+
+	bit = 8;
+	bit <<= (train - 1);
+	cnt = 10;
+	while (cnt--) {
+		data = edp_read(ep->base + EDP_MAINLINK_READY);
+		if (data & bit)
+			break;
+	}
+
+	if (cnt == 0)
+		pr_err("%s: set link_train=%d failed\n", __func__, train);
+}
+
+char vm_pre_emphasis[4][4] = {
+	{0x03, 0x06, 0x09, 0x0C},	/* pe0, 0 db */
+	{0x03, 0x06, 0x09, 0xFF},	/* pe1, 3.5 db */
+	{0x03, 0x06, 0xFF, 0xFF},	/* pe2, 6.0 db */
+	{0x03, 0xFF, 0xFF, 0xFF}	/* pe3, 9.5 db */
+};
+
+/* voltage swing, 0.2v and 1.0v are not support */
+char vm_voltage_swing[4][4] = {
+	{0x14, 0x18, 0x1A, 0x1E}, /* sw0, 0.4v  */
+	{0x18, 0x1A, 0x1E, 0xFF}, /* sw1, 0.6 v */
+	{0x1A, 0x1E, 0xFF, 0xFF}, /* sw1, 0.8 v */
+	{0x1E, 0xFF, 0xFF, 0xFF}  /* sw1, 1.2 v, optional */
+};
+
+static void edp_voltage_pre_emphasise_set(struct mdss_edp_drv_pdata *ep)
+{
+	u32 value0 = 0;
+	u32 value1 = 0;
+
+	pr_debug("%s: v=%d p=%d\n", __func__, ep->v_level, ep->p_level);
+
+	value0 = vm_pre_emphasis[(int)(ep->v_level)][(int)(ep->p_level)];
+	value1 = vm_voltage_swing[(int)(ep->v_level)][(int)(ep->p_level)];
+
+	/* Configure host and panel only if both values are allowed */
+	if (value0 != 0xFF && value1 != 0xFF) {
+		edp_write(ep->base + EDP_PHY_EDPPHY_GLB_VM_CFG0, value0);
+		edp_write(ep->base + EDP_PHY_EDPPHY_GLB_VM_CFG1, value1);
+		pr_debug("%s: value0=0x%x value1=0x%x", __func__,
+						value0, value1);
+		edp_lane_set_write(ep, ep->v_level, ep->p_level);
+	}
+
+}
+
+static int edp_start_link_train_1(struct mdss_edp_drv_pdata *ep)
+{
+	int tries, old_v_level;
+	int ret = 0;
+
+	pr_debug("%s:", __func__);
+
+	edp_host_train_set(ep, 0x01); /* train_1 */
+	edp_voltage_pre_emphasise_set(ep);
+	edp_train_pattern_set_write(ep, 0x21); /* train_1 */
+
+	tries = 0;
+	old_v_level = ep->v_level;
+	while (1) {
+		usleep(ep->dpcd.training_read_interval);
+
+		edp_link_status_read(ep, 6);
+		if (edp_sink_clock_recovery_done(ep)) {
+			ret = 0;
+			break;
+		}
+
+		if (ep->v_level == DPCD_LINK_VOLTAGE_MAX) {
+			ret = -1;
+			break;	/* quit */
+		}
+
+		if (old_v_level == ep->v_level) {
+			tries++;
+			if (tries >= 5) {
+				ret = -1;
+				break;	/* quit */
+			}
+		} else {
+			tries = 0;
+			old_v_level = ep->v_level;
+		}
+
+		edp_sink_train_set_adjust(ep);
+		edp_voltage_pre_emphasise_set(ep);
+	}
+
+	return ret;
+}
+
+static int edp_start_link_train_2(struct mdss_edp_drv_pdata *ep)
+{
+	int tries;
+	int ret = 0;
+	char pattern;
+
+	pr_debug("%s:", __func__);
+
+	if (ep->dpcd.flags & DPCD_TPS3)
+		pattern = 0x03;
+	else
+		pattern = 0x02;
+
+	edp_host_train_set(ep, pattern); /* train_2 */
+	edp_voltage_pre_emphasise_set(ep);
+	edp_train_pattern_set_write(ep, pattern | 0x20);/* train_2 */
+
+	tries = 0;
+	while (1) {
+		usleep(ep->dpcd.training_read_interval);
+
+		edp_link_status_read(ep, 6);
+
+		if (edp_sink_channel_eq_done(ep)) {
+			ret = 0;
+			break;
+		}
+
+		tries++;
+		if (tries > 5) {
+			ret = -1;
+			break;
+		}
+
+		edp_sink_train_set_adjust(ep);
+		edp_voltage_pre_emphasise_set(ep);
+	}
+
+	return ret;
+}
+
+static int edp_link_rate_shift(struct mdss_edp_drv_pdata *ep)
+{
+	/* add calculation later */
+	return -EINVAL;
+}
+
+static void edp_clear_training_pattern(struct mdss_edp_drv_pdata *ep)
+{
+	pr_debug("%s:\n", __func__);
+	edp_write(ep->base + EDP_STATE_CTRL, 0);
+	edp_train_pattern_set_write(ep, 0);
+	usleep(ep->dpcd.training_read_interval);
+}
+
+static int edp_aux_link_train(struct mdss_edp_drv_pdata *ep)
+{
+	int ret = 0;
+
+	pr_debug("%s", __func__);
+	ret = edp_aux_chan_ready(ep);
+	if (ret == 0) {
+		pr_err("%s: LINK Train failed: aux chan NOT ready\n", __func__);
+		complete(&ep->train_comp);
+		return ret;
+	}
+
+	/* start with max rate and lane */
+	ep->lane_cnt = ep->dpcd.max_lane_count;
+	ep->link_rate = ep->dpcd.max_link_rate;
+	edp_write(ep->base + EDP_MAINLINK_CTRL, 0x1);
+
+train_start:
+	ep->v_level = 0; /* start from default level */
+	ep->p_level = 0;
+	edp_cap_lane_rate_set(ep);
+
+	edp_clear_training_pattern(ep);
+	usleep(ep->dpcd.training_read_interval);
+	edp_powerstate_write(ep, 1);
+
+	ret = edp_start_link_train_1(ep);
+	if (ret < 0) {
+		if (edp_link_rate_shift(ep) == 0) {
+			goto train_start;
+		} else {
+			pr_err("%s: Training 1 failed", __func__);
+			ret = -1;
+			goto clear;
+		}
+	}
+
+	pr_debug("%s: Training 1 completed successfully", __func__);
+
+	edp_clear_training_pattern(ep);
+	ret = edp_start_link_train_2(ep);
+	if (ret < 0) {
+		if (edp_link_rate_shift(ep) == 0) {
+			goto train_start;
+		} else {
+			pr_err("%s: Training 2 failed", __func__);
+			ret = -1;
+			goto clear;
+		}
+	}
+
+	pr_debug("%s: Training 2 completed successfully", __func__);
+
+clear:
+	edp_clear_training_pattern(ep);
+
+	complete(&ep->train_comp);
+	return ret;
+}
+
+void mdss_edp_dpcd_cap_read(struct mdss_edp_drv_pdata *ep)
+{
+	edp_sink_capability_read(ep, 16);
+}
+
+void mdss_edp_dpcd_status_read(struct mdss_edp_drv_pdata *ep)
+{
+	edp_link_status_read(ep, 6);
+}
+
+void mdss_edp_edid_read(struct mdss_edp_drv_pdata *ep, int block)
+{
+	edp_sink_edid_read(ep, block);
+}
+
+int mdss_edp_link_train(struct mdss_edp_drv_pdata *ep)
+{
+	return edp_aux_link_train(ep);
+}
+
+void mdss_edp_aux_init(struct mdss_edp_drv_pdata *ep)
+{
+	mutex_init(&ep->aux_mutex);
+	init_completion(&ep->aux_comp);
+	init_completion(&ep->train_comp);
+	complete(&ep->train_comp); /* make non block at first time */
+
+	edp_buf_init(&ep->txp, ep->txbuf, sizeof(ep->txbuf));
+	edp_buf_init(&ep->rxp, ep->rxbuf, sizeof(ep->rxbuf));
+}
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index d9fffa8..ac87cbd 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -111,7 +111,7 @@
 		return ret;
 	}
 
-	if (notify > NOTIFY_UPDATE_STOP)
+	if (notify > NOTIFY_UPDATE_POWER_OFF)
 		return -EINVAL;
 
 	if (notify == NOTIFY_UPDATE_START) {
@@ -119,12 +119,19 @@
 		ret = wait_for_completion_interruptible_timeout(
 						&mfd->update.comp, 4 * HZ);
 		to_user = mfd->update.value;
-	} else {
+	} else if (notify == NOTIFY_UPDATE_STOP) {
 		INIT_COMPLETION(mfd->no_update.comp);
 		ret = wait_for_completion_interruptible_timeout(
 						&mfd->no_update.comp, 4 * HZ);
 		to_user = mfd->no_update.value;
+	} else {
+		if (mfd->panel_power_on) {
+			INIT_COMPLETION(mfd->power_off_comp);
+			ret = wait_for_completion_interruptible_timeout(
+						&mfd->power_off_comp, 1 * HZ);
+		}
 	}
+
 	if (ret == 0)
 		ret = -ETIMEDOUT;
 	else if (ret > 0)
@@ -205,9 +212,42 @@
 	return ret;
 }
 
+static void mdss_fb_parse_dt_split(struct msm_fb_data_type *mfd)
+{
+	u32 data[2];
+	struct platform_device *pdev = mfd->pdev;
+	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,mdss-fb-split",
+				       data, 2))
+		return;
+	if (data[0] && data[1] &&
+	    (mfd->panel_info->xres == (data[0] + data[1]))) {
+		mfd->split_fb_left = data[0];
+		mfd->split_fb_right = data[1];
+		pr_info("split framebuffer left=%d right=%d\n",
+			mfd->split_fb_left, mfd->split_fb_right);
+	} else {
+		mfd->split_fb_left = 0;
+		mfd->split_fb_right = 0;
+	}
+}
+
+static ssize_t mdss_fb_get_split(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = 0;
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
+	ret = snprintf(buf, PAGE_SIZE, "%d %d\n",
+		       mfd->split_fb_left, mfd->split_fb_right);
+	return ret;
+}
+
 static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
+static DEVICE_ATTR(msm_fb_split, S_IRUGO, mdss_fb_get_split, NULL);
+
 static struct attribute *mdss_fb_attrs[] = {
 	&dev_attr_msm_fb_type.attr,
+	&dev_attr_msm_fb_split.attr,
 	NULL,
 };
 
@@ -230,6 +270,16 @@
 	sysfs_remove_group(&mfd->fbi->dev->kobj, &mdss_fb_attr_group);
 }
 
+static void mdss_fb_shutdown(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+
+	if (mfd->ref_cnt > 1)
+		mfd->ref_cnt = 1;
+
+	mdss_fb_release(mfd->fbi, 0);
+}
+
 static int mdss_fb_probe(struct platform_device *pdev)
 {
 	struct msm_fb_data_type *mfd = NULL;
@@ -509,6 +559,7 @@
 	.remove = mdss_fb_remove,
 	.suspend = mdss_fb_suspend,
 	.resume = mdss_fb_resume,
+	.shutdown = mdss_fb_shutdown,
 	.driver = {
 		.name = "mdss_fb",
 		.of_match_table = mdss_fb_dt_match,
@@ -605,6 +656,9 @@
 	if (!op_enable)
 		return -EPERM;
 
+	if (mfd->dcm_state == DCM_ENTER)
+		return -EPERM;
+
 	switch (blank_mode) {
 	case FB_BLANK_UNBLANK:
 		if (!mfd->panel_power_on && mfd->mdp.on_fnc) {
@@ -646,6 +700,7 @@
 			else
 				mdss_fb_release_fences(mfd);
 			mfd->op_enable = true;
+			complete(&mfd->power_off_comp);
 		}
 		break;
 	}
@@ -975,6 +1030,9 @@
 
 	mfd->ref_cnt = 0;
 	mfd->panel_power_on = false;
+	mfd->dcm_state = DCM_UNINIT;
+
+	mdss_fb_parse_dt_split(mfd);
 
 	if (mdss_fb_alloc_fbmem(mfd)) {
 		pr_err("unable to allocate framebuffer memory\n");
@@ -991,6 +1049,7 @@
 	mfd->no_update.timer.data = (unsigned long)mfd;
 	init_completion(&mfd->update.comp);
 	init_completion(&mfd->no_update.comp);
+	init_completion(&mfd->power_off_comp);
 	init_completion(&mfd->commit_comp);
 	init_completion(&mfd->power_set_comp);
 	INIT_WORK(&mfd->commit_work, mdss_fb_commit_wq_handler);
@@ -1063,7 +1122,8 @@
 		ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info,
 				       mfd->op_enable);
 		if (ret) {
-			pr_err("can't turn off display!\n");
+			pr_err("can't turn off display attached to fb%d!\n",
+				mfd->index);
 			return ret;
 		}
 	}
@@ -1475,6 +1535,58 @@
 	return 0;
 }
 
+int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state)
+{
+	int ret = -EINVAL;
+
+	if (req_state == mfd->dcm_state) {
+		pr_warn("Already in correct DCM state");
+		ret = 0;
+	}
+
+	switch (req_state) {
+	case DCM_UNBLANK:
+		if (mfd->dcm_state == DCM_UNINIT &&
+			!mfd->panel_power_on && mfd->mdp.on_fnc) {
+			ret = mfd->mdp.on_fnc(mfd);
+			if (ret == 0) {
+				mfd->panel_power_on = true;
+				mfd->dcm_state = DCM_UNBLANK;
+			}
+		}
+		break;
+	case DCM_ENTER:
+		if (mfd->dcm_state == DCM_UNBLANK) {
+			/* Keep unblank path available for only
+			DCM operation */
+			mfd->panel_power_on = false;
+			mfd->dcm_state = DCM_ENTER;
+			ret = 0;
+		}
+		break;
+	case DCM_EXIT:
+		if (mfd->dcm_state == DCM_ENTER) {
+			/* Release the unblank path for exit */
+			mfd->panel_power_on = true;
+			mfd->dcm_state = DCM_EXIT;
+			ret = 0;
+		}
+		break;
+	case DCM_BLANK:
+		if ((mfd->dcm_state == DCM_EXIT ||
+			mfd->dcm_state == DCM_UNBLANK) &&
+			mfd->panel_power_on && mfd->mdp.off_fnc) {
+			ret = mfd->mdp.off_fnc(mfd);
+			if (ret == 0) {
+				mfd->panel_power_on = false;
+				mfd->dcm_state = DCM_UNINIT;
+			}
+		}
+		break;
+	}
+	return ret;
+}
+
 static int mdss_fb_cursor(struct fb_info *info, void __user *p)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 98bca03..030fd67 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -90,6 +90,8 @@
 	struct panel_id panel;
 	struct mdss_panel_info *panel_info;
 	int split_display;
+	int split_fb_left;
+	int split_fb_right;
 
 	u32 dest;
 	struct fb_info *fbi;
@@ -122,6 +124,7 @@
 
 	struct disp_info_notify update;
 	struct disp_info_notify no_update;
+	struct completion power_off_comp;
 
 	struct msm_mdp_interface mdp;
 
@@ -143,6 +146,8 @@
 	void *msm_fb_backup;
 	struct completion power_set_comp;
 	u32 is_power_setting;
+
+	u32 dcm_state;
 };
 
 struct msm_fb_backup_type {
@@ -175,4 +180,5 @@
 void mdss_fb_wait_for_fence(struct msm_fb_data_type *mfd);
 void mdss_fb_signal_timeline(struct msm_fb_data_type *mfd);
 int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp);
+int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state);
 #endif /* MDSS_FB_H */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index 9a5b20b..65dc19c 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -366,8 +366,9 @@
 {
 	const u8 *b = NULL;
 	u32 ndx, check_sum, print_len;
-	int block_size = 0x80;
+	int block_size;
 	int i, status;
+	int retry_cnt = 0;
 	struct hdmi_tx_ddc_data ddc_data;
 	b = edid_buf;
 
@@ -376,6 +377,9 @@
 		return -EINVAL;
 	}
 
+read_retry:
+	block_size = 0x80;
+	status = 0;
 	do {
 		DEV_DBG("EDID: reading block(%d) with block-size=%d\n",
 			block, block_size);
@@ -422,6 +426,10 @@
 				ndx, ndx+3,
 				b[ndx+0], b[ndx+1], b[ndx+2], b[ndx+3]);
 		status = -EPROTO;
+		if (retry_cnt++ < 3) {
+			DEV_DBG("Retrying reading EDID %d time\n", retry_cnt);
+			goto read_retry;
+		}
 		goto error;
 	}
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index 1f0efd3..bcd5f28 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -140,6 +140,48 @@
 		__func__, HDCP_STATE_NAME, hdcp_ddc_status, failure, nack0);
 } /* reset_hdcp_ddc_failures */
 
+static void hdmi_hdcp_hw_ddc_clean(struct hdmi_hdcp_ctrl *hdcp_ctrl)
+{
+	struct dss_io_data *io = NULL;
+	u32 hdcp_ddc_status, ddc_hw_status;
+	u32 ddc_xfer_done, ddc_xfer_req, ddc_hw_done;
+	u32 ddc_hw_not_ready;
+	u32 timeout_count;
+
+	if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	io = hdcp_ctrl->init_data.core_io;
+	if (!io->base) {
+			DEV_ERR("%s: core io not inititalized\n", __func__);
+			return;
+	}
+
+	if (DSS_REG_R(io, HDMI_DDC_HW_STATUS) != 0) {
+		/* Wait to be clean on DDC HW engine */
+		timeout_count = 100;
+		do {
+			hdcp_ddc_status = DSS_REG_R(io, HDMI_HDCP_DDC_STATUS);
+			ddc_hw_status = DSS_REG_R(io, HDMI_DDC_HW_STATUS);
+			ddc_xfer_done = (hdcp_ddc_status & BIT(10)) ;
+			ddc_xfer_req = (hdcp_ddc_status & BIT(4)) ;
+			ddc_hw_done = (ddc_hw_status & BIT(3)) ;
+			ddc_hw_not_ready = ((ddc_xfer_done != 1) ||
+			(ddc_xfer_req != 0) || (ddc_hw_done != 1));
+
+			DEV_DBG("%s: %s: timeout count(%d):ddc hw%sready\n",
+				__func__, HDCP_STATE_NAME, timeout_count,
+					ddc_hw_not_ready ? " not " : " ");
+			DEV_DBG("hdcp_ddc_status[0x%x], ddc_hw_status[0x%x]\n",
+					hdcp_ddc_status, ddc_hw_status);
+			if (ddc_hw_not_ready)
+				msleep(20);
+			} while (ddc_hw_not_ready && --timeout_count);
+	}
+} /* hdmi_hdcp_hw_ddc_clean */
+
 static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
 {
 	int rc;
@@ -853,6 +895,7 @@
 	struct delayed_work *dw = to_delayed_work(work);
 	struct hdmi_hdcp_ctrl *hdcp_ctrl = container_of(dw,
 		struct hdmi_hdcp_ctrl, hdcp_auth_work);
+	struct dss_io_data *io;
 
 	if (!hdcp_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
@@ -865,6 +908,11 @@
 		return;
 	}
 
+	io = hdcp_ctrl->init_data.core_io;
+	/* Enabling Software DDC */
+	DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION , DSS_REG_R(io,
+				HDMI_DDC_ARBITRATION) & ~(BIT(4)));
+
 	rc = hdmi_hdcp_authentication_part1(hdcp_ctrl);
 	if (rc) {
 		DEV_DBG("%s: %s: HDCP Auth Part I failed\n", __func__,
@@ -878,6 +926,10 @@
 			HDCP_STATE_NAME);
 		goto error;
 	}
+	/* Disabling software DDC before going into part3 to make sure
+	 * there is no Arbitratioon between software and hardware for DDC */
+	DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION , DSS_REG_R(io,
+				HDMI_DDC_ARBITRATION) | (BIT(4)));
 
 error:
 	/*
@@ -969,6 +1021,9 @@
 
 	DSS_REG_W(io, HDMI_HDCP_RESET, BIT(0));
 
+	/* Wait to be clean on DDC HW engine */
+	hdmi_hdcp_hw_ddc_clean(hdcp_ctrl);
+
 	/* Disable encryption and disable the HDCP block */
 	DSS_REG_W(io, HDMI_HDCP_CTRL, 0);
 
@@ -1036,6 +1091,9 @@
 
 	DSS_REG_W(io, HDMI_HDCP_RESET, BIT(0));
 
+	/* Wait to be clean on DDC HW engine */
+	hdmi_hdcp_hw_ddc_clean(hdcp_ctrl);
+
 	/* Disable encryption and disable the HDCP block */
 	DSS_REG_W(io, HDMI_HDCP_CTRL, 0);
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 91e5660..1fef395 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -87,6 +87,9 @@
 static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
 static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
 	enum hdmi_tx_power_module_type module, int enable);
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
+				bool wait_audio_tx);
+static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl);
 
 struct mdss_hw hdmi_tx_hw = {
 	.hw_ndx = MDSS_HW_HDMI,
@@ -863,13 +866,14 @@
 static void hdmi_tx_hpd_int_work(struct work_struct *work)
 {
 	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+	struct dss_io_data *io;
 
 	hdmi_ctrl = container_of(work, struct hdmi_tx_ctrl, hpd_int_work);
 	if (!hdmi_ctrl || !hdmi_ctrl->hpd_initialized) {
 		DEV_DBG("%s: invalid input\n", __func__);
 		return;
 	}
-
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	DEV_DBG("%s: Got HPD interrupt\n", __func__);
 
 	if (hdmi_ctrl->hpd_state) {
@@ -877,6 +881,9 @@
 			DEV_ERR("%s: Failed to enable ddc power\n", __func__);
 			return;
 		}
+		/* Enable SW DDC before EDID read */
+		DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION ,
+			DSS_REG_R(io, HDMI_DDC_ARBITRATION) & ~(BIT(4)));
 
 		hdmi_tx_read_sink_info(hdmi_ctrl);
 		hdmi_tx_send_cable_notification(hdmi_ctrl, 1);
@@ -1676,10 +1683,11 @@
 } /* hdmi_tx_powerdown_phy */
 
 static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
-	bool enabled, int num_of_channels)
+	bool enabled)
 {
 	/* Read first before writing */
 	u32 acr_pck_ctrl_reg;
+	u32 sample_rate;
 	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
@@ -1687,6 +1695,8 @@
 		return -EINVAL;
 	}
 
+	sample_rate = hdmi_ctrl->audio_data.sample_rate;
+
 	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	if (!io->base) {
 		DEV_ERR("%s: core io not inititalized\n", __func__);
@@ -1721,18 +1731,19 @@
 			return -EPERM;
 		}
 
-		n = audio_acr->lut[hdmi_ctrl->audio_sample_rate].n;
-		cts = audio_acr->lut[hdmi_ctrl->audio_sample_rate].cts;
-		layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+		n = audio_acr->lut[sample_rate].n;
+		cts = audio_acr->lut[sample_rate].cts;
+		layout = (MSM_HDMI_AUDIO_CHANNEL_2 ==
+			hdmi_ctrl->audio_data.channel_num) ? 0 : 1;
 
 		if (
-		(AUDIO_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
 			multiplier = 4;
 			n >>= 2; /* divide N by 4 and use multiplier */
 		} else if (
-		(AUDIO_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate)) {
+		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate)) {
 			multiplier = 2;
 			n >>= 1; /* divide N by 2 and use multiplier */
 		} else {
@@ -1743,12 +1754,16 @@
 
 		/* AUDIO_PRIORITY | SOURCE */
 		acr_pck_ctrl_reg |= 0x80000100;
+
+		/* Reset multiplier bits */
+		acr_pck_ctrl_reg &= ~(7 << 16);
+
 		/* N_MULTIPLE(multiplier) */
 		acr_pck_ctrl_reg |= (multiplier & 7) << 16;
 
-		if ((AUDIO_SAMPLE_RATE_48KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate)) {
+		if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate)) {
 			/* SELECT(3) */
 			acr_pck_ctrl_reg |= 3 << 4;
 			/* CTS_48 */
@@ -1759,9 +1774,9 @@
 			/* N */
 			DSS_REG_W(io, HDMI_ACR_48_1, n);
 		} else if (
-		(AUDIO_SAMPLE_RATE_44_1KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+		(AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
 			/* SELECT(2) */
 			acr_pck_ctrl_reg |= 2 << 4;
 			/* CTS_44 */
@@ -1800,12 +1815,15 @@
 } /* hdmi_tx_audio_acr_setup */
 
 static int hdmi_tx_audio_iframe_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
-	bool enabled, u32 num_of_channels, u32 channel_allocation,
-	u32 level_shift, bool down_mix)
+	bool enabled)
 {
 	struct dss_io_data *io = NULL;
 
 	u32 channel_count = 1; /* Def to 2 channels -> Table 17 in CEA-D */
+	u32 num_of_channels;
+	u32 channel_allocation;
+	u32 level_shift;
+	u32 down_mix;
 	u32 check_sum, audio_info_0_reg, audio_info_1_reg;
 	u32 audio_info_ctrl_reg;
 	u32 aud_pck_ctrl_2_reg;
@@ -1816,6 +1834,11 @@
 		return -EINVAL;
 	}
 
+	num_of_channels    = hdmi_ctrl->audio_data.channel_num;
+	channel_allocation = hdmi_ctrl->audio_data.spkr_alloc;
+	level_shift        = hdmi_ctrl->audio_data.level_shift;
+	down_mix           = hdmi_ctrl->audio_data.down_mix;
+
 	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	if (!io->base) {
 		DEV_ERR("%s: core io not inititalized\n", __func__);
@@ -1926,8 +1949,8 @@
 } /* hdmi_tx_audio_iframe_setup */
 
 static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
-	u32 num_of_channels, u32 channel_allocation, u32 level_shift,
-	bool down_mix)
+	u32 sample_rate, u32 num_of_channels, u32 channel_allocation,
+	u32 level_shift, bool down_mix)
 {
 	int rc = 0;
 	struct hdmi_tx_ctrl *hdmi_ctrl = platform_get_drvdata(pdev);
@@ -1937,10 +1960,31 @@
 		return -ENODEV;
 	}
 
-	if (hdmi_ctrl->panel_power_on) {
-		rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true,
-			num_of_channels, channel_allocation, level_shift,
-			down_mix);
+	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl) && hdmi_ctrl->panel_power_on) {
+
+		/* Map given sample rate to Enum */
+		if (sample_rate == 32000)
+			sample_rate = AUDIO_SAMPLE_RATE_32KHZ;
+		else if (sample_rate == 44100)
+			sample_rate = AUDIO_SAMPLE_RATE_44_1KHZ;
+		else if (sample_rate == 48000)
+			sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+		else if (sample_rate == 88200)
+			sample_rate = AUDIO_SAMPLE_RATE_88_2KHZ;
+		else if (sample_rate == 96000)
+			sample_rate = AUDIO_SAMPLE_RATE_96KHZ;
+		else if (sample_rate == 176400)
+			sample_rate = AUDIO_SAMPLE_RATE_176_4KHZ;
+		else if (sample_rate == 192000)
+			sample_rate = AUDIO_SAMPLE_RATE_192KHZ;
+
+		hdmi_ctrl->audio_data.sample_rate = sample_rate;
+		hdmi_ctrl->audio_data.channel_num = num_of_channels;
+		hdmi_ctrl->audio_data.spkr_alloc  = channel_allocation;
+		hdmi_ctrl->audio_data.level_shift = level_shift;
+		hdmi_ctrl->audio_data.down_mix    = down_mix;
+
+		rc = hdmi_tx_audio_setup(hdmi_ctrl);
 		if (rc)
 			DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.rc=%d\n",
 				__func__, rc);
@@ -2047,7 +2091,6 @@
 static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	int rc = 0;
-	const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
 	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
@@ -2061,14 +2104,14 @@
 		return -EINVAL;
 	}
 
-	rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true, channels);
+	rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true);
 	if (rc) {
 		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed. rc=%d\n",
 			__func__, rc);
 		return rc;
 	}
 
-	rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true, channels, 0, 0, false);
+	rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true);
 	if (rc) {
 		DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed. rc=%d\n",
 			__func__, rc);
@@ -2080,9 +2123,10 @@
 	return 0;
 } /* hdmi_tx_audio_setup */
 
-static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
+				bool wait_audio_tx)
 {
-	u32 i, status, sleep_us, timeout_us, timeout_sec = 15;
+	u32 i = 0, status, sleep_us, timeout_us, timeout_sec = 15;
 	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
@@ -2096,33 +2140,43 @@
 		return;
 	}
 
-	/* Check if audio engine is turned off by QDSP or not */
-	/* send off notification after every 1 sec for 15 seconds */
-	for (i = 0; i < timeout_sec; i++) {
-		sleep_us = 5000; /* Maximum time to sleep between two reads */
-		timeout_us = 1000 * 1000; /* Total time for condition to meet */
+	if (wait_audio_tx) {
+		/* Check if audio engine is turned off by QDSP or not */
+		/* send off notification after every 1 sec for 15 seconds */
+		for (i = 0; i < timeout_sec; i++) {
+			/* Maximum time to sleep between two reads */
+			sleep_us = 5000;
+			/* Total time for condition to meet */
+			timeout_us = 1000 * 1000;
 
-		if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
-			status, ((status & BIT(0)) == 0),
-			sleep_us, timeout_us)) {
+			if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
+				status, ((status & BIT(0)) == 0),
+				sleep_us, timeout_us)) {
 
-			DEV_ERR("%s: audio still on after %d sec. try again\n",
+				DEV_ERR(
+				"%s: audio still on after %d sec. try again\n",
 				__func__, i+1);
 
-			hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, true);
-			continue;
+				hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0,
+					true);
+				continue;
+			}
+			break;
 		}
-		break;
 	}
+
 	if (i == timeout_sec)
 		DEV_ERR("%s: Error: cannot turn off audio engine\n", __func__);
 
-	if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false, 0, 0, 0, false))
+	if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false))
 		DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.\n", __func__);
 
-	if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false, 0))
+	if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false))
 		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed.\n", __func__);
 
+	hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+	hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
+
 	DEV_INFO("HDMI Audio: Disabled\n");
 } /* hdmi_tx_audio_off */
 
@@ -2239,7 +2293,7 @@
 
 	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
 		hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
-		hdmi_tx_audio_off(hdmi_ctrl);
+		hdmi_tx_audio_off(hdmi_ctrl, true);
 	}
 
 	hdmi_tx_powerdown_phy(hdmi_ctrl);
@@ -2656,7 +2710,8 @@
 
 	INIT_WORK(&hdmi_ctrl->power_off_work, hdmi_tx_power_off_work);
 
-	hdmi_ctrl->audio_sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+	hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+	hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
 
 	hdmi_ctrl->sdev.name = "hdmi";
 	if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
@@ -3216,13 +3271,13 @@
 				__func__, hdmi_tx_pm_name(module_type), rc);
 			goto error;
 		}
-		mp->vreg_config[j].peak_current = val_array[i];
+		mp->vreg_config[j].enable_load = val_array[i];
 
 		DEV_DBG("%s: %s min=%d, max=%d, pc=%d\n", __func__,
 			mp->vreg_config[j].vreg_name,
 			mp->vreg_config[j].min_voltage,
 			mp->vreg_config[j].max_voltage,
-			mp->vreg_config[j].peak_current);
+			mp->vreg_config[j].enable_load);
 
 		ndx_mask >>= 1;
 		j++;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index d4f8e67..18ee782 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -38,12 +38,20 @@
 	struct dss_module_power power_data[HDMI_TX_MAX_PM];
 };
 
+struct hdmi_audio {
+	int sample_rate;
+	int channel_num;
+	int spkr_alloc;
+	int level_shift;
+	int down_mix;
+};
+
 struct hdmi_tx_ctrl {
 	struct platform_device *pdev;
 	struct hdmi_tx_platform_data pdata;
 	struct mdss_panel_data panel_data;
 
-	int audio_sample_rate;
+	struct hdmi_audio audio_data;
 
 	struct mutex mutex;
 	struct kobject *kobj;
diff --git a/drivers/video/msm/mdss/mdss_io_util.c b/drivers/video/msm/mdss/mdss_io_util.c
index 31058f8..c862e78 100644
--- a/drivers/video/msm/mdss/mdss_io_util.c
+++ b/drivers/video/msm/mdss/mdss_io_util.c
@@ -213,7 +213,7 @@
 			}
 			msleep(in_vreg[i].pre_on_sleep);
 			rc = regulator_set_optimum_mode(in_vreg[i].vreg,
-				in_vreg[i].peak_current);
+				in_vreg[i].enable_load);
 			if (rc < 0) {
 				DEV_ERR("%pS->%s: %s set opt m fail\n",
 					__builtin_return_address(0), __func__,
@@ -233,7 +233,8 @@
 		for (i = num_vreg-1; i >= 0; i--)
 			if (regulator_is_enabled(in_vreg[i].vreg)) {
 				msleep(in_vreg[i].pre_off_sleep);
-				regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+				regulator_set_optimum_mode(in_vreg[i].vreg,
+					in_vreg[i].disable_load);
 				regulator_disable(in_vreg[i].vreg);
 				msleep(in_vreg[i].post_off_sleep);
 			}
@@ -241,12 +242,13 @@
 	return rc;
 
 disable_vreg:
-	regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+	regulator_set_optimum_mode(in_vreg[i].vreg, in_vreg[i].disable_load);
 
 vreg_set_opt_mode_fail:
 	for (i--; i >= 0; i--) {
 		msleep(in_vreg[i].pre_off_sleep);
-		regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+		regulator_set_optimum_mode(in_vreg[i].vreg,
+			in_vreg[i].disable_load);
 		regulator_disable(in_vreg[i].vreg);
 		msleep(in_vreg[i].post_off_sleep);
 	}
diff --git a/drivers/video/msm/mdss/mdss_io_util.h b/drivers/video/msm/mdss/mdss_io_util.h
index cb0fb70..6ad21e8 100644
--- a/drivers/video/msm/mdss/mdss_io_util.h
+++ b/drivers/video/msm/mdss/mdss_io_util.h
@@ -52,7 +52,8 @@
 	char vreg_name[32];
 	int min_voltage;
 	int max_voltage;
-	int peak_current;
+	int enable_load;
+	int disable_load;
 	int pre_on_sleep;
 	int post_on_sleep;
 	int pre_off_sleep;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 56a4ac4..6f9c98e 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -133,6 +133,7 @@
 struct mdss_hw *mdss_irq_handlers[MDSS_MAX_HW_BLK];
 
 static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on);
+static inline int mdss_mdp_suspend_sub(struct mdss_data_type *mdata);
 static int mdss_mdp_parse_dt(struct platform_device *pdev);
 static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev);
 static int mdss_mdp_parse_dt_mixer(struct platform_device *pdev);
@@ -910,6 +911,18 @@
 	}
 }
 
+static void mdss_mdp_shutdown(struct platform_device *pdev)
+{
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+
+	if (!mdata)
+		return;
+
+	pr_debug("display shutdown\n");
+
+	mdss_mdp_suspend_sub(mdata);
+}
+
 static int mdss_mdp_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -1511,10 +1524,16 @@
 
 	rc = mdss_mdp_smp_setup(mdata, data[0], data[1]);
 
-	if (rc)
+	if (rc) {
 		pr_err("unable to setup smp data\n");
+		return rc;
+	}
 
-	return rc;
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-smp-mb-per-pipe", data);
+	mdata->smp_mb_per_pipe = (!rc ? data[0] : 0);
+
+	return 0;
 }
 
 static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
@@ -1776,7 +1795,7 @@
 	.remove = mdss_mdp_remove,
 	.suspend = mdss_mdp_suspend,
 	.resume = mdss_mdp_resume,
-	.shutdown = NULL,
+	.shutdown = mdss_mdp_shutdown,
 	.driver = {
 		/*
 		 * Driver name must match the device name added in
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 950fd27..aba77e3 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -579,6 +579,10 @@
 struct mdss_mdp_ctl *mdss_mdp_ctl_mixer_switch(struct mdss_mdp_ctl *ctl,
 					       u32 return_type);
 
+int mdss_mdp_wb_set_format(struct msm_fb_data_type *mfd, int dst_format);
+int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd,
+					struct mdp_mixer_cfg *mixer_cfg);
+
 #define mfd_to_mdp5_data(mfd) (mfd->mdp.private1)
 #define mfd_to_mdata(mfd) (((struct mdss_overlay_private *)\
 				(mfd->mdp.private1))->mdata)
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index e656131..b5a5383 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -613,6 +613,7 @@
 {
 	struct mdss_mdp_ctl *split_ctl;
 	u32 width, height;
+	int split_fb;
 
 	if (!ctl || !ctl->panel_data) {
 		pr_err("invalid ctl handle\n");
@@ -624,6 +625,13 @@
 	width = ctl->panel_data->panel_info.xres;
 	height = ctl->panel_data->panel_info.yres;
 
+	split_fb = (ctl->mfd->split_fb_left &&
+		    ctl->mfd->split_fb_right &&
+		    (ctl->mfd->split_fb_left <= MAX_MIXER_WIDTH) &&
+		    (ctl->mfd->split_fb_right <= MAX_MIXER_WIDTH)) ? 1 : 0;
+	pr_debug("max=%d xres=%d left=%d right=%d\n", MAX_MIXER_WIDTH,
+		 width, ctl->mfd->split_fb_left, ctl->mfd->split_fb_right);
+
 	if ((split_ctl && (width > MAX_MIXER_WIDTH)) ||
 			(width > (2 * MAX_MIXER_WIDTH))) {
 		pr_err("Unsupported panel resolution: %dx%d\n", width, height);
@@ -636,14 +644,16 @@
 	if (!ctl->mixer_left) {
 		ctl->mixer_left =
 			mdss_mdp_mixer_alloc(ctl, MDSS_MDP_MIXER_TYPE_INTF,
-					(width > MAX_MIXER_WIDTH));
+			 ((width > MAX_MIXER_WIDTH) || split_fb));
 		if (!ctl->mixer_left) {
 			pr_err("unable to allocate layer mixer\n");
 			return -ENOMEM;
 		}
 	}
 
-	if (width > MAX_MIXER_WIDTH)
+	if (split_fb)
+		width = ctl->mfd->split_fb_left;
+	else if (width > MAX_MIXER_WIDTH)
 		width /= 2;
 
 	ctl->mixer_left->width = width;
@@ -654,6 +664,9 @@
 		return 0;
 	}
 
+	if (split_fb)
+		width = ctl->mfd->split_fb_right;
+
 	if (width < ctl->width) {
 		if (ctl->mixer_right == NULL) {
 			ctl->mixer_right = mdss_mdp_mixer_alloc(ctl,
@@ -1722,9 +1735,13 @@
 
 static inline int __mdss_mdp_ctl_get_mixer_off(struct mdss_mdp_mixer *mixer)
 {
-	if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF)
-		return MDSS_MDP_REG_CTL_LAYER(mixer->num);
-	else
+	if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
+		if (mixer->num == MDSS_MDP_INTF_LAYERMIXER3)
+			return MDSS_MDP_CTL_X_LAYER_5;
+		else
+			return MDSS_MDP_REG_CTL_LAYER(mixer->num);
+	} else {
 		return MDSS_MDP_REG_CTL_LAYER(mixer->num +
-				MDSS_MDP_INTF_MAX_LAYERMIXER);
+				MDSS_MDP_INTF_LAYERMIXER3);
+	}
 }
diff --git a/drivers/video/msm/mdss/mdss_mdp_formats.h b/drivers/video/msm/mdss/mdss_mdp_formats.h
index acb8dc2..f5da8e6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_formats.h
+++ b/drivers/video/msm/mdss/mdss_mdp_formats.h
@@ -124,6 +124,7 @@
 	FMT_RGB_8888(MDP_RGBA_8888, 1, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA),
 	FMT_RGB_8888(MDP_RGBX_8888, 0, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA),
 	FMT_RGB_8888(MDP_BGRA_8888, 1, C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA),
+	FMT_RGB_8888(MDP_BGRX_8888, 0, C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA),
 
 	FMT_YUV_PSEUDO(MDP_Y_CRCB_H1V1, MDSS_MDP_CHROMA_RGB, C2_R_Cr, C1_B_Cb),
 	FMT_YUV_PSEUDO(MDP_Y_CBCR_H1V1, MDSS_MDP_CHROMA_RGB, C1_B_Cb, C2_R_Cr),
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index c4c19b3..ccd6e56 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -235,6 +235,7 @@
 
 #define MDSS_MDP_NUM_REG_MIXERS 3
 #define MDSS_MDP_NUM_WB_MIXERS 2
+#define MDSS_MDP_CTL_X_LAYER_5 0x24
 
 enum mdss_mdp_mixer_intf_index {
 	MDSS_MDP_INTF_LAYERMIXER0,
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index d0c1818..cb4c1f2 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -224,7 +224,6 @@
 		mdss_mdp_ctl_intf_event
 			(ctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)0);
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
-		complete(&ctx->stop_comp);
 	}
 	mutex_unlock(&ctx->clk_mtx);
 }
@@ -255,6 +254,7 @@
 	if (ctx->rdptr_enabled == 0) {
 		mdss_mdp_irq_disable_nosync
 			(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num);
+		complete(&ctx->stop_comp);
 		schedule_work(&ctx->clk_work);
 	}
 
@@ -456,7 +456,7 @@
 	struct mdss_mdp_cmd_ctx *ctx;
 	unsigned long flags;
 	int need_wait = 0;
-	int ret;
+	int ret = 0;
 
 	ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
 	if (!ctx) {
@@ -474,13 +474,15 @@
 	}
 	spin_unlock_irqrestore(&ctx->clk_lock, flags);
 
-	if (need_wait) {
+	if (need_wait)
 		if (wait_for_completion_timeout(&ctx->stop_comp, STOP_TIMEOUT)
-		    <= 0) {
+		    <= 0)
 			WARN(1, "stop cmd time out\n");
-			mdss_mdp_cmd_clk_off(ctx);
-		}
-	}
+
+	if (cancel_work_sync(&ctx->clk_work))
+		pr_debug("no pending clk work\n");
+
+	mdss_mdp_cmd_clk_off(ctx);
 
 	ctx->panel_on = 0;
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 24b27b4..4032b91 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -823,7 +823,7 @@
 		}
 		if (pipe->back_buf.num_planes) {
 			buf = &pipe->back_buf;
-		} else if (ctl->play_cnt == 0) {
+		} else if (ctl->play_cnt == 0 && pipe->front_buf.num_planes) {
 			pipe->params_changed++;
 			buf = &pipe->front_buf;
 		} else if (!pipe->params_changed) {
@@ -1601,6 +1601,13 @@
 	if (ret)
 		return ret;
 
+	/* Supprt only MDP register read/write and
+	exit_dcm in DCM state*/
+	if (mfd->dcm_state == DCM_ENTER &&
+			(mdp_pp.op != mdp_op_calib_buffer &&
+			mdp_pp.op != mdp_op_calib_dcm_state))
+		return -EPERM;
+
 	switch (mdp_pp.op) {
 	case mdp_op_pa_cfg:
 		ret = mdss_mdp_pa_config(mdp5_data->ctl,
@@ -1681,6 +1688,9 @@
 				(struct mdp_calib_config_buffer *)
 				 &mdp_pp.data.calib_buffer, &copyback);
 		break;
+	case mdp_op_calib_dcm_state:
+		ret = mdss_fb_dcm(mfd, mdp_pp.data.calib_dcm.dcm_state);
+		break;
 	default:
 		pr_err("Unsupported request to MDP_PP IOCTL. %d = op\n",
 								mdp_pp.op);
@@ -1757,6 +1767,10 @@
 			return -EPERM;
 		ret = mdss_misr_crc_set(mdata, &metadata->data.misr_request);
 		break;
+	case metadata_op_wb_format:
+		ret = mdss_mdp_wb_set_format(mfd,
+				metadata->data.mixer_cfg.writeback_format);
+		break;
 	default:
 		pr_warn("unsupported request to MDP META IOCTL\n");
 		ret = -EINVAL;
@@ -1798,6 +1812,9 @@
 			return -EPERM;
 		ret = mdss_misr_crc_get(mdata, &metadata->data.misr_request);
 		break;
+	case metadata_op_wb_format:
+		ret = mdss_mdp_wb_get_format(mfd, &metadata->data.mixer_cfg);
+		break;
 	default:
 		pr_warn("Unsupported request to MDP META IOCTL.\n");
 		ret = -EINVAL;
@@ -1859,6 +1876,7 @@
 	case MSMFB_OVERLAY_PLAY_ENABLE:
 		if (!copy_from_user(&val, argp, sizeof(val))) {
 			mdp5_data->overlay_play_enable = val;
+			ret = 0;
 		} else {
 			pr_err("OVERLAY_PLAY_ENABLE failed (%d)\n", ret);
 			ret = -EFAULT;
@@ -1978,7 +1996,8 @@
 
 	if (!mfd->panel_info->cont_splash_enabled) {
 		rc = mdss_mdp_overlay_start(mfd);
-		if (!IS_ERR_VALUE(rc) && (mfd->panel_info->type != DTV_PANEL))
+		if (!IS_ERR_VALUE(rc) && (mfd->panel_info->type != DTV_PANEL) &&
+			(mfd->panel_info->type != WRITEBACK_PANEL))
 			rc = mdss_mdp_overlay_kickoff(mfd);
 	} else {
 		rc = mdss_mdp_ctl_setup(mdp5_data->ctl);
@@ -2001,6 +2020,8 @@
 {
 	int rc;
 	struct mdss_overlay_private *mdp5_data;
+	struct mdss_mdp_mixer *mixer;
+
 	if (!mfd)
 		return -ENODEV;
 
@@ -2018,6 +2039,15 @@
 		return 0;
 
 	mdss_mdp_overlay_free_fb_pipe(mfd);
+
+	mixer = mdss_mdp_mixer_get(mdp5_data->ctl, MDSS_MDP_MIXER_MUX_LEFT);
+	if (mixer)
+		mixer->cursor_enabled = 0;
+
+	mixer = mdss_mdp_mixer_get(mdp5_data->ctl, MDSS_MDP_MIXER_MUX_RIGHT);
+	if (mixer)
+		mixer->cursor_enabled = 0;
+
 	if (!mfd->ref_cnt) {
 		mdss_mdp_overlay_release_all(mfd);
 	} else {
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index c033781..3f75053 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -30,6 +30,7 @@
 static DECLARE_BITMAP(mdss_mdp_smp_mmb_pool, MDSS_MDP_SMP_MMB_BLOCKS);
 
 static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
+static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp);
 
 static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
 				       u32 reg, u32 val)
@@ -94,6 +95,11 @@
 	}
 }
 
+static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp)
+{
+	return bitmap_weight(smp, SMP_MB_CNT) == 0;
+}
+
 static void mdss_mdp_smp_set_wm_levels(struct mdss_mdp_pipe *pipe, int mb_cnt)
 {
 	u32 fetch_size, val, wm[3];
@@ -156,6 +162,9 @@
 	int i;
 	int rc = 0, rot_mode = 0;
 	u32 nlines;
+	u16 width;
+
+	width = pipe->src.w >> pipe->horz_deci;
 
 	if (pipe->bwc_mode) {
 		rc = mdss_mdp_get_rau_strides(pipe->src.w, pipe->src.h,
@@ -166,11 +175,11 @@
 			ps.ystride[0], ps.ystride[1]);
 	} else if (mdata->has_decimation && pipe->src_fmt->is_yuv) {
 		ps.num_planes = 2;
-		ps.ystride[0] = pipe->src.w >> pipe->horz_deci;
-		ps.ystride[1] = pipe->src.h >> pipe->vert_deci;
+		ps.ystride[0] = width;
+		ps.ystride[1] = ps.ystride[0];
 	} else {
 		rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format,
-			pipe->src.w, pipe->src.h, &ps, 0);
+			width, pipe->src.h, &ps, 0);
 		if (rc)
 			return rc;
 
@@ -178,7 +187,7 @@
 			rot_mode = 1;
 		else if (ps.num_planes == 1)
 			ps.ystride[0] = MAX_BPP *
-				max(pipe->mixer->width, pipe->src.w);
+				max(pipe->mixer->width, width);
 	}
 
 	nlines = pipe->bwc_mode ? 1 : 2;
@@ -193,6 +202,11 @@
 
 			if (mdata->mdp_rev == MDSS_MDP_HW_REV_100)
 				num_blks = roundup_pow_of_two(num_blks);
+
+			if (mdata->smp_mb_per_pipe &&
+				(num_blks > mdata->smp_mb_per_pipe) &&
+				!(pipe->flags & MDP_FLIP_LR))
+				num_blks = mdata->smp_mb_per_pipe;
 		}
 
 		pr_debug("reserving %d mmb for pnum=%d plane=%d\n",
@@ -222,6 +236,8 @@
 
 	mutex_lock(&mdss_mdp_smp_lock);
 	for (i = 0; i < MAX_PLANES; i++) {
+		if (__mdss_mdp_pipe_smp_mmb_is_empty(pipe->smp_map[i].reserved))
+			continue;
 		mdss_mdp_smp_mmb_amend(pipe->smp_map[i].allocated,
 			pipe->smp_map[i].reserved);
 		cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i,
@@ -703,10 +719,9 @@
 		if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG)
 			mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_VIG_OP_MODE,
 			opmode);
-
-		mdss_mdp_smp_alloc(pipe);
 	}
 
+	mdss_mdp_smp_alloc(pipe);
 	ret = mdss_mdp_src_addr_setup(pipe, src_data);
 	if (ret) {
 		pr_err("addr setup error for pnum=%d\n", pipe->num);
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index ff54067..0c74137 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -577,6 +577,86 @@
 	}
 }
 
+int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd,
+					struct mdp_mixer_cfg *mixer_cfg)
+{
+	int dst_format;
+	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+
+	if (!ctl) {
+		pr_err("No panel data!\n");
+		return -EINVAL;
+	}
+
+	switch (ctl->dst_format) {
+	case MDP_RGB_888:
+		dst_format = WB_FORMAT_RGB_888;
+		break;
+	case MDP_RGB_565:
+		dst_format = WB_FORMAT_RGB_565;
+		break;
+	case MDP_XRGB_8888:
+		dst_format = WB_FORMAT_xRGB_8888;
+		break;
+	case MDP_ARGB_8888:
+		dst_format = WB_FORMAT_ARGB_8888;
+		break;
+	case MDP_BGRA_8888:
+		dst_format = WB_FORMAT_BGRA_8888;
+		break;
+	case MDP_BGRX_8888:
+		dst_format = WB_FORMAT_BGRX_8888;
+		break;
+	case MDP_Y_CBCR_H2V2_VENUS:
+		dst_format = WB_FORMAT_NV12;
+		break;
+	default:
+		return -EINVAL;
+	}
+	mixer_cfg->writeback_format = dst_format;
+	return 0;
+}
+
+int mdss_mdp_wb_set_format(struct msm_fb_data_type *mfd, int dst_format)
+{
+	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+
+	if (!ctl) {
+		pr_err("No panel data!\n");
+		return -EINVAL;
+	}
+
+	switch (dst_format) {
+	case WB_FORMAT_RGB_888:
+		ctl->dst_format = MDP_RGB_888;
+		break;
+	case WB_FORMAT_RGB_565:
+		ctl->dst_format = MDP_RGB_565;
+		break;
+	case WB_FORMAT_xRGB_8888:
+		ctl->dst_format = MDP_XRGB_8888;
+		break;
+	case WB_FORMAT_ARGB_8888:
+		ctl->dst_format = MDP_ARGB_8888;
+		break;
+	case WB_FORMAT_BGRA_8888:
+		ctl->dst_format = MDP_BGRA_8888;
+		break;
+	case WB_FORMAT_BGRX_8888:
+		ctl->dst_format = MDP_BGRX_8888;
+		break;
+	case WB_FORMAT_NV12:
+		ctl->dst_format = MDP_Y_CBCR_H2V2_VENUS;
+		break;
+	default:
+		pr_err("wfd format not supported\n");
+		return -EINVAL;
+	}
+
+	pr_debug("wfd format %d\n", ctl->dst_format);
+	return 0;
+}
+
 int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd,
 				void *arg)
 {
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 3f03725..82b56e3 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -373,7 +373,7 @@
 
 /*  USB_HANDSHAKING FUNCTIONS */
 static int mhl_sii_device_discovery(void *data, int id,
-			     void (*usb_notify_cb)(int online))
+			     void (*usb_notify_cb)(void *, int), void *ctx)
 {
 	int rc;
 	struct mhl_tx_ctrl *mhl_ctrl = data;
@@ -398,8 +398,10 @@
 		return -EINVAL;
 	}
 
-	if (!mhl_ctrl->notify_usb_online)
+	if (!mhl_ctrl->notify_usb_online) {
 		mhl_ctrl->notify_usb_online = usb_notify_cb;
+		mhl_ctrl->notify_ctx = ctx;
+	}
 
 	if (!mhl_ctrl->disc_enabled) {
 		spin_lock_irqsave(&mhl_ctrl->lock, flags);
@@ -904,7 +906,7 @@
 		mhl_ctrl->mhl_mode = 1;
 		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
-			mhl_ctrl->notify_usb_online(1);
+			mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 1);
 	} else {
 		pr_debug("%s: non-mhl sink\n", __func__);
 		mhl_ctrl->mhl_mode = 0;
@@ -1004,7 +1006,7 @@
 		mhl_msm_disconnection(mhl_ctrl);
 		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
-			mhl_ctrl->notify_usb_online(0);
+			mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 0);
 		return 0;
 	}
 
@@ -1019,7 +1021,7 @@
 		mhl_msm_disconnection(mhl_ctrl);
 		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
-			mhl_ctrl->notify_usb_online(0);
+			mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 0);
 		return 0;
 	}
 
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index aab67df..c24f643 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -237,17 +237,24 @@
 		return;
 	}
 
-	pr_debug("%s: Setting clock rates: pclk=%d, byteclk=%d escclk=%d\n",
+	if (!ctrl_pdata->panel_data.panel_info.cont_splash_enabled) {
+		pr_debug("%s: Set clk rates: pclk=%d, byteclk=%d escclk=%d\n",
 			__func__, ctrl_pdata->pclk_rate,
 			ctrl_pdata->byte_clk_rate, esc_clk_rate);
-	if (clk_set_rate(ctrl_pdata->esc_clk, esc_clk_rate) < 0)
-		pr_err("%s: dsi_esc_clk - clk_set_rate failed\n", __func__);
+		if (clk_set_rate(ctrl_pdata->esc_clk, esc_clk_rate) < 0)
+			pr_err("%s: dsi_esc_clk - clk_set_rate failed\n",
+				__func__);
 
-	if (clk_set_rate(ctrl_pdata->byte_clk, ctrl_pdata->byte_clk_rate) < 0)
-		pr_err("%s: dsi_byte_clk - clk_set_rate failed\n", __func__);
+		if (clk_set_rate(ctrl_pdata->byte_clk,
+			ctrl_pdata->byte_clk_rate) < 0)
+			pr_err("%s: dsi_byte_clk - clk_set_rate failed\n",
+				__func__);
 
-	if (clk_set_rate(ctrl_pdata->pixel_clk, ctrl_pdata->pclk_rate) < 0)
-		pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n", __func__);
+		if (clk_set_rate(ctrl_pdata->pixel_clk,
+			ctrl_pdata->pclk_rate) < 0)
+			pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n",
+				__func__);
+	}
 
 	clk_enable(ctrl_pdata->esc_clk);
 	clk_enable(ctrl_pdata->byte_clk);
@@ -450,30 +457,84 @@
 
 }
 
-/* EDP phy configuration settings */
-void mdss_edp_phy_sw_reset(unsigned char *edp_base)
+void mdss_edp_timing_engine_ctrl(unsigned char *edp_base, int enable)
 {
-	/* phy sw reset */
-	edp_write(edp_base + 0x74, 0x100); /* EDP_PHY_CTRL */
-	wmb();
-	usleep(1);
-	edp_write(edp_base + 0x74, 0x000); /* EDP_PHY_CTRL */
-	wmb();
-	usleep(1);
-
-	/* phy PLL sw reset */
-	edp_write(edp_base + 0x74, 0x001); /* EDP_PHY_CTRL */
-	wmb();
-	usleep(1);
-	edp_write(edp_base + 0x74, 0x000); /* EDP_PHY_CTRL */
-	wmb();
-	usleep(1);
+	/* should eb last reg to program */
+	edp_write(edp_base + 0x94, enable); /* EDP_TIMING_ENGINE_EN */
 }
 
-void mdss_edp_hw_powerup(unsigned char *edp_base, int enable)
+void mdss_edp_mainlink_ctrl(unsigned char *edp_base, int enable)
 {
-	int ret = 0;
+	edp_write(edp_base + 0x04, enable); /* EDP_MAINLINK_CTRL */
+}
 
+void mdss_edp_mainlink_reset(unsigned char *edp_base)
+{
+	edp_write(edp_base + 0x04, 0x02); /* EDP_MAINLINK_CTRL */
+	usleep(1000);
+	edp_write(edp_base + 0x04, 0); /* EDP_MAINLINK_CTRL */
+}
+
+void mdss_edp_aux_reset(unsigned char *edp_base)
+{
+	/*reset AUX */
+	edp_write(edp_base + 0x300, BIT(1)); /* EDP_AUX_CTRL */
+	usleep(1000);
+	edp_write(edp_base + 0x300, 0); /* EDP_AUX_CTRL */
+}
+
+void mdss_edp_aux_ctrl(unsigned char *edp_base, int enable)
+{
+	u32 data;
+
+	data = edp_read(edp_base + 0x300);
+	if (enable)
+		data |= 0x01;
+	else
+		data |= ~0x01;
+	edp_write(edp_base + 0x300, data); /* EDP_AUX_CTRL */
+}
+
+void mdss_edp_phy_pll_reset(unsigned char *edp_base)
+{
+	/* EDP_PHY_CTRL */
+	edp_write(edp_base + 0x74, 0x005); /* bit 0, 2 */
+	usleep(1000);
+	edp_write(edp_base + 0x74, 0x000); /* EDP_PHY_CTRL */
+}
+
+int mdss_edp_phy_pll_ready(unsigned char *edp_base)
+{
+	int cnt;
+	u32 status;
+
+	cnt = 10;
+	while (cnt--) {
+		status = edp_read(edp_base + 0x6c0);
+		if (status & 0x01)
+			break;
+		usleep(100);
+	}
+
+	if (cnt == 0) {
+		pr_err("%s: PLL NOT ready\n", __func__);
+		return 0;
+	} else
+		return 1;
+}
+
+int mdss_edp_phy_ready(unsigned char *edp_base)
+{
+	u32 status;
+
+	status = edp_read(edp_base + 0x598);
+	status &= 0x01;
+
+	return status;
+}
+
+void mdss_edp_phy_powerup(unsigned char *edp_base, int enable)
+{
 	if (enable) {
 		/* EDP_PHY_EDPPHY_GLB_PD_CTL */
 		edp_write(edp_base + 0x52c, 0x3f);
@@ -481,9 +542,6 @@
 		edp_write(edp_base + 0x528, 0x1);
 		/* EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG */
 		edp_write(edp_base + 0x620, 0xf);
-		/* EDP_AUX_CTRL */
-		ret = edp_read(edp_base + 0x300);
-		edp_write(edp_base + 0x300, ret | 0x1);
 	} else {
 		/* EDP_PHY_EDPPHY_GLB_PD_CTL */
 		edp_write(edp_base + 0x52c, 0xc0);
@@ -520,7 +578,7 @@
 		edp_write(edp_base + 0x620, 0x7);
 		edp_write(edp_base + 0x620, 0xf);
 
-	} else if (rate == 138500000) {
+	} else if (rate == 138530000) {
 		edp_write(edp_base + 0x664, 0x5); /* UNIPHY_PLL_LKDET_CFG2 */
 		edp_write(edp_base + 0x600, 0x1); /* UNIPHY_PLL_REFCLK_CFG */
 		edp_write(edp_base + 0x638, 0x36); /* UNIPHY_PLL_SDM_CFG0 */
@@ -551,7 +609,7 @@
 		edp_write(edp_base + 0x620, 0x7); /* UNIPHY_PLL_GLB_CFG */
 		edp_write(edp_base + 0x620, 0xf); /* UNIPHY_PLL_GLB_CFG */
 	} else {
-		pr_err("%s: Unknown configuration rate\n", __func__);
+		pr_err("%s: rate=%d is NOT supported\n", __func__, rate);
 	}
 }
 
@@ -591,22 +649,20 @@
 	}
 }
 
-void mdss_edp_enable_lane_bist(unsigned char *edp_base, int lane, int enable)
+void mdss_edp_lane_power_ctrl(unsigned char *edp_base, int max_lane, int up)
 {
-	unsigned char *addr_ln_bist_cfg, *addr_ln_pd_ctrl;
+	int i, off;
+	u32 data;
+
+	if (up)
+		data = 0;	/* power up */
+	else
+		data = 0x7;	/* power down */
 
 	/* EDP_PHY_EDPPHY_LNn_PD_CTL */
-	addr_ln_pd_ctrl = edp_base + 0x404 + (0x40 * lane);
-	/* EDP_PHY_EDPPHY_LNn_BIST_CFG0 */
-	addr_ln_bist_cfg = edp_base + 0x408 + (0x40 * lane);
-
-	if (enable) {
-		edp_write(addr_ln_pd_ctrl, 0x0);
-		edp_write(addr_ln_bist_cfg, 0x10);
-
-	} else {
-		edp_write(addr_ln_pd_ctrl, 0xf);
-		edp_write(addr_ln_bist_cfg, 0x10);
+	for (i = 0; i < max_lane; i++) {
+		off = 0x40 * i;
+		edp_write(edp_base + 0x404 + off , data);
 	}
 }
 
@@ -661,12 +717,47 @@
 	return -EPERM;
 }
 
-
-void mdss_edp_clk_enable(struct mdss_edp_drv_pdata *edp_drv)
+int mdss_edp_aux_clk_enable(struct mdss_edp_drv_pdata *edp_drv)
 {
+	int ret;
+
+	if (clk_set_rate(edp_drv->aux_clk, 19200000) < 0)
+		pr_err("%s: aux_clk - clk_set_rate failed\n",
+					__func__);
+
+	ret = clk_enable(edp_drv->aux_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable aux clk\n", __func__);
+		goto c2;
+	}
+
+	ret = clk_enable(edp_drv->ahb_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable ahb clk\n", __func__);
+		goto c1;
+	}
+
+	return 0;
+c1:
+	clk_disable(edp_drv->aux_clk);
+c2:
+	return ret;
+
+}
+
+void mdss_edp_aux_clk_disable(struct mdss_edp_drv_pdata *edp_drv)
+{
+	clk_disable(edp_drv->aux_clk);
+	clk_disable(edp_drv->ahb_clk);
+}
+
+int mdss_edp_clk_enable(struct mdss_edp_drv_pdata *edp_drv)
+{
+	int ret;
+
 	if (edp_drv->clk_on) {
 		pr_info("%s: edp clks are already ON\n", __func__);
-		return;
+		return 0;
 	}
 
 	if (clk_set_rate(edp_drv->aux_clk, 19200000) < 0)
@@ -681,12 +772,39 @@
 		pr_err("%s: link_clk - clk_set_rate failed\n",
 					__func__);
 
-	clk_enable(edp_drv->aux_clk);
-	clk_enable(edp_drv->pixel_clk);
-	clk_enable(edp_drv->ahb_clk);
-	clk_enable(edp_drv->link_clk);
+	ret = clk_enable(edp_drv->aux_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable aux clk\n", __func__);
+		goto c4;
+	}
+	ret = clk_enable(edp_drv->pixel_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable pixel clk\n", __func__);
+		goto c3;
+	}
+	ret = clk_enable(edp_drv->ahb_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable ahb clk\n", __func__);
+		goto c2;
+	}
+	ret = clk_enable(edp_drv->link_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable link clk\n", __func__);
+		goto c1;
+	}
 
 	edp_drv->clk_on = 1;
+
+	return 0;
+
+c1:
+	clk_disable(edp_drv->ahb_clk);
+c2:
+	clk_disable(edp_drv->pixel_clk);
+c3:
+	clk_disable(edp_drv->aux_clk);
+c4:
+	return ret;
 }
 
 void mdss_edp_clk_disable(struct mdss_edp_drv_pdata *edp_drv)
@@ -704,12 +822,69 @@
 	edp_drv->clk_on = 0;
 }
 
-void mdss_edp_prepare_clocks(struct mdss_edp_drv_pdata *edp_drv)
+int mdss_edp_prepare_aux_clocks(struct mdss_edp_drv_pdata *edp_drv)
 {
-	clk_prepare(edp_drv->aux_clk);
-	clk_prepare(edp_drv->pixel_clk);
-	clk_prepare(edp_drv->ahb_clk);
-	clk_prepare(edp_drv->link_clk);
+	int ret;
+
+	ret = clk_prepare(edp_drv->aux_clk);
+	if (ret) {
+		pr_err("%s: Failed to prepare aux clk\n", __func__);
+		goto c2;
+	}
+	ret = clk_prepare(edp_drv->ahb_clk);
+	if (ret) {
+		pr_err("%s: Failed to prepare ahb clk\n", __func__);
+		goto c1;
+	}
+
+	return 0;
+c1:
+	clk_unprepare(edp_drv->aux_clk);
+c2:
+	return ret;
+
+}
+
+void mdss_edp_unprepare_aux_clocks(struct mdss_edp_drv_pdata *edp_drv)
+{
+	clk_unprepare(edp_drv->aux_clk);
+	clk_unprepare(edp_drv->ahb_clk);
+}
+
+int mdss_edp_prepare_clocks(struct mdss_edp_drv_pdata *edp_drv)
+{
+	int ret;
+
+	ret = clk_prepare(edp_drv->aux_clk);
+	if (ret) {
+		pr_err("%s: Failed to prepare aux clk\n", __func__);
+		goto c4;
+	}
+	ret = clk_prepare(edp_drv->pixel_clk);
+	if (ret) {
+		pr_err("%s: Failed to prepare pixel clk\n", __func__);
+		goto c3;
+	}
+	ret = clk_prepare(edp_drv->ahb_clk);
+	if (ret) {
+		pr_err("%s: Failed to prepare ahb clk\n", __func__);
+		goto c2;
+	}
+	ret = clk_prepare(edp_drv->link_clk);
+	if (ret) {
+		pr_err("%s: Failed to prepare link clk\n", __func__);
+		goto c1;
+	}
+
+	return 0;
+c1:
+	clk_unprepare(edp_drv->ahb_clk);
+c2:
+	clk_unprepare(edp_drv->pixel_clk);
+c3:
+	clk_unprepare(edp_drv->aux_clk);
+c4:
+	return ret;
 }
 
 void mdss_edp_unprepare_clocks(struct mdss_edp_drv_pdata *edp_drv)
@@ -768,14 +943,29 @@
 	mdss_edp_enable_pixel_clk(edp_base, mmss_cc_base, 0);
 }
 
-void mdss_edp_phy_misc_cfg(unsigned char *edp_base)
+void mdss_edp_clock_synchrous(unsigned char *edp_base, int sync)
+{
+	u32 data;
+
+	/* EDP_MISC1_MISC0 */
+	data = edp_read(edp_base + 0x02c);
+
+	if (sync)
+		data |= 0x01;
+	else
+		data &= ~0x01;
+
+	/* EDP_MISC1_MISC0 */
+	edp_write(edp_base + 0x2c, data);
+}
+
+/* voltage mode and pre emphasis cfg */
+void mdss_edp_phy_vm_pe_init(unsigned char *edp_base)
 {
 	/* EDP_PHY_EDPPHY_GLB_VM_CFG0 */
-	edp_write(edp_base + 0x510, 0x3);
+	edp_write(edp_base + 0x510, 0x3);	/* vm only */
 	/* EDP_PHY_EDPPHY_GLB_VM_CFG1 */
 	edp_write(edp_base + 0x514, 0x64);
 	/* EDP_PHY_EDPPHY_GLB_MISC9 */
 	edp_write(edp_base + 0x518, 0x6c);
-	/* EDP_MISC1_MISC0 */
-	edp_write(edp_base + 0x2c, 0x1);
 }
diff --git a/include/linux/mfd/pm8xxx/batterydata-lib.h b/include/linux/batterydata-lib.h
similarity index 93%
rename from include/linux/mfd/pm8xxx/batterydata-lib.h
rename to include/linux/batterydata-lib.h
index 644eede..fe2d86f 100644
--- a/include/linux/mfd/pm8xxx/batterydata-lib.h
+++ b/include/linux/batterydata-lib.h
@@ -10,8 +10,8 @@
  * GNU General Public License for more details.
  */
 
-#ifndef __PM8XXX_BMS_BATTERYDATA_H
-#define __PM8XXX_BMS_BATTERYDATA_H
+#ifndef __BMS_BATTERYDATA_H
+#define __BMS_BATTERYDATA_H
 
 #include <linux/errno.h>
 
@@ -95,6 +95,11 @@
  *				battery capacitance
  * @flat_ocv_threshold_uv: the voltage where the battery's discharge curve
  *				starts flattening out.
+ * @max_voltage_uv:	max voltage of the battery
+ * @cutoff_uv:		cutoff voltage of the battery
+ * @iterm_ua:		termination current of the battery when charging
+ *			to 100%
+ * @batt_id_kohm:	battery id resistor value
  */
 
 struct bms_battery_data {
@@ -108,6 +113,10 @@
 	int			delta_rbatt_mohm;
 	int			rbatt_capacitive_mohm;
 	int			flat_ocv_threshold_uv;
+	int			max_voltage_uv;
+	int			cutoff_uv;
+	int			iterm_ua;
+	int			batt_id_kohm;
 };
 
 #if defined(CONFIG_PM8921_BMS) || \
diff --git a/include/linux/bug.h b/include/linux/bug.h
index 72961c3..cd141a4 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -96,4 +96,10 @@
 }
 
 #endif	/* CONFIG_GENERIC_BUG */
+
+#ifdef CONFIG_PANIC_ON_DATA_CORRUPTION
+#define PANIC_CORRUPTION 1
+#else
+#define PANIC_CORRUPTION 0
+#endif  /* CONFIG_PANIC_ON_DATA_CORRUPTION */
 #endif	/* _LINUX_BUG_H */
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index cfc690e..5b69884 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -39,8 +39,8 @@
 
 enum coresight_clk_rate {
 	CORESIGHT_CLK_RATE_OFF,
-	CORESIGHT_CLK_RATE_TRACE,
-	CORESIGHT_CLK_RATE_HSTRACE,
+	CORESIGHT_CLK_RATE_TRACE = 1000,
+	CORESIGHT_CLK_RATE_HSTRACE = 2000,
 };
 
 enum coresight_dev_type {
diff --git a/include/linux/epm_adc.h b/include/linux/epm_adc.h
index 4fa41b5..f94eb94 100644
--- a/include/linux/epm_adc.h
+++ b/include/linux/epm_adc.h
@@ -97,6 +97,23 @@
 	uint32_t gain;
 };
 
+struct epm_marker_level {
+	uint8_t		level;
+};
+
+struct epm_gpio_buffer_request {
+	uint8_t		cmd;
+	uint8_t		bitmask_monitor_pin;
+	uint8_t		status;
+};
+
+struct epm_get_gpio_buffer_resp {
+	uint8_t		cmd;
+	uint8_t		status;
+	uint8_t		bitmask_monitor_pin;
+	uint32_t	timestamp;
+};
+
 #ifdef __KERNEL__
 struct epm_adc_platform_data {
 	struct epm_chan_properties *channel;
@@ -121,7 +138,19 @@
 #define EPM_ADC_DEINIT		_IOR(EPM_ADC_IOCTL_CODE, 3,	\
 					     uint32_t)
 
-#define EPM_PSOC_ADC_INIT		_IOR(EPM_ADC_IOCTL_CODE, 4, \
+#define EPM_MARKER1_REQUEST	_IOWR(EPM_ADC_IOCTL_CODE, 90,	\
+						uint32_t)
+
+#define EPM_MARKER1_RELEASE	_IOWR(EPM_ADC_IOCTL_CODE, 91,	\
+						uint32_t)
+
+#define EPM_MARKER2_REQUEST	_IOWR(EPM_ADC_IOCTL_CODE, 95,	\
+						uint32_t)
+
+#define EPM_MARKER2_RELEASE	_IOWR(EPM_ADC_IOCTL_CODE, 92,	\
+						uint32_t)
+
+#define EPM_PSOC_ADC_INIT		_IOWR(EPM_ADC_IOCTL_CODE, 4, \
 					struct epm_psoc_init_resp)
 
 #define EPM_PSOC_ADC_CHANNEL_ENABLE	_IOWR(EPM_ADC_IOCTL_CODE, 5, \
@@ -157,4 +186,18 @@
 #define EPM_PSOC_ADC_SET_VADC_REFERENCE		_IOWR(EPM_ADC_IOCTL_CODE, 15, \
 						struct epm_psoc_set_vadc)
 
+#define EPM_PSOC_ADC_DEINIT		_IOWR(EPM_ADC_IOCTL_CODE, 16,	\
+							     uint32_t)
+
+#define EPM_PSOC_GPIO_BUFFER_REQUEST	_IOWR(EPM_ADC_IOCTL_CODE, 17,	\
+					struct epm_gpio_buffer_request)
+
+#define EPM_PSOC_GET_GPIO_BUFFER_DATA	_IOWR(EPM_ADC_IOCTL_CODE, 18,	\
+					struct epm_get_gpio_buffer_resp)
+
+#define EPM_PSOC_PAUSE_CONVERSION_REQUEST _IOWR(EPM_ADC_IOCTL_CODE, 19,	\
+								uint32_t)
+
+#define EPM_PSOC_UNPAUSE_CONVERSION_REQUEST _IOWR(EPM_ADC_IOCTL_CODE, 20, \
+								uint32_t)
 #endif /* __EPM_ADC_H */
diff --git a/include/linux/firmware.h b/include/linux/firmware.h
index 1e7c011..4f6fffb 100644
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -36,6 +36,8 @@
 	__used __section(.builtin_fw) = { name, blob, size }
 
 #if defined(CONFIG_FW_LOADER) || (defined(CONFIG_FW_LOADER_MODULE) && defined(MODULE))
+int request_firmware_direct(const char *name, struct device *device,
+			    phys_addr_t addr, size_t size);
 int request_firmware(const struct firmware **fw, const char *name,
 		     struct device *device);
 int request_firmware_nowait(
@@ -45,6 +47,12 @@
 
 void release_firmware(const struct firmware *fw);
 #else
+static inline int request_firmware_direct(const char *name,
+					  struct device *device,
+					  phys_addr_t addr, size_t size)
+{
+	return -EINVAL;
+}
 static inline int request_firmware(const struct firmware **fw,
 				   const char *name,
 				   struct device *device)
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index b903dfb..e9fbf90 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -77,6 +77,7 @@
 	int *key_codes;
 	bool need_calibration;
 	bool no_force_update;
+	bool no_lpm_support;
 	u8 bl_addr;
 
 	u8(*read_chg) (void);
diff --git a/include/linux/input/kxtj9.h b/include/linux/input/kxtj9.h
index d415579..65378c0 100644
--- a/include/linux/input/kxtj9.h
+++ b/include/linux/input/kxtj9.h
@@ -46,7 +46,7 @@
 	/* Output resolution: 8-bit valid or 12-bit valid */
 	#define RES_8BIT		0
 	#define RES_12BIT		(1 << 6)
-	u8 res_12bit;
+	u8 res_ctl;
 	/* Output g-range: +/-2g, 4g, or 8g */
 	#define KXTJ9_G_2G		0
 	#define KXTJ9_G_4G		(1 << 3)
diff --git a/include/linux/input/synaptics_dsx.h b/include/linux/input/synaptics_dsx.h
index 73016d6..d121695 100644
--- a/include/linux/input/synaptics_dsx.h
+++ b/include/linux/input/synaptics_dsx.h
@@ -35,8 +35,11 @@
  * struct synaptics_rmi4_platform_data - rmi4 platform data
  * @x_flip: x flip flag
  * @y_flip: y flip flag
+ * @i2c_pull_up: pull up i2c bus with regulator
+ * @power_down_enable: enable complete regulator shutdown in suspend
  * @irq_gpio: attention interrupt gpio
  * @irq_flags: flags used by the irq
+ * @reset_flags: flags used by reset line
  * @reset_gpio: reset gpio
  * @panel_x: panel maximum values on the x
  * @panel_y: panel maximum values on the y
@@ -47,6 +50,7 @@
 	bool x_flip;
 	bool y_flip;
 	bool i2c_pull_up;
+	bool power_down_enable;
 	unsigned irq_gpio;
 	u32 irq_flags;
 	u32 reset_flags;
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index cd70726..85dec85 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -14,7 +14,7 @@
 #define __PM8XXX_BMS_H
 
 #include <linux/errno.h>
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
 
 #define PM8921_BMS_DEV_NAME	"pm8921-bms"
 
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index 7297ff3..560f75b 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -137,7 +137,8 @@
 	uint8_t chip_rev_id;
 	int mhl_mode;
 	struct completion rgnd_done;
-	void (*notify_usb_online)(int online);
+	void (*notify_usb_online)(void *ctx, int online);
+	void *notify_ctx;
 	struct usb_ext_notification *mhl_info;
 	bool disc_enabled;
 	struct power_supply mhl_psy;
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 72e31b2..424b1d9 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -23,6 +23,11 @@
 	s32 cookie;
 };
 
+enum sdhci_power_policy {
+	SDHCI_PERFORMANCE_MODE,
+	SDHCI_POWER_SAVE_MODE,
+};
+
 struct sdhci_host {
 	/* Data set by hardware interface driver */
 	const char *hw_name;	/* Hardware bus name */
@@ -238,9 +243,13 @@
 
 	unsigned int cpu_dma_latency_us;
 	struct pm_qos_request pm_qos_req_dma;
+	unsigned int pm_qos_timeout_us;         /* timeout for PM QoS request */
+	struct device_attribute pm_qos_tout;
 
 	struct sdhci_next next_data;
 	ktime_t data_start_time;
+	struct mutex ios_mutex;
+	enum sdhci_power_policy power_policy;
 
 	unsigned long private[0] ____cacheline_aligned;
 };
diff --git a/include/linux/msm_audio_acdb.h b/include/linux/msm_audio_acdb.h
index a741107..e8ca1cd 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -54,12 +54,16 @@
 #define AUDIO_SET_ASM_CUSTOM_TOPOLOGY	_IOW(AUDIO_IOCTL_MAGIC, \
 			(AUDIO_MAX_COMMON_IOCTL_NUM+24), unsigned)
 #define AUDIO_SET_SPEAKER_PROT _IOW(AUDIO_IOCTL_MAGIC, 25, \
-		struct msm_spk_prot_cfg)
+			struct msm_spk_prot_cfg)
 #define AUDIO_GET_SPEAKER_PROT _IOR(AUDIO_IOCTL_MAGIC, 26, \
-		struct msm_spk_prot_status)
+			struct msm_spk_prot_status)
 #define AUDIO_SET_AANC_CAL		_IOW(AUDIO_IOCTL_MAGIC, \
 			(AUDIO_MAX_COMMON_IOCTL_NUM+27), unsigned)
-#define	AUDIO_MAX_ACDB_IOCTL	(AUDIO_MAX_COMMON_IOCTL_NUM+30)
+#define AUDIO_REGISTER_VOCPROC_VOL_TABLE	_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+28), unsigned)
+#define AUDIO_DEREGISTER_VOCPROC_VOL_TABLE	_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+29), unsigned)
+#define	AUDIO_MAX_ACDB_IOCTL	(AUDIO_MAX_COMMON_IOCTL_NUM+40)
 
 /* ACDB structures */
 struct cal_block {
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index 6a8633b..16a1000 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -72,6 +72,12 @@
  */
 #define ION_FLAG_FORCE_CONTIGUOUS (1 << 30)
 
+/*
+ * Used in conjunction with heap which pool memory to force an allocation
+ * to come from the page allocator directly instead of from the pool allocation
+ */
+#define ION_FLAG_POOL_FORCE_ALLOC (1 << 16)
+
 /**
 * Deprecated! Please use the corresponding ION_FLAG_*
 */
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index c3ff9de..2455212 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -87,6 +87,7 @@
 enum {
 	NOTIFY_UPDATE_START,
 	NOTIFY_UPDATE_STOP,
+	NOTIFY_UPDATE_POWER_OFF,
 };
 
 enum {
@@ -612,6 +613,19 @@
 	uint32_t *buffer;
 };
 
+struct mdp_calib_dcm_state {
+	uint32_t ops;
+	uint32_t dcm_state;
+};
+
+enum {
+	DCM_UNINIT,
+	DCM_UNBLANK,
+	DCM_ENTER,
+	DCM_EXIT,
+	DCM_BLANK,
+};
+
 #define MDSS_MAX_BL_BRIGHTNESS 255
 #define AD_BL_LIN_LEN (MDSS_MAX_BL_BRIGHTNESS + 1)
 
@@ -704,6 +718,7 @@
 	mdp_op_ad_input,
 	mdp_op_calib_mode,
 	mdp_op_calib_buffer,
+	mdp_op_calib_dcm_state,
 	mdp_op_max,
 };
 
@@ -713,6 +728,8 @@
 	WB_FORMAT_RGB_888,
 	WB_FORMAT_xRGB_8888,
 	WB_FORMAT_ARGB_8888,
+	WB_FORMAT_BGRA_8888,
+	WB_FORMAT_BGRX_8888,
 	WB_FORMAT_ARGB_8888_INPUT_ALPHA /* Need to support */
 };
 
@@ -732,6 +749,7 @@
 		struct mdss_calib_cfg mdss_calib_cfg;
 		struct mdss_ad_input ad_input;
 		struct mdp_calib_config_buffer calib_buffer;
+		struct mdp_calib_dcm_state calib_dcm;
 	} data;
 };
 
diff --git a/include/linux/of_batterydata.h b/include/linux/of_batterydata.h
new file mode 100644
index 0000000..b2ed5a1
--- /dev/null
+++ b/include/linux/of_batterydata.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/batterydata-lib.h>
+
+#ifdef CONFIG_OF_BATTERYDATA
+/**
+ * of_batterydata_read_data() - Populate battery data from the device tree
+ * @container_node: pointer to the battery-data container device node
+ *		containing the profile nodes.
+ * @batt_data: pointer to an allocated bms_battery_data structure that the
+ *		loaded profile will be written to.
+ * @batt_id_uv: ADC voltage of the battery id line used to differentiate
+ *		between different battery profiles. If there are multiple
+ *		battery data in the device tree, the one with the closest
+ *		battery id resistance will be automatically loaded.
+ *
+ * This routine loads the closest match battery data from device tree based on
+ * the battery id reading. Then, it will try to load all the relevant data from
+ * the device tree battery data profile.
+ *
+ * If any of the lookup table pointers are NULL, this routine will skip trying
+ * to read them.
+ */
+int of_batterydata_read_data(struct device_node *container_node,
+				struct bms_battery_data *batt_data,
+				int batt_id_uv);
+#else
+static inline int of_batterydata_read_data(struct device_node *container_node,
+				struct bms_battery_data *batt_data,
+				int batt_id_uv);
+{
+	return -ENXIO;
+}
+#endif /* CONFIG_OF_QPNP */
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 3d7b1c9..5d6cdac 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -98,7 +98,9 @@
 	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_VOLTAGE_AVG,
+	POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
 	POWER_SUPPLY_PROP_CURRENT_MAX,
+	POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CURRENT_AVG,
 	POWER_SUPPLY_PROP_POWER_NOW,
@@ -283,6 +285,7 @@
 	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
 	case POWER_SUPPLY_PROP_CHARGE_COUNTER_SHADOW:
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
 	case POWER_SUPPLY_PROP_CURRENT_AVG:
 		return 1;
diff --git a/include/linux/qpnp/power-on.h b/include/linux/qpnp/power-on.h
index 5e87259..772bf62 100644
--- a/include/linux/qpnp/power-on.h
+++ b/include/linux/qpnp/power-on.h
@@ -35,12 +35,28 @@
 	PON_KPDPWR_N,
 };
 
+/**
+ * enum pon_power_off_type: Possible power off actions to perform
+ * %PON_POWER_OFF_WARM_RESET:	Reset the MSM but not all PMIC peripherals
+ * %PON_POWER_OFF_SHUTDOWN:	Shutdown the MSM and PMIC completely
+ * %PON_POWER_OFF_HARD_RESET:	Reset the MSM and all PMIC peripherals
+};
+ */
+enum pon_power_off_type {
+	PON_POWER_OFF_WARM_RESET	= 0x01,
+	PON_POWER_OFF_SHUTDOWN		= 0x04,
+	PON_POWER_OFF_HARD_RESET	= 0x07,
+};
+
 #ifdef CONFIG_QPNP_POWER_ON
-int qpnp_pon_system_pwr_off(bool reset);
+int qpnp_pon_system_pwr_off(enum pon_power_off_type type);
 int qpnp_pon_is_warm_reset(void);
 int qpnp_pon_trigger_config(enum pon_trigger_source pon_src, bool enable);
 #else
-static int qpnp_pon_system_pwr_off(bool reset) { return -ENODEV; }
+static int qpnp_pon_system_pwr_off(enum pon_power_off_type type)
+{
+	return -ENODEV;
+}
 static inline int qpnp_pon_is_warm_reset(void) { return -ENODEV; }
 static inline int qpnp_pon_trigger_config(enum pon_trigger_source pon_src,
 							bool enable)
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index dfb156f..013a778 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -1419,11 +1419,16 @@
 	enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result,
 	enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result);
 /**
- * qpnp_iadc_calibrate_for_trim() - Clients can use this API to re-calibrate
- *		IADC.
- * @result:	0 on success.
+ * qpnp_iadc_calibrate_for_trim - Clients can use this API to re-calibrate
+ *		IADC. The offset and gain values are programmed in the trim
+ *		registers. The offset and the gain can be retrieved using
+ *		qpnp_iadc_get_gain_and_offset
+ * @batfet_closed: batfet is opened or closed. The IADC chooses proper
+ *			channel (internal/external) based on batfet status
+ *			for calibration.
+ * RETURNS:	0 on success.
  */
-int32_t qpnp_iadc_calibrate_for_trim(void);
+int32_t qpnp_iadc_calibrate_for_trim(bool batfet_closed);
 int32_t qpnp_iadc_comp_result(int64_t *result);
 #else
 static inline int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
@@ -1440,7 +1445,7 @@
 	enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result,
 	enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result)
 { return -ENXIO; }
-static inline int32_t qpnp_iadc_calibrate_for_trim(void)
+static inline int32_t qpnp_iadc_calibrate_for_trim(bool batfet_closed)
 { return -ENXIO; }
 static inline int32_t qpnp_iadc_comp_result(int64_t *result, int32_t sign)
 { return -ENXIO; }
diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h
index 294c881..6d2db8f3 100644
--- a/include/linux/qseecom.h
+++ b/include/linux/qseecom.h
@@ -36,7 +36,6 @@
 	unsigned int resp_len; /* in/out */
 };
 
-
 /*
  * struct qseecom_ion_fd_info - ion fd handle data information
  * @fd - ion handle to some memory allocated in user space
@@ -62,6 +61,7 @@
 	unsigned int resp_len; /* in/out */
 	struct qseecom_ion_fd_info ifd_data[MAX_ION_FD];
 };
+
 /*
  * struct qseecom_listener_send_resp_req - signal to continue the send_cmd req.
  * Used as a trigger from HLOS service to notify QSEECOM that it's done with its
@@ -157,6 +157,27 @@
 	int is_activated; /* out */
 };
 
+enum qseecom_buffer_protection {
+	QSEOS_UNPROTECTED_BUFFER,
+	QSEOS_PROTECT_BUFFER,
+	QSEOS_UNPROTECT_PROTECTED_BUFFER,
+};
+
+/*
+ * struct qseecom_send_modfd_resp - for send command ioctl request
+ * @req_len - command buffer length
+ * @req_buf - command buffer
+ * @ifd_data_fd - ion handle to memory allocated in user space
+ * @cmd_buf_offset - command buffer offset
+ */
+struct qseecom_send_modfd_listener_resp {
+	void *resp_buf_ptr; /* in */
+	unsigned int resp_len; /* in */
+	struct qseecom_ion_fd_info ifd_data[MAX_ION_FD]; /* in */
+	enum qseecom_buffer_protection protection_mode; /* in */
+};
+
+
 #define QSEECOM_IOC_MAGIC    0x97
 
 
@@ -220,4 +241,9 @@
 #define QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ \
 	_IOWR(QSEECOM_IOC_MAGIC, 20, struct qseecom_is_es_activated_req)
 
+#define QSEECOM_IOCTL_SEND_MODFD_RESP \
+	_IOWR(QSEECOM_IOC_MAGIC, 21, struct qseecom_send_modfd_listener_resp)
+
+#define QSEECOM_IOCTL_UNPROTECT_BUF \
+	_IOWR(QSEECOM_IOC_MAGIC, 22, int)
 #endif /* __QSEECOM_H_ */
diff --git a/include/linux/smux.h b/include/linux/smux.h
index 56b18fa..1157cef 100644
--- a/include/linux/smux.h
+++ b/include/linux/smux.h
@@ -1,6 +1,6 @@
 /* include/linux/smux.h
  *
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-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
@@ -79,6 +79,8 @@
 	SMUX_HIGH_WM_HIT,     /* @metadata is NULL */
 	SMUX_RX_RETRY_HIGH_WM_HIT,  /* @metadata is NULL */
 	SMUX_RX_RETRY_LOW_WM_HIT,   /* @metadata is NULL */
+	SMUX_LOCAL_CLOSED,
+	SMUX_REMOTE_CLOSED,
 };
 
 /**
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 1c9884c..8d104c6 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -26,6 +26,7 @@
 #include <linux/pm_qos.h>
 #include <linux/hrtimer.h>
 #include <linux/power_supply.h>
+#include <linux/cdev.h>
 /*
  * The following are bit fields describing the usb_request.udc_priv word.
  * These bit fields are set by function drivers that wish to queue
@@ -227,6 +228,8 @@
  *              interrupt threshold (ITC), when log2_itc is
  *              between 1 to 7.
  * @l1_supported: enable link power management support.
+ * @dpdm_pulldown_added: Indicates whether pull down resistors are
+		connected on data lines or not.
  */
 struct msm_otg_platform_data {
 	int *phy_init_seq;
@@ -254,6 +257,7 @@
 	const char *mhl_dev_name;
 	int log2_itc;
 	bool l1_supported;
+	bool dpdm_pulldown_added;
 };
 
 /* phy related flags */
@@ -347,6 +351,7 @@
 	struct clk *phy_reset_clk;
 	struct clk *core_clk;
 	long core_clk_rate;
+	struct resource *io_res;
 	void __iomem *regs;
 #define ID		0
 #define B_SESS_VLD	1
@@ -433,7 +438,16 @@
 	struct power_supply usb_psy;
 	unsigned int online;
 	unsigned int host_mode;
+	unsigned int voltage_max;
 	unsigned int current_max;
+
+	dev_t ext_chg_dev;
+	struct cdev ext_chg_cdev;
+	struct class *ext_chg_class;
+	struct device *ext_chg_device;
+	bool ext_chg_opened;
+	bool ext_chg_active;
+	struct completion ext_chg_wait;
 };
 
 struct ci13xxx_platform_data {
@@ -452,6 +466,7 @@
 	unsigned data;
 	bool ignore_cal_pad_config;
 	bool phy_sof_workaround;
+	u32 reset_delay;
 	int strobe_pad_offset;
 	int data_pad_offset;
 
@@ -496,7 +511,7 @@
 /**
  * struct usb_ext_notification: event notification structure
  * @notify: pointer to client function to call when ID event is detected.
- *          The last parameter is provided by driver to be called back when
+ *          The function parameter is provided by driver to be called back when
  *          external client indicates it is done using the USB. This function
  *          should return 0 if handled successfully, otherise an error code.
  * @ctxt: client-specific context pointer
@@ -510,17 +525,19 @@
  * called with the online parameter set to false.
  */
 struct usb_ext_notification {
-	int (*notify)(void *, int, void (*)(int online));
+	int (*notify)(void *, int, void (*)(void *, int online), void *);
 	void *ctxt;
 };
 #ifdef CONFIG_USB_BAM
 bool msm_bam_lpm_ok(void);
+void msm_bam_notify_lpm_resume(void);
 void msm_bam_set_hsic_host_dev(struct device *dev);
 void msm_bam_wait_for_hsic_prod_granted(void);
 bool msm_bam_hsic_lpm_ok(void);
 void msm_bam_hsic_notify_on_resume(void);
 #else
 static inline bool msm_bam_lpm_ok(void) { return true; }
+static inline void msm_bam_notify_lpm_resume(void) {}
 static inline void msm_bam_set_hsic_host_dev(struct device *dev) {}
 static inline void msm_bam_wait_for_hsic_prod_granted(void) {}
 static inline bool msm_bam_hsic_lpm_ok(void) { return true; }
@@ -540,7 +557,7 @@
 int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size,
 	u8 dst_pipe_idx);
 
-void msm_dwc3_restart_usb_session(void);
+void msm_dwc3_restart_usb_session(struct usb_gadget *gadget);
 
 int msm_register_usb_ext_notification(struct usb_ext_notification *info);
 #else
@@ -560,7 +577,7 @@
 	return -ENODEV;
 }
 
-static inline void msm_dwc3_restart_usb_session(void)
+static inline void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
 {
 	return;
 }
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index ba75cb9..064d210 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -24,6 +24,7 @@
 #define USB_HS_GPTIMER_BASE  (MSM_USB_BASE + 0x80)
 
 #define GENCFG2_SESS_VLD_CTRL_EN	BIT(7)
+#define GENCFG2_LINESTATE_DIFF_WAKEUP_EN BIT(12)
 
 #define USB_USBCMD           (MSM_USB_BASE + 0x0140)
 #define USB_USBSTS           (MSM_USB_BASE + 0x0144)
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 81187aa..4404df5 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -703,6 +703,7 @@
 #define V4L2_QCOM_BUF_FLAG_IDRFRAME	0x20000	/* Image is a IDR-frame */
 #define V4L2_QCOM_BUF_FLAG_DECODEONLY 0x40000
 #define V4L2_QCOM_BUF_DATA_CORRUPT 0x80000
+#define V4L2_QCOM_BUF_DROP_FRAME 0x100000
 
 /*
  *	O V E R L A Y   P R E V I E W
@@ -1856,6 +1857,21 @@
 	V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED = 0,
 	V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED = 1
 };
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE		\
+		(V4L2_CID_MPEG_MSM_VIDC_BASE+30)
+enum v4l2_mpeg_vidc_video_alloc_mode_type {
+	V4L2_MPEG_VIDC_VIDEO_STATIC	= 0,
+	V4L2_MPEG_VIDC_VIDEO_RING	= 1,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY	\
+		(V4L2_CID_MPEG_MSM_VIDC_BASE+31)
+enum v4l2_mpeg_vidc_video_assembly {
+	V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE	= 0,
+	V4L2_MPEG_VIDC_FRAME_ASSEMBLY_ENABLE	= 1,
+};
+
 /*  Camera class control IDs */
 #define V4L2_CID_CAMERA_CLASS_BASE 	(V4L2_CTRL_CLASS_CAMERA | 0x900)
 #define V4L2_CID_CAMERA_CLASS 		(V4L2_CTRL_CLASS_CAMERA | 1)
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 6358f8a..2805401 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -46,6 +46,8 @@
 
 #define MAX_EEPROM_NAME 32
 
+#define MAX_AF_ITERATIONS 3
+
 enum msm_camera_i2c_reg_addr_type {
 	MSM_CAMERA_I2C_BYTE_ADDR = 1,
 	MSM_CAMERA_I2C_WORD_ADDR,
@@ -78,6 +80,11 @@
 enum msm_sensor_power_seq_gpio_t {
 	SENSOR_GPIO_RESET,
 	SENSOR_GPIO_STANDBY,
+	SENSOR_GPIO_AF_PWDM,
+	SENSOR_GPIO_VIO,
+	SENSOR_GPIO_VANA,
+	SENSOR_GPIO_VDIG,
+	SENSOR_GPIO_VAF,
 	SENSOR_GPIO_MAX,
 };
 
@@ -133,6 +140,11 @@
 	REG_GPIO,
 };
 
+enum sensor_af_t {
+	SENSOR_AF_FOCUSSED,
+	SENSOR_AF_NOT_FOCUSSED,
+};
+
 struct msm_sensor_power_setting {
 	enum msm_sensor_power_seq_type_t seq_type;
 	uint16_t seq_val;
@@ -346,6 +358,11 @@
 	CFG_SET_RESOLUTION,
 	CFG_SET_STOP_STREAM,
 	CFG_SET_START_STREAM,
+	CFG_SET_SATURATION,
+	CFG_SET_CONTRAST,
+	CFG_SET_SHARPNESS,
+	CFG_SET_AUTOFOCUS,
+	CFG_CANCEL_AUTOFOCUS,
 };
 
 enum msm_actuator_cfg_type_t {
@@ -509,6 +526,9 @@
 #define VIDIOC_MSM_EEPROM_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_eeprom_cfg_data)
 
+#define VIDIOC_MSM_SENSOR_GET_AF_STATUS \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 9, uint32_t)
+
 #define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
 
 #endif /* __LINUX_MSM_CAM_SENSOR_H */
diff --git a/include/media/msmb_camera.h b/include/media/msmb_camera.h
index 388b308..62e7b27 100644
--- a/include/media/msmb_camera.h
+++ b/include/media/msmb_camera.h
@@ -39,6 +39,13 @@
 
 #define MSM_MAX_CAMERA_SENSORS  5
 
+/* The below macro is defined to put an upper limit on maximum
+ * number of buffer requested per stream. In case of extremely
+ * large value for number of buffer due to data structure corruption
+ * we return error to avoid integer overflow. This value may be
+ * configured in future*/
+#define MSM_CAMERA_MAX_STREAM_BUF 40
+
 /* featur base */
 #define MSM_CAMERA_FEATURE_BASE     0x00010000
 #define MSM_CAMERA_FEATURE_SHUTDOWN (MSM_CAMERA_FEATURE_BASE + 1)
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index 8e9aedf..162729a 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -6,6 +6,7 @@
 #endif
 #include <linux/videodev2.h>
 #include <linux/types.h>
+#include <media/msmb_generic_buf_mgr.h>
 
 /* Should be same as VIDEO_MAX_PLANES in videodev2.h */
 #define MAX_PLANES VIDEO_MAX_PLANES
@@ -174,6 +175,10 @@
 	struct msm_vpe_buffer_info_t output_buffer_info;
 };
 
+struct msm_pproc_queue_buf_info {
+	struct msm_buf_mngr_info buff_mgr_info;
+	uint8_t is_buf_dirty;
+};
 
 #define VIDIOC_MSM_CPP_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE, struct msm_camera_v4l2_ioctl_t)
@@ -218,6 +223,9 @@
 #define VIDIOC_MSM_VPE_DEQUEUE_STREAM_BUFF_INFO \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 13, struct msm_camera_v4l2_ioctl_t)
 
+#define VIDIOC_MSM_CPP_QUEUE_BUF \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 14, struct msm_camera_v4l2_ioctl_t)
+
 #define V4L2_EVENT_CPP_FRAME_DONE  (V4L2_EVENT_PRIVATE_START + 0)
 #define V4L2_EVENT_VPE_FRAME_DONE  (V4L2_EVENT_PRIVATE_START + 1)
 
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index 887b291..4cbac7b 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -77,6 +77,9 @@
 #define RDS_PS0_LEN 6
 #define RX_REPEATE_BYTE_OFFSET 5
 
+#define FM_AF_LIST_MAX_SIZE   200
+#define AF_LIST_MAX     (FM_AF_LIST_MAX_SIZE / 4) /* Each AF frequency consist
+							of sizeof(int) bytes */
 /* HCI timeouts */
 #define RADIO_HCI_TIMEOUT	(10000)	/* 10 seconds */
 
@@ -485,7 +488,7 @@
 	__le32   tune_freq;
 	__le16   pi_code;
 	__u8    af_size;
-	__u8    af_list[25];
+	__u8    af_list[FM_AF_LIST_MAX_SIZE];
 } __packed;
 
 struct hci_ev_cmd_complete {
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 364de9a..88fcf61 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -6924,6 +6924,11 @@
 /* Dolby DAP topology */
 #define DOLBY_ADM_COPP_TOPOLOGY_ID	0x0001033B
 
+/* RMS value from DSP */
+#define RMS_MODULEID_APPI_PASSTHRU  0x10009011
+#define RMS_PARAM_FIRST_SAMPLE 0x10009012
+#define RMS_PAYLOAD_LEN 4
+
 struct afe_svc_cmd_set_clip_bank_selection {
 	struct apr_hdr hdr;
 	struct afe_svc_cmd_set_param param;
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index 795bb99..e07f634 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -32,7 +32,7 @@
 int adm_open(int port, int path, int rate, int mode, int topology,
 				bool perf_mode, uint16_t bits_per_sample);
 
-int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+int adm_get_params(int port_id, uint32_t module_id, uint32_t param_id,
 			uint32_t params_length, char *params);
 
 int adm_dolby_dap_send_params(int port_id, char *params,
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index ea7a203..41f8607 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -51,6 +51,44 @@
 );
 
 /*
+ * Tracepoint for task enqueue/dequeue:
+ */
+TRACE_EVENT(sched_enq_deq_task,
+
+	TP_PROTO(struct task_struct *p, int enqueue),
+
+	TP_ARGS(p, enqueue),
+
+	TP_STRUCT__entry(
+		__array(	char,	comm,	TASK_COMM_LEN	)
+		__field(	pid_t,	pid			)
+		__field(	int,	prio			)
+		__field(	int,	cpu			)
+		__field(	int,	enqueue			)
+		__field(unsigned int,	nr_running		)
+		__field(unsigned long,	cpu_load		)
+		__field(unsigned int,	rt_nr_running		)
+	),
+
+	TP_fast_assign(
+		memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
+		__entry->pid		= p->pid;
+		__entry->prio		= p->prio;
+		__entry->cpu		= task_cpu(p);
+		__entry->enqueue	= enqueue;
+		__entry->nr_running	= task_rq(p)->nr_running;
+		__entry->cpu_load	= task_rq(p)->cpu_load[0];
+		__entry->rt_nr_running	= task_rq(p)->rt.rt_nr_running;
+	),
+
+	TP_printk("cpu=%d %s comm=%s pid=%d prio=%d nr_running=%u cpu_load=%lu rt_nr_running=%u",
+			__entry->cpu, __entry->enqueue ? "enqueue" : "dequeue",
+			__entry->comm, __entry->pid,
+			__entry->prio, __entry->nr_running,
+			__entry->cpu_load, __entry->rt_nr_running)
+);
+
+/*
  * Tracepoint for waking up a task:
  */
 DECLARE_EVENT_CLASS(sched_wakeup_template,
@@ -179,6 +217,31 @@
 		  __entry->orig_cpu, __entry->dest_cpu)
 );
 
+/*
+ * Tracepoint for a CPU going offline/online:
+ */
+TRACE_EVENT(sched_cpu_hotplug,
+
+	TP_PROTO(int affected_cpu, int error, int status),
+
+	TP_ARGS(affected_cpu, error, status),
+
+	TP_STRUCT__entry(
+		__field(	int,	affected_cpu		)
+		__field(	int,	error			)
+		__field(	int,	status			)
+	),
+
+	TP_fast_assign(
+		__entry->affected_cpu	= affected_cpu;
+		__entry->error		= error;
+		__entry->status		= status;
+	),
+
+	TP_printk("cpu %d %s error=%d", __entry->affected_cpu,
+		__entry->status ? "online" : "offline", __entry->error)
+);
+
 DECLARE_EVENT_CLASS(sched_process_template,
 
 	TP_PROTO(struct task_struct *p),
diff --git a/kernel/cpu.c b/kernel/cpu.c
index fb4a5ac..d5ab2e6 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -17,6 +17,8 @@
 #include <linux/gfp.h>
 #include <linux/suspend.h>
 
+#include <trace/events/sched.h>
+
 #ifdef CONFIG_SMP
 /* Serializes the updates to cpu_online_mask, cpu_present_mask */
 static DEFINE_MUTEX(cpu_add_remove_lock);
@@ -264,6 +266,7 @@
 
 out_release:
 	cpu_hotplug_done();
+	trace_sched_cpu_hotplug(cpu, err, 0);
 	if (!err)
 		cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu);
 	return err;
@@ -321,6 +324,7 @@
 	if (ret != 0)
 		__cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL);
 	cpu_hotplug_done();
+	trace_sched_cpu_hotplug(cpu, ret, 1);
 
 	return ret;
 }
diff --git a/kernel/power/earlysuspend.c b/kernel/power/earlysuspend.c
index 5a6b2fa..b15f02e 100644
--- a/kernel/power/earlysuspend.c
+++ b/kernel/power/earlysuspend.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/rtc.h>
+#include <linux/syscalls.h> /* sys_sync */
 #include <linux/wakelock.h>
 #include <linux/workqueue.h>
 
@@ -102,7 +103,10 @@
 	}
 	mutex_unlock(&early_suspend_lock);
 
-	suspend_sys_sync_queue();
+	if (debug_mask & DEBUG_SUSPEND)
+		pr_info("early_suspend: sync\n");
+
+	sys_sync();
 abort:
 	spin_lock_irqsave(&state_lock, irqflags);
 	if (state == SUSPEND_REQUESTED_AND_SUSPENDED)
diff --git a/kernel/power/process.c b/kernel/power/process.c
index a63b9c1..31b6f25 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -173,10 +173,6 @@
 {
 	int error;
 
-	error = sys_sync();
-	if (error)
-		return error;
-
 	printk("Freezing remaining freezable tasks ... ");
 	pm_nosig_freezing = true;
 	error = try_to_freeze_tasks(false);
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 424a389..172e415 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -279,7 +279,10 @@
 	if (!mutex_trylock(&pm_mutex))
 		return -EBUSY;
 
+	printk(KERN_INFO "PM: Syncing filesystems ... ");
 	sys_sync();
+	printk("done.\n");
+
 	pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
 	error = suspend_prepare();
 	if (error)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 3513fef..d9c4b64 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -727,6 +727,7 @@
 	update_rq_clock(rq);
 	sched_info_queued(p);
 	p->sched_class->enqueue_task(rq, p, flags);
+	trace_sched_enq_deq_task(p, 1);
 }
 
 static void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
@@ -734,6 +735,7 @@
 	update_rq_clock(rq);
 	sched_info_dequeued(p);
 	p->sched_class->dequeue_task(rq, p, flags);
+	trace_sched_enq_deq_task(p, 0);
 }
 
 void activate_task(struct rq *rq, struct task_struct *p, int flags)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index f1a6e9e..90fd57d 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -41,6 +41,7 @@
 #include <linux/debug_locks.h>
 #include <linux/lockdep.h>
 #include <linux/idr.h>
+#include <linux/bug.h>
 
 #include "workqueue_sched.h"
 
@@ -1878,6 +1879,7 @@
 		printk(KERN_ERR "    last function: ");
 		print_symbol("%s\n", (unsigned long)f);
 		debug_show_held_locks(current);
+		BUG_ON(PANIC_CORRUPTION);
 		dump_stack();
 	}
 
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 097d70f..b9060a1 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1290,6 +1290,13 @@
 
 	  If unsure, say N.
 
+config PANIC_ON_DATA_CORRUPTION
+	bool "Cause a Kernel Panic When Data Corruption is detected"
+	help
+	 Select this option to upgrade warnings for potentially
+	 recoverable data corruption scenarios to system-halting panics,
+	 for easier detection and debug.
+
 source "samples/Kconfig"
 
 source "lib/Kconfig.kgdb"
diff --git a/lib/list_debug.c b/lib/list_debug.c
index 982b850..6a039a6 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -10,6 +10,7 @@
 #include <linux/list.h>
 #include <linux/bug.h>
 #include <linux/kernel.h>
+#include <linux/bug.h>
 
 /*
  * Insert a new entry between two known consecutive entries.
@@ -30,6 +31,10 @@
 		"list_add corruption. prev->next should be "
 		"next (%p), but was %p. (prev=%p).\n",
 		next, prev->next, prev);
+
+	BUG_ON(((prev->next != next) || (next->prev != prev)) &&
+		PANIC_CORRUPTION);
+
 	next->prev = new;
 	new->next = next;
 	new->prev = prev;
@@ -55,8 +60,10 @@
 		"but was %p\n", entry, prev->next) ||
 	    WARN(next->prev != entry,
 		"list_del corruption. next->prev should be %p, "
-		"but was %p\n", entry, next->prev))
+		"but was %p\n", entry, next->prev)) {
+		BUG_ON(PANIC_CORRUPTION);
 		return;
+	}
 
 	__list_del(prev, next);
 }
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index f2aa5de..ac516f4 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -12,6 +12,7 @@
 #include <linux/debug_locks.h>
 #include <linux/delay.h>
 #include <linux/export.h>
+#include <linux/bug.h>
 
 void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name,
 			  struct lock_class_key *key)
@@ -64,6 +65,7 @@
 		owner ? owner->comm : "<none>",
 		owner ? task_pid_nr(owner) : -1,
 		lock->owner_cpu);
+	BUG_ON(PANIC_CORRUPTION);
 	dump_stack();
 }
 
diff --git a/net/core/flow.c b/net/core/flow.c
index e318c7e..9a517c6 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -423,6 +423,7 @@
 	if (!fc->percpu)
 		return -ENOMEM;
 
+	get_online_cpus();
 	for_each_online_cpu(i) {
 		if (flow_cache_cpu_prepare(fc, i))
 			goto err;
@@ -431,6 +432,7 @@
 		.notifier_call = flow_cache_cpu,
 	};
 	register_hotcpu_notifier(&fc->hotcpu_notifier);
+	put_online_cpus();
 
 	setup_timer(&fc->rnd_timer, flow_cache_new_hashrnd,
 		    (unsigned long) fc);
@@ -440,6 +442,7 @@
 	return 0;
 
 err:
+	put_online_cpus();
 	for_each_possible_cpu(i) {
 		struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, i);
 		kfree(fcp->hash_table);
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index 2b486b1..21d66c2 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -1408,12 +1408,15 @@
 		 ifname, uid, sk, direction, proto, bytes);
 
 
+	spin_lock_bh(&iface_stat_list_lock);
 	iface_entry = get_iface_entry(ifname);
 	if (!iface_entry) {
+		spin_unlock_bh(&iface_stat_list_lock);
 		pr_err("qtaguid: iface_stat: stat_update() %s not found\n",
 		       ifname);
 		return;
 	}
+	spin_unlock_bh(&iface_stat_list_lock);
 	/* It is ok to process data when an iface_entry is inactive */
 
 	MT_DEBUG("qtaguid: iface_stat: stat_update() dev=%s entry=%p\n",
diff --git a/scripts/build-all.py b/scripts/build-all.py
index c585e4a..5a109bb 100755
--- a/scripts/build-all.py
+++ b/scripts/build-all.py
@@ -46,8 +46,8 @@
 make_env = os.environ
 make_env.update({
         'ARCH': 'arm',
-        'CROSS_COMPILE': 'arm-none-linux-gnueabi-',
         'KCONFIG_NOTIMESTAMP': 'true' })
+make_env.setdefault('CROSS_COMPILE', 'arm-none-linux-gnueabi-')
 all_options = {}
 
 def error(msg):
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index de0b4da..46b0a91 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -2891,6 +2891,7 @@
 	if (client->addr != HELICON_CORE_0_I2C_ADDR)
 		goto rtn;
 
+	dev_set_name(&client->dev, "%s", MSM8X10_CODEC_NAME);
 	dev = &client->dev;
 	if (client->dev.of_node) {
 		dev_dbg(&client->dev, "%s:Platform data from device tree\n",
diff --git a/sound/soc/codecs/msm8x10-wcd.h b/sound/soc/codecs/msm8x10-wcd.h
index d8f6ace..8e561cf 100644
--- a/sound/soc/codecs/msm8x10-wcd.h
+++ b/sound/soc/codecs/msm8x10-wcd.h
@@ -32,6 +32,7 @@
 #define MSM8X10_DINO_LPASS_DIGCODEC_CBCR			0xFE02C014
 #define MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR			0xFE02C018
 
+#define MSM8X10_CODEC_NAME "msm8x10_wcd_codec"
 
 #define MSM8X10_WCD_IS_DINO_REG(reg) \
 	(((reg >= 0x400) && (reg <= 0x5FF)) ? 1 : 0)
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index 46bce9e..e5d5c32 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -113,7 +113,7 @@
 		channel_allocation);
 
 	codec_data->hdmi_ops.audio_info_setup(codec_data->hdmi_core_pdev,
-			num_channels, channel_allocation,
+			params_rate(params), num_channels, channel_allocation,
 			level_shift, down_mix);
 
 	return 0;
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 7b896c2..a6390dd 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -4554,7 +4554,6 @@
 		}
 	}
 
-	wcd9xxx_resmgr_post_ssr(&tapan->resmgr);
 	if (spkr_drv_wrnd == 1)
 		snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80, 0x80);
 
@@ -4567,6 +4566,8 @@
 
 	tapan_slim_interface_init_reg(codec);
 
+	wcd9xxx_resmgr_post_ssr(&tapan->resmgr);
+
 	wcd9xxx_mbhc_deinit(&tapan->mbhc);
 
 	if (TAPAN_IS_1_0(wcd9xxx->version))
@@ -4575,7 +4576,7 @@
 		rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
 
 	ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
-				&mbhc_cb, rco_clk_rate);
+				&mbhc_cb, rco_clk_rate, false);
 	if (ret)
 		pr_err("%s: mbhc init failed %d\n", __func__, ret);
 	else
@@ -4677,7 +4678,7 @@
 		rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
 
 	ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
-				&mbhc_cb, rco_clk_rate);
+				&mbhc_cb, rco_clk_rate, false);
 
 	if (ret) {
 		pr_err("%s: mbhc init failed %d\n", __func__, ret);
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 69e4cca..212924fd 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -2639,17 +2639,31 @@
 	case SND_SOC_DAPM_PRE_PMU:
 
 		(*dmic_clk_cnt)++;
-		if (*dmic_clk_cnt == 1)
+		if (*dmic_clk_cnt == 1) {
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x0);
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x0);
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x0);
 			snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
 					dmic_clk_en, dmic_clk_en);
+		}
 
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 
 		(*dmic_clk_cnt)--;
-		if (*dmic_clk_cnt  == 0)
+		if (*dmic_clk_cnt  == 0) {
 			snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
 					dmic_clk_en, 0);
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x4);
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x4);
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x4);
+		}
 		break;
 	}
 	return 0;
@@ -8772,6 +8786,13 @@
 				      tabla_2_higher_codec_reg_init_val[i].mask,
 				      tabla_2_higher_codec_reg_init_val[i].val);
 	}
+	snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x4);
+	snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x4);
+	snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x4);
+	snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x90, 0x90);
+	snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x8, 0x8);
+	snd_soc_update_bits(codec, TABLA_A_PIN_CTL_DATA0, 0x90, 0x0);
+	snd_soc_update_bits(codec, TABLA_A_PIN_CTL_DATA1, 0x8, 0x0);
 }
 
 static void tabla_update_reg_address(struct tabla_priv *priv)
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 03de4e0..c27e085 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -3096,6 +3096,8 @@
 {
 	struct snd_soc_codec *codec = w->codec;
 	struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
+	uint32_t impedl, impedr;
+	int ret = 0;
 
 	pr_debug("%s %s %d\n", __func__, w->name, event);
 
@@ -3107,6 +3109,13 @@
 						 WCD9XXX_CLSH_STATE_HPHL,
 						 WCD9XXX_CLSH_REQ_ENABLE,
 						 WCD9XXX_CLSH_EVENT_PRE_DAC);
+		ret = wcd9xxx_mbhc_get_impedance(&taiko_p->mbhc,
+					&impedl, &impedr);
+		if (!ret)
+			wcd9xxx_clsh_imped_config(codec, impedl);
+		else
+			dev_err(codec->dev, "Failed to get mbhc impedance %d\n",
+						ret);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
@@ -6221,7 +6230,6 @@
 						codec->reg_size, GFP_KERNEL);
 	}
 
-	wcd9xxx_resmgr_post_ssr(&taiko->resmgr);
 	if (spkr_drv_wrnd == 1)
 		snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
 
@@ -6234,6 +6242,8 @@
 	taiko_init_slim_slave_cfg(codec);
 	taiko_slim_interface_init_reg(codec);
 
+	wcd9xxx_resmgr_post_ssr(&taiko->resmgr);
+
 	if (taiko->mbhc_started) {
 		wcd9xxx_mbhc_deinit(&taiko->mbhc);
 		taiko->mbhc_started = false;
@@ -6245,7 +6255,7 @@
 
 		ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
 					taiko_enable_mbhc_micbias,
-					NULL, rco_clk_rate);
+					NULL, rco_clk_rate, true);
 		if (ret) {
 			pr_err("%s: mbhc init failed %d\n", __func__, ret);
 		} else {
@@ -6427,7 +6437,7 @@
 	/* init and start mbhc */
 	ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
 				taiko_enable_mbhc_micbias,
-				NULL, rco_clk_rate);
+				NULL, rco_clk_rate, true);
 	if (ret) {
 		pr_err("%s: mbhc init failed %d\n", __func__, ret);
 		goto err_init;
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index bfd66ea..d00b843 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -30,6 +30,387 @@
 #define BUCK_SETTLE_TIME_US 50
 #define NCP_SETTLE_TIME_US 50
 
+#define MAX_IMPED_PARAMS 13
+
+struct wcd9xxx_imped_val {
+	u32 imped_val;
+	u8 index;
+};
+
+static const struct wcd9xxx_reg_mask_val imped_table[][MAX_IMPED_PARAMS] = {
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x46},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x15},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x04},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0C},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x47},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x15},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x05},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0C},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x49},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x12},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x35},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x4E},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0E},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x49},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x16},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x17},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x5F},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xCF},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0F},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x59},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x15},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xCE},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xBD},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x07},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x10},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x66},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9A},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xBD},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA6},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x07},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x11},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x79},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x37},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA6},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAD},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x08},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x12},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x76},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x4E},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAD},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x09},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x12},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x78},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x12},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xD0},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0A},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x13},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x7A},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xB7},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0B},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x14},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x60},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x09},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA4},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1F},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0C},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x14},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x79},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x17},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAE},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1F},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0D},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x15},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x78},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x16},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0E},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x89},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x40},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x10},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x97},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xD0},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x12},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x17},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8A},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xB7},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x10},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x13},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x17},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8A},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA4},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x15},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x18},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x9A},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x08},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAE},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x27},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x18},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8B},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x18},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x20},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1A},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x9A},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x17},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1D},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x1A},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xA9},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1F},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xB9},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x10},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x23},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x18},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xA9},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x27},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x35},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x26},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
+	},
+};
+
+static const struct wcd9xxx_imped_val imped_index[] = {
+	{4000, 0},
+	{4500, 1},
+	{5000, 2},
+	{5500, 3},
+	{6000, 4},
+	{6500, 5},
+	{7000, 6},
+	{7700, 7},
+	{8470, 8},
+	{9317, 9},
+	{10248, 10},
+	{11273, 11},
+	{12400, 12},
+	{13641, 13},
+	{15005, 14},
+	{16505, 15},
+	{18156, 16},
+	{19971, 17},
+	{21969, 18},
+	{24165, 19},
+	{26582, 20},
+	{29240, 21},
+	{32164, 22},
+};
+
 static inline void wcd9xxx_enable_clsh_block(
 	struct snd_soc_codec *codec,
 	bool on)
@@ -165,6 +546,40 @@
 	}
 }
 
+static int get_impedance_index(u32 imped)
+{
+	int i = 0;
+	if (imped < imped_index[i].imped_val) {
+		pr_debug("%s, detected impedance is less than 4 Ohm\n",
+				__func__);
+		goto ret;
+	}
+	for (i = 0; i < ARRAY_SIZE(imped_index); i++) {
+		if (imped >= imped_index[i].imped_val &&
+			imped < imped_index[i + 1].imped_val)
+			break;
+	}
+ret:
+	pr_debug("%s: selected impedance index = %d\n",
+			__func__, imped_index[i].index);
+	return imped_index[i].index;
+}
+
+void wcd9xxx_clsh_imped_config(struct snd_soc_codec *codec,
+				  int imped)
+{
+	int i  = 0;
+	int index = 0;
+	index = get_impedance_index(imped);
+	if (index > ARRAY_SIZE(imped_index)) {
+		pr_err("%s, invalid imped = %d\n", __func__, imped);
+		return;
+	}
+	for (i = 0; i < MAX_IMPED_PARAMS; i++)
+		snd_soc_write(codec, imped_table[index][i].reg,
+					imped_table[index][i].val);
+}
+
 static void wcd9xxx_clsh_comp_req(struct snd_soc_codec *codec,
 				  struct wcd9xxx_clsh_cdc_data *clsh_d,
 				  int compute_pa, bool on)
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index 50381c9..654964e 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -74,6 +74,9 @@
 extern void wcd9xxx_clsh_init(struct wcd9xxx_clsh_cdc_data *clsh,
 			      struct wcd9xxx_resmgr *resmgr);
 
+extern void wcd9xxx_clsh_imped_config(struct snd_soc_codec *codec,
+				  int imped);
+
 enum wcd9xxx_codec_event {
 	WCD9XXX_CODEC_EVENT_CODEC_UP = 0,
 };
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 6605b26..6909ba7 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -220,11 +220,15 @@
 	pr_debug("%s: leave\n", __func__);
 }
 
-/* called under codec_resource_lock acquisition */
-static void __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc,
+/*
+ * called under codec_resource_lock acquisition
+ * return old status
+ */
+static bool __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc,
 				     int vddio_switch, bool restartpolling,
 				     bool checkpolling)
 {
+	bool ret;
 	int cfilt_k_val;
 	bool override;
 	struct snd_soc_codec *codec;
@@ -234,9 +238,11 @@
 
 	if (mbhc->micbias_enable) {
 		pr_debug("%s: micbias is already on\n", __func__);
-		return;
+		ret = mbhc->mbhc_micbias_switched;
+		return ret;
 	}
 
+	ret = mbhc->mbhc_micbias_switched;
 	if (vddio_switch && !mbhc->mbhc_micbias_switched &&
 	    (!checkpolling || mbhc->polling_active)) {
 		if (restartpolling)
@@ -343,11 +349,13 @@
 		mbhc->mbhc_micbias_switched = false;
 		pr_debug("%s: VDDIO switch disabled\n", __func__);
 	}
+
+	return ret;
 }
 
 static void wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc, int vddio_switch)
 {
-	return __wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
+	__wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
 }
 
 static s16 wcd9xxx_get_current_v(struct wcd9xxx_mbhc *mbhc,
@@ -791,8 +799,8 @@
 			pr_debug("%s: Enabling micbias\n", __func__);
 			mbhc->micbias_enable_cb(mbhc->codec, true);
 		}
-
-		wcd9xxx_detect_impedance(mbhc, &mbhc->zl, &mbhc->zr);
+		if (mbhc->impedance_detect)
+			wcd9xxx_detect_impedance(mbhc, &mbhc->zl, &mbhc->zr);
 		pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
 			 jack_type, mbhc->hph_status);
 		wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
@@ -1124,10 +1132,15 @@
 /*
  * wcd9xxx_find_plug_type : Find out and return the best plug type with given
  *			    list of wcd9xxx_mbhc_detect structure.
+ * param mbhc wcd9xxx_mbhc structure
+ * param dt collected measurements
+ * param size array size of dt
+ * param event_state mbhc->event_state when dt is collected
  */
 static enum wcd9xxx_mbhc_plug_type
 wcd9xxx_find_plug_type(struct wcd9xxx_mbhc *mbhc,
-		       struct wcd9xxx_mbhc_detect *dt, const int size)
+		       struct wcd9xxx_mbhc_detect *dt, const int size,
+		       unsigned long event_state)
 {
 	int i;
 	int ch;
@@ -1140,6 +1153,8 @@
 	const s16 hs_max = plug_type->v_hs_max;
 	const s16 no_mic = plug_type->v_no_mic;
 
+	pr_debug("%s: event_state 0x%lx\n", __func__, event_state);
+
 	for (i = 0, d = dt, ch = 0; i < size; i++, d++) {
 		vdce = wcd9xxx_codec_sta_dce_v(mbhc, true, d->dce);
 		if (d->vddio)
@@ -1181,7 +1196,10 @@
 			goto exit;
 		}
 	}
-	if (ch != size && ch > 0) {
+
+	if (event_state & (1 << MBHC_EVENT_PA_HPHL)) {
+		pr_debug("%s: HPHL PA was ON\n", __func__);
+	} else if (ch != size && ch > 0) {
 		pr_debug("%s: Invalid, inconsistent HPHL\n", __func__);
 		type = PLUG_TYPE_INVALID;
 		goto exit;
@@ -1221,12 +1239,18 @@
 		     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;
+
+	/* if HPHL PA was on, we cannot use hphl status */
+	if (!(event_state & (1UL << MBHC_EVENT_PA_HPHL))) {
+		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;
+		}
 	}
+
 	if (type == PLUG_TYPE_HEADSET && dvddio) {
 		if ((dvddio->_vdces > hs_max) ||
 		    (dvddio->_vdces > minv + WCD9XXX_THRESHOLD_MIC_THRESHOLD)) {
@@ -1294,6 +1318,7 @@
 wcd9xxx_codec_get_plug_type(struct wcd9xxx_mbhc *mbhc, bool highhph)
 {
 	int i;
+	bool vddioon;
 	struct wcd9xxx_mbhc_plug_type_cfg *plug_type_ptr;
 	struct wcd9xxx_mbhc_detect rt[NUM_DCE_PLUG_INS_DETECT];
 	enum wcd9xxx_mbhc_plug_type type = PLUG_TYPE_INVALID;
@@ -1308,6 +1333,13 @@
 	/* GND and MIC swap detection requires at least 2 rounds of DCE */
 	BUG_ON(NUM_DCE_PLUG_INS_DETECT < 2);
 
+	/*
+	 * There are chances vddio switch is on and cfilt voltage is adjusted
+	 * to vddio voltage even after plug type removal reported.
+	 */
+	vddioon = __wcd9xxx_switch_micbias(mbhc, 0, false, false);
+	pr_debug("%s: vddio switch was %s\n", __func__, vddioon ? "on" : "off");
+
 	plug_type_ptr =
 	    WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
 
@@ -1350,7 +1382,11 @@
 			wcd9xxx_codec_hphr_gnd_switch(codec, false);
 	}
 
-	type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt));
+	if (vddioon)
+		__wcd9xxx_switch_micbias(mbhc, 1, false, false);
+
+	type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt),
+				      mbhc->event_state);
 
 	pr_debug("%s: leave\n", __func__);
 	return type;
@@ -2134,6 +2170,7 @@
 	unsigned long timeout;
 	int retry = 0, pt_gnd_mic_swap_cnt = 0;
 	bool correction = false;
+	bool wrk_complete = true;
 
 	pr_debug("%s: enter\n", __func__);
 
@@ -2159,12 +2196,14 @@
 		++retry;
 		rmb();
 		if (mbhc->hs_detect_work_stop) {
+			wrk_complete = false;
 			pr_debug("%s: stop requested\n", __func__);
 			break;
 		}
 
 		msleep(HS_DETECT_PLUG_INERVAL_MS);
 		if (wcd9xxx_swch_level_remove(mbhc)) {
+			wrk_complete = false;
 			pr_debug("%s: Switch level is low\n", __func__);
 			break;
 		}
@@ -2238,7 +2277,9 @@
 	if (plug_type == PLUG_TYPE_HIGH_HPH) {
 		pr_debug("%s: polling is done, still HPH, so enabling MIC trigger\n",
 			 __func__);
+		WCD9XXX_BCL_LOCK(mbhc->resmgr);
 		wcd9xxx_find_plug_and_report(mbhc, plug_type);
+		WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
 	}
 	/* Turn off override */
 	if (!correction)
@@ -2248,10 +2289,11 @@
 
 	if (mbhc->mbhc_cfg->detect_extn_cable) {
 		WCD9XXX_BCL_LOCK(mbhc->resmgr);
-		if (mbhc->current_plug == PLUG_TYPE_HEADPHONE ||
+		if ((mbhc->current_plug == PLUG_TYPE_HEADPHONE &&
+		    wrk_complete) ||
 		    mbhc->current_plug == PLUG_TYPE_GND_MIC_SWAP ||
 		    mbhc->current_plug == PLUG_TYPE_INVALID ||
-		    plug_type == PLUG_TYPE_INVALID) {
+		    (plug_type == PLUG_TYPE_INVALID && wrk_complete)) {
 			/* Enable removal detection */
 			wcd9xxx_cleanup_hs_polling(mbhc);
 			wcd9xxx_enable_hs_detect(mbhc, 0, 0, false);
@@ -3896,7 +3938,8 @@
 int wcd9xxx_mbhc_init(struct wcd9xxx_mbhc *mbhc, struct wcd9xxx_resmgr *resmgr,
 		      struct snd_soc_codec *codec,
 		      int (*micbias_enable_cb) (struct snd_soc_codec*,  bool),
-		      const struct wcd9xxx_mbhc_cb *mbhc_cb, int rco_clk_rate)
+		      const struct wcd9xxx_mbhc_cb *mbhc_cb, int rco_clk_rate,
+		      bool impedance_det_en)
 {
 	int ret;
 	void *core;
@@ -3922,6 +3965,7 @@
 	mbhc->micbias_enable_cb = micbias_enable_cb;
 	mbhc->rco_clk_rate = rco_clk_rate;
 	mbhc->mbhc_cb = mbhc_cb;
+	mbhc->impedance_detect = impedance_det_en;
 
 	if (mbhc->headset_jack.jack == NULL) {
 		ret = snd_soc_jack_new(codec, "Headset Jack", WCD9XXX_JACK_MASK,
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index 1f6502f..0599ccb 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -291,6 +291,7 @@
 	bool micbias_enable;
 	int (*micbias_enable_cb) (struct snd_soc_codec*,  bool);
 
+	bool impedance_detect;
 	/* impedance of hphl and hphr */
 	uint32_t zl, zr;
 
@@ -363,7 +364,8 @@
 		      struct snd_soc_codec *codec,
 		      int (*micbias_enable_cb) (struct snd_soc_codec*,  bool),
 		      const struct wcd9xxx_mbhc_cb *mbhc_cb,
-		      int rco_clk_rate);
+		      int rco_clk_rate,
+		      bool impedance_det_en);
 void wcd9xxx_mbhc_deinit(struct wcd9xxx_mbhc *mbhc);
 void *wcd9xxx_mbhc_cal_btn_det_mp(
 			    const struct wcd9xxx_mbhc_btn_detect_cfg *btn_det,
diff --git a/sound/soc/msm/apq8074.c b/sound/soc/msm/apq8074.c
index cb101bd..3a055e2 100644
--- a/sound/soc/msm/apq8074.c
+++ b/sound/soc/msm/apq8074.c
@@ -123,7 +123,7 @@
 	.gpio = 0,
 	.gpio_irq = 0,
 	.gpio_level_insert = 1,
-	.detect_extn_cable = true,
+	.detect_extn_cable = false,
 	.insert_detect = true,
 	.swap_gnd_mic = NULL,
 };
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index a0ed887..41fe8aa 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -741,6 +741,30 @@
 		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "MultiMedia9",
 	},
+	{
+		.playback = {
+			.stream_name = "QCHAT Playback",
+			.aif_name = "QCHAT_DL",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min = 8000,
+			.rate_max = 48000,
+		},
+		.capture = {
+			.stream_name = "QCHAT Capture",
+			.aif_name = "QCHAT_UL",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min = 8000,
+			.rate_max = 48000,
+		},
+		.ops = &msm_fe_dai_ops,
+		.name = "QCHAT",
+	},
 };
 
 static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 043a998..d3ba3d5 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -36,12 +36,20 @@
 #define BTSCO_RATE_8KHZ 8000
 #define BTSCO_RATE_16KHZ 16000
 
+/* It takes about 13ms for Class-D PAs to ramp-up */
+#define EXT_CLASS_D_EN_DELAY 13000
+#define EXT_CLASS_D_DIS_DELAY 3000
+#define EXT_CLASS_D_DELAY_DELTA 2000
+
 #define WCD9XXX_MBHC_DEF_BUTTONS 8
 #define WCD9XXX_MBHC_DEF_RLOADS 5
 #define TAPAN_EXT_CLK_RATE 9600000
 
 #define NUM_OF_AUXPCM_GPIOS 4
 
+#define LO_1_SPK_AMP   0x1
+#define LO_2_SPK_AMP   0x2
+
 static int msm8226_auxpcm_rate = 8000;
 static atomic_t auxpcm_rsc_ref;
 static const char *const auxpcm_rate_text[] = {"rate_8000", "rate_16000"};
@@ -116,6 +124,7 @@
 	SLIM_4_TX_1 = 150, /* In-call musid delivery TX */
 };
 
+static int msm8226_ext_spk_pamp;
 static int msm_slim_0_rx_ch = 1;
 static int msm_slim_0_tx_ch = 1;
 
@@ -125,6 +134,7 @@
 static struct mutex cdc_mclk_mutex;
 static struct clk *codec_clk;
 static int clk_users;
+static int ext_spk_amp_gpio = -1;
 static int vdd_spkr_gpio = -1;
 static int msm_proxy_rx_ch = 2;
 
@@ -189,6 +199,99 @@
 	return 0;
 }
 
+static void msm8226_ext_spk_power_amp_enable(u32 enable)
+{
+	if (enable) {
+		gpio_direction_output(ext_spk_amp_gpio, enable);
+		/* time takes enable the external power amplifier */
+		usleep_range(EXT_CLASS_D_EN_DELAY,
+			EXT_CLASS_D_EN_DELAY + EXT_CLASS_D_DELAY_DELTA);
+	} else {
+		gpio_direction_output(ext_spk_amp_gpio, enable);
+		/* time takes disable the external power amplifier */
+		usleep_range(EXT_CLASS_D_DIS_DELAY,
+			EXT_CLASS_D_DIS_DELAY + EXT_CLASS_D_DELAY_DELTA);
+	}
+
+	pr_debug("%s: %s external speaker PAs.\n", __func__,
+		enable ? "Enable" : "Disable");
+}
+
+static void msm8226_ext_spk_power_amp_on(u32 spk)
+{
+	if (gpio_is_valid(ext_spk_amp_gpio)) {
+		if (spk & (LO_1_SPK_AMP | LO_2_SPK_AMP)) {
+			pr_debug("%s:Enable left and right speakers case spk = 0x%x\n",
+				__func__, spk);
+
+			msm8226_ext_spk_pamp |= spk;
+
+			if ((msm8226_ext_spk_pamp & LO_1_SPK_AMP) &&
+				(msm8226_ext_spk_pamp & LO_2_SPK_AMP))
+				if (ext_spk_amp_gpio >= 0) {
+					pr_debug("%s  enable power", __func__);
+					msm8226_ext_spk_power_amp_enable(1);
+				}
+		} else  {
+			pr_err("%s: Invalid external speaker ampl. spk = 0x%x\n",
+				__func__, spk);
+		}
+	}
+}
+
+static void msm8226_ext_spk_power_amp_off(u32 spk)
+{
+	if (gpio_is_valid(ext_spk_amp_gpio)) {
+		if (spk & (LO_1_SPK_AMP | LO_2_SPK_AMP)) {
+			pr_debug("%s Disable left and right speakers case spk = 0x%08x",
+				__func__, spk);
+
+			msm8226_ext_spk_pamp &= ~spk;
+
+			if (!msm8226_ext_spk_pamp) {
+				if (ext_spk_amp_gpio >= 0) {
+					pr_debug("%s  disable power", __func__);
+					msm8226_ext_spk_power_amp_enable(0);
+				}
+				msm8226_ext_spk_pamp = 0;
+			}
+		 } else  {
+			pr_err("%s: ERROR : Invalid Ext Spk Ampl. spk = 0x%08x\n",
+				__func__, spk);
+		}
+	}
+}
+
+static int msm8226_ext_spkramp_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *k, int event)
+{
+	pr_debug("%s()\n", __func__);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		if (!strncmp(w->name, "Lineout_1 amp", 14))
+			msm8226_ext_spk_power_amp_on(LO_1_SPK_AMP);
+		else if (!strncmp(w->name, "Lineout_2 amp", 14))
+			msm8226_ext_spk_power_amp_on(LO_2_SPK_AMP);
+		else {
+			pr_err("%s() Invalid Speaker Widget = %s\n",
+				__func__, w->name);
+			return -EINVAL;
+		}
+	} else {
+		if (!strncmp(w->name, "Lineout_1 amp", 14))
+			msm8226_ext_spk_power_amp_off(LO_1_SPK_AMP);
+		else if (!strncmp(w->name, "Lineout_2 amp", 14))
+			msm8226_ext_spk_power_amp_off(LO_2_SPK_AMP);
+		else {
+			pr_err("%s() Invalid Speaker Widget = %s\n",
+				__func__, w->name);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 static int msm8226_vdd_spkr_event(struct snd_soc_dapm_widget *w,
 		struct snd_kcontrol *kcontrol, int event)
 {
@@ -230,6 +333,9 @@
 	SND_SOC_DAPM_MIC("Digital Mic5", NULL),
 	SND_SOC_DAPM_MIC("Digital Mic6", NULL),
 
+	SND_SOC_DAPM_SPK("Lineout_1 amp", msm8226_ext_spkramp_event),
+	SND_SOC_DAPM_SPK("Lineout_2 amp", msm8226_ext_spkramp_event),
+
 	SND_SOC_DAPM_SUPPLY("EXT_VDD_SPKR",  SND_SOC_NOPM, 0, 0,
 	msm8226_vdd_spkr_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 };
@@ -1437,7 +1543,7 @@
 	pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
 				"qcom,cdc-us-euro-gpios", 0);
 	if (pdata->us_euro_gpio < 0) {
-		dev_info(&pdev->dev,
+		dev_dbg(&pdev->dev,
 			"property %s in node %s not found %d\n",
 			"qcom,cdc-us-euro-gpios", pdev->dev.of_node->full_name,
 			pdata->us_euro_gpio);
@@ -1527,7 +1633,7 @@
 	vdd_spkr_gpio = of_get_named_gpio(pdev->dev.of_node,
 				"qcom,cdc-vdd-spkr-gpios", 0);
 	if (vdd_spkr_gpio < 0) {
-		dev_err(&pdev->dev,
+		dev_dbg(&pdev->dev,
 			"Looking up %s property in node %s failed %d\n",
 			"qcom, cdc-vdd-spkr-gpios",
 			pdev->dev.of_node->full_name, vdd_spkr_gpio);
@@ -1542,19 +1648,38 @@
 		}
 	}
 
+	ext_spk_amp_gpio = of_get_named_gpio(pdev->dev.of_node,
+			"qcom,cdc-lineout-spkr-gpios", 0);
+	if (ext_spk_amp_gpio < 0) {
+		dev_err(&pdev->dev,
+			"Looking up %s property in node %s failed %d\n",
+			"qcom, cdc-lineout-spkr-gpios",
+			pdev->dev.of_node->full_name, ext_spk_amp_gpio);
+	} else {
+		ret = gpio_request(ext_spk_amp_gpio,
+				"TAPAN_CODEC_LINEOUT_SPKR");
+		if (ret) {
+			/* GPIO to enable EXT AMP exists, but failed request */
+			dev_err(card->dev,
+				"%s: Failed to request tapan amp spkr gpio %d\n",
+				__func__, ext_spk_amp_gpio);
+			goto err_vdd_spkr;
+		}
+	}
+
 	mbhc_cfg.gpio_level_insert = of_property_read_bool(pdev->dev.of_node,
 					"qcom,headset-jack-type-NO");
 	msm8226_setup_hs_jack(pdev, pdata);
 
 	ret = msm8226_prepare_codec_mclk(card);
 	if (ret)
-		goto err_vdd_spkr;
+		goto err_lineout_spkr;
 
 	ret = snd_soc_register_card(card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
 			ret);
-		goto err_vdd_spkr;
+		goto err_lineout_spkr;
 	}
 	mutex_init(&cdc_mclk_mutex);
 
@@ -1564,7 +1689,7 @@
 		dev_err(&pdev->dev, "Looking up %s property in node %s failed",
 			"qcom,prim-auxpcm-gpio-set",
 			pdev->dev.of_node->full_name);
-		goto err_vdd_spkr;
+		goto err_lineout_spkr;
 	}
 	if (!strcmp(auxpcm_pri_gpio_set, "prim-gpio-prim")) {
 		lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_PRI_MODE_MUXSEL, 4);
@@ -1574,16 +1699,22 @@
 		dev_err(&pdev->dev, "Invalid value %s for AUXPCM GPIO set\n",
 			auxpcm_pri_gpio_set);
 		ret = -EINVAL;
-		goto err_vdd_spkr;
+		goto err_lineout_spkr;
 	}
 	if (lpaif_pri_muxsel_virt_addr == NULL) {
 		pr_err("%s Pri muxsel virt addr is null\n", __func__);
 		ret = -EINVAL;
-		goto err_vdd_spkr;
+		goto err_lineout_spkr;
 	}
 
 	return 0;
 
+err_lineout_spkr:
+	if (ext_spk_amp_gpio >= 0) {
+		gpio_free(ext_spk_amp_gpio);
+		ext_spk_amp_gpio = -1;
+	}
+
 err_vdd_spkr:
 	if (vdd_spkr_gpio >= 0) {
 		gpio_free(vdd_spkr_gpio);
@@ -1607,11 +1738,15 @@
 	struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
 
 	gpio_free(pdata->mclk_gpio);
-	gpio_free(vdd_spkr_gpio);
+	if (vdd_spkr_gpio >= 0)
+		gpio_free(vdd_spkr_gpio);
+	if (ext_spk_amp_gpio >= 0)
+		gpio_free(ext_spk_amp_gpio);
 	if (pdata->us_euro_gpio > 0)
 		gpio_free(pdata->us_euro_gpio);
 
 	vdd_spkr_gpio = -1;
+	ext_spk_amp_gpio = -1;
 	snd_soc_unregister_card(card);
 
 	return 0;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 0b7e7f2..b28f0f49 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -2150,6 +2150,22 @@
 		 /* this dainlink has playback support */
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
 	},
+	{
+		.name = "QCHAT",
+		.stream_name = "QCHAT",
+		.cpu_dai_name   = "QCHAT",
+		.platform_name  = "msm-pcm-voice",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.be_id = MSM_FRONTEND_DAI_QCHAT,
+	},
 	/* HDMI Hostless */
 	{
 		.name = "HDMI_RX_HOSTLESS",
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index 4d9632c..340d3db 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -587,7 +587,7 @@
 		.stream_name = "Secondary MI2S Playback",
 		.cpu_dai_name = "msm-dai-q6-mi2s.1",
 		.platform_name = "msm-pcm-routing",
-		.codec_name     = "msm8x10-wcd-i2c-core.5-000d",
+		.codec_name     = MSM8X10_CODEC_NAME,
 		.codec_dai_name = "msm8x10_wcd_i2s_rx1",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
@@ -601,7 +601,7 @@
 		.stream_name = "Primary MI2S Capture",
 		.cpu_dai_name = "msm-dai-q6-mi2s.0",
 		.platform_name = "msm-pcm-routing",
-		.codec_name     = "msm8x10-wcd-i2c-core.5-000d",
+		.codec_name     = MSM8X10_CODEC_NAME,
 		.codec_dai_name = "msm8x10_wcd_i2s_tx1",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_PRI_MI2S_TX,
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index d6090cf..2836b87 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/msm_audio_ion.h>
 #include "audio_acdb.h"
+#include "q6voice.h"
 
 
 #define MAX_NETWORKS			15
@@ -949,6 +950,36 @@
 	return result;
 }
 
+static int register_vocvol_table(void)
+{
+	int result = 0;
+	pr_debug("%s\n", __func__);
+
+	result = voc_register_vocproc_vol_table();
+	if (result < 0) {
+		pr_err("%s: Register vocproc vol failed!\n", __func__);
+		goto done;
+	}
+
+done:
+	return result;
+}
+
+static int deregister_vocvol_table(void)
+{
+	int result = 0;
+	pr_debug("%s\n", __func__);
+
+	result = voc_deregister_vocproc_vol_table();
+	if (result < 0) {
+		pr_err("%s: Deregister vocproc vol failed!\n", __func__);
+		goto done;
+	}
+
+done:
+	return result;
+}
+
 static int acdb_open(struct inode *inode, struct file *f)
 {
 	s32 result = 0;
@@ -1139,10 +1170,16 @@
 		}
 		if (copy_to_user((void *)arg, &prot_status,
 			sizeof(prot_status))) {
-			pr_err("%s Failed to update prot_status\n", __func__);
+			pr_err("%s: Failed to update prot_status\n", __func__);
 		}
 		mutex_unlock(&acdb_data.acdb_mutex);
 		goto done;
+	case AUDIO_REGISTER_VOCPROC_VOL_TABLE:
+		result = register_vocvol_table();
+		goto done;
+	case AUDIO_DEREGISTER_VOCPROC_VOL_TABLE:
+		result = deregister_vocvol_table();
+		goto done;
 	}
 
 	if (copy_from_user(&size, (void *) arg, sizeof(size))) {
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 9f4e189..aa6ef6b 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -127,6 +127,7 @@
 	int i = 0;
 	int time_stamp_flag = 0;
 	int buffer_length = 0;
+	int stop_playback = 0;
 
 	pr_debug("%s opcode =%08x\n", __func__, opcode);
 	switch (opcode) {
@@ -151,9 +152,15 @@
 		/*
 		 * check for underrun
 		 */
+		snd_pcm_stream_lock_irq(substream);
 		if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
-			pr_info("render stopped");
 			runtime->render_flag |= SNDRV_RENDER_STOPPED;
+			stop_playback = 1;
+		}
+		snd_pcm_stream_unlock_irq(substream);
+
+		if (stop_playback) {
+			pr_err("underrun! render stopped\n");
 			break;
 		}
 
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
index ca2afaf..cd08b39 100644
--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -557,7 +557,7 @@
 		return -ENOMEM;
 	}
 	if (DOLBY_PARAM_ID_VER == dolby_dap_params_get.param_id) {
-		rc = adm_dolby_dap_get_params(dolby_dap_params_get.port_id,
+		rc = adm_get_params(dolby_dap_params_get.port_id,
 						DOLBY_BUNDLE_MODULE_ID,
 						DOLBY_PARAM_ID_VER,
 						params_length +
@@ -575,7 +575,7 @@
 			params_length = (dolby_dap_params_length[i] +
 						DOLBY_PARAM_PAYLOAD_SIZE) *
 						sizeof(uint32_t);
-			rc = adm_dolby_dap_get_params(
+			rc = adm_get_params(
 						dolby_dap_params_get.port_id,
 						DOLBY_BUNDLE_MODULE_ID,
 						dolby_dap_params_id[i],
@@ -652,7 +652,7 @@
 	}
 	offset = 0;
 	params_length = length * sizeof(uint32_t);
-	rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+	rc = adm_get_params(dolby_dap_params_states.port_id,
 					DOLBY_BUNDLE_MODULE_ID,
 					DOLBY_PARAM_ID_VCBG,
 					params_length + param_payload_len,
@@ -664,7 +664,7 @@
 	}
 
 	offset = length * sizeof(uint32_t);
-	rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+	rc = adm_get_params(dolby_dap_params_states.port_id,
 					DOLBY_BUNDLE_MODULE_ID,
 					DOLBY_PARAM_ID_VCBE,
 					params_length + param_payload_len,
diff --git a/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
index 4297ddb..39e6934 100644
--- a/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
@@ -141,7 +141,7 @@
 	}
 	case ASM_DATA_EVENT_RENDERED_EOS:
 		pr_debug("ASM_DATA_CMDRSP_EOS\n");
-		prtd->cmd_ack = 1;
+		clear_bit(CMD_EOS, &prtd->cmd_pending);
 		wake_up(&the_locks.eos_wait);
 		break;
 	case ASM_DATA_EVENT_READ_DONE_V2: {
@@ -241,7 +241,7 @@
 	atomic_set(&prtd->out_count, runtime->periods);
 
 	prtd->enabled = 1;
-	prtd->cmd_ack = 0;
+	prtd->cmd_pending = 0;
 	prtd->cmd_interrupt = 0;
 
 	return 0;
@@ -299,8 +299,12 @@
 		atomic_set(&prtd->start, 0);
 		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
 			break;
-		prtd->cmd_ack = 0;
+		/* pending CMD_EOS isn't expected */
+		WARN_ON_ONCE(test_bit(CMD_EOS, &prtd->cmd_pending));
+		set_bit(CMD_EOS, &prtd->cmd_pending);
 		q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+		if (ret)
+			clear_bit(CMD_EOS, &prtd->cmd_pending);
 		break;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -379,9 +383,6 @@
 			prtd->audio_client->perf_mode,
 			prtd->session_id, substream->stream);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		prtd->cmd_ack = 1;
-
 	ret = snd_pcm_hw_constraint_list(runtime, 0,
 				SNDRV_PCM_HW_PARAM_RATE,
 				&constraints_sample_rates);
@@ -502,13 +503,15 @@
 	int dir = 0;
 	int ret = 0;
 
-	pr_debug("%s\n", __func__);
+	pr_debug("%s: cmd_pending 0x%lx\n", __func__, prtd->cmd_pending);
 
 	dir = IN;
 	ret = wait_event_timeout(the_locks.eos_wait,
-				prtd->cmd_ack, 5 * HZ);
+				 !test_bit(CMD_EOS, &prtd->cmd_pending),
+				 5 * HZ);
 	if (!ret)
-		pr_err("%s: CMD_EOS failed\n", __func__);
+		pr_err("%s: CMD_EOS failed, cmd_pending 0x%lx\n",
+		       __func__, prtd->cmd_pending);
 	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 	q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 49bc488..11326f6 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -143,7 +143,7 @@
 	}
 	case ASM_DATA_EVENT_RENDERED_EOS:
 		pr_debug("ASM_DATA_EVENT_RENDERED_EOS\n");
-		prtd->cmd_ack = 1;
+		clear_bit(CMD_EOS, &prtd->cmd_pending);
 		wake_up(&the_locks.eos_wait);
 		break;
 	case ASM_DATA_EVENT_READ_DONE_V2: {
@@ -243,7 +243,7 @@
 	atomic_set(&prtd->out_count, runtime->periods);
 
 	prtd->enabled = 1;
-	prtd->cmd_ack = 0;
+	prtd->cmd_pending = 0;
 	prtd->cmd_interrupt = 0;
 
 	return 0;
@@ -312,8 +312,12 @@
 		atomic_set(&prtd->start, 0);
 		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
 			break;
-		prtd->cmd_ack = 0;
+		/* pending CMD_EOS isn't expected */
+		WARN_ON_ONCE(test_bit(CMD_EOS, &prtd->cmd_pending));
+		set_bit(CMD_EOS, &prtd->cmd_pending);
 		ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+		if (ret)
+			clear_bit(CMD_EOS, &prtd->cmd_pending);
 		break;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -473,14 +477,16 @@
 	int dir = 0;
 	int ret = 0;
 
-	pr_debug("%s\n", __func__);
+	pr_debug("%s: cmd_pending 0x%lx\n", __func__, prtd->cmd_pending);
 
 	if (prtd->audio_client) {
 		dir = IN;
 		ret = wait_event_timeout(the_locks.eos_wait,
-					prtd->cmd_ack, 5 * HZ);
+					 !test_bit(CMD_EOS, &prtd->cmd_pending),
+					 5 * HZ);
 		if (!ret)
-			pr_err("%s: CMD_EOS failed\n", __func__);
+			pr_err("%s: CMD_EOS failed, cmd_pending 0x%lx\n",
+			       __func__, prtd->cmd_pending);
 		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 		q6asm_audio_client_buf_free_contiguous(dir,
 					prtd->audio_client);
@@ -701,7 +707,6 @@
 		msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
 				prtd->audio_client->perf_mode,
 				prtd->session_id, substream->stream);
-		prtd->cmd_ack = 1;
 	}
 
 	/* Capture Path */
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
index f7719ed..5d5c995 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
@@ -72,6 +72,13 @@
 	int enabled;
 	int close_ack;
 	int cmd_ack;
+	/*
+	 * cmd_ack doesn't tell if paticular command has been sent so can't
+	 * determine if it needs to wait for completion.
+	 * Use cmd_pending instead when checking whether a command is been
+	 * sent or not.
+	 */
+	unsigned long cmd_pending;
 	atomic_t start;
 	atomic_t stop;
 	atomic_t out_count;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 76a525d..edb24fc 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -30,6 +30,7 @@
 #include <sound/tlv.h>
 #include <sound/asound.h>
 #include <sound/pcm_params.h>
+#include <linux/slab.h>
 
 #include "msm-pcm-routing-v2.h"
 #include "msm-dolby-dap-config.h"
@@ -627,6 +628,8 @@
 		session_id = voc_get_session_id(VOLTE_SESSION_NAME);
 	else if (val == MSM_FRONTEND_DAI_VOICE2)
 		session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+	else if (val == MSM_FRONTEND_DAI_QCHAT)
+		session_id = voc_get_session_id(QCHAT_SESSION_NAME);
 	else
 		session_id = voc_get_session_id(VOIP_SESSION_NAME);
 
@@ -1869,6 +1872,9 @@
 	SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mmul5_mixer_controls[] = {
@@ -1914,6 +1920,9 @@
 	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new sec_i2s_rx_voice_mixer_controls[] = {
@@ -1932,6 +1941,9 @@
 	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new sec_mi2s_rx_voice_mixer_controls[] = {
@@ -1950,6 +1962,9 @@
 	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
 	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
@@ -1971,6 +1986,9 @@
 	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
 	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
@@ -1992,6 +2010,9 @@
 	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
 	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new mi2s_rx_voice_mixer_controls[] = {
@@ -2013,6 +2034,9 @@
 	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_MI2S_RX,
 	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
@@ -2034,6 +2058,9 @@
 	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new aux_pcm_rx_voice_mixer_controls[] = {
@@ -2055,6 +2082,9 @@
 	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new sec_aux_pcm_rx_voice_mixer_controls[] = {
@@ -2073,6 +2103,9 @@
 	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
 	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
@@ -2094,6 +2127,9 @@
 	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new stub_rx_mixer_controls[] = {
@@ -2243,6 +2279,33 @@
 	msm_routing_put_voice_stub_mixer),
 };
 
+static const struct snd_kcontrol_new tx_qchat_mixer_controls[] = {
+	SOC_SINGLE_EXT("PRI_TX_QCHAT", MSM_BACKEND_DAI_PRI_I2S_TX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SLIM_0_TX_QCHAT", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_QCHAT",
+	MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_QCHAT, 1, 0,
+	msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("AFE_PCM_TX_QCHAT", MSM_BACKEND_DAI_AFE_PCM_TX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("AUX_PCM_TX_QCHAT", MSM_BACKEND_DAI_AUXPCM_TX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_TX_QCHAT", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("MI2S_TX_QCHAT", MSM_BACKEND_DAI_MI2S_TX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("PRI_MI2S_TX_QCHAT", MSM_BACKEND_DAI_PRI_MI2S_TX,
+	MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+};
+
 static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
 	SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
@@ -2271,7 +2334,7 @@
 	SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
-	SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
 };
@@ -2284,7 +2347,7 @@
 	MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
 	SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
-	MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+	MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
 };
 
@@ -2526,6 +2589,49 @@
 	msm_routing_put_dolby_dap_endpoint_control),
 };
 
+int msm_routing_get_rms_value_control(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol) {
+	int rc = 0;
+	char *param_value;
+	int *update_param_value;
+	uint32_t param_length = sizeof(uint32_t);
+	uint32_t param_payload_len = RMS_PAYLOAD_LEN * sizeof(uint32_t);
+	param_value = kzalloc(param_length, GFP_KERNEL);
+	if (!param_value) {
+		pr_err("%s, param memory alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	rc = adm_get_params(SLIMBUS_0_TX,
+			RMS_MODULEID_APPI_PASSTHRU,
+			RMS_PARAM_FIRST_SAMPLE,
+			param_length + param_payload_len,
+			param_value);
+	if (rc) {
+		pr_err("%s: get parameters failed\n", __func__);
+		kfree(param_value);
+		return -EINVAL;
+	}
+	update_param_value = (int *)param_value;
+	ucontrol->value.integer.value[0] = update_param_value[0];
+
+	pr_debug("%s: FROM DSP value[0] 0x%x\n",
+		__func__, update_param_value[0]);
+	kfree(param_value);
+	return 0;
+}
+
+int msm_routing_put_rms_value_control(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	/* not used */
+	return 0;
+}
+
+static const struct snd_kcontrol_new get_rms_controls[] = {
+	SOC_SINGLE_EXT("Get RMS", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+	0, msm_routing_get_rms_value_control,
+	msm_routing_put_rms_value_control),
+};
+
 static const struct snd_kcontrol_new eq_enable_mixer_controls[] = {
 	SOC_SINGLE_EXT("MultiMedia1 EQ Enable", SND_SOC_NOPM,
 	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_eq_enable_mixer,
@@ -2831,6 +2937,8 @@
 	/* LSM */
 	SND_SOC_DAPM_AIF_OUT("LSM_UL_HL", "Listen Audio Service Capture",
 			     0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("QCHAT_DL", "QCHAT Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("QCHAT_UL", "QCHAT Capture", 0, 0, 0, 0),
 	/* Backend AIF */
 	/* Stream name equals to backend dai link stream name
 	*/
@@ -3065,6 +3173,9 @@
 	SND_SOC_DAPM_MIXER("PRI_MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0,
 	primary_mi2s_rx_port_mixer_controls,
 	ARRAY_SIZE(primary_mi2s_rx_port_mixer_controls)),
+	SND_SOC_DAPM_MIXER("QCHAT_Tx Mixer",
+	SND_SOC_NOPM, 0, 0, tx_qchat_mixer_controls,
+	ARRAY_SIZE(tx_qchat_mixer_controls)),
 	/* Virtual Pins to force backends ON atm */
 	SND_SOC_DAPM_OUTPUT("BE_OUT"),
 	SND_SOC_DAPM_INPUT("BE_IN"),
@@ -3136,6 +3247,7 @@
 	{"MultiMedia1 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
 	{"MultiMedia1 Mixer", "SLIM_4_TX", "SLIMBUS_4_TX"},
 	{"MultiMedia4 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+	{"MultiMedia4 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 	{"MultiMedia5 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -3266,6 +3378,7 @@
 	{"MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
 	{"MI2S_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+	{"MI2S_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
 	{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
 
 	{"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3273,6 +3386,7 @@
 	{"PRI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"PRI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+	{"PRI_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
 	{"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
 
 	{"SEC_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3280,6 +3394,7 @@
 	{"SEC_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"SEC_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SEC_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+	{"SEC_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
 	{"SEC_I2S_RX", NULL, "SEC_RX_Voice Mixer"},
 
 	{"SEC_MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3287,6 +3402,7 @@
 	{"SEC_MI2S_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"SEC_MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SEC_MI2S_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+	{"SEC_MI2S_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
 	{"SEC_MI2S_RX", NULL, "SEC_MI2S_RX_Voice Mixer"},
 
 	{"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3295,6 +3411,7 @@
 	{"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SLIM_0_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"SLIM_0_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+	{"SLIM_0_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
 	{"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
 
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3302,6 +3419,7 @@
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+	{"INTERNAL_BT_SCO_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
 
 	{"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3309,6 +3427,7 @@
 	{"AFE_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"AFE_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+	{"AFE_PCM_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
 	{"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
 
 	{"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3317,6 +3436,7 @@
 	{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"AUX_PCM_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+	{"AUX_PCM_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
 
 	{"SEC_AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3324,6 +3444,7 @@
 	{"SEC_AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"SEC_AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"SEC_AUX_PCM_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+	{"SEC_AUX_PCM_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
 	{"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX_Voice Mixer"},
 
 	{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3331,6 +3452,7 @@
 	{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"HDMI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+	{"HDMI_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
 	{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
 	{"HDMI", NULL, "HDMI_DL_HL"},
 
@@ -3339,6 +3461,7 @@
 	{"MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"MI2S_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+	{"MI2S_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
 	{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
 
 	{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
@@ -3398,6 +3521,16 @@
 	{"LSM1 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"},
 	{"LSM_UL_HL", NULL, "LSM1 MUX"},
 
+	{"QCHAT_Tx Mixer", "PRI_TX_QCHAT", "PRI_I2S_TX"},
+	{"QCHAT_Tx Mixer", "SLIM_0_TX_QCHAT", "SLIMBUS_0_TX"},
+	{"QCHAT_Tx Mixer", "INTERNAL_BT_SCO_TX_QCHAT", "INT_BT_SCO_TX"},
+	{"QCHAT_Tx Mixer", "AFE_PCM_TX_QCHAT", "PCM_TX"},
+	{"QCHAT_Tx Mixer", "AUX_PCM_TX_QCHAT", "AUX_PCM_TX"},
+	{"QCHAT_Tx Mixer", "SEC_AUX_PCM_TX_QCHAT", "SEC_AUX_PCM_TX"},
+	{"QCHAT_Tx Mixer", "MI2S_TX_QCHAT", "MI2S_TX"},
+	{"QCHAT_Tx Mixer", "PRI_MI2S_TX_QCHAT", "PRI_MI2S_TX"},
+	{"QCHAT_UL", NULL, "QCHAT_Tx Mixer"},
+
 	{"INT_FM_RX", NULL, "INTFM_DL_HL"},
 	{"INTFM_UL_HL", NULL, "INT_FM_TX"},
 	{"AUX_PCM_RX", NULL, "AUXPCM_DL_HL"},
@@ -3773,6 +3906,10 @@
 	snd_soc_add_platform_controls(platform,
 				ec_ref_rx_mixer_controls,
 			ARRAY_SIZE(ec_ref_rx_mixer_controls));
+
+	snd_soc_add_platform_controls(platform,
+				get_rms_controls,
+			ARRAY_SIZE(get_rms_controls));
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 4ce0db5..10be150 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -81,6 +81,7 @@
 	MSM_FRONTEND_DAI_DTMF_RX,
 	MSM_FRONTEND_DAI_LSM1,
 	MSM_FRONTEND_DAI_VOICE2,
+	MSM_FRONTEND_DAI_QCHAT,
 	MSM_FRONTEND_DAI_MAX,
 };
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 071db4e..1074d76 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -51,7 +51,7 @@
 
 	.fifo_size =            0,
 };
-static int is_volte(struct msm_voice *pvolte)
+static bool is_volte(struct msm_voice *pvolte)
 {
 	if (pvolte == &voice_info[VOLTE_SESSION_INDEX])
 		return true;
@@ -59,7 +59,7 @@
 		return false;
 }
 
-static int is_voice2(struct msm_voice *pvoice2)
+static bool is_voice2(struct msm_voice *pvoice2)
 {
 	if (pvoice2 == &voice_info[VOICE2_SESSION_INDEX])
 		return true;
@@ -67,6 +67,14 @@
 		return false;
 }
 
+static bool is_qchat(struct msm_voice *pqchat)
+{
+	if (pqchat == &voice_info[QCHAT_SESSION_INDEX])
+		return true;
+	else
+		return false;
+}
+
 static uint32_t get_session_id(struct msm_voice *pvoc)
 {
 	uint32_t session_id = 0;
@@ -75,6 +83,8 @@
 		session_id = voc_get_session_id(VOLTE_SESSION_NAME);
 	else if (is_voice2(pvoc))
 		session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+	else if (is_qchat(pvoc))
+		session_id = voc_get_session_id(QCHAT_SESSION_NAME);
 	else
 		session_id = voc_get_session_id(VOICE_SESSION_NAME);
 
@@ -120,6 +130,10 @@
 		voice = &voice_info[VOICE2_SESSION_INDEX];
 		pr_debug("%s: Open Voice2 Substream Id=%s\n",
 			 __func__, substream->pcm->id);
+	} else if (!strncmp("QCHAT", substream->pcm->id, 5)) {
+		voice = &voice_info[QCHAT_SESSION_INDEX];
+		pr_debug("%s: Open QCHAT Substream Id=%s\n",
+			 __func__, substream->pcm->id);
 	} else {
 		voice = &voice_info[VOICE_SESSION_INDEX];
 		pr_debug("%s: Open VOICE Substream Id=%s\n",
@@ -333,174 +347,83 @@
 	return ret;
 }
 
-static int msm_voice_volume_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
+static int msm_voice_gain_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
 {
-	ucontrol->value.integer.value[0] = 0;
-	return 0;
-}
-
-static int msm_voice_volume_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
+	int ret = 0;
 	int volume = ucontrol->value.integer.value[0];
-	pr_debug("%s: volume: %d\n", __func__, volume);
-	voc_set_rx_vol_index(voc_get_session_id(VOICE_SESSION_NAME),
-						RX_PATH, volume);
-	return 0;
-}
+	uint32_t session_id = ucontrol->value.integer.value[1];
+	int ramp_duration = ucontrol->value.integer.value[2];
 
-static int msm_volte_volume_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = 0;
-	return 0;
-}
+	if ((volume < 0) || (ramp_duration < 0)
+		|| (ramp_duration > MAX_RAMP_DURATION)) {
+		pr_err(" %s Invalid arguments", __func__);
 
-static int msm_volte_volume_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	int volume = ucontrol->value.integer.value[0];
-	pr_debug("%s: volume: %d\n", __func__, volume);
-	voc_set_rx_vol_index(voc_get_session_id(VOLTE_SESSION_NAME),
-						RX_PATH, volume);
-	return 0;
-}
+		ret = -EINVAL;
+		goto done;
+	}
 
-static int msm_voice2_volume_get(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = 0;
-	return 0;
-}
+	pr_debug("%s: volume: %d session_id: %#x ramp_duration: %d\n", __func__,
+		volume, session_id, ramp_duration);
 
-static int msm_voice2_volume_put(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_value *ucontrol)
-{
-	int volume = ucontrol->value.integer.value[0];
-	pr_debug("%s: volume: %d\n", __func__, volume);
+	voc_set_rx_vol_step(session_id, RX_PATH, volume, ramp_duration);
 
-	voc_set_rx_vol_index(voc_get_session_id(VOICE2_SESSION_NAME),
-						RX_PATH, volume);
-	return 0;
-}
-
-static int msm_voice_mute_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = 0;
-	return 0;
+done:
+	return ret;
 }
 
 static int msm_voice_mute_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
+			      struct snd_ctl_elem_value *ucontrol)
 {
+	int ret = 0;
 	int mute = ucontrol->value.integer.value[0];
+	uint32_t session_id = ucontrol->value.integer.value[1];
+	int ramp_duration = ucontrol->value.integer.value[2];
 
-	pr_debug("%s: mute=%d\n", __func__, mute);
+	if ((mute < 0) || (mute > 1) || (ramp_duration < 0)
+		|| (ramp_duration > MAX_RAMP_DURATION)) {
+		pr_err(" %s Invalid arguments", __func__);
 
-	voc_set_tx_mute(voc_get_session_id(VOICE_SESSION_NAME), TX_PATH, mute);
+		ret = -EINVAL;
+		goto done;
+	}
 
-	return 0;
+	pr_debug("%s: mute=%d session_id=%#x ramp_duration=%d\n", __func__,
+		mute, session_id, ramp_duration);
+
+	voc_set_tx_mute(session_id, TX_PATH, mute, ramp_duration);
+
+done:
+	return ret;
 }
 
-static int msm_volte_mute_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = 0;
-	return 0;
-}
-
-static int msm_volte_mute_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	int mute = ucontrol->value.integer.value[0];
-
-	pr_debug("%s: mute=%d\n", __func__, mute);
-
-	voc_set_tx_mute(voc_get_session_id(VOLTE_SESSION_NAME), TX_PATH, mute);
-
-	return 0;
-}
-
-static int msm_voice2_mute_get(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = 0;
-	return 0;
-}
-
-static int msm_voice2_mute_put(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *ucontrol)
-{
-	int mute = ucontrol->value.integer.value[0];
-
-	pr_debug("%s: mute=%d\n", __func__, mute);
-
-	voc_set_tx_mute(voc_get_session_id(VOICE2_SESSION_NAME), TX_PATH, mute);
-
-	return 0;
-}
-
-static int msm_voice_rx_device_mute_get(struct snd_kcontrol *kcontrol,
-					struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] =
-		voc_get_rx_device_mute(voc_get_session_id(VOICE_SESSION_NAME));
-	return 0;
-}
 
 static int msm_voice_rx_device_mute_put(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
+	int ret = 0;
 	int mute = ucontrol->value.integer.value[0];
+	uint32_t session_id = ucontrol->value.integer.value[1];
+	int ramp_duration = ucontrol->value.integer.value[2];
 
-	pr_debug("%s: mute=%d\n", __func__, mute);
+	if ((mute < 0) || (mute > 1) || (ramp_duration < 0)
+		|| (ramp_duration > MAX_RAMP_DURATION)) {
+		pr_err(" %s Invalid arguments", __func__);
 
-	voc_set_rx_device_mute(voc_get_session_id(VOICE_SESSION_NAME), mute);
+		ret = -EINVAL;
+		goto done;
+	}
 
-	return 0;
+	pr_debug("%s: mute=%d session_id=%#x ramp_duration=%d\n", __func__,
+		mute, session_id, ramp_duration);
+
+	voc_set_rx_device_mute(session_id, mute, ramp_duration);
+
+done:
+	return ret;
 }
 
-static int msm_volte_rx_device_mute_get(struct snd_kcontrol *kcontrol,
-					struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] =
-		voc_get_rx_device_mute(voc_get_session_id(VOLTE_SESSION_NAME));
-	return 0;
-}
 
-static int msm_volte_rx_device_mute_put(struct snd_kcontrol *kcontrol,
-					struct snd_ctl_elem_value *ucontrol)
-{
-	int mute = ucontrol->value.integer.value[0];
-
-	pr_debug("%s: mute=%d\n", __func__, mute);
-
-	voc_set_rx_device_mute(voc_get_session_id(VOLTE_SESSION_NAME), mute);
-
-	return 0;
-}
-
-static int msm_voice2_rx_device_mute_get(struct snd_kcontrol *kcontrol,
-					 struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] =
-		voc_get_rx_device_mute(voc_get_session_id(VOICE2_SESSION_NAME));
-	return 0;
-}
-
-static int msm_voice2_rx_device_mute_put(struct snd_kcontrol *kcontrol,
-					 struct snd_ctl_elem_value *ucontrol)
-{
-	int mute = ucontrol->value.integer.value[0];
-
-	pr_debug("%s: mute=%d\n", __func__, mute);
-
-	voc_set_rx_device_mute(voc_get_session_id(VOICE2_SESSION_NAME), mute);
-
-	return 0;
-}
 
 static const char const *tty_mode[] = {"OFF", "HCO", "VCO", "FULL"};
 static const struct soc_enum msm_tty_mode_enum[] = {
@@ -533,52 +456,28 @@
 			struct snd_ctl_elem_value *ucontrol)
 {
 	int st_enable = ucontrol->value.integer.value[0];
+	uint32_t session_id = ucontrol->value.integer.value[1];
 
-	pr_debug("%s: st enable=%d\n", __func__, st_enable);
+	pr_debug("%s: st enable=%d session_id=%#x\n", __func__, st_enable,
+		 session_id);
 
-	voc_set_pp_enable(voc_get_session_id(VOICE_SESSION_NAME),
-			  MODULE_ID_VOICE_MODULE_ST, st_enable);
-	voc_set_pp_enable(voc_get_session_id(VOICE2_SESSION_NAME),
+	voc_set_pp_enable(session_id,
 			  MODULE_ID_VOICE_MODULE_ST, st_enable);
 
 	return 0;
 }
 
-static int msm_voice_slowtalk_get(struct snd_kcontrol *kcontrol,
-			struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] =
-		voc_get_pp_enable(voc_get_session_id(VOICE_SESSION_NAME),
-				MODULE_ID_VOICE_MODULE_ST);
-	return 0;
-}
-
 static struct snd_kcontrol_new msm_voice_controls[] = {
-	SOC_SINGLE_EXT("Voice Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
-				msm_voice_rx_device_mute_get,
-				msm_voice_rx_device_mute_put),
-	SOC_SINGLE_EXT("Voice Tx Mute", SND_SOC_NOPM, 0, 1, 0,
-				msm_voice_mute_get, msm_voice_mute_put),
-	SOC_SINGLE_EXT("Voice Rx Volume", SND_SOC_NOPM, 0, 5, 0,
-				msm_voice_volume_get, msm_voice_volume_put),
+	SOC_SINGLE_MULTI_EXT("Voice Rx Device Mute", SND_SOC_NOPM, 0, VSID_MAX,
+				0, 3, NULL, msm_voice_rx_device_mute_put),
+	SOC_SINGLE_MULTI_EXT("Voice Tx Mute", SND_SOC_NOPM, 0, VSID_MAX,
+				0, 3, NULL, msm_voice_mute_put),
+	SOC_SINGLE_MULTI_EXT("Voice Rx Gain", SND_SOC_NOPM, 0, VSID_MAX, 0, 3,
+				NULL, msm_voice_gain_put),
 	SOC_ENUM_EXT("TTY Mode", msm_tty_mode_enum[0], msm_voice_tty_mode_get,
 				msm_voice_tty_mode_put),
-	SOC_SINGLE_EXT("Slowtalk Enable", SND_SOC_NOPM, 0, 1, 0,
-				msm_voice_slowtalk_get, msm_voice_slowtalk_put),
-	SOC_SINGLE_EXT("VoLTE Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
-			msm_volte_rx_device_mute_get,
-			msm_volte_rx_device_mute_put),
-	SOC_SINGLE_EXT("VoLTE Tx Mute", SND_SOC_NOPM, 0, 1, 0,
-				msm_volte_mute_get, msm_volte_mute_put),
-	SOC_SINGLE_EXT("VoLTE Rx Volume", SND_SOC_NOPM, 0, 5, 0,
-				msm_volte_volume_get, msm_volte_volume_put),
-	SOC_SINGLE_EXT("Voice2 Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
-		       msm_voice2_rx_device_mute_get,
-		       msm_voice2_rx_device_mute_put),
-	SOC_SINGLE_EXT("Voice2 Tx Mute", SND_SOC_NOPM, 0, 1, 0,
-		       msm_voice2_mute_get, msm_voice2_mute_put),
-	SOC_SINGLE_EXT("Voice2 Rx Volume", SND_SOC_NOPM, 0, 5, 0,
-		       msm_voice2_volume_get, msm_voice2_volume_put),
+	SOC_SINGLE_MULTI_EXT("Slowtalk Enable", SND_SOC_NOPM, 0, VSID_MAX, 0, 2,
+				NULL, msm_voice_slowtalk_put),
 };
 
 static struct snd_pcm_ops msm_pcm_ops = {
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
index 5425c46..f199be6 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
@@ -17,6 +17,7 @@
 	VOICE_SESSION_INDEX,
 	VOLTE_SESSION_INDEX,
 	VOICE2_SESSION_INDEX,
+	QCHAT_SESSION_INDEX,
 	VOICE_SESSION_INDEX_MAX,
 };
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index ae454a8..4a829fd 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -173,41 +173,53 @@
 
 
 static int msm_voip_mute_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
+			     struct snd_ctl_elem_value *ucontrol)
 {
+	int ret = 0;
 	int mute = ucontrol->value.integer.value[0];
+	int ramp_duration = ucontrol->value.integer.value[1];
 
-	pr_debug("%s: mute=%d\n", __func__, mute);
+	if ((mute < 0) || (mute > 1) || (ramp_duration < 0)) {
+		pr_err(" %s Invalid arguments", __func__);
 
-	voc_set_tx_mute(voc_get_session_id(VOIP_SESSION_NAME), TX_PATH, mute);
+		ret = -EINVAL;
+		goto done;
+	}
 
-	return 0;
+	pr_debug("%s: mute=%d ramp_duration=%d\n", __func__, mute,
+		ramp_duration);
+
+	voc_set_tx_mute(voc_get_session_id(VOIP_SESSION_NAME), TX_PATH, mute,
+					ramp_duration);
+
+done:
+	return ret;
 }
 
-static int msm_voip_mute_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
+static int msm_voip_gain_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
 {
-	ucontrol->value.integer.value[0] = 0;
-	return 0;
-}
-
-static int msm_voip_volume_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
+	int ret = 0;
 	int volume = ucontrol->value.integer.value[0];
+	int ramp_duration = ucontrol->value.integer.value[1];
 
-	pr_debug("%s: volume: %d\n", __func__, volume);
+	if ((volume < 0) || (ramp_duration < 0)) {
+		pr_err(" %s Invalid arguments", __func__);
 
-	voc_set_rx_vol_index(voc_get_session_id(VOIP_SESSION_NAME),
-			     RX_PATH,
-			     volume);
-	return 0;
-}
-static int msm_voip_volume_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = 0;
-	return 0;
+		ret = -EINVAL;
+		goto done;
+	}
+
+	pr_debug("%s: volume: %d ramp_duration: %d\n", __func__, volume,
+		ramp_duration);
+
+	voc_set_rx_vol_step(voc_get_session_id(VOIP_SESSION_NAME),
+						RX_PATH,
+						volume,
+						ramp_duration);
+
+done:
+	return ret;
 }
 
 static int msm_voip_dtx_mode_put(struct snd_kcontrol *kcontrol,
@@ -236,15 +248,17 @@
 }
 
 static struct snd_kcontrol_new msm_voip_controls[] = {
-	SOC_SINGLE_EXT("Voip Tx Mute", SND_SOC_NOPM, 0, 1, 0,
-				msm_voip_mute_get, msm_voip_mute_put),
-	SOC_SINGLE_EXT("Voip Rx Volume", SND_SOC_NOPM, 0, 5, 0,
-				msm_voip_volume_get, msm_voip_volume_put),
+	SOC_SINGLE_MULTI_EXT("Voip Tx Mute", SND_SOC_NOPM, 0,
+			     MAX_RAMP_DURATION,
+			     0, 2, NULL, msm_voip_mute_put),
+	SOC_SINGLE_MULTI_EXT("Voip Rx Gain", SND_SOC_NOPM, 0,
+			     MAX_RAMP_DURATION,
+			     0, 2, NULL, msm_voip_gain_put),
 	SOC_SINGLE_MULTI_EXT("Voip Mode Rate Config", SND_SOC_NOPM, 0, 23850,
-				0, 2, msm_voip_mode_rate_config_get,
-				msm_voip_mode_rate_config_put),
+			     0, 2, msm_voip_mode_rate_config_get,
+			     msm_voip_mode_rate_config_put),
 	SOC_SINGLE_EXT("Voip Dtx Mode", SND_SOC_NOPM, 0, 1, 0,
-				msm_voip_dtx_mode_get, msm_voip_dtx_mode_put),
+		       msm_voip_dtx_mode_get, msm_voip_dtx_mode_put),
 };
 
 static int msm_pcm_voip_probe(struct snd_soc_platform *platform)
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index a6ae357..df0fa6a 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -69,7 +69,7 @@
 						{0, 0, 0, 0, 0, 0, 0, 0}
 					      };
 
-static int adm_dolby_get_parameters[ADM_GET_PARAMETER_LENGTH];
+static int adm_get_parameters[ADM_GET_PARAMETER_LENGTH];
 
 int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
 {
@@ -333,10 +333,10 @@
 	return rc;
 }
 
-int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
-				uint32_t params_length, char *params)
+int adm_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+		uint32_t params_length, char *params)
 {
-	struct adm_cmd_get_pp_params_v5	*adm_params = NULL;
+	struct adm_cmd_get_pp_params_v5 *adm_params = NULL;
 	int sz, rc = 0, i = 0, index = afe_get_port_index(port_id);
 	int *params_data = (int *)params;
 
@@ -345,17 +345,17 @@
 			__func__, index, port_id);
 		return -EINVAL;
 	}
-	sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
+	sz = sizeof(struct adm_cmd_get_pp_params_v5) + params_length;
 	adm_params = kzalloc(sz, GFP_KERNEL);
 	if (!adm_params) {
 		pr_err("%s, adm params memory alloc failed", __func__);
 		return -ENOMEM;
 	}
 
-	memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
-			params, params_length);
+	memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_get_pp_params_v5)),
+		params, params_length);
 	adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
 	adm_params->hdr.pkt_size = sz;
 	adm_params->hdr.src_svc = APR_SVC_ADM;
 	adm_params->hdr.src_domain = APR_DOMAIN_APPS;
@@ -376,31 +376,33 @@
 	atomic_set(&this_adm.copp_stat[index], 0);
 	rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
 	if (rc < 0) {
-		pr_err("%s: Failed to Get DOLBY Params on port %d\n", __func__,
+		pr_err("%s: Failed to Get Params on port %d\n", __func__,
 			port_id);
 		rc = -EINVAL;
-		goto dolby_dap_get_param_return;
+		goto adm_get_param_return;
 	}
 	/* Wait for the callback with copp id */
 	rc = wait_event_timeout(this_adm.wait[index],
-			atomic_read(&this_adm.copp_stat[index]),
-			msecs_to_jiffies(TIMEOUT_MS));
+	atomic_read(&this_adm.copp_stat[index]),
+		msecs_to_jiffies(TIMEOUT_MS));
 	if (!rc) {
-		pr_err("%s: DOLBY get params timed out port = %d\n", __func__,
+		pr_err("%s: get params timed out port = %d\n", __func__,
 			port_id);
 		rc = -EINVAL;
-		goto dolby_dap_get_param_return;
+		goto adm_get_param_return;
 	}
 	if (params_data) {
-		for (i = 0; i < adm_dolby_get_parameters[0]; i++)
-			params_data[i] = adm_dolby_get_parameters[1+i];
+		for (i = 0; i < adm_get_parameters[0]; i++)
+			params_data[i] = adm_get_parameters[1+i];
 	}
 	rc = 0;
-dolby_dap_get_param_return:
+adm_get_param_return:
 	kfree(adm_params);
+
 	return rc;
 }
 
+
 static void adm_callback_debug_print(struct apr_client_data *data)
 {
 	uint32_t *payload;
@@ -574,11 +576,11 @@
 					__func__, payload[0]);
 			rtac_make_adm_callback(payload,
 				data->payload_size);
-			adm_dolby_get_parameters[0] = payload[3];
+			adm_get_parameters[0] = payload[3];
 			pr_debug("GET_PP PARAM:received parameter length: %x\n",
-					adm_dolby_get_parameters[0]);
+					adm_get_parameters[0]);
 			for (i = 0; i < payload[3]; i++)
-				adm_dolby_get_parameters[1+i] = payload[4+i];
+				adm_get_parameters[1+i] = payload[4+i];
 			atomic_set(&this_adm.copp_stat[index], 1);
 			wake_up(&this_adm.wait[index]);
 			break;
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 0eb13d4..1810770 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -139,13 +139,13 @@
 		pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x token=%d\n",
 					__func__, data->opcode,
 					payload[0], payload[1], data->token);
-		/* payload[1] contains the error status for response */
-		if (payload[1] != 0) {
-			atomic_set(&this_afe.status, -1);
-			pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
-					__func__, payload[0], payload[1]);
-		}
 		if (data->opcode == APR_BASIC_RSP_RESULT) {
+			/* payload[1] contains the error status for response */
+			if (payload[1] != 0) {
+				atomic_set(&this_afe.status, -1);
+				pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
+					__func__, payload[0], payload[1]);
+			}
 			switch (payload[0]) {
 			case AFE_PORT_CMD_DEVICE_STOP:
 			case AFE_PORT_CMD_DEVICE_START:
@@ -175,8 +175,9 @@
 			}
 		} else if (data->opcode ==
 				AFE_SERVICE_CMDRSP_SHARED_MEM_MAP_REGIONS) {
-			pr_debug("%s: mmap_handle: 0x%x\n",
-						__func__, payload[0]);
+			pr_debug("%s: mmap_handle: 0x%x, cal index %d\n",
+				 __func__, payload[0],
+				 atomic_read(&this_afe.mem_map_cal_index));
 			if (atomic_read(&this_afe.mem_map_cal_index) != -1)
 				atomic_set(&this_afe.mem_map_cal_handles[
 					atomic_read(
@@ -379,8 +380,10 @@
 	int						size = 4096;
 	struct acdb_cal_block				cal_block;
 	struct afe_audioif_config_command_no_payload	afe_cal;
-	pr_debug("%s: path %d\n", __func__, path);
+	atomic_t *hptr;
+	u32 handle;
 
+	pr_debug("%s: path %d\n", __func__, path);
 	if (path == AANC_TX_CAL) {
 		get_aanc_cal(&cal_block);
 	} else {
@@ -396,11 +399,17 @@
 		(cal_block.cal_size > this_afe.afe_cal_addr[path].cal_size)) {
 		atomic_set(&this_afe.mem_map_cal_index, path);
 		if (this_afe.afe_cal_addr[path].cal_paddr != 0) {
-			result = afe_cmd_memory_unmap(
-				this_afe.afe_cal_addr[path].cal_paddr);
+			hptr = &this_afe.mem_map_cal_handles[path];
+			handle = atomic_xchg(hptr, 0);
+			if (!handle) {
+				pr_err("%s: invalid NULL handle\n", __func__);
+				result = -EINVAL;
+				goto done;
+			}
+			result = afe_cmd_memory_unmap(handle);
 			if (result) {
-				pr_err("%s: AFE memory unmap failed\n",
-						__func__);
+				WARN(1, "%s: AFE memory unmap failed %d, handle 0x%x\n",
+				     __func__, result, handle);
 				atomic_set(&this_afe.mem_map_cal_index, -1);
 				goto done;
 			}
@@ -2118,7 +2127,7 @@
 	struct afe_service_cmd_shared_mem_unmap_regions mregion;
 	int index = 0;
 
-	pr_debug("%s:\n", __func__);
+	pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
 
 	if (this_afe.apr == NULL) {
 		this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
@@ -2161,7 +2170,7 @@
 	int ret = 0;
 	struct afe_service_cmd_shared_mem_unmap_regions mregion;
 
-	pr_debug("%s:\n", __func__);
+	pr_debug("%s: handle 0x%x\n", __func__, mem_map_handle);
 
 	if (this_afe.apr == NULL) {
 		this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
@@ -3143,12 +3152,15 @@
 static void __exit afe_exit(void)
 {
 	int i;
+	atomic_t *hptr;
+	u32 handle;
 
 	config_debug_fs_exit();
-	for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
-		if (this_afe.afe_cal_addr[i].cal_paddr != 0)
-			afe_cmd_memory_unmap_nowait(
-				this_afe.afe_cal_addr[i].cal_paddr);
+	for (i = 0; i < ARRAY_SIZE(this_afe.mem_map_cal_handles); i++) {
+		hptr = &this_afe.mem_map_cal_handles[i];
+		handle = atomic_xchg(hptr, 0);
+		if (handle != 0)
+			afe_cmd_memory_unmap_nowait(handle);
 	}
 }
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index f268171..7243f19 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -55,7 +55,7 @@
 static int voice_send_attach_vocproc_cmd(struct voice_data *v);
 static int voice_send_set_device_cmd(struct voice_data *v);
 static int voice_send_disable_vocproc_cmd(struct voice_data *v);
-static int voice_send_vol_index_cmd(struct voice_data *v);
+static int voice_send_vol_step_cmd(struct voice_data *v);
 static int voice_send_mvm_unmap_memory_physical_cmd(struct voice_data *v,
 						    uint32_t mem_handle);
 static int voice_send_mvm_cal_network_cmd(struct voice_data *v);
@@ -95,7 +95,40 @@
 static int voice_alloc_and_map_oob_mem(struct voice_data *v);
 
 static struct voice_data *voice_get_session_by_idx(int idx);
-static int voice_get_idx_for_session(u32 session_id);
+
+static void voice_itr_init(struct voice_session_itr *itr,
+			   u32 session_id)
+{
+	if (itr == NULL)
+		return;
+	itr->session_idx = voice_get_idx_for_session(session_id);
+	if (session_id == ALL_SESSION_VSID)
+		itr->cur_idx = 0;
+	else
+		itr->cur_idx = itr->session_idx;
+
+}
+
+static bool voice_itr_get_next_session(struct voice_session_itr *itr,
+					struct voice_data **voice)
+{
+	bool ret = false;
+
+	if (itr == NULL)
+		return false;
+	pr_debug("%s : cur idx = %d session idx = %d",
+			 __func__, itr->cur_idx, itr->session_idx);
+
+	if (itr->cur_idx <= itr->session_idx) {
+		ret = true;
+		*voice = voice_get_session_by_idx(itr->cur_idx);
+		itr->cur_idx++;
+	} else {
+		*voice = NULL;
+	}
+
+	return ret;
+}
 
 static u16 voice_get_mvm_handle(struct voice_data *v)
 {
@@ -175,6 +208,9 @@
 	} else if (session_id ==
 			common.voice[VOC_PATH_VOLTE_PASSIVE].session_id) {
 		session_name = VOLTE_SESSION_NAME;
+	} else if (session_id ==
+			common.voice[VOC_PATH_QCHAT_PASSIVE].session_id) {
+		session_name = QCHAT_SESSION_NAME;
 	} else if (session_id == common.voice[VOC_PATH_FULL].session_id) {
 		session_name = VOIP_SESSION_NAME;
 	}
@@ -194,6 +230,9 @@
 		else if (!strncmp(name, "VoLTE session", 13))
 			session_id =
 			common.voice[VOC_PATH_VOLTE_PASSIVE].session_id;
+		else if (!strncmp(name, "QCHAT session", 13))
+			session_id =
+			common.voice[VOC_PATH_QCHAT_PASSIVE].session_id;
 		else
 			session_id = common.voice[VOC_PATH_FULL].session_id;
 
@@ -225,6 +264,10 @@
 		v = &common.voice[VOC_PATH_FULL];
 		break;
 
+	case QCHAT_SESSION_VSID:
+		v = &common.voice[VOC_PATH_QCHAT_PASSIVE];
+		break;
+
 	case ALL_SESSION_VSID:
 		break;
 
@@ -240,7 +283,7 @@
 	return v;
 }
 
-static int voice_get_idx_for_session(u32 session_id)
+int voice_get_idx_for_session(u32 session_id)
 {
 	int idx = 0;
 
@@ -261,6 +304,10 @@
 		idx = VOC_PATH_FULL;
 		break;
 
+	case QCHAT_SESSION_VSID:
+		idx = VOC_PATH_QCHAT_PASSIVE;
+		break;
+
 	case ALL_SESSION_VSID:
 		idx = MAX_VOC_SESSIONS - 1;
 		break;
@@ -280,11 +327,6 @@
 				NULL : &common.voice[idx]);
 }
 
-static bool is_voice_session(u32 session_id)
-{
-	return (session_id == common.voice[VOC_PATH_PASSIVE].session_id);
-}
-
 static bool is_voip_session(u32 session_id)
 {
 	return (session_id == common.voice[VOC_PATH_FULL].session_id);
@@ -300,6 +342,21 @@
 	return (session_id == common.voice[VOC_PATH_VOICE2_PASSIVE].session_id);
 }
 
+static bool is_qchat_session(u32 session_id)
+{
+	return (session_id == common.voice[VOC_PATH_QCHAT_PASSIVE].session_id);
+}
+
+static bool is_voc_state_active(int voc_state)
+{
+	if ((voc_state == VOC_RUN) ||
+		(voc_state == VOC_CHANGE) ||
+		(voc_state == VOC_STANDBY))
+		return true;
+
+	return false;
+}
+
 static bool is_other_session_active(u32 session_id)
 {
 	int i;
@@ -310,9 +367,7 @@
 		if (common.voice[i].session_id == session_id)
 			continue;
 
-		if ((common.voice[i].voc_state == VOC_RUN) ||
-		    (common.voice[i].voc_state == VOC_CHANGE) ||
-		    (common.voice[i].voc_state == VOC_STANDBY)) {
+		if (is_voc_state_active(common.voice[i].voc_state)) {
 			ret = true;
 			break;
 		}
@@ -322,12 +377,19 @@
 	return ret;
 }
 
+static bool is_voice_app_id(u32 session_id)
+{
+	return (((session_id & APP_ID_MASK) >> APP_ID_SHIFT) ==
+						VSID_APP_CS_VOICE);
+}
+
 static void init_session_id(void)
 {
 	common.voice[VOC_PATH_PASSIVE].session_id = VOICE_SESSION_VSID;
 	common.voice[VOC_PATH_VOLTE_PASSIVE].session_id = VOLTE_SESSION_VSID;
 	common.voice[VOC_PATH_VOICE2_PASSIVE].session_id = VOICE2_SESSION_VSID;
 	common.voice[VOC_PATH_FULL].session_id = VOIP_SESSION_VSID;
+	common.voice[VOC_PATH_QCHAT_PASSIVE].session_id = QCHAT_SESSION_VSID;
 }
 
 static int voice_apr_register(void)
@@ -452,10 +514,8 @@
 		pr_err("%s: apr_mvm is NULL.\n", __func__);
 		return -EINVAL;
 	}
-	pr_debug("%s: VoLTE command to MVM\n", __func__);
-	if (is_volte_session(v->session_id) ||
-		is_voice_session(v->session_id) ||
-		is_voice2_session(v->session_id)) {
+	pr_debug("%s: Send Dual Control command to MVM\n", __func__);
+	if (!is_voip_session(v->session_id)) {
 		mvm_handle = voice_get_mvm_handle(v);
 		mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(
 						APR_MSG_TYPE_SEQ_CMD,
@@ -529,9 +589,7 @@
 	/* send cmd to create mvm session and wait for response */
 
 	if (!mvm_handle) {
-		if (is_voice_session(v->session_id) ||
-			is_volte_session(v->session_id) ||
-			is_voice2_session(v->session_id)) {
+		if (!is_voip_session(v->session_id)) {
 			mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD(
 						APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
@@ -556,6 +614,10 @@
 				strlcpy(mvm_session_cmd.mvm_session.name,
 				VOICE2_SESSION_VSID_STR,
 				sizeof(mvm_session_cmd.mvm_session.name));
+			} else if (is_qchat_session(v->session_id)) {
+				strlcpy(mvm_session_cmd.mvm_session.name,
+				QCHAT_SESSION_VSID_STR,
+				sizeof(mvm_session_cmd.mvm_session.name));
 			} else {
 				strlcpy(mvm_session_cmd.mvm_session.name,
 				"default modem voice",
@@ -618,9 +680,7 @@
 	}
 	/* send cmd to create cvs session */
 	if (!cvs_handle) {
-		if (is_voice_session(v->session_id) ||
-			is_volte_session(v->session_id) ||
-			is_voice2_session(v->session_id)) {
+		if (!is_voip_session(v->session_id)) {
 			pr_debug("%s: creating CVS passive session\n",
 				 __func__);
 
@@ -646,6 +706,10 @@
 				strlcpy(cvs_session_cmd.cvs_session.name,
 				VOICE2_SESSION_VSID_STR,
 				sizeof(cvs_session_cmd.cvs_session.name));
+			} else if (is_qchat_session(v->session_id)) {
+				strlcpy(cvs_session_cmd.cvs_session.name,
+				QCHAT_SESSION_VSID_STR,
+				sizeof(cvs_session_cmd.cvs_session.name));
 			} else {
 			strlcpy(cvs_session_cmd.cvs_session.name,
 				"default modem voice",
@@ -834,7 +898,9 @@
 		}
 	}
 
-	if (is_voip_session(v->session_id) || v->voc_state == VOC_ERROR) {
+	if (is_voip_session(v->session_id) ||
+	    is_qchat_session(v->session_id) ||
+	    v->voc_state == VOC_ERROR) {
 		/* Destroy CVS. */
 		pr_debug("%s: CVS destroy session\n", __func__);
 
@@ -1213,9 +1279,8 @@
 	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
 		v = &common.voice[i];
 		if ((v->dtmf_rx_detect_en) &&
-			((v->voc_state == VOC_RUN) ||
-			 (v->voc_state == VOC_CHANGE) ||
-			 (v->voc_state == VOC_STANDBY))) {
+			is_voc_state_active(v->voc_state)) {
+
 			pr_debug("disable dtmf det on ses_id=%d\n",
 				 v->session_id);
 			voice_send_dtmf_rx_detection_cmd(v, 0);
@@ -1236,9 +1301,7 @@
 	mutex_lock(&v->lock);
 	v->dtmf_rx_detect_en = enable;
 
-	if ((v->voc_state == VOC_RUN) ||
-	    (v->voc_state == VOC_CHANGE) ||
-	    (v->voc_state == VOC_STANDBY))
+	if (is_voc_state_active(v->voc_state))
 		ret = voice_send_dtmf_rx_detection_cmd(v,
 						       v->dtmf_rx_detect_en);
 
@@ -2327,6 +2390,62 @@
 	return ret;
 }
 
+int voc_register_vocproc_vol_table(void)
+{
+	int			result = 0;
+	int			i;
+	struct voice_data	*v = NULL;
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&common.common_lock);
+	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+		v = &common.voice[i];
+
+		mutex_lock(&v->lock);
+		if (is_voc_state_active(v->voc_state)) {
+			result = voice_send_cvp_register_vol_cal_cmd(v);
+			if (result) {
+				pr_err("%s: Failed to register vocvol table for session 0x%x!\n",
+					__func__, v->session_id);
+				mutex_unlock(&v->lock);
+				goto done;
+			}
+		}
+		mutex_unlock(&v->lock);
+	}
+done:
+	mutex_unlock(&common.common_lock);
+	return result;
+}
+
+int voc_deregister_vocproc_vol_table(void)
+{
+	int			result = 0;
+	int			i;
+	struct voice_data	*v = NULL;
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&common.common_lock);
+	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+		v = &common.voice[i];
+
+		mutex_lock(&v->lock);
+		if (is_voc_state_active(v->voc_state)) {
+			result = voice_send_cvp_deregister_vol_cal_cmd(v);
+			if (result) {
+				pr_err("%s: Failed to deregister vocvol table for session 0x%x!\n",
+					__func__, v->session_id);
+				mutex_unlock(&v->lock);
+				goto done;
+			}
+		}
+		mutex_unlock(&v->lock);
+	}
+done:
+	mutex_unlock(&common.common_lock);
+	return result;
+}
+
 static int voice_map_memory_physical_cmd(struct voice_data *v,
 					 struct mem_map_table *table_info,
 					 dma_addr_t phys,
@@ -3160,7 +3279,8 @@
 	cvs_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
 	cvs_mute_cmd.cvs_set_mute.direction = VSS_IVOLUME_DIRECTION_TX;
 	cvs_mute_cmd.cvs_set_mute.mute_flag = v->stream_tx.stream_mute;
-	cvs_mute_cmd.cvs_set_mute.ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
+	cvs_mute_cmd.cvs_set_mute.ramp_duration_ms =
+				v->stream_tx.stream_mute_ramp_duration_ms;
 
 	v->cvs_state = CMD_STATUS_FAIL;
 	ret = apr_send_pkt(common.apr_q6_cvs, (uint32_t *) &cvs_mute_cmd);
@@ -3185,7 +3305,7 @@
 }
 
 static int voice_send_device_mute_cmd(struct voice_data *v, uint16_t direction,
-				      uint16_t mute_flag)
+				     uint16_t mute_flag, uint32_t ramp_duration)
 {
 	struct cvp_set_mute_cmd cvp_mute_cmd;
 	int ret = 0;
@@ -3214,7 +3334,7 @@
 	cvp_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
 	cvp_mute_cmd.cvp_set_mute.direction = direction;
 	cvp_mute_cmd.cvp_set_mute.mute_flag = mute_flag;
-	cvp_mute_cmd.cvp_set_mute.ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
+	cvp_mute_cmd.cvp_set_mute.ramp_duration_ms = ramp_duration;
 
 	v->cvp_state = CMD_STATUS_FAIL;
 	ret = apr_send_pkt(common.apr_q6_cvp, (uint32_t *) &cvp_mute_cmd);
@@ -3238,9 +3358,9 @@
 	return -EINVAL;
 }
 
-static int voice_send_vol_index_cmd(struct voice_data *v)
+static int voice_send_vol_step_cmd(struct voice_data *v)
 {
-	struct cvp_set_rx_volume_index_cmd cvp_vol_cmd;
+	struct cvp_set_rx_volume_step_cmd cvp_vol_step_cmd;
 	int ret = 0;
 	void *apr_cvp;
 	u16 cvp_handle;
@@ -3257,21 +3377,29 @@
 	cvp_handle = voice_get_cvp_handle(v);
 
 	/* send volume index to cvp */
-	cvp_vol_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+	cvp_vol_step_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
 						APR_PKT_VER);
-	cvp_vol_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
-					sizeof(cvp_vol_cmd) - APR_HDR_SIZE);
-	cvp_vol_cmd.hdr.src_port =
+	cvp_vol_step_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+				sizeof(cvp_vol_step_cmd) - APR_HDR_SIZE);
+	cvp_vol_step_cmd.hdr.src_port =
 				voice_get_idx_for_session(v->session_id);
-	cvp_vol_cmd.hdr.dest_port = cvp_handle;
-	cvp_vol_cmd.hdr.token = 0;
-	cvp_vol_cmd.hdr.opcode = VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX;
-	cvp_vol_cmd.cvp_set_vol_idx.vol_index = v->dev_rx.volume;
+	cvp_vol_step_cmd.hdr.dest_port = cvp_handle;
+	cvp_vol_step_cmd.hdr.token = 0;
+	cvp_vol_step_cmd.hdr.opcode = VSS_IVOLUME_CMD_SET_STEP;
+	cvp_vol_step_cmd.cvp_set_vol_step.direction = VSS_IVOLUME_DIRECTION_RX;
+	cvp_vol_step_cmd.cvp_set_vol_step.value = v->dev_rx.volume_step_value;
+	cvp_vol_step_cmd.cvp_set_vol_step.ramp_duration_ms =
+					v->dev_rx.volume_ramp_duration_ms;
+	 pr_debug("%s step_value:%d, ramp_duration_ms:%d",
+			__func__,
+			cvp_vol_step_cmd.cvp_set_vol_step.value,
+			cvp_vol_step_cmd.cvp_set_vol_step.ramp_duration_ms);
+
 	v->cvp_state = CMD_STATUS_FAIL;
-	ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_vol_cmd);
+	ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_vol_step_cmd);
 	if (ret < 0) {
-		pr_err("Fail in sending RX VOL INDEX\n");
+		pr_err("Fail in sending RX VOL step\n");
 		return -EINVAL;
 	}
 	ret = wait_event_timeout(v->cvp_wait,
@@ -3776,22 +3904,28 @@
 			pr_debug("%s: TX and RX mute ON\n", __func__);
 
 			voice_send_device_mute_cmd(v,
-						   VSS_IVOLUME_DIRECTION_TX,
-						   VSS_IVOLUME_MUTE_ON);
+						VSS_IVOLUME_DIRECTION_TX,
+						VSS_IVOLUME_MUTE_ON,
+						DEFAULT_MUTE_RAMP_DURATION);
 			voice_send_device_mute_cmd(v,
-						   VSS_IVOLUME_DIRECTION_RX,
-						   VSS_IVOLUME_MUTE_ON);
+						VSS_IVOLUME_DIRECTION_RX,
+						VSS_IVOLUME_MUTE_ON,
+						DEFAULT_MUTE_RAMP_DURATION);
 		} else if (v->lch_mode == VOICE_LCH_STOP) {
 			pr_debug("%s: TX and RX mute OFF\n", __func__);
 
 			voice_send_device_mute_cmd(v,
-						   VSS_IVOLUME_DIRECTION_TX,
-						   VSS_IVOLUME_MUTE_OFF);
+						VSS_IVOLUME_DIRECTION_TX,
+						VSS_IVOLUME_MUTE_OFF,
+						DEFAULT_MUTE_RAMP_DURATION);
 			voice_send_device_mute_cmd(v,
-						   VSS_IVOLUME_DIRECTION_RX,
-						   VSS_IVOLUME_MUTE_OFF);
+						VSS_IVOLUME_DIRECTION_RX,
+						VSS_IVOLUME_MUTE_OFF,
+						DEFAULT_MUTE_RAMP_DURATION);
 			/* Reset lch mode when VOICE_LCH_STOP is recieved */
 			v->lch_mode = 0;
+			/* Apply cached mute setting */
+			voice_send_stream_mute_cmd(v);
 		} else {
 			pr_debug("%s: Mute commands not sent for lch_mode=%d\n",
 				 __func__, v->lch_mode);
@@ -3855,53 +3989,67 @@
 	return -EINVAL;
 }
 
-int voc_set_tx_mute(uint32_t session_id, uint32_t dir, uint32_t mute)
+int voc_set_tx_mute(uint32_t session_id, uint32_t dir, uint32_t mute,
+		    uint32_t ramp_duration)
 {
-	struct voice_data *v = voice_get_session(session_id);
+	struct voice_data *v = NULL;
 	int ret = 0;
+	struct voice_session_itr itr;
 
-	if (v == NULL) {
-		pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+	voice_itr_init(&itr, session_id);
+	while (voice_itr_get_next_session(&itr, &v)) {
+		if (v != NULL) {
+			mutex_lock(&v->lock);
+			v->stream_tx.stream_mute = mute;
+			v->stream_tx.stream_mute_ramp_duration_ms =
+								ramp_duration;
+			if (is_voc_state_active(v->voc_state) &&
+				(v->lch_mode == 0))
+				ret = voice_send_stream_mute_cmd(v);
+			mutex_unlock(&v->lock);
+		} else {
+			pr_err("%s: invalid session_id 0x%x\n", __func__,
+				session_id);
 
-		return -EINVAL;
+			ret = -EINVAL;
+			break;
+		}
 	}
 
-	mutex_lock(&v->lock);
-
-	v->stream_tx.stream_mute = mute;
-
-	if ((v->voc_state == VOC_RUN) ||
-	    (v->voc_state == VOC_CHANGE) ||
-	    (v->voc_state == VOC_STANDBY))
-		ret = voice_send_stream_mute_cmd(v);
-
-	mutex_unlock(&v->lock);
-
 	return ret;
 }
 
-int voc_set_rx_device_mute(uint32_t session_id, uint32_t mute)
+int voc_set_rx_device_mute(uint32_t session_id, uint32_t mute,
+					uint32_t ramp_duration)
 {
-	struct voice_data *v = voice_get_session(session_id);
+	struct voice_data *v = NULL;
 	int ret = 0;
+	struct voice_session_itr itr;
 
-	if (v == NULL) {
-		pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+	voice_itr_init(&itr, session_id);
+	while (voice_itr_get_next_session(&itr, &v)) {
+		if (v != NULL) {
+			mutex_lock(&v->lock);
+			v->dev_rx.dev_mute = mute;
+			v->dev_rx.dev_mute_ramp_duration_ms =
+							ramp_duration;
+			if (((v->voc_state == VOC_RUN) ||
+				(v->voc_state == VOC_STANDBY)) &&
+				(v->lch_mode == 0))
+				ret = voice_send_device_mute_cmd(v,
+						VSS_IVOLUME_DIRECTION_RX,
+						v->dev_rx.dev_mute,
+						ramp_duration);
+			mutex_unlock(&v->lock);
+		} else {
+			pr_err("%s: invalid session_id 0x%x\n", __func__,
+				session_id);
 
-		return -EINVAL;
+			ret = -EINVAL;
+			break;
+		}
 	}
 
-	mutex_lock(&v->lock);
-
-	v->dev_rx.dev_mute = mute;
-
-	if (v->voc_state == VOC_RUN)
-		ret = voice_send_device_mute_cmd(v,
-						 VSS_IVOLUME_DIRECTION_RX,
-						 v->dev_rx.dev_mute);
-
-	mutex_unlock(&v->lock);
-
 	return ret;
 }
 
@@ -3967,28 +4115,37 @@
 
 int voc_set_pp_enable(uint32_t session_id, uint32_t module_id, uint32_t enable)
 {
-	struct voice_data *v = voice_get_session(session_id);
+	struct voice_data *v = NULL;
 	int ret = 0;
+	struct voice_session_itr itr;
 
-	if (v == NULL) {
-		pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+	voice_itr_init(&itr, session_id);
+	while (voice_itr_get_next_session(&itr, &v)) {
+		if (v != NULL) {
+			if (!(is_voice_app_id(v->session_id) ||
+			      is_volte_session(v->session_id)))
+				continue;
 
-		return -EINVAL;
-	}
+			mutex_lock(&v->lock);
+			if (module_id == MODULE_ID_VOICE_MODULE_ST)
+				v->st_enable = enable;
 
-	mutex_lock(&v->lock);
-	if (module_id == MODULE_ID_VOICE_MODULE_ST)
-		v->st_enable = enable;
-
-	if (v->voc_state == VOC_RUN) {
-		if (module_id == MODULE_ID_VOICE_MODULE_ST)
-			ret = voice_send_set_pp_enable_cmd(v,
+			if (v->voc_state == VOC_RUN) {
+				if (module_id ==
+				    MODULE_ID_VOICE_MODULE_ST)
+					ret = voice_send_set_pp_enable_cmd(v,
 						MODULE_ID_VOICE_MODULE_ST,
 						enable);
+			}
+			mutex_unlock(&v->lock);
+		} else {
+			pr_err("%s: invalid session_id 0x%x\n", __func__,
+								session_id);
+			ret =  -EINVAL;
+			break;
+		}
 	}
 
-	mutex_unlock(&v->lock);
-
 	return ret;
 }
 
@@ -4011,28 +4168,34 @@
 	return ret;
 }
 
-int voc_set_rx_vol_index(uint32_t session_id, uint32_t dir, uint32_t vol_idx)
+int voc_set_rx_vol_step(uint32_t session_id, uint32_t dir, uint32_t vol_step,
+			uint32_t ramp_duration)
 {
-	struct voice_data *v = voice_get_session(session_id);
+	struct voice_data *v = NULL;
 	int ret = 0;
+	struct voice_session_itr itr;
 
-	if (v == NULL) {
-		pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+	pr_debug("%s session id = %#x vol = %u", __func__, session_id,
+		vol_step);
 
-		return -EINVAL;
+	voice_itr_init(&itr, session_id);
+	while (voice_itr_get_next_session(&itr, &v)) {
+		if (v != NULL) {
+			mutex_lock(&v->lock);
+			v->dev_rx.volume_step_value = vol_step;
+			v->dev_rx.volume_ramp_duration_ms = ramp_duration;
+			if (is_voc_state_active(v->voc_state))
+				ret = voice_send_vol_step_cmd(v);
+			mutex_unlock(&v->lock);
+		} else {
+			pr_err("%s: invalid session_id 0x%x\n", __func__,
+				session_id);
+
+			ret = -EINVAL;
+			break;
+		}
 	}
 
-	mutex_lock(&v->lock);
-
-	v->dev_rx.volume = vol_idx;
-
-	if ((v->voc_state == VOC_RUN) ||
-	    (v->voc_state == VOC_CHANGE) ||
-	    (v->voc_state == VOC_STANDBY))
-		ret = voice_send_vol_index_cmd(v);
-
-	mutex_unlock(&v->lock);
-
 	return ret;
 }
 
@@ -4318,7 +4481,7 @@
 			goto fail;
 		}
 
-		ret = voice_send_vol_index_cmd(v);
+		ret = voice_send_vol_step_cmd(v);
 		if (ret < 0)
 			pr_err("voice volume failed\n");
 
@@ -4407,6 +4570,11 @@
 			v = voice_get_session(session_id);
 			if (v != NULL)
 				v->voc_state = VOC_ERROR;
+
+			session_id = voc_get_session_id(QCHAT_SESSION_NAME);
+			v = voice_get_session(session_id);
+			if (v != NULL)
+				v->voc_state = VOC_ERROR;
 		} else {
 			pr_debug("%s: Reset event received in Voice service\n",
 				__func__);
@@ -4550,6 +4718,11 @@
 			v = voice_get_session(session_id);
 			if (v != NULL)
 				v->voc_state = VOC_ERROR;
+
+			session_id = voc_get_session_id(QCHAT_SESSION_NAME);
+			v = voice_get_session(session_id);
+			if (v != NULL)
+				v->voc_state = VOC_ERROR;
 		} else {
 			pr_debug("%s: Reset event received in Voice service\n",
 				 __func__);
@@ -4822,6 +4995,11 @@
 			v = voice_get_session(session_id);
 			if (v != NULL)
 				v->voc_state = VOC_ERROR;
+
+			session_id = voc_get_session_id(QCHAT_SESSION_NAME);
+			v = voice_get_session(session_id);
+			if (v != NULL)
+				v->voc_state = VOC_ERROR;
 		} else {
 			pr_debug("%s: Reset event received in Voice service\n",
 				 __func__);
@@ -4866,7 +5044,7 @@
 				wake_up(&v->cvp_wait);
 				break;
 			case VSS_IVOCPROC_CMD_SET_DEVICE_V2:
-			case VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX:
+			case VSS_IVOLUME_CMD_SET_STEP:
 			case VSS_IVOCPROC_CMD_ENABLE:
 			case VSS_IVOCPROC_CMD_DISABLE:
 			case APRV2_IBASIC_CMD_DESTROY_SESSION:
@@ -5161,8 +5339,10 @@
 
 	/* set default value */
 	common.default_mute_val = 0;  /* default is un-mute */
-	common.default_vol_val = 0;
 	common.default_sample_val = 8000;
+	common.default_vol_step_val = 0;
+	common.default_vol_ramp_duration_ms = DEFAULT_VOLUME_RAMP_DURATION;
+	common.default_mute_ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
 
 	/* Initialize MVS info. */
 	common.mvs_info.network_type = VSS_NETWORK_ID_DEFAULT;
@@ -5175,9 +5355,16 @@
 	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
 
 		/* initialize dev_rx and dev_tx */
-		common.voice[i].dev_rx.volume = common.default_vol_val;
 		common.voice[i].dev_rx.dev_mute =  common.default_mute_val;
 		common.voice[i].dev_tx.dev_mute =  common.default_mute_val;
+		common.voice[i].dev_rx.volume_step_value =
+					common.default_vol_step_val;
+		common.voice[i].dev_rx.volume_ramp_duration_ms =
+					common.default_vol_ramp_duration_ms;
+		common.voice[i].dev_rx.dev_mute_ramp_duration_ms =
+					common.default_mute_ramp_duration_ms;
+		common.voice[i].dev_tx.dev_mute_ramp_duration_ms =
+					common.default_mute_ramp_duration_ms;
 		common.voice[i].stream_rx.stream_mute = common.default_mute_val;
 		common.voice[i].stream_tx.stream_mute = common.default_mute_val;
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index b8f7008..1e9c813 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -45,16 +45,19 @@
 /* Stream information payload structure */
 struct stream_data {
 	uint32_t stream_mute;
+	uint32_t stream_mute_ramp_duration_ms;
 };
 
 /* Device information payload structure */
 struct device_data {
-	uint32_t volume; /* in index */
 	uint32_t dev_mute;
 	uint32_t sample;
 	uint32_t enabled;
 	uint32_t dev_id;
 	uint32_t port_id;
+	uint32_t volume_step_value;
+	uint32_t volume_ramp_duration_ms;
+	uint32_t dev_mute_ramp_duration_ms;
 };
 
 struct voice_dev_route_state {
@@ -588,6 +591,8 @@
 #define VSS_IVOLUME_MUTE_ON		1
 
 #define DEFAULT_MUTE_RAMP_DURATION	500
+#define DEFAULT_VOLUME_RAMP_DURATION	20
+#define MAX_RAMP_DURATION		5000
 
 struct vss_ivolume_cmd_mute_v2_t {
 	uint16_t direction;
@@ -902,7 +907,7 @@
 
 #define VSS_IVOCPROC_CMD_SET_VP3_DATA			0x000110EB
 
-#define VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX		0x000110EE
+#define VSS_IVOLUME_CMD_SET_STEP			0x000112C2
 
 #define VSS_IVOCPROC_CMD_ENABLE				0x000100C6
 /**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
@@ -1036,6 +1041,25 @@
 	 */
 } __packed;
 
+struct vss_ivolume_cmd_set_step_t {
+	uint16_t direction;
+	/*
+	* The direction field sets the direction to apply the volume command.
+	* The supported values:
+	* #VSS_IVOLUME_DIRECTION_RX
+	*/
+	uint32_t value;
+	/*
+	* Volume step used to find the corresponding linear volume and
+	* the best match index in the registered volume calibration table.
+	*/
+	uint16_t ramp_duration_ms;
+	/*
+	* Volume change ramp duration in milliseconds.
+	* The supported values: 0 to 5000.
+	*/
+} __packed;
+
 struct vss_ivocproc_cmd_set_device_v2_t {
 	uint16_t tx_port_id;
 	/*
@@ -1143,6 +1167,11 @@
 	struct vss_ivocproc_cmd_set_volume_index_t cvp_set_vol_idx;
 } __packed;
 
+struct cvp_set_rx_volume_step_cmd {
+	struct apr_hdr hdr;
+	struct vss_ivolume_cmd_set_step_t cvp_set_vol_step;
+} __packed;
+
 struct cvp_register_dev_cfg_cmd {
 	struct apr_hdr hdr;
 	struct vss_ivocproc_cmd_register_device_config_t cvp_dev_cfg_data;
@@ -1280,13 +1309,15 @@
 	void *buf;
 };
 
-#define MAX_VOC_SESSIONS 4
+#define MAX_VOC_SESSIONS 5
 
 struct common_data {
 	/* these default values are for all devices */
 	uint32_t default_mute_val;
-	uint32_t default_vol_val;
 	uint32_t default_sample_val;
+	uint32_t default_vol_step_val;
+	uint32_t default_vol_ramp_duration_ms;
+	uint32_t default_mute_ramp_duration_ms;
 
 	/* APR to MVM in the Q6 */
 	void *apr_q6_mvm;
@@ -1309,6 +1340,11 @@
 	struct voice_data voice[MAX_VOC_SESSIONS];
 };
 
+struct voice_session_itr {
+	int cur_idx;
+	int session_idx;
+};
+
 void voc_register_mvs_cb(ul_cb_fn ul_cb,
 			dl_cb_fn dl_cb,
 			void *private_data);
@@ -1336,19 +1372,35 @@
 #define VOC_PATH_FULL 1
 #define VOC_PATH_VOLTE_PASSIVE 2
 #define VOC_PATH_VOICE2_PASSIVE 3
+#define VOC_PATH_QCHAT_PASSIVE 4
 
 #define MAX_SESSION_NAME_LEN 32
 #define VOICE_SESSION_NAME  "Voice session"
 #define VOIP_SESSION_NAME   "VoIP session"
 #define VOLTE_SESSION_NAME  "VoLTE session"
 #define VOICE2_SESSION_NAME "Voice2 session"
+#define QCHAT_SESSION_NAME  "QCHAT session"
 
 #define VOICE2_SESSION_VSID_STR "10DC1000"
+#define QCHAT_SESSION_VSID_STR "10803000"
 #define VOICE_SESSION_VSID  0x10C01000
 #define VOICE2_SESSION_VSID 0x10DC1000
 #define VOLTE_SESSION_VSID  0x10C02000
 #define VOIP_SESSION_VSID   0x10004000
+#define QCHAT_SESSION_VSID  0x10803000
 #define ALL_SESSION_VSID    0xFFFFFFFF
+#define VSID_MAX            ALL_SESSION_VSID
+
+#define APP_ID_MASK         0x3F000
+#define APP_ID_SHIFT		12
+enum vsid_app_type {
+	VSID_APP_NONE = 0,
+	VSID_APP_CS_VOICE = 1,
+	VSID_APP_IMS = 2, /* IMS voice services covering VoLTE etc */
+	VSID_APP_QCHAT = 3,
+	VSID_APP_VOIP = 4, /* VoIP on AP HLOS without modem processor */
+	VSID_APP_MAX,
+};
 
 /* called  by alsa driver */
 int voc_set_pp_enable(uint32_t session_id, uint32_t module_id,
@@ -1364,9 +1416,12 @@
 int voc_set_rxtx_port(uint32_t session_id,
 		      uint32_t dev_port_id,
 		      uint32_t dev_type);
-int voc_set_rx_vol_index(uint32_t session_id, uint32_t dir, uint32_t voc_idx);
-int voc_set_tx_mute(uint32_t session_id, uint32_t dir, uint32_t mute);
-int voc_set_rx_device_mute(uint32_t session_id, uint32_t mute);
+int voc_set_rx_vol_step(uint32_t session_id, uint32_t dir, uint32_t vol_step,
+			uint32_t ramp_duration);
+int voc_set_tx_mute(uint32_t session_id, uint32_t dir, uint32_t mute,
+		    uint32_t ramp_duration);
+int voc_set_rx_device_mute(uint32_t session_id, uint32_t mute,
+			   uint32_t ramp_duration);
 int voc_get_rx_device_mute(uint32_t session_id);
 int voc_disable_cvp(uint32_t session_id);
 int voc_enable_cvp(uint32_t session_id);
@@ -1377,9 +1432,13 @@
 int voc_alloc_cal_shared_memory(void);
 int voc_alloc_voip_shared_memory(void);
 int is_voc_initialized(void);
+int voc_register_vocproc_vol_table(void);
+int voc_deregister_vocproc_vol_table(void);
 
 uint32_t voc_get_session_id(char *name);
 
 int voc_start_playback(uint32_t set, uint16_t port_id);
 int voc_start_record(uint32_t port_id, uint32_t set);
+int voice_get_idx_for_session(u32 session_id);
+
 #endif
diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c
index 1f2a487..a4983d3 100644
--- a/sound/soc/msm/qdsp6v2/rtac.c
+++ b/sound/soc/msm/qdsp6v2/rtac.c
@@ -24,7 +24,7 @@
 #include <sound/q6asm-v2.h>
 #include <sound/q6afe-v2.h>
 #include <sound/apr_audio-v2.h>
-
+#include <q6voice.h>
 #include "audio_acdb.h"
 
 
@@ -352,13 +352,13 @@
 	return;
 }
 
-static int get_voice_index_cvs(u32 cvs_handle)
+static u32 get_voice_session_id_cvs(u32 cvs_handle)
 {
 	u32 i;
 
 	for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
 		if (rtac_voice_data.voice[i].cvs_handle == cvs_handle)
-			return i;
+			return voice_session_id[i];
 	}
 
 	pr_err("%s: No voice index for CVS handle %d found returning 0\n",
@@ -366,13 +366,13 @@
 	return 0;
 }
 
-static int get_voice_index_cvp(u32 cvp_handle)
+static u32 get_voice_session_id_cvp(u32 cvp_handle)
 {
 	u32 i;
 
 	for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
 		if (rtac_voice_data.voice[i].cvp_handle == cvp_handle)
-			return i;
+			return voice_session_id[i];
 	}
 
 	pr_err("%s: No voice index for CVP handle %d found returning 0\n",
@@ -383,9 +383,11 @@
 static int get_voice_index(u32 mode, u32 handle)
 {
 	if (mode == RTAC_CVP)
-		return get_voice_index_cvp(handle);
+		return voice_get_idx_for_session(
+			get_voice_session_id_cvp(handle));
 	if (mode == RTAC_CVS)
-		return get_voice_index_cvs(handle);
+		return voice_get_idx_for_session(
+			get_voice_session_id_cvs(handle));
 
 	pr_err("%s: Invalid mode %d, returning 0\n",
 	       __func__, mode);
@@ -847,8 +849,7 @@
 		payload_size);
 	voice_params.src_svc = 0;
 	voice_params.src_domain = APR_DOMAIN_APPS;
-	voice_params.src_port = voice_session_id[
-					get_voice_index(mode, dest_port)];
+	voice_params.src_port = get_voice_index(mode, dest_port);
 	voice_params.dest_svc = 0;
 	voice_params.dest_domain = APR_DOMAIN_MODEM;
 	voice_params.dest_port = (u16)dest_port;