Merge "wcnss: Convert FIQ register address from virtual to physical"
diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
index eb3986e..7851d53 100644
--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
+++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
@@ -6,7 +6,7 @@
 The timer is attached to a GIC to deliver its two per-processor
 interrupts (one for the secure mode, one for the non-secure mode).
 
-** Timer node properties:
+** CP15 Timer node properties:
 
 - compatible : Should be "arm,armv7-timer"
 
@@ -21,3 +21,52 @@
 		interrupts = <1 13 0xf08 1 14 0xf08>;
 		clock-frequency = <100000000>;
 	};
+
+** Memory mapped timer node properties:
+
+- compatible : Should at least contain "arm,armv7-timer-mem".
+
+- clock-frequency : The frequency of the main counter, in Hz. Optional.
+
+- reg : The control frame base address.
+
+Note that #address-cells, #size-cells, and ranges shall be present to ensure
+the CPU can address the frame's registers.
+
+Each timer node has up to 8 frame sub-nodes with the following properties:
+
+- frame-number: 0 to 7.
+
+- interrupts : Interrupt list for physical and virtual timers in that order.
+  The virtual timer interrupt is optional.
+
+- reg : The first and second view base addresses in that order. The second view
+  base address is optional.
+
+- status : "disabled" indicates the frame is not available for use. Optional.
+
+Example:
+
+	timer@f0000000 {
+		compatible = "arm,armv7-timer-mem";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xf0000000 0x1000>;
+		clock-frequency = <50000000>;
+
+		frame0@f0001000 {
+			frame-number = <0>
+			interrupts = <0 13 0x8>,
+				     <0 14 0x8>;
+			reg = <0xf0001000 0x1000>,
+			      <0xf0002000 0x1000>;
+		};
+
+		frame1@f0003000 {
+			frame-number = <1>
+			interrupts = <0 15 0x8>;
+			reg = <0xf0003000 0x1000>;
+			status = "disabled";
+		};
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
index 4d441ba..6b2f962 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
@@ -87,6 +87,10 @@
 			(In Bytes).
 qcom,prio-rd:		Read priority for a BIMC bus master (Can be 0/1/2)
 qcom,prio-wr:		Write priority for a BIMC bus master (Can be 0/1/2)
+qcom,prio0:		Priority low signal for a NoC bus master
+			(Can be 0/1/2).
+qcom,prio1:		Priority high signal for a NoC bus master
+			(Can be 0/1/2)
 
 
 Example:
@@ -149,7 +153,7 @@
 
 - qcom,msm-bus,name:		String representing the client-name
 - qcom,msm-bus,num-cases:	Total number of usecases
-- qcom,msm-bus,active-only:	Context flag for requests in active or
+- qcom,msm-bus,active-only:	Boolean context flag for requests in active or
 				dual (active & sleep) contex
 - qcom,msm-bus,num-paths:	Total number of master-slave pairs
 - qcom,msm-bus,vectors-KBps:	Arrays of unsigned integers representing:
@@ -160,7 +164,7 @@
 
 	qcom,msm-bus,name = "client-name";
 	qcom,msm-bus,num-cases = <3>;
-	qcom,msm-bus,active-only = <0>;
+	qcom,msm-bus,active-only;
 	qcom,msm-bus,num-paths = <2>;
 	qcom,msm-bus,vectors =
 			<22 512 0 0>, <26 512 0 0>,
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
index 5d1fafb..31600ca 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
@@ -19,9 +19,55 @@
 			Typically the sensor closest to CPU0.
 - qcom,poll-ms: Sampling interval to read sensor, in ms.
 - qcom,limit-temp: Threshold temperature to start stepping CPU down, in degC.
-- qcom,temp-hysteresis: Degrees below threshold temperature to step CPU up.
+- qcom,temp-hysteresis: Degrees C below threshold temperature to step CPU up.
 - qcom,freq-step: Number of frequency steps to take on each CPU mitigation.
 
+Optional properties
+
+- qcom,core-limit-temp: Threshold temperature to start shutting down cores
+			in degC
+- qcom,core-temp-hysterisis: Degrees C below which the cores will be brought
+			online in sequence.
+- qcom,core-control-mask: The cpu mask that will be used to determine if a
+			core can be controlled or not. A mask of 0 indicates
+			the feature is disabled.
+- qcom,vdd-restriction-temp: When temperature is below this threshold, will
+			enable vdd restriction which will set higher voltage on
+			key voltage rails, in degC.
+- qcom,vdd-restriction-temp-hysteresis: When temperature is above this threshold
+			will disable vdd restriction on key rails, in degC.
+- qcom,pmic-sw-mode-temp: Threshold temperature to disable auto mode on the
+			rail, in degC. If this property exists,
+			qcom,pmic-sw-mode-temp-hysteresis and
+			qcom,pmic-sw-mode-regs need to exist, otherwise return error.
+- qcom,pmic-sw-mode-temp-hysteresis: Degree below threshold temperature to
+			enable auto mode on the rail, in degC. If this property exists,
+			qcom,pmic-sw-mode-temp and qcom,pmic-sw-mode-regs need to
+			exist, otherwise return error.
+- qcom,pmic-sw-mode-regs: Array of the regulator names that will want to
+			disable/enable automode based on the threshold. If this
+			property exists, qcom,pmic-sw-mode-temp and
+			qcom,pmic-sw-mode-temp-hysteresis need to exist, otherwise
+			return error. Also, if this property is defined, will have to
+			define <consumer_supply_name>-supply = <&phandle_of_regulator>
+- <consumer_supply_name>-supply = <&phandle_of_regulator>: consumer_supply_name
+			is the name that's defined in thermal driver.
+			phandle_of_regulator is defined by reuglator device tree.
+
+Optional child nodes
+- qcom,<vdd restriction child node name>: Define the name of the child node.
+			If this property exisits, qcom,vdd-rstr-reg, qcom,levels,
+			qcom,min-level and qcom,freq-req need to exist, otherwise
+			we return an error.
+- qcom,vdd-rstr-reg: Name of the rail
+- qcom,levels: Array of the level values. Unit is corner voltage for voltage request
+			or kHz for frequency request.
+- qcom,min-level: Request this level as minimum level when disabling voltage
+			restriction. Unit is corner voltage for voltage request
+			or kHz for frequency request.
+- qcom,freq-req: Flag to determine if we should restrict frequency on this rail
+			instead of voltage.
+
 Example:
 
 	qcom,msm-thermal {
@@ -31,4 +77,20 @@
 		qcom,limit-temp = <60>;
 		qcom,temp-hysteresis = <10>;
 		qcom,freq-step = <2>;
+		qcom,core-limit-temp = <90>;
+		qcom,core-temp-hysterisis = <10>;
+		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,vdd-restriction-temp = <5>;
+		qcom,vdd-restriction-temp-hysteresis = <10>;
+		vdd_dig-supply=<&pm8841_s2_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 */
+		};
 	};
+
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcedev.txt b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
index b9a71f6..7eb65d2 100644
--- a/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
+++ b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
@@ -9,7 +9,7 @@
   - qcom,ce-hw-instance : should contain crypto HW instance.
   - qcom,msm_bus,name: Should be "qcedev-noc"
   - qcom,msm_bus,num_cases: Depends on the use cases for bus scaling
-  - qcom,msm_bus,active-only: Default vector index
+  - qcom,msm_bus,active-only: Boolean flag for context of request (actve/dual)
   - qcom,msm_bus,num_paths: The paths for source and destination ports
   - qcom,msm_bus,vectors: Vectors for bus topology.
 
@@ -31,7 +31,6 @@
 		qcom,ce-hw-shared;
                 qcom,msm-bus,name = "qcedev-noc";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<56 512 0 0>,
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
index 59f9879..79dc287 100644
--- a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
+++ b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
@@ -9,7 +9,7 @@
   - qcom,ce-hw-instance : should contain crypto HW instance.
   - qcom,msm_bus,name: Should be "qcrypto-noc"
   - qcom,msm_bus,num_cases: Depends on the use cases for bus scaling
-  - qcom,msm_bus,active-only: Default vector index
+  - qcom,msm_bus,active-only: Boolean flag for context of request (actve/dual)
   - qcom,msm_bus,num_paths: The paths for source and destination ports
   - qcom,msm_bus,vectors: Vectors for bus topology.
 
@@ -30,7 +30,6 @@
 		qcom,ce-hw-shared;
                 qcom,msm-bus,name = "qcrypto-noc";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<56 512 0 0>,
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index 0004302..436dfc7 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -97,7 +97,6 @@
 		/* Bus Scale Settings */
 		qcom,msm-bus,name = "grp3d";
 		qcom,msm-bus,num-cases = <6>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <2>;
 		qcom,msm-bus,vectors-KBps =
 				<26 512 0 0>, <89 604 0 0>,
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index 2caa959..ac60e38 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -6,6 +6,8 @@
 - qcom,hfi : supported Host-Firmware Interface, one of:
 	- "venus"
 	- "q6"
+- qcom,max-hw-load: The maximum load the hardware can support expressed in units
+  of macroblocks per second.
 
 Optional properties:
 - reg : offset and length of the register set for the device.
@@ -40,8 +42,6 @@
   (enum hal_buffer) to its corresponding TZ usage. The TZ usages are defined
   as "enum cp_mem_usage" in include/linux/msm_ion.h
 - qcom,has-ocmem: indicate the target has ocmem if this property exists
-- qcom,max-hw-load: The maximum load the hardware can support expressed in units
-  of macroblocks per second.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index b99b716..caead84 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -92,7 +92,6 @@
 
 	qcom,msm-bus,name = "sdcc2";
 	qcom,msm-bus,num-cases = <7>;
-	qcom,msm-bus,active-only = <0>;
 	qcom,msm-bus,num-paths = <1>;
 	qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
 			<81 512 6656 13312>, /* 13 MB/s*/
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 87281f7..013d56e 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -155,7 +155,6 @@
 		qcom,cpu-dma-latency-us = <200>;
 		qcom,msm-bus,name = "sdhc2";
 		qcom,msm-bus,num-cases = <7>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
 				<81 512 6656 13312>, /* 13 MB/s*/
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index f5465a4..b8a39d3 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -7,12 +7,12 @@
 Each of these peripherals are implemented as subnodes in the example at the
 end of this file.
 
-- qcom,chg-chgr:	Supports charging control and status
+- qcom,chgr:		Supports charging control and status
 			reporting.
-- qcom,chg-bat-if:	Battery status reporting such as presence,
+- qcom,bat-if:		Battery status reporting such as presence,
 			temperature reporting and voltage collapse
 			protection.
-- qcom,chg-buck:	Charger buck configuration and status
+- qcom,buck:		Charger buck configuration and status
 			reporting with regards to several regulation
 			loops such as vdd, ibat etc.
 - qcom,usb-chgpth:	USB charge path detection and input current
@@ -23,38 +23,38 @@
 			settings, comparator override features etc.
 
 Parent node required properties:
-- qcom,chg-vddmax-mv:			Target voltage of battery in mV.
-- qcom,chg-vddsafe-mv:			Maximum Vdd voltage in mV.
-- qcom,chg-vinmin-mv:			Minimum input voltage in mV.
-- qcom,chg-ibatmax-ma:			Maximum battery charge current in mA
-- qcom,chg-ibatsafe-ma:			Safety battery current setting
-- qcom,chg-thermal-mitigation:		Array of ibatmax values for different
+- qcom,vddmax-mv:			Target voltage of battery in mV.
+- qcom,vddsafe-mv:			Maximum Vdd voltage in mV.
+- qcom,vinmin-mv:			Minimum input voltage in mV.
+- qcom,ibatmax-ma:			Maximum battery charge current in mA
+- qcom,ibatsafe-ma:			Safety battery current setting
+- qcom,thermal-mitigation:		Array of ibatmax values for different
 					system thermal mitigation level.
 
 Parent node optional properties:
-- qcom,chg-ibatterm-ma:			Current at which charging is terminated when
+- qcom,ibatterm-ma:			Current at which charging is terminated when
 					the analog end of charge option is selected.
-- qcom,chg-maxinput-usb-ma:		Maximum input current USB.
-- qcom,chg-maxinput-dc-ma:		Maximum input current DC.
-- qcom,chg-vbatdet-delta-mv:		Battery charging resume delta.
-- qcom,chg-charging-disabled:		Set this property to disable charging
+- qcom,maxinput-usb-ma:			Maximum input current USB.
+- qcom,maxinput-dc-ma:			Maximum input current DC.
+- qcom,vbatdet-delta-mv:		Battery charging resume delta.
+- qcom,charging-disabled:		Set this property to disable charging
 					by default. This can then be overriden
 					writing the the module parameter
 					"charging_disabled".
-- qcom,chg-use-default-batt-values:	Set this flag to force reporting of
+- qcom,use-default-batt-values:		Set this flag to force reporting of
 					battery temperature of 250 decidegree
 					Celsius, state of charge to be 50%
 					and disable charging.
-- qcom,chg-warm-bat-decidegc:		Warm battery temperature in decidegC.
-- qcom,chg-cool-bat-decidegc:		Cool battery temperature in decidegC.
+- qcom,warm-bat-decidegc:		Warm battery temperature in decidegC.
+- qcom,cool-bat-decidegc:		Cool battery temperature in decidegC.
 					Note that if both warm and cool battery
 					temperatures are set, the corresponding
 					ibatmax and bat-mv properties are
 					required to be set.
-- qcom,chg-ibatmax-cool-ma:		Maximum cool battery charge current.
-- qcom,chg-ibatmax-warm-ma:		Maximum warm battery charge current.
-- qcom,chg-warm-bat-mv:			Warm temperature battery target voltage.
-- qcom,chg-cool-bat-mv:			Cool temperature battery target voltage.
+- qcom,ibatmax-cool-ma:			Maximum cool battery charge current.
+- qcom,ibatmax-warm-ma:			Maximum warm battery charge current.
+- qcom,warm-bat-mv:			Warm temperature battery target voltage.
+- qcom,cool-bat-mv:			Cool temperature battery target voltage.
 
 Sub node required structure:
 - A qcom,chg node must be a child of an SPMI node that has specified
@@ -77,13 +77,13 @@
 
 			qcom,usb-chgpth:
 			 - usbin-valid
-			qcom,chg-chgr:
+			qcom,chgr:
 			 - chg-done
 			 - chg-failed
 
 			The following interrupts are available:
 
-			qcom,chg-chgr:
+			qcom,chgr:
 			 - chg-done:		Triggers on charge completion.
 			 - chg-failed:		Notifies of charge failures.
 			 - fast-chg-on:		Notifies of fast charging state.
@@ -98,7 +98,7 @@
 						setting, can be used as
 						battery alarm.
 
-			qcom,chg-buck:
+			qcom,buck:
 			 - vdd-loop:		VDD loop change interrupt.
 			 - ibat-loop:		Ibat loop change interrupt.
 			 - ichg-loop:		Charge current loop change.
@@ -107,7 +107,7 @@
 			 - vref-ov:		Reference overvoltage interrupt.
 			 - vbat-ov:		Battery overvoltage interrupt.
 
-			qcom,chg-bat-if:
+			qcom,bat-if:
 			 - psi:			PMIC serial interface interrupt.
 			 - vcp-on:		Voltage collapse protection
 						status interrupt.
@@ -140,22 +140,22 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 
-		qcom,chg-vddmax-mv = <4200>;
-		qcom,chg-vddsafe-mv = <4200>;
-		qcom,chg-vinmin-mv = <4200>;
-		qcom,chg-ibatmax-ma = <1500>;
-		qcom,chg-ibatterm-ma = <200>;
-		qcom,chg-ibatsafe-ma = <1500>;
-		qcom,chg-thermal-mitigation = <1500 700 600 325>;
-		qcom,chg-cool-bat-degc = <10>;
-		qcom,chg-cool-bat-mv = <4100>;
-		qcom,chg-ibatmax-warm-ma = <350>;
-		qcom,chg-warm-bat-degc = <45>;
-		qcom,chg-warm-bat-mv = <4100>;
-		qcom,chg-ibatmax-cool-ma = <350>;
-		qcom,chg-vbatdet-delta-mv = <60>;
+		qcom,vddmax-mv = <4200>;
+		qcom,vddsafe-mv = <4200>;
+		qcom,vinmin-mv = <4200>;
+		qcom,ibatmax-ma = <1500>;
+		qcom,ibatterm-ma = <200>;
+		qcom,ibatsafe-ma = <1500>;
+		qcom,thermal-mitigation = <1500 700 600 325>;
+		qcom,cool-bat-degc = <10>;
+		qcom,cool-bat-mv = <4100>;
+		qcom,ibatmax-warm-ma = <350>;
+		qcom,warm-bat-degc = <45>;
+		qcom,warm-bat-mv = <4100>;
+		qcom,ibatmax-cool-ma = <350>;
+		qcom,vbatdet-delta-mv = <60>;
 
-		qcom,chg-chgr@1000 {
+		qcom,chgr@1000 {
 			reg = <0x1000 0x100>;
 			interrupts =	<0x0 0x10 0x0>,
 				<0x0 0x10 0x1>,
@@ -176,7 +176,7 @@
 						"vbat-det-lo";
 		};
 
-		qcom,chg-buck@1100 {
+		qcom,buck@1100 {
 			reg = <0x1100 0x100>;
 			interrupts =	<0x0 0x11 0x0>,
 					<0x0 0x11 0x1>,
@@ -195,7 +195,7 @@
 						"vbat-ov";
 		};
 
-		qcom,chg-bat-if@1200 {
+		qcom,bat-if@1200 {
 			reg = <0x1200 0x100>;
 			interrupts =	<0x0 0x12 0x0>,
 					<0x0 0x12 0x1>,
@@ -210,7 +210,7 @@
 						"batt-pres";
 		};
 
-		qcom,chg-usb-chgpth@1300 {
+		qcom,usb-chgpth@1300 {
 			reg = <0x1300 0x100>;
 			interrupts =	<0 0x13 0x0>,
 					<0 0x13 0x1>,
@@ -221,7 +221,7 @@
 						"chg-gone";
 		};
 
-		qcom,chg-dc-chgpth@1400 {
+		qcom,dc-chgpth@1400 {
 			reg = <0x1400 0x100>;
 			interrupts =	<0x0 0x14 0x0>,
 					<0x0 0x14 0x1>;
@@ -230,7 +230,7 @@
 						"coarse-det-dc";
 		};
 
-		qcom,chg-boost@1500 {
+		qcom,boost@1500 {
 			reg = <0x1500 0x100>;
 			interrupts =	<0x0 0x15 0x0>,
 					<0x0 0x15 0x1>;
@@ -239,7 +239,7 @@
 						"boost-pwr-ok";
 		};
 
-		qcom,chg-misc@1600 {
+		qcom,misc@1600 {
 			reg = <0x1600 0x100>;
 		};
 	};
diff --git a/Documentation/devicetree/bindings/regulator/krait-regulator.txt b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
index aaa731e..6a02e86 100644
--- a/Documentation/devicetree/bindings/regulator/krait-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
@@ -13,6 +13,8 @@
 				register base
 - reg-names:			"apcs_gcc" -string to identify the area where
 				the APCS GCC registers reside.
+- qcom,pfm-threshold		The power coeff threshold in abstract power units below which
+				pmic will be made to operate in PFM mode.
 
 Optional properties:
 - qcom,use-phase-switching	indicates whether the driver should add/shed phases on the PMIC
@@ -51,6 +53,7 @@
 		reg-names = "apcs_gcc";
 		compatible = "qcom,krait-pdn";
 		qcom,use-phase-switching;
+		qcom,pfm-threshold = <376975>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
diff --git a/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt
index ffea58f..777933a 100644
--- a/Documentation/devicetree/bindings/sound/taiko_codec.txt
+++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt
@@ -35,6 +35,10 @@
  - qcom,cdc-vddcx-2-voltage: cx-2 supply's voltage level min and max in mV.
  - qcom,cdc-vddcx-2-current: cx-2 supply's max current in mA.
 
+ - qcom,cdc-static-supplies: List of supplies to be enabled prior to codec
+			     hardware probe.  Supplies in this list will be
+			     stay enabled.
+
  - qcom,cdc-micbias-ldoh-v - LDOH output in volts (should be 1.95 V and 3.00 V).
 
  - qcom,cdc-micbias-cfilt1-mv - cfilt1 output voltage in milli volts.
@@ -67,6 +71,11 @@
 			 values for 9.6MHZ mclk can be 2400000 Hz, 3200000 Hz
 			 and 4800000 Hz.  The values for 12.288MHz mclk can be
 			 3072200 Hz, 4096000 Hz and 6144000 Hz.
+
+ - qcom,cdc-on-demand-supplies: List of supplies which can be enabled
+				dynamically.
+				Supplies in this list are off by default.
+
 Example:
 
 taiko_codec {
@@ -103,6 +112,16 @@
 	qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
 	qcom,cdc-vddcx-2-current = <5000>;
 
+	qcom,cdc-static-supplies = "cdc-vdd-buck",
+				   "cdc-vdd-tx-h",
+				   "cdc-vdd-rx-h",
+				   "cdc-vddpx-1",
+				   "cdc-vdd-a-1p2v",
+				   "cdc-vddcx-1",
+				   "cdc-vddcx-2";
+
+	com,cdc-on-demand-supplies = "cdc-vdd-spkdrv";
+
 	qcom,cdc-micbias-ldoh-v = <0x3>;
 	qcom,cdc-micbias-cfilt1-mv = <1800>;
 	qcom,cdc-micbias-cfilt2-mv = <2700>;
@@ -155,6 +174,10 @@
  - qcom,cdc-vddcx-2-voltage: cx-2 supply's voltage level min and max in mV.
  - qcom,cdc-vddcx-2-current: cx-2 supply's max current in mA.
 
+ - qcom,cdc-static-supplies: List of supplies to be enabled prior to codec
+			     hardware probe.  Supplies in this list will be
+			     stay enabled.
+
  - qcom,cdc-micbias-ldoh-v - LDOH output in volts (should be 1.95 V and 3.00 V).
 
  - qcom,cdc-micbias-cfilt1-mv - cfilt1 output voltage in milli volts.
@@ -179,6 +202,20 @@
  - qcom,cdc-mclk-clk-rate - Specifies the master clock rate in Hz required for
 			    codec.
 
+Optional properties:
+
+ - cdc-vdd-spkdrv-supply: phandle of spkdrv supply's regulator device tree node.
+ - qcom,cdc-vdd-spkdrv-voltage: spkdrv supply voltage level min and max in mV.
+ - qcom,cdc-vdd-spkdrv-current: spkdrv supply max current in mA.
+
+ - cdc-vdd-spkdrv-supply: phandle of spkdrv supply's regulator device tree node.
+ - qcom,cdc-vdd-spkdrv-voltage: spkdrv supply voltage level min and max in mV.
+ - qcom,cdc-vdd-spkdrv-current: spkdrv supply max current in mA.
+
+ - qcom,cdc-on-demand-supplies: List of supplies which can be enabled
+				dynamically.
+				Supplies in this list are off by default.
+
 Example:
 i2c@f9925000 {
 	cell-index = <3>;
@@ -228,6 +265,16 @@
 		qcom,cdc-vddcx-2-voltage = <1200000 1200000>;
 		qcom,cdc-vddcx-2-current = <10000>;
 
+		qcom,cdc-static-supplies = "cdc-vdd-buck",
+					   "cdc-vdd-tx-h",
+					   "cdc-vdd-rx-h",
+					   "cdc-vddpx-1",
+					   "cdc-vdd-a-1p2v",
+					   "cdc-vddcx-1",
+					   "cdc-vddcx-2";
+
+		com,cdc-on-demand-supplies = "cdc-vdd-spkdrv";
+
 		qcom,cdc-micbias-ldoh-v = <0x3>;
 		qcom,cdc-micbias-cfilt1-mv = <1800>;
 		qcom,cdc-micbias-cfilt2-mv = <2700>;
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
index 5861eea..9754c2e 100644
--- a/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
@@ -77,7 +77,6 @@
 
 		qcom,msm-bus,name = "serial_uart0";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<84 512 0 0>,
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
index c597536..96c9486 100644
--- a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
@@ -93,7 +93,6 @@
 
 		qcom,msm-bus,name = "uart7";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<84 512 0 0>,
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 6ea9e62..8ce31d9 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -74,7 +74,6 @@
 
 		qcom,msm-bus,name = "hsic";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<85 512 0 0>,
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index c1d4a05..6d06e99 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -7,7 +7,8 @@
 - regs : offset and length of the register set in the memory map
 - interrupts: IRQ line
 - interrupt-names: OTG interrupt name(s) referenced in interrupts above
-            HSUSB OTG expects "core_irq" and optionally "async_irq".
+            HSUSB OTG expects "core_irq" which is IRQ line from CORE and
+            optional ones are described in next section.
 - qcom,hsusb-otg-phy-type: PHY type can be one of
             1 - Chipidea 45nm PHY
 	    2 - Synopsis 28nm PHY
@@ -28,6 +29,9 @@
          "HSUSB_1p8-supply" and "HSUSB_3p3-supply".
 
 Optional properties :
+- interrupt-names : Optional interrupt resource entries are:
+    "async_irq" : Interrupt from HSPHY for asynchronous wakeup events in LPM.
+    "pmic_id_irq" : Interrupt from PMIC for external ID pin notification.
 - qcom,hsusb-otg-disable-reset: If present then core is RESET only during
 	    init, otherwise core is RESET for every cable disconnect as well
 - qcom,hsusb-otg-pnoc-errata-fix: If present then workaround for PNOC
@@ -43,7 +47,6 @@
 - qcom,hsusb-otg-power-budget: VBUS power budget in mA
   0 will be treated as 500mA
 - qcom,hsusb-otg-pclk-src-name: The source of pclk
-- qcom,hsusb-otg-pmic-id-irq: ID, routed to PMIC IRQ number
 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
   below optional properties:
     - qcom,msm_bus,name
@@ -66,6 +69,8 @@
 - qcom,dp-manual-pullup: If present, vbus is not routed to USB controller/phy
 	and controller driver therefore enables pull-up explicitly before
 	starting controller using usbcmd run/stop bit.
+- qcom,usb2-enable-hsphy2: If present then USB2 controller is connected to 2nd
+	HSPHY.
 
 Example HSUSB OTG controller device node :
 	usb@f9690000 {
@@ -83,7 +88,6 @@
 		qcom,hsusb-otg-phy-init-seq = <0x01 0x90 0xffffffff>;
 		qcom,hsusb-otg-power-budget = <500>;
 		qcom,hsusb-otg-pclk-src-name = "dfab_usb_clk";
-		qcom,hsusb-otg-pmic-id-irq = <47>
 		qcom,hsusb-otg-lpm-on-dev-suspend;
 		qcom,hsusb-otg-clk-always-on-workaround;
 		hsusb_vdd_dig-supply = <&pm8226_s1_corner>;
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 c52b7dd..c0c9107 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -38,7 +38,7 @@
 		qcom,mdss-pan-dsi-stream = <0>;
 		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
 		qcom,mdss-pan-dsi-dma-tr = <0x04>;
-		qcom,mdss-pan-frame-rate = <60>;
+		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
diff --git a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
index 7bd95e7..448d357 100644
--- a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
@@ -36,7 +36,7 @@
 		qcom,mdss-pan-dsi-stream = <0>;
 		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
 		qcom,mdss-pan-dsi-dma-tr = <0x04>;
-		qcom,mdss-pan-frame-rate = <60>;
+		qcom,mdss-pan-dsi-frame-rate = <60>;
 		qcom,panel-phy-regulatorSettings = [03 01 01 00  /* Regualotor settings */
 						    20 00 01];
 		qcom,panel-phy-timingSettings = [69 29 1f 00 55 55
diff --git a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
new file mode 100644
index 0000000..f853285
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
@@ -0,0 +1,67 @@
+/* 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,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 02 01 00 /* sw reset */
+					05 01 00 00 0a 02 11 00 /* exit sleep */
+					15 01 00 00 0a 02 53 2c /* backlight on */
+					15 01 00 00 0a 02 51 ff /* brightness max */
+					05 01 00 00 0a 02 29 00 /* display on */
+					15 01 00 00 0a 02 ae 03 /* set num of lanes */
+					15 01 00 00 0a 02 3a 77 /* rgb_888 */];
+		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+		qcom,panel-off-cmds = [05 01 00 00 0a 02 28 00 /* display off */
+					05 01 00 00 78 02 10 00 /* enter sleep */];
+		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
index 98074c8..9a734a0 100644
--- a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
@@ -37,7 +37,7 @@
 		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,mdss-pan-dsi-frame-rate = <60>;
 		qcom,panel-on-cmds = [32 01 00 00 00 02 00 00];
 		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
 		qcom,panel-off-cmds = [22 01 00 00 00 02 00 00];
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 42f6033..2937cde 100644
--- a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -40,7 +40,7 @@
 		qcom,mdss-pan-dsi-stream = <0>;
 		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
 		qcom,mdss-pan-dsi-dma-tr = <0x04>;
-		qcom,mdss-pan-frame-rate = <60>;
+		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
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index ec42cfc..28766cf 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -88,6 +88,24 @@
 				qcom,fast-avg-setup = <0>;
 			};
 		};
+
+		qcom,pm8110_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,pm8110_rtc_rw@6000 {
+				reg = <0x6000 0x100>;
+			};
+
+			qcom,pm8110_rtc_alarm@6100 {
+				reg = <0x6100 0x100>;
+				interrupts = <0x0 0x61 0x1>;
+			};
+		};
 	};
 
 	qcom,pm8110@1 {
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index f702abb..161b580 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -56,16 +56,16 @@
 			#size-cells = <1>;
 			status = "disabled";
 
-			qcom,chg-vddmax-mv = <4200>;
-			qcom,chg-vddsafe-mv = <4200>;
-			qcom,chg-vinmin-mv = <4200>;
-			qcom,chg-vbatdet-mv = <4100>;
-			qcom,chg-ibatmax-ma = <1500>;
-			qcom,chg-ibatterm-ma = <200>;
-			qcom,chg-ibatsafe-ma = <1500>;
-			qcom,chg-thermal-mitigation = <1500 700 600 325>;
+			qcom,vddmax-mv = <4200>;
+			qcom,vddsafe-mv = <4200>;
+			qcom,vinmin-mv = <4200>;
+			qcom,vbatdet-mv = <4100>;
+			qcom,ibatmax-ma = <1500>;
+			qcom,ibatterm-ma = <200>;
+			qcom,ibatsafe-ma = <1500>;
+			qcom,thermal-mitigation = <1500 700 600 325>;
 
-			qcom,chg-chgr@1000 {
+			qcom,chgr@1000 {
 				status = "disabled";
 				reg = <0x1000 0x100>;
 				interrupts =	<0x0 0x10 0x0>,
@@ -87,7 +87,7 @@
 							"chg-done";
 			};
 
-			qcom,chg-buck@1100 {
+			qcom,buck@1100 {
 				status = "disabled";
 				reg = <0x1100 0x100>;
 				interrupts =	<0x0 0x11 0x0>,
@@ -107,7 +107,7 @@
 							"vdd-loop";
 			};
 
-			qcom,chg-bat-if@1200 {
+			qcom,bat-if@1200 {
 				status = "disabled";
 				reg = <0x1200 0x100>;
 				interrupts =	<0x0 0x12 0x0>,
@@ -124,7 +124,7 @@
 
 			};
 
-			qcom,chg-usb-chgpth@1300 {
+			qcom,usb-chgpth@1300 {
 				status = "disabled";
 				reg = <0x1300 0x100>;
 				interrupts =	<0 0x13 0x0>,
@@ -136,7 +136,7 @@
 							"chg-gone";
 			};
 
-			qcom,chg-boost@1500 {
+			qcom,boost@1500 {
 				status = "disabled";
 				reg = <0x1500 0x100>;
 				interrupts =	<0x0 0x15 0x0>,
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index d712e5f..21606e2 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -171,21 +171,21 @@
 			#size-cells = <1>;
 			status = "disabled";
 
-			qcom,chg-vddmax-mv = <4200>;
-			qcom,chg-vddsafe-mv = <4200>;
-			qcom,chg-vinmin-mv = <4200>;
-			qcom,chg-ibatmax-ma = <1500>;
-			qcom,chg-ibatsafe-ma = <1500>;
-			qcom,chg-thermal-mitigation = <1500 700 600 325>;
-			qcom,chg-cool-bat-decidegc = <100>;
-			qcom,chg-cool-bat-mv = <4100>;
-			qcom,chg-ibatmax-warm-ma = <350>;
-			qcom,chg-warm-bat-decidegc = <450>;
-			qcom,chg-warm-bat-mv = <4100>;
-			qcom,chg-ibatmax-cool-ma = <350>;
-			qcom,chg-vbatdet-delta-mv = <350>;
+			qcom,vddmax-mv = <4200>;
+			qcom,vddsafe-mv = <4200>;
+			qcom,vinmin-mv = <4200>;
+			qcom,ibatmax-ma = <1500>;
+			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 = <350>;
 
-			qcom,chg-chgr@1000 {
+			qcom,chgr@1000 {
 				status = "disabled";
 				reg = <0x1000 0x100>;
 				interrupts =	<0x0 0x10 0x0>,
@@ -207,7 +207,7 @@
 							"chg-done";
 			};
 
-			qcom,chg-buck@1100 {
+			qcom,buck@1100 {
 				status = "disabled";
 				reg = <0x1100 0x100>;
 				interrupts =	<0x0 0x11 0x0>,
@@ -227,7 +227,7 @@
 							"vdd-loop";
 			};
 
-			qcom,chg-bat-if@1200 {
+			qcom,bat-if@1200 {
 				status = "disabled";
 				reg = <0x1200 0x100>;
 				interrupts =	<0x0 0x12 0x0>,
@@ -244,7 +244,7 @@
 
 			};
 
-			qcom,chg-usb-chgpth@1300 {
+			qcom,usb-chgpth@1300 {
 				status = "disabled";
 				reg = <0x1300 0x100>;
 				interrupts =	<0 0x13 0x0>,
@@ -256,7 +256,7 @@
 							"chg-gone";
 			};
 
-			qcom,chg-dc-chgpth@1400 {
+			qcom,dc-chgpth@1400 {
 				status = "disabled";
 				reg = <0x1400 0x100>;
 				interrupts =	<0x0 0x14 0x0>,
@@ -266,7 +266,7 @@
 							"dcin-valid";
 			};
 
-			qcom,chg-boost@1500 {
+			qcom,boost@1500 {
 				status = "disabled";
 				reg = <0x1500 0x100>;
 				interrupts =	<0x0 0x15 0x0>,
@@ -768,6 +768,17 @@
 				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>;
+			};
 		};
 
 		iadc@3600 {
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 0186e54..510bb7d 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -99,9 +99,9 @@
 			"MIC BIAS1 Internal1", "Handset Mic",
 			"AMIC2", "MIC BIAS2 External",
 			"MIC BIAS2 External", "Headset Mic",
-			"AMIC3", "MIC BIAS2 External",
-			"MIC BIAS2 External", "ANCRight Headset Mic",
 			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCRight Headset Mic",
+			"AMIC5", "MIC BIAS2 External",
 			"MIC BIAS2 External", "ANCLeft Headset Mic",
 			"DMIC1", "MIC BIAS1 External",
 			"MIC BIAS1 External", "Digital Mic1",
@@ -272,6 +272,6 @@
 };
 
 &pm8226_chg {
-	qcom,chg-charging-disabled;
-	qcom,chg-use-default-batt-values;
+	qcom,charging-disabled;
+	qcom,use-default-batt-values;
 };
diff --git a/arch/arm/boot/dts/msm8226-gpu.dtsi b/arch/arm/boot/dts/msm8226-gpu.dtsi
index 6a8ba3a..bb2f0d4 100644
--- a/arch/arm/boot/dts/msm8226-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8226-gpu.dtsi
@@ -33,7 +33,6 @@
 		/* Bus Scale Settings */
 		qcom,msm-bus,name = "grp3d";
 		qcom,msm-bus,num-cases = <4>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <2>;
 		qcom,msm-bus,vectors-KBps =
 			<26 512 0 0>, <89 604 0 0>,
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index d72c07b..f8a4e31 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -65,6 +65,65 @@
 		clock-frequency = <19200000>;
 	};
 
+	timer@f9020000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "arm,armv7-timer-mem";
+		reg = <0xf9020000 0x1000>;
+		clock-frequency = <19200000>;
+
+		frame@f9021000 {
+			frame-number = <0>;
+			interrupts = <0 8 0x4>,
+				     <0 7 0x4>;
+			reg = <0xf9021000 0x1000>,
+			      <0xf9022000 0x1000>;
+		};
+
+		frame@f9023000 {
+			frame-number = <1>;
+			interrupts = <0 9 0x4>;
+			reg = <0xf9023000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9024000 {
+			frame-number = <2>;
+			interrupts = <0 10 0x4>;
+			reg = <0xf9024000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9025000 {
+			frame-number = <3>;
+			interrupts = <0 11 0x4>;
+			reg = <0xf9025000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9026000 {
+			frame-number = <4>;
+			interrupts = <0 12 0x4>;
+			reg = <0xf9026000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9027000 {
+			frame-number = <5>;
+			interrupts = <0 13 0x4>;
+			reg = <0xf9027000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9028000 {
+			frame-number = <6>;
+			interrupts = <0 14 0x4>;
+			reg = <0xf9028000 0x1000>;
+			status = "disabled";
+		};
+	};
+
 	qcom,vidc@fdc00000 {
 		compatible = "qcom,msm-vidc";
 		reg = <0xfdc00000 0xff000>;
@@ -176,7 +235,6 @@
 
 		qcom,msm-bus,name = "usb2";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<87 512 0 0>,
@@ -235,6 +293,12 @@
 			qcom,cdc-vdd-cx-voltage = <1200000 1200000>;
 			qcom,cdc-vdd-cx-current = <10000>;
 
+			qcom,cdc-static-supplies = "cdc-vdd-buck",
+						   "cdc-vdd-h",
+						   "cdc-vdd-px",
+						   "cdc-vdd-a-1p2v",
+						   "cdc-vdd-cx";
+
 			qcom,cdc-micbias-ldoh-v = <0x3>;
 			qcom,cdc-micbias-cfilt1-mv = <1800>;
 			qcom,cdc-micbias-cfilt2-mv = <1800>;
@@ -937,28 +1001,38 @@
 		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>;
+	};
 };
 
 &pm8226_chg {
 	status = "ok";
 
-	qcom,chg-chgr@1000 {
+	qcom,chgr@1000 {
 		status = "ok";
 	};
 
-	qcom,chg-buck@1100 {
+	qcom,buck@1100 {
 		status = "ok";
 	};
 
-	qcom,chg-bat-if@1200 {
+	qcom,bat-if@1200 {
 		status = "ok";
 	};
 
-	qcom,chg-usb-chgpth@1300 {
+	qcom,usb-chgpth@1300 {
 		status = "ok";
 	};
 
-	qcom,chg-boost@1500 {
+	qcom,boost@1500 {
 		status = "ok";
 	};
 
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 5b0eb33..08da115 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -38,7 +38,7 @@
 
 	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
 	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
 	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
 
 	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
@@ -61,7 +61,7 @@
 
 	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
 	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
 	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
 
 	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
diff --git a/arch/arm/boot/dts/msm8610-gpu.dtsi b/arch/arm/boot/dts/msm8610-gpu.dtsi
index f3a8259..5e57430 100644
--- a/arch/arm/boot/dts/msm8610-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8610-gpu.dtsi
@@ -33,7 +33,6 @@
 		/* Bus Scale Settings */
 		qcom,msm-bus,name = "grp3d";
 		qcom,msm-bus,num-cases = <4>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 			<26 512 0 0>,
diff --git a/arch/arm/boot/dts/msm8610-ion.dtsi b/arch/arm/boot/dts/msm8610-ion.dtsi
index 848a6f5..41b58da 100644
--- a/arch/arm/boot/dts/msm8610-ion.dtsi
+++ b/arch/arm/boot/dts/msm8610-ion.dtsi
@@ -35,14 +35,6 @@
 			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
 			qcom,memory-reservation-size = <0x100000>;
 		};
-
-		qcom,ion-heap@28 { /* AUDIO HEAP */
-			compatible = "qcom,msm-ion-reserve";
-			reg = <28>;
-			qcom,heap-align = <0x1000>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x314000>;
-		};
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 595fabd..2013bb8 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -92,6 +92,35 @@
 		qcom,max-hw-load = <97200>; /* FWVGA @ 30 * 2 */
 	};
 
+	qcom,usbbam@f9a44000 {
+		compatible = "qcom,usb-bam-msm";
+		reg = <0xf9a44000 0x11000>;
+		reg-names = "hsusb";
+		interrupts = <0 135 0>;
+		interrupt-names = "hsusb";
+		qcom,usb-bam-num-pipes = <16>;
+		qcom,usb-bam-fifo-baseaddr = <0xfe803000>;
+		qcom,ignore-core-reset-ack;
+		qcom,disable-clk-gating;
+
+		qcom,pipe0 {
+			label = "hsusb-qdss-in-0";
+			qcom,usb-bam-mem-type = <3>;
+			qcom,bam-type = <1>;
+			qcom,dir = <1>;
+			qcom,pipe-num = <0>;
+			qcom,peer-bam = <1>;
+			qcom,src-bam-physical-address = <0xfc37c000>;
+			qcom,src-bam-pipe-index = <0>;
+			qcom,dst-bam-physical-address = <0xf9a44000>;
+			qcom,dst-bam-pipe-index = <2>;
+			qcom,data-fifo-offset = <0x0>;
+			qcom,data-fifo-size = <0x600>;
+			qcom,descriptor-fifo-offset = <0x600>;
+			qcom,descriptor-fifo-size = <0x200>;
+		};
+	};
+
 	usb@f9a55000 {
 		compatible = "qcom,hsusb-otg";
 		reg = <0xf9a55000 0x400>;
@@ -495,6 +524,25 @@
 		compatible = "qcom,msm-pcm-hostless";
 	};
 
+	qcom,wcnss-wlan@fb000000 {
+		compatible = "qcom,wcnss_wlan";
+		reg = <0xfb000000 0x280000>;
+		reg-names = "wcnss_mmio";
+		interrupts = <0 145 0>, <0 146 0>;
+		interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
+
+		qcom,pronto-vddmx-supply = <&pm8110_l3>;
+		qcom,pronto-vddcx-supply = <&pm8110_s1>;
+		qcom,pronto-vddpx-supply = <&pm8110_l6>;
+		qcom,iris-vddxo-supply = <&pm8110_l10>;
+		qcom,iris-vddrfa-supply = <&pm8110_l5>;
+		qcom,iris-vddpa-supply = <&pm8110_l16>;
+		qcom,iris-vdddig-supply = <&pm8110_l5>;
+
+		gpios = <&msmgpio 23 0>, <&msmgpio 24 0>, <&msmgpio 25 0>, <&msmgpio 26 0>, <&msmgpio 27 0>;
+		qcom,has_pronto_hw;
+	};
+
 	qcom,mss@fc880000 {
 		compatible = "qcom,pil-q6v5-mss";
 		reg = <0xfc880000 0x100>,
@@ -561,6 +609,12 @@
 		reg = <0xfd484000 0x400>;
 		qcom,num-locks = <8>;
 	};
+
+	qcom,bam_dmux@fc834000 {
+		compatible = "qcom,bam_dmux";
+		reg = <0xfc834000 0x7000>;
+		interrupts = <0 29 1>;
+	};
 };
 
 &gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8974-bus.dtsi b/arch/arm/boot/dts/msm8974-bus.dtsi
index cebb907..bb4b48e 100644
--- a/arch/arm/boot/dts/msm8974-bus.dtsi
+++ b/arch/arm/boot/dts/msm8974-bus.dtsi
@@ -284,8 +284,8 @@
 			qcom,qport = <0>;
 			qcom,mas-hw-id = <18>;
 			qcom,mode = "Fixed";
-			qcom,prio-rd = <2>;
-			qcom,prio-wr = <2>;
+			qcom,prio1 = <2>;
+			qcom,prio0 = <2>;
 		};
 
 		mas-qdss-bam {
@@ -296,8 +296,8 @@
 			qcom,mode = "Fixed";
 			qcom,qport = <1>;
 			qcom,mas-hw-id = <19>;
-			qcom,prio-rd = <1>;
-			qcom,prio-wr = <1>;
+			qcom,prio1 = <1>;
+			qcom,prio0 = <1>;
 			qcom,hw-sel = "NoC";
 		};
 
@@ -342,8 +342,8 @@
 			qcom,mas-hw-id = <29>;
 			qcom,slv-hw-id = <28>;
 			qcom,mode = "Fixed";
-			qcom,prio-rd = <2>;
-			qcom,prio-wr = <2>;
+			qcom,prio1 = <2>;
+			qcom,prio0 = <2>;
 		};
 
 		fab-ovnoc {
@@ -364,8 +364,8 @@
 			qcom,qport = <2>;
 			qcom,mas-hw-id = <23>;
 			qcom,hw-sel = "NoC";
-			qcom,prio-rd = <1>;
-			qcom,prio-wr = <1>;
+			qcom,prio1 = <1>;
+			qcom,prio0 = <1>;
 		};
 
 		mas-crypto-core1 {
@@ -377,8 +377,8 @@
 			qcom,qport = <3>;
 			qcom,mas-hw-id = <24>;
 			qcom,hw-sel = "NoC";
-			qcom,prio-rd = <1>;
-			qcom,prio-wr = <1>;
+			qcom,prio1 = <1>;
+			qcom,prio0 = <1>;
 		};
 
 		mas-lpass-proc {
@@ -389,8 +389,8 @@
 			qcom,qport = <4>;
 			qcom,mas-hw-id = <25>;
 			qcom,mode = "Fixed";
-			qcom,prio-rd = <2>;
-			qcom,prio-wr = <2>;
+			qcom,prio1 = <2>;
+			qcom,prio0 = <2>;
 		};
 
 		mas-mss {
@@ -435,8 +435,8 @@
 			qcom,qport = <10>;
 			qcom,mode = "Fixed";
 			qcom,mas-hw-id = <31>;
-			qcom,prio-rd = <1>;
-			qcom,prio-wr = <1>;
+			qcom,prio1 = <1>;
+			qcom,prio0 = <1>;
 			qcom,hw-sel = "NoC";
 		};
 
@@ -448,8 +448,8 @@
 			qcom,mode = "Fixed";
 			qcom,qport = <11>;
 			qcom,mas-hw-id = <32>;
-			qcom,prio-rd = <1>;
-			qcom,prio-wr = <1>;
+			qcom,prio1 = <1>;
+			qcom,prio0 = <1>;
 			qcom,hw-sel = "NoC";
 			qcom,iface-clk-node = "msm_usb3";
 		};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 41e3783..0319128 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -229,13 +229,25 @@
 
 		qcom,msm-bus,name = "hsic";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<85 512 0 0>,
 				<85 512 40000 160000>;
         };
 
+	wlan0: qca,wlan {
+		compatible = "qca,ar6004-hsic";
+		qcom,msm-bus,name = "wlan";
+		qcom,msm-bus,num-cases = <5>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<85 512 0 0>,
+				<85 512 40000 160000>,
+				<85 512 40000 320000>,
+				<85 512 40000 480000>,
+				<85 512 40000 640000>;
+	};
 };
 
 &spmi_bus {
@@ -382,23 +394,23 @@
 &pm8941_chg {
 	status = "ok";
 
-	qcom,chg-chgr@1000 {
+	qcom,chgr@1000 {
 		status = "ok";
 	};
 
-	qcom,chg-buck@1100 {
+	qcom,buck@1100 {
 		status = "ok";
 	};
 
-	qcom,chg-usb-chgpth@1300 {
+	qcom,usb-chgpth@1300 {
 		status = "ok";
 	};
 
-	qcom,chg-dc-chgpth@1400 {
+	qcom,dc-chgpth@1400 {
 		status = "ok";
 	};
 
-	qcom,chg-boost@1500 {
+	qcom,boost@1500 {
 		status = "ok";
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index de370e7..79e6371 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -355,27 +355,27 @@
 	status = "ok";
 	qcom,chg-charging-disabled;
 
-	qcom,chg-chgr@1000 {
+	qcom,chgr@1000 {
 		status = "ok";
 	};
 
-	qcom,chg-buck@1100 {
+	qcom,buck@1100 {
 		status = "ok";
 	};
 
-	qcom,chg-bat-if@1200 {
+	qcom,bat-if@1200 {
 		status = "ok";
 	};
 
-	qcom,chg-usb-chgpth@1300 {
+	qcom,usb-chgpth@1300 {
 		status = "ok";
 	};
 
-	qcom,chg-dc-chgpth@1400 {
+	qcom,dc-chgpth@1400 {
 		status = "ok";
 	};
 
-	qcom,chg-boost@1500 {
+	qcom,boost@1500 {
 		status = "ok";
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index 28d1d61..3779dbd 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -33,7 +33,6 @@
 		/* Bus Scale Settings */
 		qcom,msm-bus,name = "grp3d";
 		qcom,msm-bus,num-cases = <6>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <2>;
 		qcom,msm-bus,vectors-KBps =
 				<26 512 0 0>, <89 604 0 0>,
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 0f38e44..be890b1 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -382,7 +382,6 @@
 
 			qcom,msm-bus,name = "hsic";
 			qcom,msm-bus,num-cases = <2>;
-			qcom,msm-bus,active-only = <0>;
 			qcom,msm-bus,num-paths = <1>;
 			qcom,msm-bus,vectors-KBps =
 					<85 512 0 0>,
@@ -737,25 +736,25 @@
 &pm8941_chg {
 	status = "ok";
 
-	qcom,chg-charging-disabled;
+	qcom,charging-disabled;
 
-	qcom,chg-chgr@1000 {
+	qcom,chgr@1000 {
 		status = "ok";
 	};
 
-	qcom,chg-buck@1100 {
+	qcom,buck@1100 {
 		status = "ok";
 	};
 
-	qcom,chg-usb-chgpth@1300 {
+	qcom,usb-chgpth@1300 {
 		status = "ok";
 	};
 
-	qcom,chg-dc-chgpth@1400 {
+	qcom,dc-chgpth@1400 {
 		status = "ok";
 	};
 
-	qcom,chg-boost@1500 {
+	qcom,boost@1500 {
 		status = "ok";
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index a81fc20..cd83668 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -338,27 +338,27 @@
 	status = "ok";
 	qcom,chg-charging-disabled;
 
-	qcom,chg-chgr@1000 {
+	qcom,chgr@1000 {
 		status = "ok";
 	};
 
-	qcom,chg-buck@1100 {
+	qcom,buck@1100 {
 		status = "ok";
 	};
 
-	qcom,chg-bat-if@1200 {
+	qcom,bat-if@1200 {
 		status = "ok";
 	};
 
-	qcom,chg-usb-chgpth@1300 {
+	qcom,usb-chgpth@1300 {
 		status = "ok";
 	};
 
-	qcom,chg-dc-chgpth@1400 {
+	qcom,dc-chgpth@1400 {
 		status = "ok";
 	};
 
-	qcom,chg-boost@1500 {
+	qcom,boost@1500 {
 		status = "ok";
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 05451671..49450f3 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -448,6 +448,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
+		qcom,pfm-threshold = <376975>;
 
 		krait0_vreg: regulator@f9088000 {
 			compatible = "qcom,krait-regulator";
diff --git a/arch/arm/boot/dts/msm8974-v1-fluid.dts b/arch/arm/boot/dts/msm8974-v1-fluid.dts
index 8f2ef31..8ab24df 100644
--- a/arch/arm/boot/dts/msm8974-v1-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-fluid.dts
@@ -23,7 +23,7 @@
 };
 
 &pm8941_chg {
-	qcom,chg-charging-disabled;
+	qcom,charging-disabled;
 };
 
 &sdcc1 {
diff --git a/arch/arm/boot/dts/msm8974-v1-mtp.dts b/arch/arm/boot/dts/msm8974-v1-mtp.dts
index 6cb9f09..09ea84b 100644
--- a/arch/arm/boot/dts/msm8974-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-mtp.dts
@@ -22,5 +22,5 @@
 };
 
 &pm8941_chg {
-	qcom,chg-charging-disabled;
+	qcom,charging-disabled;
 };
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index a0b9be6..ec6b14a 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -188,7 +188,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <1>;
 			qcom,ss-power = <784>;
 			qcom,energy-overhead = <190000>;
@@ -205,7 +205,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <75>;
 			qcom,ss-power = <735>;
 			qcom,energy-overhead = <77341>;
@@ -223,7 +223,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <95>;
 			qcom,ss-power = <725>;
 			qcom,energy-overhead = <99500>;
@@ -240,7 +240,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <2000>;
 			qcom,ss-power = <138>;
 			qcom,energy-overhead = <1208400>;
@@ -257,7 +257,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO  */
 			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <3000>;
 			qcom,ss-power = <110>;
 			qcom,energy-overhead = <1250300>;
@@ -446,9 +446,9 @@
 		qcom,offset-page-indices = <56>;
 	};
 
-	qcom,rpm-stats@0xfc19dbd0{
+	qcom,rpm-stats@fc19dba0 {
 		compatible = "qcom,rpm-stats";
-		reg = <0xfc19dbd0 0x1000>;
+		reg = <0xfc19dba0 0x1000>;
 		reg-names = "phys_addr_base";
 		qcom,sleep-stats-version = <2>;
 	};
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 24b68b5..41837c1 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -188,7 +188,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <1>;
 			qcom,ss-power = <784>;
 			qcom,energy-overhead = <190000>;
@@ -205,7 +205,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <75>;
 			qcom,ss-power = <735>;
 			qcom,energy-overhead = <77341>;
@@ -223,7 +223,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <95>;
 			qcom,ss-power = <725>;
 			qcom,energy-overhead = <99500>;
@@ -240,7 +240,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <2000>;
 			qcom,ss-power = <138>;
 			qcom,energy-overhead = <1208400>;
@@ -257,7 +257,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO  */
 			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <3000>;
 			qcom,ss-power = <110>;
 			qcom,energy-overhead = <1250300>;
@@ -446,9 +446,9 @@
 		qcom,offset-page-indices = <56>;
 	};
 
-	qcom,rpm-stats@0xfc19dbd0{
+	qcom,rpm-stats@fc19dba0 {
 		compatible = "qcom,rpm-stats";
-		reg = <0xfc19dbd0 0x1000>;
+		reg = <0xfc19dba0 0x1000>;
 		reg-names = "phys_addr_base";
 		qcom,sleep-stats-version = <2>;
 	};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 7018863..a7ea5c3 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -84,6 +84,66 @@
 		clock-frequency = <19200000>;
 	};
 
+	timer@f9020000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "arm,armv7-timer-mem";
+		reg = <0xf9020000 0x1000>;
+		clock-frequency = <19200000>;
+
+		frame@f9021000 {
+			frame-number = <0>;
+			interrupts = <0 8 0x4>,
+				     <0 7 0x4>;
+			reg = <0xf9021000 0x1000>,
+			      <0xf9022000 0x1000>;
+		};
+
+		frame@f9023000 {
+			frame-number = <1>;
+			interrupts = <0 9 0x4>;
+			reg = <0xf9023000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9024000 {
+			frame-number = <2>;
+			interrupts = <0 10 0x4>;
+			reg = <0xf9024000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9025000 {
+			frame-number = <3>;
+			interrupts = <0 11 0x4>;
+			reg = <0xf9025000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9026000 {
+			frame-number = <4>;
+			interrupts = <0 12 0x4>;
+			reg = <0xf9026000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9027000 {
+			frame-number = <5>;
+			interrupts = <0 13 0x4>;
+			reg = <0xf9027000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9028000 {
+			frame-number = <6>;
+			interrupts = <0 14 0x4>;
+			reg = <0xf9028000 0x1000>;
+			status = "disabled";
+		};
+	};
+
+
 	qcom,mpm2-sleep-counter@fc4a3000 {
 		compatible = "qcom,mpm2-sleep-counter";
 		reg = <0xfc4a3000 0x1000>;
@@ -102,6 +162,7 @@
 	qcom,vidc {
 		compatible = "qcom,msm-vidc";
 		qcom,hfi = "q6";
+		qcom,max-hw-load = <108000>; /* 720p @ 30 */
 	};
 
 	qcom,wfd {
@@ -130,7 +191,6 @@
 
 		qcom,msm-bus,name = "serial_uart2";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<84 512 0 0>,
@@ -157,7 +217,6 @@
 
 		qcom,msm-bus,name = "usb2";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<87 512 0 0>,
@@ -198,7 +257,6 @@
 
 		qcom,msm-bus,name = "sdcc1";
 		qcom,msm-bus,num-cases = <8>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
 				<78 512 1600 3200>,    /* 400 KB/s*/
@@ -245,7 +303,6 @@
 
 		qcom,msm-bus,name = "sdcc2";
 		qcom,msm-bus,num-cases = <8>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
 				<81 512 1600 3200>,    /* 400 KB/s*/
@@ -292,7 +349,6 @@
 
 		qcom,msm-bus,name = "sdcc3";
 		qcom,msm-bus,num-cases = <8>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
 				<79 512 1600 3200>,    /* 400 KB/s*/
@@ -338,7 +394,6 @@
 
 		qcom,msm-bus,name = "sdcc4";
 		qcom,msm-bus,num-cases = <8>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps = <80 512 0 0>, /* No vote */
 				<80 512 1600 3200>,    /* 400 KB/s*/
@@ -365,7 +420,6 @@
 
 		qcom,msm-bus,name = "sdhc1";
 		qcom,msm-bus,num-cases = <8>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
 				<78 512 1600 3200>,    /* 400 KB/s*/
@@ -392,7 +446,6 @@
 
 		qcom,msm-bus,name = "sdhc2";
 		qcom,msm-bus,num-cases = <8>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
 				<81 512 1600 3200>,    /* 400 KB/s*/
@@ -426,7 +479,6 @@
 
 		qcom,msm-bus,name = "sdhc3";
 		qcom,msm-bus,num-cases = <8>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
 				<79 512 1600 3200>,    /* 400 KB/s*/
@@ -460,7 +512,6 @@
 
 		qcom,msm-bus,name = "sdhc4";
 		qcom,msm-bus,num-cases = <8>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps = <80 512 0 0>, /* No vote */
 				<80 512 1600 3200>,    /* 400 KB/s*/
@@ -582,6 +633,14 @@
 			qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
 			qcom,cdc-vddcx-2-current = <10000>;
 
+			qcom,cdc-static-supplies = "cdc-vdd-buck",
+						   "cdc-vdd-tx-h",
+						   "cdc-vdd-rx-h",
+						   "cdc-vddpx-1",
+						   "cdc-vdd-a-1p2v",
+						   "cdc-vddcx-1",
+						   "cdc-vddcx-2";
+
 			qcom,cdc-micbias-ldoh-v = <0x3>;
 			qcom,cdc-micbias-cfilt1-mv = <1800>;
 			qcom,cdc-micbias-cfilt2-mv = <2700>;
@@ -734,7 +793,6 @@
 
 		qcom,msm-bus,name = "usb3";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<61 512 0 0>,
@@ -1002,7 +1060,6 @@
 		compatible = "qcom,msm-ocmem-audio";
 		qcom,msm-bus,name = "audio-ocmem";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 			<11 604 0 0>,
@@ -1144,7 +1201,6 @@
 		qcom,qsee-ce-hw-instance = <0>;
 		qcom,msm-bus,name = "qseecom-noc";
 		qcom,msm-bus,num-cases = <4>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<55 512 0 0>,
@@ -1225,7 +1281,6 @@
 		qcom,ce-hw-instance = <1>;
                 qcom,msm-bus,name = "qcedev-noc";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<56 512 0 0>,
@@ -1242,7 +1297,6 @@
 		qcom,ce-hw-instance = <1>;
                 qcom,msm-bus,name = "qcrypto-noc";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<56 512 0 0>,
@@ -1305,6 +1359,29 @@
 		qcom,limit-temp = <60>;
 		qcom,temp-hysteresis = <10>;
 		qcom,freq-step = <2>;
+		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>;
+		qcom,pmic-sw-mode-temp = <90>;
+		qcom,pmic-sw-mode-temp-hysteresis = <70>;
+		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,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,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
+			qcom,min-level = <1>; /* No Request */
+		};
+
 	};
 
 	qcom,bam_dmux@fc834000 {
@@ -1332,7 +1409,6 @@
 		qcom,bam-rx-ep-pipe-index = <1>;
 		qcom,msm-bus,name = "uart7";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<84 512 0 0>,
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 51a3faa..3e421a8 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -80,7 +80,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <100>;
 			qcom,ss-power = <8000>;
 			qcom,energy-overhead = <100000>;
@@ -97,7 +97,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <2000>;
 			qcom,ss-power = <5000>;
 			qcom,energy-overhead = <60100000>;
@@ -114,7 +114,7 @@
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <3500>;
 			qcom,ss-power = <5000>;
 			qcom,energy-overhead = <60350000>;
@@ -131,7 +131,7 @@
 			qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
 			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
 			qcom,irqs-detectable;
-			qcom.gpios-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <4500>;
 			qcom,ss-power = <5000>;
 			qcom,energy-overhead = <60350000>;
@@ -289,9 +289,9 @@
 		qcom,offset-page-indices = <56>;
 	};
 
-	qcom,rpm-stats@fc19dbd0 {
+	qcom,rpm-stats@fc19dba0 {
 		compatible = "qcom,rpm-stats";
-		reg = <0xfc19dbd0 0x1000>;
+		reg = <0xfc19dba0 0x1000>;
 		reg-names = "phys_addr_base";
 		qcom,sleep-stats-version = <2>;
 	};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index ee61dc3..7faa07d 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -66,6 +66,72 @@
 		clock-frequency = <19200000>;
 	};
 
+	timer@f9020000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "arm,armv7-timer-mem";
+		reg = <0xf9020000 0x1000>;
+		clock-frequency = <19200000>;
+
+		frame@f9021000 {
+			frame-number = <0>;
+			interrupts = <0 7 0x4>,
+				     <0 6 0x4>;
+			reg = <0xf9021000 0x1000>,
+			      <0xf9022000 0x1000>;
+		};
+
+		frame@f9023000 {
+			frame-number = <1>;
+			interrupts = <0 8 0x4>;
+			reg = <0xf9023000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9024000 {
+			frame-number = <2>;
+			interrupts = <0 9 0x4>;
+			reg = <0xf9024000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9025000 {
+			frame-number = <3>;
+			interrupts = <0 10 0x4>;
+			reg = <0xf9025000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9026000 {
+			frame-number = <4>;
+			interrupts = <0 11 0x4>;
+			reg = <0xf9026000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9027000 {
+			frame-number = <5>;
+			interrupts = <0 12 0x4>;
+			reg = <0xf9027000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9028000 {
+			frame-number = <6>;
+			interrupts = <0 13 0x4>;
+			reg = <0xf9028000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9029000 {
+			frame-number = <7>;
+			interrupts = <0 14 0x4>;
+			reg = <0xf9029000 0x1000>;
+			status = "disabled";
+		};
+	};
+
 	qcom,sps@f9980000 {
 		compatible = "qcom,msm_sps";
 		reg = <0xf9984000 0x15000>,
@@ -101,7 +167,6 @@
 
 		qcom,msm-bus,name = "usb2";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<87 512 0 0>,
@@ -118,7 +183,6 @@
 
 		qcom,msm-bus,name = "hsic";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<85 512 0 0>,
@@ -507,6 +571,14 @@
 			qcom,cdc-vddcx-2-voltage = <1200000 1200000>;
 			qcom,cdc-vddcx-2-current = <10000>;
 
+			qcom,cdc-static-supplies = "cdc-vdd-buck",
+						   "cdc-vdd-tx-h",
+						   "cdc-vdd-rx-h",
+						   "cdc-vddpx-1",
+						   "cdc-vdd-a-1p2v",
+						   "cdc-vddcx-1",
+						   "cdc-vddcx-2";
+
 			qcom,cdc-micbias-ldoh-v = <0x3>;
 			qcom,cdc-micbias-cfilt1-mv = <1800>;
 			qcom,cdc-micbias-cfilt2-mv = <2700>;
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index f23a096..3291919 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -267,6 +267,8 @@
 CONFIG_MSMB_CAMERA=y
 CONFIG_OV9724=y
 CONFIG_MSMB_JPEG=y
+CONFIG_SWITCH=y
+CONFIG_MSM_WFD=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_VIDEOBUF2_MSM_MEM=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
@@ -327,7 +329,6 @@
 CONFIG_QPNP_PWM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_MSM_IOMMU=y
-CONFIG_MSM_IOMMU_PMON=y
 CONFIG_CORESIGHT=y
 CONFIG_CORESIGHT_TMC=y
 CONFIG_CORESIGHT_TPIU=y
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index c60e89a..a61f5ca 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -128,122 +128,122 @@
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),  825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),  825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),  825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),  825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),  825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),  825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),  825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10), 825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10), 825000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10), 825000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10), 825000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12), 835000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12), 855000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12), 870000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12), 885000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16), 900000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16), 910000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 925000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 940000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),  825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),  825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),  825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),  825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),  825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),  825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),  825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10), 825000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10), 825000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10), 825000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10), 825000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12), 835000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12), 855000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12), 870000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12), 885000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16), 900000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16), 910000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 925000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 940000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 950000, 506 },
 	{ 0, { 0 } }
 };
 
@@ -284,618 +284,618 @@
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  815000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  835000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  845000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  855000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  865000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  875000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  890000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  900000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  915000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  925000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  940000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  950000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  965000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  980000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  995000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16), 1010000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1025000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1040000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1055000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1070000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1085000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1100000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  815000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  835000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  845000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  855000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  865000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  875000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  890000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  900000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  915000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  925000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  940000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  950000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  965000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  980000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  995000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16), 1010000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1025000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1040000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1055000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1070000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1085000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1100000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  810000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  820000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  830000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  840000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  850000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  860000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  875000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  885000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  895000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  910000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  920000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  930000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  945000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  960000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  975000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  990000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1005000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1020000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1030000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1045000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1060000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  810000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  820000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  830000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  840000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  850000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  860000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  875000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  885000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  895000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  910000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  920000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  930000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  945000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  960000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  975000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  990000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1005000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1020000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1030000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1045000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1060000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  785000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  795000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  910000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  955000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  970000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1005000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1020000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1035000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  785000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  795000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  910000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  955000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  970000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1005000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1020000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1035000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  780000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  790000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  935000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  970000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  985000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  995000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1010000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  780000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  790000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  935000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  970000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  985000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  995000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1010000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  780000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  790000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  870000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  880000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  950000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  960000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  975000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  985000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  780000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  790000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  870000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  880000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  950000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  960000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  975000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  985000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs5[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  760000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  770000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  780000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  790000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  800000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  810000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  820000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  830000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  840000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  850000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  860000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  870000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  880000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  920000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  930000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  940000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  955000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  965000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  975000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  760000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  770000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  780000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  790000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  800000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  810000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  820000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  830000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  840000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  850000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  860000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  870000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  880000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  920000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  930000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  940000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  955000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  965000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  975000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  760000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  770000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  870000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  905000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  915000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  760000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  770000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  870000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  905000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  915000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  915000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  950000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  965000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1010000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1025000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1040000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1055000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1070000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1085000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1100000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  915000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  950000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  965000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1010000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1025000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1040000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1055000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1070000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1085000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1100000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  920000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  930000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  945000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  975000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  990000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1005000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1020000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1030000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1045000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1060000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1075000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  920000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  930000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  945000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  975000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  990000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1005000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1020000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1030000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1045000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1060000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1075000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  785000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  795000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  805000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  815000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  835000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  845000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  865000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  875000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  890000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  900000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  910000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  925000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  955000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  970000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  980000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  995000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  785000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  795000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  805000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  815000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  825000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  835000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  845000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  865000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  875000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  890000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  900000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  910000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  925000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  955000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  970000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  980000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  995000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  885000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  895000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  935000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  950000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  960000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  970000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  985000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  995000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  885000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  895000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  935000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  950000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  960000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  970000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  985000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  995000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  870000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  880000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  920000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  930000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  940000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  950000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  960000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  975000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  985000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  870000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  880000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  920000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  930000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  940000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  950000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  960000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  975000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  985000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs5[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  760000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  770000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  890000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  900000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  910000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  920000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  930000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  940000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  955000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  965000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  975000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  760000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  770000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  890000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  900000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  910000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  920000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  930000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  940000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  955000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  965000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  975000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  875000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  885000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  895000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  905000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  915000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  920000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  930000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  940000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  875000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  885000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  895000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  905000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  915000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  920000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  930000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  940000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  950000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  805000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  815000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  835000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  845000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  855000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  865000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  890000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  900000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  915000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  940000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  965000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  980000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  995000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1010000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1025000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  805000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  815000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  825000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  835000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  845000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  855000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  865000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  890000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  900000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  915000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  940000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  965000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  980000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  995000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1010000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1025000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  875000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  885000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  945000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  960000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  975000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  990000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1005000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  875000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  885000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  945000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  960000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  975000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  990000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1005000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  785000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  795000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  805000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  815000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  825000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  835000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  845000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  855000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  865000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  940000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  955000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  970000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  980000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  995000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  785000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  795000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  805000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  815000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  825000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  835000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  845000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  855000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  865000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  940000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  955000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  970000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  980000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  995000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  925000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  935000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  950000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  960000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  970000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  985000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  995000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  925000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  935000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  950000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  960000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  970000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  985000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  995000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  775000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  895000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  910000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  960000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  975000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  985000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  775000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  895000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  910000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  960000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  975000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  985000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs5[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  880000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  890000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  900000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  910000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  920000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  930000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  940000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  955000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  965000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  975000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  880000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  890000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  900000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  910000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  920000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  930000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  940000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  955000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  965000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  975000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  750000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  760000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  770000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  780000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  790000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  800000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  810000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  820000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  830000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  840000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  850000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  860000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  870000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  875000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  885000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  895000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  905000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  915000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  920000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  930000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  940000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  750000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  760000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  770000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  780000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  790000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  800000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  810000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  820000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  830000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  840000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  850000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  860000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  870000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  875000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  885000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  895000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  905000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  915000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  920000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  930000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  940000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  950000, 691 },
 	{ 0, { 0 } }
 };
 
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index 0fdb298..4b435de 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -47,6 +47,36 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+static struct gpiomux_setting lcd_en_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_HIGH,
+};
+
+static struct gpiomux_setting lcd_en_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config msm_lcd_configs[] __initdata = {
+	{
+		.gpio = 41,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &lcd_en_act_cfg,
+			[GPIOMUX_SUSPENDED] = &lcd_en_sus_cfg,
+		},
+	},
+	{
+		.gpio = 7,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &lcd_en_act_cfg,
+			[GPIOMUX_SUSPENDED] = &lcd_en_sus_cfg,
+		},
+	},
+};
+
 static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
 	{
 		.gpio      = 10,	/* BLSP1 QUP3 I2C_SDA */
@@ -137,4 +167,5 @@
 	msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
 	msm_gpiomux_install(wcnss_5wire_interface,
 			ARRAY_SIZE(wcnss_5wire_interface));
+	msm_gpiomux_install(msm_lcd_configs, ARRAY_SIZE(msm_lcd_configs));
 }
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 01b8a4c..8be128c 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -957,7 +957,7 @@
 	},
 	{
 		ARRAY_SIZE(qseecom_enable_dfab_vectors),
-		qseecom_enable_sfpb_vectors,
+		qseecom_enable_dfab_vectors,
 	},
 	{
 		ARRAY_SIZE(qseecom_enable_sfpb_vectors),
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index e30d0ba..705275c 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -743,7 +743,8 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
-static struct msm_gpiomux_config msm8974_pri_auxpcm_configs[] __initdata = {
+/* Primary AUXPCM port sharing GPIO lines with Primary MI2S */
+static struct msm_gpiomux_config msm8974_pri_pri_auxpcm_configs[] __initdata = {
 	{
 		.gpio = 65,
 		.settings = {
@@ -774,6 +775,38 @@
 	},
 };
 
+/* Primary AUXPCM port sharing GPIO lines with Tertiary MI2S */
+static struct msm_gpiomux_config msm8974_pri_ter_auxpcm_configs[] __initdata = {
+	{
+		.gpio = 74,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+		},
+	},
+	{
+		.gpio = 75,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+		},
+	},
+	{
+		.gpio = 76,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+		},
+	},
+	{
+		.gpio = 77,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+		},
+	},
+};
+
 static struct msm_gpiomux_config msm8974_sec_auxpcm_configs[] __initdata = {
 	{
 		.gpio = 79,
@@ -1064,8 +1097,9 @@
 			 ARRAY_SIZE(msm_blsp2_uart7_configs));
 	msm_gpiomux_install(wcnss_5wire_interface,
 				ARRAY_SIZE(wcnss_5wire_interface));
-	msm_gpiomux_install_nowrite(ath_gpio_configs,
-				ARRAY_SIZE(ath_gpio_configs));
+	if (of_board_is_liquid())
+		msm_gpiomux_install_nowrite(ath_gpio_configs,
+					ARRAY_SIZE(ath_gpio_configs));
 	msm_gpiomux_install(msm8974_slimbus_config,
 			ARRAY_SIZE(msm8974_slimbus_config));
 
@@ -1090,8 +1124,13 @@
 		msm_gpiomux_install(msm_mhl_configs,
 				    ARRAY_SIZE(msm_mhl_configs));
 
-	msm_gpiomux_install(msm8974_pri_auxpcm_configs,
-				 ARRAY_SIZE(msm8974_pri_auxpcm_configs));
+	if (of_board_is_liquid())
+		msm_gpiomux_install(msm8974_pri_ter_auxpcm_configs,
+				 ARRAY_SIZE(msm8974_pri_ter_auxpcm_configs));
+	else
+		msm_gpiomux_install(msm8974_pri_pri_auxpcm_configs,
+				 ARRAY_SIZE(msm8974_pri_pri_auxpcm_configs));
+
 	msm_gpiomux_install(msm8974_sec_auxpcm_configs,
 				 ARRAY_SIZE(msm8974_sec_auxpcm_configs));
 
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 80907c8..5f9eafd 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -2776,6 +2776,7 @@
 	},
 	.base = &virt_bases[APCS_PLL_BASE],
 	.c = {
+		.parent = &xo_a_clk.c,
 		.dbg_name = "a7sspll",
 		.ops = &clk_ops_sr2_pll,
 		.vdd_class = &vdd_sr2_pll,
@@ -3529,17 +3530,6 @@
 		panic("clock-8226: Unable to get the vdd_sr2_dig regulator!");
 
 	/*
-	 * These regulators are used at boot. Ensure they stay on
-	 * while the clock framework comes online.
-	 */
-	vote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
-	regulator_enable(vdd_sr2_pll.regulator[0]);
-	regulator_enable(vdd_sr2_pll.regulator[1]);
-
-	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	regulator_enable(vdd_dig.regulator[0]);
-
-	/*
 	 * Hold an active set vote at a rate of 40MHz for the MMSS NOC AHB
 	 * source. Sleep set vote is 0.
 	 * RPM will also turn on gcc_mmss_noc_cfg_ahb_clk, which is needed to
@@ -3561,17 +3551,9 @@
 	mdss_clk_ctrl_pre_init(&mdss_ahb_clk.c);
 }
 
-static int __init msm8226_clock_late_init(void)
-{
-	unvote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
-	unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	return 0;
-}
-
 struct clock_init_data msm8226_clock_init_data __initdata = {
 	.table = msm_clocks_8226,
 	.size = ARRAY_SIZE(msm_clocks_8226),
 	.pre_init = msm8226_clock_pre_init,
 	.post_init = msm8226_clock_post_init,
-	.late_init = msm8226_clock_late_init,
 };
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index c9c71f0..87572da 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -564,6 +564,7 @@
 	},
 	.base = &virt_bases[APCS_PLL_BASE],
 	.c = {
+		.parent = &gcc_xo_a_clk_src.c,
 		.dbg_name = "a7sspll",
 		.ops = &clk_ops_sr2_pll,
 		.vdd_class = &vdd_sr2_pll,
@@ -2549,6 +2550,8 @@
 
 	CLK_LOOKUP("iface_clk",  gcc_blsp1_ahb_clk.c, "f991f000.serial"),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_uart3_apps_clk.c, "f991f000.serial"),
+	CLK_LOOKUP("iface_clk",  gcc_blsp1_ahb_clk.c, "f991e000.serial"),
+	CLK_LOOKUP("core_clk",  gcc_blsp1_uart2_apps_clk.c, "f991e000.serial"),
 
 	CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
 	CLK_LOOKUP("bus_clk",  pnoc_qseecom_clk.c, "qseecom"),
@@ -2789,8 +2792,9 @@
 	CLK_LOOKUP("core_clk", mdp_axi_clk.c, "fd900000.qcom,mdss_mdp"),
 	CLK_LOOKUP("lcdc_clk", mdp_lcdc_clk.c, "fd900000.qcom,mdss_mdp"),
 	CLK_LOOKUP("vsync_clk", mdp_vsync_clk.c, "fd900000.qcom,mdss_mdp"),
+	CLK_LOOKUP("dsi_clk", mdp_dsi_clk.c, "fd900000.qcom,mdss_mdp"),
 	CLK_LOOKUP("iface_clk", dsi_ahb_clk.c, "fdd00000.qcom,mdss_dsi"),
-	CLK_LOOKUP("core_clk", dsi_clk.c, "fdd00000.qcom,mdss_dsi"),
+	CLK_LOOKUP("dsi_clk", dsi_clk.c, "fdd00000.qcom,mdss_dsi"),
 	CLK_LOOKUP("byte_clk", dsi_byte_clk.c, "fdd00000.qcom,mdss_dsi"),
 	CLK_LOOKUP("esc_clk", dsi_esc_clk.c, "fdd00000.qcom,mdss_dsi"),
 	CLK_LOOKUP("pixel_clk", dsi_pclk_clk.c, "fdd00000.qcom,mdss_dsi"),
@@ -2969,19 +2973,6 @@
 	if (IS_ERR(vdd_sr2_pll.regulator[1]))
 		panic("clock-8610: Unable to get the vdd_sr2_dig regulator!");
 
-	vote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
-	regulator_enable(vdd_sr2_pll.regulator[0]);
-	regulator_enable(vdd_sr2_pll.regulator[1]);
-
-	/*
-	 * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
-	 * until late_init. This may not be necessary with clock handoff;
-	 * Investigate this code on a real non-simulator target to determine
-	 * its necessity.
-	 */
-	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	regulator_enable(vdd_dig.regulator[0]);
-
 	enable_rpm_scaling();
 
 	/* Enable a clock to allow access to MMSS clock registers */
@@ -2998,17 +2989,9 @@
 	clk_prepare_enable(&mmss_s0_axi_clk.c);
 }
 
-static int __init msm8610_clock_late_init(void)
-{
-	unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	unvote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
-	return 0;
-}
-
 struct clock_init_data msm8610_clock_init_data __initdata = {
 	.table = msm_clocks_8610,
 	.size = ARRAY_SIZE(msm_clocks_8610),
 	.pre_init = msm8610_clock_pre_init,
 	.post_init = msm8610_clock_post_init,
-	.late_init = msm8610_clock_late_init,
 };
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index aefaa5c..509443d 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -6740,8 +6740,6 @@
 	if ((readl_relaxed(PRNG_CLK_NS_REG) & 0x7F) == 0x2B)
 		prng_clk.freq_tbl = clk_tbl_prng_64;
 
-	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-
 	clk_ops_local_pll.enable = sr_pll_clk_enable;
 }
 
@@ -6852,7 +6850,7 @@
 	if (WARN(rc, "cfpb_a_clk not enabled (%d)\n", rc))
 		return rc;
 
-	return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+	return 0;
 }
 
 struct clock_init_data msm8960_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 9751ab2..b96924f 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -1405,7 +1405,14 @@
 };
 
 static struct clk_freq_tbl ftbl_gcc_gp_clk[] = {
-	F(19200000,  cxo,  1,   0,   0),
+	F( 4800000,   cxo,  4,  0,   0),
+	F( 6000000, gpll0, 10,  1,  10),
+	F( 6750000, gpll0,  1,  1,  89),
+	F( 8000000, gpll0, 15,  1,   5),
+	F( 9600000,   cxo,  2,  0,   0),
+	F(16000000, gpll0,  1,  2,  75),
+	F(19200000,   cxo,  1,  0,   0),
+	F(24000000, gpll0,  5,  1,   5),
 	F_END
 };
 
@@ -4816,6 +4823,11 @@
 	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,     "qseecom"),
 	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,         "qseecom"),
 
+	CLK_LOOKUP("ce_drv_core_clk",     gcc_ce2_clk.c,         "qseecom"),
+	CLK_LOOKUP("ce_drv_iface_clk",    gcc_ce2_ahb_clk.c,     "qseecom"),
+	CLK_LOOKUP("ce_drv_bus_clk",      gcc_ce2_axi_clk.c,     "qseecom"),
+	CLK_LOOKUP("ce_drv_core_clk_src", ce2_clk_src.c,         "qseecom"),
+
 	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,         "scm"),
 	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c,     "scm"),
 	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,     "scm"),
@@ -5488,15 +5500,6 @@
 	if (IS_ERR(vdd_dig.regulator[0]))
 		panic("clock-8974: Unable to get the vdd_dig regulator!");
 
-	/*
-	 * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
-	 * until late_init. This may not be necessary with clock handoff;
-	 * Investigate this code on a real non-simulator target to determine
-	 * its necessity.
-	 */
-	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	regulator_enable(vdd_dig.regulator[0]);
-
 	enable_rpm_scaling();
 
 	reg_init();
@@ -5533,11 +5536,6 @@
 	mdss_clk_ctrl_pre_init(&mdss_ahb_clk.c);
 }
 
-static int __init msm8974_clock_late_init(void)
-{
-	return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-}
-
 static void __init msm8974_rumi_clock_pre_init(void)
 {
 	virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
@@ -5553,15 +5551,6 @@
 	vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
 	if (IS_ERR(vdd_dig.regulator[0]))
 		panic("clock-8974: Unable to get the vdd_dig regulator!");
-
-	/*
-	 * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
-	 * until late_init. This may not be necessary with clock handoff;
-	 * Investigate this code on a real non-simulator target to determine
-	 * its necessity.
-	 */
-	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	regulator_enable(vdd_dig.regulator[0]);
 }
 
 struct clock_init_data msm8974_clock_init_data __initdata = {
@@ -5569,7 +5558,6 @@
 	.size = ARRAY_SIZE(msm_clocks_8974),
 	.pre_init = msm8974_clock_pre_init,
 	.post_init = msm8974_clock_post_init,
-	.late_init = msm8974_clock_late_init,
 };
 
 struct clock_init_data msm8974_rumi_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index d0b4a32..5d55966 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3777,8 +3777,6 @@
 
 static void __init msm8660_clock_pre_init(void)
 {
-	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-
 	/* Setup MM_PLL2 (PLL3), but turn it off. Rate set by set_rate_tv(). */
 	rmwreg(0, MM_PLL2_MODE_REG, BIT(0)); /* Disable output */
 	/* Set ref, bypass, assert reset, disable output, disable test mode */
@@ -3900,7 +3898,7 @@
 	if (WARN(rc, "mmfpb_a_clk not enabled (%d)\n", rc))
 		return rc;
 
-	return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+	return 0;
 }
 
 struct clock_init_data msm8x60_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index d6ae4335..6b218a1 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1754,8 +1754,6 @@
 {
 	u32 regval, is_pll_enabled, pll9_lval;
 
-	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-
 	clk_ops_local_pll.enable = sr_pll_clk_enable;
 
 	/* Enable PDM CXO source. */
@@ -1831,15 +1829,9 @@
 	clk_disable_unprepare(&pdm_clk.c);
 }
 
-static int __init msm9615_clock_late_init(void)
-{
-	return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-}
-
 struct clock_init_data msm9615_clock_init_data __initdata = {
 	.table = msm_clocks_9615,
 	.size = ARRAY_SIZE(msm_clocks_9615),
 	.pre_init = msm9615_clock_pre_init,
 	.post_init = msm9615_clock_post_init,
-	.late_init = msm9615_clock_late_init,
 };
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 6817c6c..0d97401 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -411,6 +411,7 @@
 	},
 	.base = &virt_bases[APCS_PLL_BASE],
 	.c = {
+		.parent = &cxo_a_clk_src.c,
 		.dbg_name = "apcspll_clk_src",
 		.ops = &clk_ops_local_pll,
 		CLK_INIT(apcspll_clk_src.c),
@@ -2089,9 +2090,6 @@
 	if (IS_ERR(vdd_dig.regulator[0]))
 		panic("clock-9625: Unable to get the vdd_dig regulator!");
 
-	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	regulator_enable(vdd_dig.regulator[0]);
-
 	enable_rpm_scaling();
 
 	reg_init();
@@ -2107,15 +2105,9 @@
 			measure_mux_common, sizeof(measure_mux_common));
 }
 
-static int __init msm9625_clock_late_init(void)
-{
-	return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-}
-
 struct clock_init_data msm9625_clock_init_data __initdata = {
 	.table = msm_clocks_9625,
 	.size = ARRAY_SIZE(msm_clocks_9625),
 	.pre_init = msm9625_clock_pre_init,
 	.post_init = msm9625_clock_post_init,
-	.late_init = msm9625_clock_late_init,
 };
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index fecb720..044fc2c 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -33,6 +33,12 @@
 };
 static LIST_HEAD(handoff_list);
 
+struct handoff_vdd {
+	struct list_head list;
+	struct clk_vdd_class *vdd_class;
+};
+static LIST_HEAD(handoff_vdd_list);
+
 /* Find the voltage level required for a given rate. */
 int find_vdd_level(struct clk *clk, unsigned long rate)
 {
@@ -588,6 +594,38 @@
 }
 EXPORT_SYMBOL(msm_clock_register);
 
+
+static void vdd_class_init(struct clk_vdd_class *vdd)
+{
+	struct handoff_vdd *v;
+	int i;
+
+	if (!vdd)
+		return;
+
+	list_for_each_entry(v, &handoff_vdd_list, list) {
+		if (v->vdd_class == vdd)
+			return;
+	}
+
+	pr_debug("voting for vdd_class %s\n", vdd->class_name);
+	if (vote_vdd_level(vdd, vdd->num_levels - 1))
+		pr_err("failed to vote for %s\n", vdd->class_name);
+
+	for (i = 0; i < vdd->num_regulators; i++)
+		regulator_enable(vdd->regulator[i]);
+
+	v = kmalloc(sizeof(*v), GFP_KERNEL);
+	if (!v) {
+		pr_err("Unable to kmalloc. %s will be stuck at max.\n",
+			vdd->class_name);
+		return;
+	}
+
+	v->vdd_class = vdd;
+	list_add_tail(&v->list, &handoff_vdd_list);
+}
+
 static int __init __handoff_clk(struct clk *clk)
 {
 	enum handoff state = HANDOFF_DISABLED_CLK;
@@ -693,6 +731,16 @@
 	init_sibling_lists(clock_tbl, num_clocks);
 
 	/*
+	 * Enable regulators and temporarily set them up at maximum voltage.
+	 * Once all the clocks have made their respective vote, remove this
+	 * temporary vote. The removing of the temporary vote is done at
+	 * late_init, by which time we assume all the clocks would have been
+	 * handed off.
+	 */
+	for (n = 0; n < num_clocks; n++)
+		vdd_class_init(clock_tbl[n].clk->vdd_class);
+
+	/*
 	 * Detect and preserve initial clock state until clock_late_init() or
 	 * a driver explicitly changes it, whichever is first.
 	 */
@@ -713,8 +761,12 @@
 static int __init clock_late_init(void)
 {
 	struct handoff_clk *h, *h_temp;
+	struct handoff_vdd *v, *v_temp;
 	int ret = 0;
 
+	if (clk_init_data->late_init)
+		ret = clk_init_data->late_init();
+
 	pr_info("%s: Removing enables held for handed-off clocks\n", __func__);
 	list_for_each_entry_safe(h, h_temp, &handoff_list, list) {
 		clk_disable_unprepare(h->clk);
@@ -722,8 +774,12 @@
 		kfree(h);
 	}
 
-	if (clk_init_data->late_init)
-		ret = clk_init_data->late_init();
+	list_for_each_entry_safe(v, v_temp, &handoff_vdd_list, list) {
+		unvote_vdd_level(v->vdd_class, v->vdd_class->num_levels - 1);
+		list_del(&v->list);
+		kfree(v);
+	}
+
 	return ret;
 }
 late_initcall(clock_late_init);
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index 6665d66..a07b13d 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -38,7 +38,7 @@
 #define EN_FEW_WAIT_VAL		(0x8 << 16)
 #define CLK_DIS_WAIT_VAL	(0x2 << 12)
 
-#define TIMEOUT_US		100
+#define TIMEOUT_US		1000
 
 struct gdsc {
 	struct regulator_dev	*rdev;
diff --git a/arch/arm/mach-msm/include/mach/iommu_perfmon.h b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
index dcae83b..dc4671c 100644
--- a/arch/arm/mach-msm/include/mach/iommu_perfmon.h
+++ b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
@@ -63,6 +63,7 @@
  * @iommu_dev:  pointer to iommu device
  * @ops:        iommu access operations pointer.
  * @hw_ops:     iommu pm hw access operations pointer.
+ * @always_on:  1 if iommu is always on, 0 otherwise.
  */
 struct iommu_info {
 	const char *iommu_name;
@@ -71,6 +72,7 @@
 	struct device *iommu_dev;
 	struct iommu_access_ops *ops;
 	struct iommu_pm_hw_ops *hw_ops;
+	unsigned int always_on;
 };
 
 /**
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index 56c4afd..6119a3c 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -70,7 +70,7 @@
 
 #ifndef __ASSEMBLY__
 void *allocate_contiguous_ebi(unsigned long, unsigned long, int);
-unsigned long allocate_contiguous_ebi_nomap(unsigned long, unsigned long);
+phys_addr_t allocate_contiguous_ebi_nomap(unsigned long, unsigned long);
 void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long);
 void clean_caches(unsigned long, unsigned long, unsigned long);
 void invalidate_caches(unsigned long, unsigned long, unsigned long);
diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h
index 4258dbd..72eb999 100644
--- a/arch/arm/mach-msm/include/mach/scm.h
+++ b/arch/arm/mach-msm/include/mach/scm.h
@@ -24,6 +24,7 @@
 #define SCM_SVC_MP			0xC
 #define SCM_SVC_CRYPTO			0xA
 #define SCM_SVC_DCVS			0xD
+#define SCM_SVC_ES			0x10
 #define SCM_SVC_TZSCHEDULER		0xFC
 
 #ifdef CONFIG_MSM_SCM
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 953f941d..af2fbab 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -61,9 +61,7 @@
 #define PMIC_VOLTAGE_MAX		1355000
 #define LV_RANGE_STEP			5000
 
-#define LOAD_PER_PHASE			3200000
-
-#define CORE_VOLTAGE_MIN		900000
+#define CORE_VOLTAGE_BOOTUP		900000
 
 #define KRAIT_LDO_VOLTAGE_MIN		465000
 #define KRAIT_LDO_VOLTAGE_OFFSET	465000
@@ -135,6 +133,7 @@
 #define LDO_DELTA_MIN		10000
 #define LDO_DELTA_MAX		100000
 
+#define MSM_L2_SAW_PHYS		0xf9012000
 /**
  * struct pmic_gang_vreg -
  * @name:			the string used to represent the gang
@@ -146,7 +145,10 @@
  *				regulator's callback functions to prevent
  *				simultaneous updates to the pmic's phase
  *				voltage.
- * @apcs_gcc_base		virtual address of the APCS GCC registers
+ * @apcs_gcc_base:		virtual address of the APCS GCC registers
+ * @manage_phases:		begin phase control
+ * @pfm_threshold:		the sum of coefficients below which PFM can be
+ *				enabled
  */
 struct pmic_gang_vreg {
 	const char		*name;
@@ -159,6 +161,8 @@
 	bool			retention_enabled;
 	bool			use_phase_switching;
 	void __iomem		*apcs_gcc_base;
+	bool			manage_phases;
+	int			pfm_threshold;
 };
 
 static struct pmic_gang_vreg *the_gang;
@@ -168,6 +172,9 @@
 	LDO_MODE = REGULATOR_MODE_IDLE,
 };
 
+#define WAIT_FOR_LOAD		0x2
+#define WAIT_FOR_VOLTAGE	0x1
+
 struct krait_power_vreg {
 	struct list_head		link;
 	struct regulator_desc		desc;
@@ -175,7 +182,7 @@
 	const char			*name;
 	struct pmic_gang_vreg		*pvreg;
 	int				uV;
-	int				load_uA;
+	int				load;
 	enum krait_supply_mode		mode;
 	void __iomem			*reg_base;
 	void __iomem			*mdd_base;
@@ -185,7 +192,10 @@
 	int				ldo_threshold_uV;
 	int				ldo_delta_uV;
 	int				cpu_num;
+	int				coeff1;
+	int				coeff2;
 	bool				online;
+	int				online_at_probe;
 };
 
 DEFINE_PER_CPU(struct krait_power_vreg *, krait_vregs);
@@ -293,6 +303,229 @@
 	return 0;
 }
 
+#define COEFF2_UV_THRESHOLD 850000
+static int get_coeff2(int krait_uV)
+{
+	int coeff2 = 0;
+	int krait_mV = krait_uV / 1000;
+
+	if (krait_uV <= COEFF2_UV_THRESHOLD)
+		coeff2 = (612229 * krait_mV) / 1000 - 211258;
+	else
+		coeff2 = (892564 * krait_mV) / 1000 - 449543;
+
+	return  coeff2;
+}
+
+static int get_coeff1(int actual_uV, int requested_uV, int load)
+{
+	int ratio = actual_uV * 1000 / requested_uV;
+	int coeff1 = 330 * load + (load * 673 * ratio / 1000);
+
+	return coeff1;
+}
+
+static int get_coeff_total(struct krait_power_vreg *from)
+{
+	int coeff_total = 0;
+	struct krait_power_vreg *kvreg;
+	struct pmic_gang_vreg *pvreg = from->pvreg;
+
+	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+		if (!kvreg->online)
+			continue;
+
+		if (kvreg->mode == LDO_MODE) {
+			kvreg->coeff1 =
+				get_coeff1(kvreg->uV - kvreg->ldo_delta_uV,
+							kvreg->uV, kvreg->load);
+			kvreg->coeff2 =
+				get_coeff2(kvreg->uV - kvreg->ldo_delta_uV);
+		} else {
+			kvreg->coeff1 =
+				get_coeff1(pvreg->pmic_vmax_uV,
+							kvreg->uV, kvreg->load);
+			kvreg->coeff2 = get_coeff2(pvreg->pmic_vmax_uV);
+		}
+		coeff_total += kvreg->coeff1 + kvreg->coeff2;
+	}
+
+	return coeff_total;
+}
+
+static int set_pmic_gang_phases(struct pmic_gang_vreg *pvreg, int phase_count)
+{
+	pr_debug("programming phase_count = %d\n", phase_count);
+	if (pvreg->use_phase_switching)
+		/*
+		 * note the PMIC sets the phase count to one more than
+		 * the value in the register - hence subtract 1 from it
+		 */
+		return msm_spm_apcs_set_phase(phase_count - 1);
+	else
+		return 0;
+}
+
+static int num_online(struct pmic_gang_vreg *pvreg)
+{
+	int online_total = 0;
+	struct krait_power_vreg *kvreg;
+
+	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+		if (kvreg->online)
+			online_total++;
+	}
+	return online_total;
+}
+
+static bool enable_phase_management(struct pmic_gang_vreg *pvreg)
+{
+	struct krait_power_vreg *kvreg;
+
+	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+		pr_debug("%s online_at_probe:0x%x\n", kvreg->name,
+							kvreg->online_at_probe);
+		if (kvreg->online_at_probe)
+			return false;
+	}
+	return true;
+}
+
+#define PMIC_FTS_MODE_PFM	0x00
+#define PMIC_FTS_MODE_PWM	0x80
+#define ONE_PHASE_COEFF		1000000
+#define TWO_PHASE_COEFF		2000000
+
+#define PHASE_SETTLING_TIME_US		10
+static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
+				int coeff_total)
+{
+	struct pmic_gang_vreg *pvreg = from->pvreg;
+	int phase_count;
+	int rc = 0;
+	int n_online = num_online(pvreg);
+
+	if (pvreg->manage_phases == false) {
+		if (enable_phase_management(pvreg))
+			pvreg->manage_phases = true;
+		else
+			return 0;
+	}
+
+	/* First check if the coeff is low for PFM mode */
+	if (coeff_total < pvreg->pfm_threshold && n_online == 1) {
+		if (!pvreg->pfm_mode) {
+			rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
+			if (rc) {
+				pr_err("%s PFM en failed coeff_t %d rc = %d\n",
+					from->name, coeff_total, rc);
+				return rc;
+			} else {
+				pvreg->pfm_mode = true;
+			}
+		}
+		return rc;
+	}
+
+	/* coeff is high switch to PWM mode before changing phases */
+	if (pvreg->pfm_mode) {
+		rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
+		if (rc) {
+			pr_err("%s PFM exit failed load %d rc = %d\n",
+				from->name, coeff_total, rc);
+			return rc;
+		} else {
+			pvreg->pfm_mode = false;
+		}
+	}
+
+	/* calculate phases */
+	if (coeff_total < ONE_PHASE_COEFF)
+		phase_count = 1;
+	else if (coeff_total < TWO_PHASE_COEFF)
+		phase_count = 2;
+	else
+		phase_count = 4;
+
+	/* don't increase the phase count higher than number of online cpus */
+	if (phase_count > n_online)
+		phase_count = n_online;
+
+	if (phase_count != pvreg->pmic_phase_count) {
+		rc = set_pmic_gang_phases(pvreg, phase_count);
+		if (rc < 0) {
+			pr_err("%s failed set phase %d rc = %d\n",
+				from->name, phase_count, rc);
+			return rc;
+		}
+
+		/* complete the writes before the delay */
+		mb();
+
+		/*
+		 * delay until the phases are settled when
+		 * the count is raised
+		 */
+		if (phase_count > pvreg->pmic_phase_count)
+			udelay(PHASE_SETTLING_TIME_US);
+
+		pvreg->pmic_phase_count = phase_count;
+	}
+
+	return rc;
+}
+
+static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
+			int input_uV, int output_uV, int load)
+{
+	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+	int coeff_total;
+	int rc;
+
+	kvreg->online_at_probe &= ~WAIT_FOR_LOAD;
+	coeff_total = get_coeff_total(kvreg);
+
+	rc = pmic_gang_set_phases(kvreg, coeff_total);
+	if (rc < 0) {
+		dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
+				kvreg->name, coeff_total, rc);
+	}
+
+	return kvreg->mode;
+}
+
+static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
+			int input_uV, int output_uV, int load_uA)
+{
+	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
+	int rc;
+
+	mutex_lock(&pvreg->krait_power_vregs_lock);
+	kvreg->load = load_uA;
+	if (!kvreg->online) {
+		mutex_unlock(&pvreg->krait_power_vregs_lock);
+		return kvreg->mode;
+	}
+
+	rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
+	mutex_unlock(&pvreg->krait_power_vregs_lock);
+
+	return rc;
+}
+
+static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	return 0;
+}
+
+static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
+{
+	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+
+	return kvreg->mode;
+}
+
 static int switch_to_using_hs(struct krait_power_vreg *kvreg)
 {
 	if (kvreg->mode == HS_MODE)
@@ -368,19 +601,6 @@
 	return 0;
 }
 
-static int set_pmic_gang_phases(struct pmic_gang_vreg *pvreg, int phase_count)
-{
-	pr_debug("programming phase_count = %d\n", phase_count);
-	if (pvreg->use_phase_switching)
-		/*
-		 * note the PMIC sets the phase count to one more than
-		 * the value in the register - hence subtract 1 from it
-		 */
-		return msm_spm_apcs_set_phase(phase_count - 1);
-	else
-		return 0;
-}
-
 static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
 {
 	int setpoint;
@@ -524,46 +744,6 @@
 	return rc;
 }
 
-#define PHASE_SETTLING_TIME_US		10
-static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
-				int load_uA)
-{
-	struct pmic_gang_vreg *pvreg = from->pvreg;
-	int phase_count = DIV_ROUND_UP(load_uA, LOAD_PER_PHASE);
-	int rc = 0;
-
-	if (phase_count <= 0)
-		phase_count = 1;
-
-	 /* Increase phases if it is less than the number of cpus online */
-	if (phase_count < num_online_cpus()) {
-		phase_count = num_online_cpus();
-	}
-
-	if (phase_count != pvreg->pmic_phase_count) {
-		rc = set_pmic_gang_phases(pvreg, phase_count);
-		if (rc < 0) {
-			dev_err(&from->rdev->dev,
-				"%s failed set phase %d rc = %d\n",
-				pvreg->name, phase_count, rc);
-			return rc;
-		}
-
-		/* complete the writes before the delay */
-		mb();
-
-		/*
-		 * delay until the phases are settled when
-		 * the count is raised
-		 */
-		if (phase_count > pvreg->pmic_phase_count)
-			udelay(PHASE_SETTLING_TIME_US);
-
-		pvreg->pmic_phase_count = phase_count;
-	}
-	return rc;
-}
-
 static int krait_power_get_voltage(struct regulator_dev *rdev)
 {
 	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
@@ -590,21 +770,6 @@
 	return vmax;
 }
 
-static int get_total_load(struct krait_power_vreg *from)
-{
-	int load_total = 0;
-	struct krait_power_vreg *kvreg;
-	struct pmic_gang_vreg *pvreg = from->pvreg;
-
-	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
-		if (!kvreg->online)
-			continue;
-		load_total += kvreg->load_uA;
-	}
-
-	return load_total;
-}
-
 #define ROUND_UP_VOLTAGE(v, res) (DIV_ROUND_UP(v, res) * res)
 static int _set_voltage(struct regulator_dev *rdev,
 			int orig_krait_uV, int requested_uV)
@@ -613,6 +778,7 @@
 	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
 	int rc;
 	int vmax;
+	int coeff_total;
 
 	pr_debug("%s: %d to %d\n", kvreg->name, orig_krait_uV, requested_uV);
 	/*
@@ -636,6 +802,11 @@
 				kvreg->name, requested_uV, orig_krait_uV, rc);
 	}
 
+	kvreg->online_at_probe &= ~WAIT_FOR_VOLTAGE;
+	coeff_total = get_coeff_total(kvreg);
+	/* adjust the phases since coeff2 would have changed */
+	rc = pmic_gang_set_phases(kvreg, coeff_total);
+
 	return rc;
 }
 
@@ -670,89 +841,6 @@
 	return rc;
 }
 
-#define PMIC_FTS_MODE_PFM	0x00
-#define PMIC_FTS_MODE_PWM	0x80
-#define PFM_LOAD_UA		500000
-static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
-			int input_uV, int output_uV, int load_uA)
-{
-	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
-	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
-	int rc;
-	int load_total_uA;
-
-	load_total_uA = get_total_load(kvreg);
-
-	if (load_total_uA < PFM_LOAD_UA) {
-		if (!pvreg->pfm_mode) {
-			rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
-			if (rc) {
-				dev_err(&rdev->dev,
-					"%s enter PFM failed load %d rc = %d\n",
-					kvreg->name, load_total_uA, rc);
-				goto out;
-			} else {
-				pvreg->pfm_mode = true;
-			}
-		}
-		return kvreg->mode;
-	}
-
-	if (pvreg->pfm_mode) {
-		rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
-		if (rc) {
-			dev_err(&rdev->dev,
-				"%s exit PFM failed load %d rc = %d\n",
-				kvreg->name, load_total_uA, rc);
-			goto out;
-		} else {
-			pvreg->pfm_mode = false;
-		}
-	}
-
-	rc = pmic_gang_set_phases(kvreg, load_total_uA);
-	if (rc < 0) {
-		dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
-				kvreg->name, load_total_uA, rc);
-		goto out;
-	}
-
-out:
-	return kvreg->mode;
-}
-
-static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
-			int input_uV, int output_uV, int load_uA)
-{
-	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
-	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
-	int rc;
-
-	mutex_lock(&pvreg->krait_power_vregs_lock);
-	kvreg->load_uA = load_uA;
-	if (!kvreg->online) {
-		mutex_unlock(&pvreg->krait_power_vregs_lock);
-		return kvreg->mode;
-	}
-
-	rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
-	mutex_unlock(&pvreg->krait_power_vregs_lock);
-
-	return rc;
-}
-
-static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
-{
-	return 0;
-}
-
-static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
-{
-	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
-
-	return kvreg->mode;
-}
-
 static int krait_power_is_enabled(struct regulator_dev *rdev)
 {
 	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
@@ -769,7 +857,7 @@
 	mutex_lock(&pvreg->krait_power_vregs_lock);
 	__krait_power_mdd_enable(kvreg, true);
 	kvreg->online = true;
-	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load_uA);
+	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
 	if (rc < 0)
 		goto en_err;
 	/*
@@ -791,8 +879,7 @@
 	mutex_lock(&pvreg->krait_power_vregs_lock);
 	kvreg->online = false;
 
-	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV,
-							kvreg->load_uA);
+	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
 	if (rc < 0)
 		goto dis_err;
 
@@ -851,8 +938,10 @@
 DEFINE_SIMPLE_ATTRIBUTE(retention_fops,
 			get_retention_dbg_uV, set_retention_dbg_uV, "%llu\n");
 
+#define CPU_PWR_CTL_ONLINE_MASK 0x80
 static void kvreg_hw_init(struct krait_power_vreg *kvreg)
 {
+	int online;
 	/*
 	 * bhs_cnt value sets the ramp-up time from power collapse,
 	 * initialize the ramp up time
@@ -865,6 +954,10 @@
 	/* Enable MDD */
 	writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
 	mb();
+	online = CPU_PWR_CTL_ONLINE_MASK
+			& readl_relaxed(kvreg->reg_base + CPU_PWR_CTL);
+	kvreg->online_at_probe
+		= online ? (WAIT_FOR_LOAD | WAIT_FOR_VOLTAGE) : 0x0;
 }
 
 static void glb_init(void __iomem *apcs_gcc_base)
@@ -1012,7 +1105,7 @@
 	kvreg->desc.ops		= &krait_power_ops;
 	kvreg->desc.type	= REGULATOR_VOLTAGE;
 	kvreg->desc.owner	= THIS_MODULE;
-	kvreg->uV		= CORE_VOLTAGE_MIN;
+	kvreg->uV		= CORE_VOLTAGE_BOOTUP;
 	kvreg->mode		= HS_MODE;
 	kvreg->desc.ops		= &krait_power_ops;
 	kvreg->headroom_uV	= headroom_uV;
@@ -1111,6 +1204,7 @@
 {
 	int rc;
 	bool use_phase_switching = false;
+	int pfm_threshold;
 	struct device *dev = &pdev->dev;
 	struct device_node *node = dev->of_node;
 	struct pmic_gang_vreg *pvreg;
@@ -1123,6 +1217,13 @@
 
 	use_phase_switching = of_property_read_bool(node,
 						"qcom,use-phase-switching");
+
+	rc = of_property_read_u32(node, "qcom,pfm-threshold", &pfm_threshold);
+	if (rc < 0) {
+		dev_err(dev, "pfm-threshold missing rc=%d, pfm disabled\n", rc);
+		return -EINVAL;
+	}
+
 	pvreg = devm_kzalloc(&pdev->dev,
 			sizeof(struct pmic_gang_vreg), GFP_KERNEL);
 	if (!pvreg) {
@@ -1148,6 +1249,7 @@
 	pvreg->retention_enabled = true;
 	pvreg->pmic_min_uV_for_retention = INT_MAX;
 	pvreg->use_phase_switching = use_phase_switching;
+	pvreg->pfm_threshold = pfm_threshold;
 
 	mutex_init(&pvreg->krait_power_vregs_lock);
 	INIT_LIST_HEAD(&pvreg->krait_power_vregs);
@@ -1208,6 +1310,8 @@
 
 void secondary_cpu_hs_init(void *base_ptr)
 {
+	void *l2_saw_base;
+
 	/* Turn on the BHS, turn off LDO Bypass and power down LDO */
 	writel_relaxed(
 		BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
@@ -1234,6 +1338,23 @@
 		| BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS
 		| BHS_EN_MASK,
 		base_ptr + APC_PWR_GATE_CTL);
+
+	if (the_gang && the_gang->manage_phases)
+		return;
+
+	/* If the driver has not yet started to manage phases then enable
+	 * max phases.
+	 */
+	l2_saw_base = ioremap_nocache(MSM_L2_SAW_PHYS, SZ_4K);
+	if (!l2_saw_base) {
+		__WARN();
+		return;
+	}
+	writel_relaxed(0x10003, l2_saw_base + 0x1c);
+	mb();
+	udelay(PHASE_SETTLING_TIME_US);
+
+	iounmap(l2_saw_base);
 }
 
 MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 5f85ee9..1680993 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -234,7 +234,7 @@
 }
 EXPORT_SYMBOL(allocate_contiguous_ebi);
 
-unsigned long allocate_contiguous_ebi_nomap(unsigned long size,
+phys_addr_t allocate_contiguous_ebi_nomap(unsigned long size,
 	unsigned long align)
 {
 	return _allocate_contiguous_memory_nomap(size, get_ebi_memtype(),
diff --git a/arch/arm/mach-msm/mpm-of.c b/arch/arm/mach-msm/mpm-of.c
index 09f784d..fcd7cef 100644
--- a/arch/arm/mach-msm/mpm-of.c
+++ b/arch/arm/mach-msm/mpm-of.c
@@ -70,9 +70,6 @@
 #define MSM_MPM_IRQ_INDEX(irq)  (irq / 32)
 #define MSM_MPM_IRQ_MASK(irq)  BIT(irq % 32)
 
-#define MSM_MPM_DETECT_CTL_INDEX(irq) (irq / 16)
-#define MSM_MPM_DETECT_CTL_SHIFT(irq) ((irq % 16) * 2)
-
 #define hashfn(val) (val % MSM_MPM_NR_MPM_IRQS)
 #define SCLK_HZ (32768)
 #define ARCH_TIMER_HZ (19200000)
@@ -81,8 +78,8 @@
 enum mpm_reg_offsets {
 	MSM_MPM_REG_WAKEUP,
 	MSM_MPM_REG_ENABLE,
-	MSM_MPM_REG_DETECT_CTL,
-	MSM_MPM_REG_DETECT_CTL1,
+	MSM_MPM_REG_FALLING_EDGE,
+	MSM_MPM_REG_RISING_EDGE,
 	MSM_MPM_REG_POLARITY,
 	MSM_MPM_REG_STATUS,
 };
@@ -91,7 +88,8 @@
 
 static uint32_t msm_mpm_enabled_irq[MSM_MPM_REG_WIDTH];
 static uint32_t msm_mpm_wake_irq[MSM_MPM_REG_WIDTH];
-static uint32_t msm_mpm_detect_ctl[MSM_MPM_REG_WIDTH * 2];
+static uint32_t msm_mpm_falling_edge[MSM_MPM_REG_WIDTH];
+static uint32_t msm_mpm_rising_edge[MSM_MPM_REG_WIDTH];
 static uint32_t msm_mpm_polarity[MSM_MPM_REG_WIDTH];
 
 enum {
@@ -174,11 +172,11 @@
 		reg = MSM_MPM_REG_ENABLE;
 		msm_mpm_write(reg, i, irqs[i]);
 
-		reg = MSM_MPM_REG_DETECT_CTL;
-		msm_mpm_write(reg, i, msm_mpm_detect_ctl[i]);
+		reg = MSM_MPM_REG_FALLING_EDGE;
+		msm_mpm_write(reg, i, msm_mpm_falling_edge[i]);
 
-		reg = MSM_MPM_REG_DETECT_CTL1;
-		msm_mpm_write(reg, i, msm_mpm_detect_ctl[2+i]);
+		reg = MSM_MPM_REG_RISING_EDGE;
+		msm_mpm_write(reg, i, msm_mpm_rising_edge[i]);
 
 		reg = MSM_MPM_REG_POLARITY;
 		msm_mpm_write(reg, i, msm_mpm_polarity[i]);
@@ -264,23 +262,24 @@
 	return 0;
 }
 
-static void msm_mpm_set_detect_ctl(int pin, unsigned int flow_type)
+static void msm_mpm_set_edge_ctl(int pin, unsigned int flow_type)
 {
 	uint32_t index;
-	uint32_t val = 0;
-	uint32_t shift;
+	uint32_t mask;
 
-	index = MSM_MPM_DETECT_CTL_INDEX(pin);
-	shift = MSM_MPM_DETECT_CTL_SHIFT(pin);
-
-	if (flow_type & IRQ_TYPE_EDGE_RISING)
-		val |= 0x02;
+	index = MSM_MPM_IRQ_INDEX(pin);
+	mask = MSM_MPM_IRQ_MASK(pin);
 
 	if (flow_type & IRQ_TYPE_EDGE_FALLING)
-		val |= 0x01;
+		msm_mpm_falling_edge[index] |= mask;
+	else
+		msm_mpm_falling_edge[index] &= ~mask;
 
-	msm_mpm_detect_ctl[index] &= ~(0x3 << shift);
-	msm_mpm_detect_ctl[index] |= (val & 0x03) << shift;
+	if (flow_type & IRQ_TYPE_EDGE_RISING)
+		msm_mpm_rising_edge[index] |= mask;
+	else
+		msm_mpm_rising_edge[index] &= ~mask;
+
 }
 
 static int msm_mpm_set_irq_type_exclusive(
@@ -300,7 +299,7 @@
 		if (index >= MSM_MPM_REG_WIDTH)
 			return -EFAULT;
 
-		msm_mpm_set_detect_ctl(mpm_irq, flow_type);
+		msm_mpm_set_edge_ctl(mpm_irq, flow_type);
 
 		if (flow_type &  IRQ_TYPE_LEVEL_HIGH)
 			msm_mpm_polarity[index] |= mask;
@@ -429,7 +428,7 @@
 
 	spin_lock_irqsave(&msm_mpm_lock, flags);
 
-	msm_mpm_set_detect_ctl(pin, flow_type);
+	msm_mpm_set_edge_ctl(pin, flow_type);
 
 	if (flow_type & IRQ_TYPE_LEVEL_HIGH)
 		msm_mpm_polarity[index] |= mask;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_of.c b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
index b9a553a..af3537c 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_of.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
@@ -79,9 +79,10 @@
 	}
 
 	pdata->num_usecases = num_usecases;
-	ret = of_property_read_u32(of_node, "qcom,msm-bus,active-only",
-		&pdata->active_only);
-	if (ret) {
+
+	if (of_property_read_bool(of_node, "qcom,msm-bus,active-only"))
+		pdata->active_only = 1;
+	else {
 		pr_debug("active_only flag absent.\n");
 		pr_debug("Using dual context by default\n");
 	}
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 3c50bc6..cd1eaaf 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -1229,18 +1229,11 @@
 	},
 };
 
-static int __devinit msm_pm_init(void)
+static int __init msm_pm_setup_saved_state(void)
 {
 	pgd_t *pc_pgd;
 	pmd_t *pmd;
 	unsigned long pmdval;
-	enum msm_pm_time_stats_id enable_stats[] = {
-		MSM_PM_STAT_IDLE_WFI,
-		MSM_PM_STAT_RETENTION,
-		MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
-		MSM_PM_STAT_IDLE_POWER_COLLAPSE,
-		MSM_PM_STAT_SUSPEND,
-	};
 	unsigned long exit_phys;
 
 	/* Page table for cores to come back up safely. */
@@ -1280,6 +1273,19 @@
 	clean_caches((unsigned long)&msm_pm_pc_pgd, sizeof(msm_pm_pc_pgd),
 		     virt_to_phys(&msm_pm_pc_pgd));
 
+	return 0;
+}
+core_initcall(msm_pm_setup_saved_state);
+
+static int __init msm_pm_init(void)
+{
+	enum msm_pm_time_stats_id enable_stats[] = {
+		MSM_PM_STAT_IDLE_WFI,
+		MSM_PM_STAT_RETENTION,
+		MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
+		MSM_PM_STAT_IDLE_POWER_COLLAPSE,
+		MSM_PM_STAT_SUSPEND,
+	};
 	msm_pm_mode_sysfs_add();
 	msm_pm_add_stats(enable_stats, ARRAY_SIZE(enable_stats));
 	suspend_set_ops(&msm_pm_ops);
diff --git a/arch/arm/mach-msm/pm-data.c b/arch/arm/mach-msm/pm-data.c
index ccc2519..249032f 100644
--- a/arch/arm/mach-msm/pm-data.c
+++ b/arch/arm/mach-msm/pm-data.c
@@ -46,7 +46,7 @@
 		.idle_supported = 0,
 		.suspend_supported = 1,
 		.idle_enabled = 0,
-		.suspend_enabled = 0,
+		.suspend_enabled = 1,
 	},
 
 	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
@@ -74,7 +74,7 @@
 		.idle_supported = 0,
 		.suspend_supported = 1,
 		.idle_enabled = 0,
-		.suspend_enabled = 0,
+		.suspend_enabled = 1,
 	},
 
 	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
@@ -102,7 +102,7 @@
 		.idle_supported = 0,
 		.suspend_supported = 1,
 		.idle_enabled = 0,
-		.suspend_enabled = 0,
+		.suspend_enabled = 1,
 	},
 
 	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
diff --git a/arch/arm/mach-msm/rpm_log.c b/arch/arm/mach-msm/rpm_log.c
index a2c74a5..53d5752 100644
--- a/arch/arm/mach-msm/rpm_log.c
+++ b/arch/arm/mach-msm/rpm_log.c
@@ -203,11 +203,14 @@
 	struct msm_rpm_log_buffer *buf;
 
 	buf = file->private_data;
-	pdata = buf->pdata;
-	if (!pdata)
-		return -EINVAL;
+
 	if (!buf)
 		return -ENOMEM;
+
+	pdata = buf->pdata;
+
+	if (!pdata)
+		return -EINVAL;
 	if (!buf->data)
 		return -ENOMEM;
 	if (!bufu || count < 0)
diff --git a/arch/arm/mach-msm/rpm_stats.c b/arch/arm/mach-msm/rpm_stats.c
index 176c3de..cb8ed19 100644
--- a/arch/arm/mach-msm/rpm_stats.c
+++ b/arch/arm/mach-msm/rpm_stats.c
@@ -63,6 +63,8 @@
 	u32 count;
 	u64 last_entered_at;
 	u64 last_exited_at;
+	u64 accumulated;
+	u32 reserved[4];
 };
 
 static inline u64 get_time_in_sec(u64 counter)
@@ -84,6 +86,7 @@
 	char stat_type[5];
 	u64 time_in_last_mode;
 	u64 time_since_last_mode;
+	u64 actual_last_sleep;
 
 	stat_type[4] = 0;
 	memcpy(stat_type, &data->stat_type, sizeof(u32));
@@ -92,12 +95,13 @@
 	time_in_last_mode = get_time_in_msec(time_in_last_mode);
 	time_since_last_mode = arch_counter_get_cntpct() - data->last_exited_at;
 	time_since_last_mode = get_time_in_sec(time_since_last_mode);
+	actual_last_sleep = get_time_in_msec(data->accumulated);
 
 	return  snprintf(buf , buflength,
 		"RPM Mode:%s\n\t count:%d\n time in last mode(msec):%llu\n"
-		"time since last mode(sec):%llu\n",
+		"time since last mode(sec):%llu\n actual last sleep(msec):%llu\n",
 		stat_type, data->count, time_in_last_mode,
-		time_since_last_mode);
+		time_since_last_mode, actual_last_sleep);
 }
 
 static inline u32 msm_rpmstats_read_long_register_v2(void __iomem *regbase,
@@ -140,6 +144,9 @@
 				i, offsetof(struct msm_rpm_stats_data_v2,
 					last_exited_at));
 
+		data.accumulated = msm_rpmstats_read_quad_register_v2(reg,
+				i, offsetof(struct msm_rpm_stats_data_v2,
+					accumulated));
 		length += msm_rpmstats_append_data_to_buf(prvdata->buf + length,
 				&data, sizeof(prvdata->buf) - length);
 		prvdata->read_idx++;
diff --git a/arch/arm/mach-msm/smem_log.c b/arch/arm/mach-msm/smem_log.c
index 169df1e..361df33 100644
--- a/arch/arm/mach-msm/smem_log.c
+++ b/arch/arm/mach-msm/smem_log.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -33,6 +33,8 @@
 #include <mach/msm_iomap.h>
 #include <mach/smem_log.h>
 
+#include <asm/arch_timer.h>
+
 #include "smd_private.h"
 #include "smd_rpc_sym.h"
 #include "modem_notifier.h"
@@ -652,13 +654,7 @@
 #else
 static inline unsigned int read_timestamp(void)
 {
-	unsigned long long val;
-
-	/* SMEM LOG uses a 32.768KHz timestamp */
-	val = sched_clock() * 32768U;
-	do_div(val, 1000000000U);
-
-	return (unsigned int)val;
+	return (unsigned int)(arch_counter_get_cntpct());
 }
 #endif
 
diff --git a/arch/arm/mach-msm/wdog_debug.c b/arch/arm/mach-msm/wdog_debug.c
index cccca26..95a85f26 100644
--- a/arch/arm/mach-msm/wdog_debug.c
+++ b/arch/arm/mach-msm/wdog_debug.c
@@ -24,7 +24,7 @@
 	ret = scm_call_atomic2(SCM_SVC_BOOT,
 			       SCM_WDOG_DEBUG_BOOT_PART, 0, BOOT_PART_EN_VAL);
 	if (ret)
-		pr_err("failed to enable wdog debug\n");
+		pr_err("failed to enable wdog debug: %d\n", ret);
 }
 EXPORT_SYMBOL(msm_enable_wdog_debug);
 
@@ -35,6 +35,6 @@
 	ret = scm_call_atomic2(SCM_SVC_BOOT,
 			       SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
 	if (ret)
-		pr_err("failed to disable wdog debug\n");
+		pr_err("failed to disable wdog debug: %d\n", ret);
 }
 EXPORT_SYMBOL(msm_disable_wdog_debug);
diff --git a/block/row-iosched.c b/block/row-iosched.c
index c8ba344..e71f6af 100644
--- a/block/row-iosched.c
+++ b/block/row-iosched.c
@@ -200,9 +200,9 @@
 	struct request			*pending_urgent_rq;
 	int				last_served_ioprio_class;
 
-#define	ROW_REG_STARVATION_TOLLERANCE	50
+#define	ROW_REG_STARVATION_TOLLERANCE	5000
 	struct starvation_data		reg_prio_starvation;
-#define	ROW_LOW_STARVATION_TOLLERANCE	1000
+#define	ROW_LOW_STARVATION_TOLLERANCE	10000
 	struct starvation_data		low_prio_starvation;
 
 	unsigned int			cycle_flags;
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index 2557983..0383d8f 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -39,6 +39,8 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
+#include <linux/proc_fs.h>
+
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
@@ -47,8 +49,10 @@
 #include <mach/msm_serial_hs.h>
 #endif
 
-unsigned int enableuartsleep = 1;
-module_param(enableuartsleep, uint, 0644);
+static int enableuartsleep = 1;
+module_param(enableuartsleep, int, 0644);
+MODULE_PARM_DESC(enableuartsleep, "Enable Atheros Sleep Protocol");
+
 /*
  * Global variables
  */
@@ -62,6 +66,9 @@
 /** Global state flags */
 static unsigned long flags;
 
+/** To Check LPM is enabled */
+static bool is_lpm_enabled;
+
 /** Workqueue to respond to change in hostwake line */
 static void wakeup_host_work(struct work_struct *work);
 
@@ -72,6 +79,8 @@
 /** Lock for state transitions */
 static spinlock_t rw_lock;
 
+#define PROC_DIR	"bluetooth/sleep"
+
 #define POLARITY_LOW 0
 #define POLARITY_HIGH 1
 
@@ -80,8 +89,11 @@
 	unsigned ext_wake;			/* wake up device */
 	unsigned host_wake_irq;
 	int irq_polarity;
+	struct uart_port *uport;
 };
 
+struct work_struct ws_sleep;
+
 /* 1 second timeout */
 #define TX_TIMER_INTERVAL  1
 
@@ -99,23 +111,24 @@
 
 	struct sk_buff_head txq;
 	struct work_struct ctxtsw;
-	struct work_struct ws_sleep;
 };
 
-static void hsuart_serial_clock_on(struct tty_struct *tty)
+static void hsuart_serial_clock_on(struct uart_port *port)
 {
-	struct uart_state *state = tty->driver_data;
-	struct uart_port *port = state->uart_port;
 	BT_DBG("");
-	msm_hs_request_clock_on(port);
+	if (port)
+		msm_hs_request_clock_on(port);
+	else
+		BT_INFO("Uart has not voted for Clock ON");
 }
 
-static void hsuart_serial_clock_off(struct tty_struct *tty)
+static void hsuart_serial_clock_off(struct uart_port *port)
 {
-	struct uart_state *state = tty->driver_data;
-	struct uart_port *port = state->uart_port;
 	BT_DBG("");
-	msm_hs_request_clock_off(port);
+	if (port)
+		msm_hs_request_clock_off(port);
+	else
+		BT_INFO("Uart has not voted for Clock OFF");
 }
 
 static void modify_timer_task(void)
@@ -127,31 +140,31 @@
 
 }
 
-static int ath_wakeup_ar3k(struct tty_struct *tty)
+static int ath_wakeup_ar3k(void)
 {
 	int status = 0;
 	if (test_bit(BT_TXEXPIRED, &flags)) {
-		hsuart_serial_clock_on(tty);
-		BT_INFO("wakeup device\n");
+		hsuart_serial_clock_on(bsi->uport);
+		BT_DBG("wakeup device\n");
 		gpio_set_value(bsi->ext_wake, 0);
 		msleep(20);
 		gpio_set_value(bsi->ext_wake, 1);
 	}
-	modify_timer_task();
+	if (!is_lpm_enabled)
+		modify_timer_task();
 	return status;
 }
 
 static void wakeup_host_work(struct work_struct *work)
 {
-	struct ath_struct *ath =
-		container_of(work, struct ath_struct, ws_sleep);
 
-	BT_INFO("wake up host");
+	BT_DBG("wake up host");
 	if (test_bit(BT_SLEEPENABLE, &flags)) {
 		if (test_bit(BT_TXEXPIRED, &flags))
-			hsuart_serial_clock_on(ath->hu->tty);
+			hsuart_serial_clock_on(bsi->uport);
 	}
-	modify_timer_task();
+	if (!is_lpm_enabled)
+		modify_timer_task();
 }
 
 static void ath_hci_uart_work(struct work_struct *work)
@@ -159,16 +172,14 @@
 	int status;
 	struct ath_struct *ath;
 	struct hci_uart *hu;
-	struct tty_struct *tty;
 
 	ath = container_of(work, struct ath_struct, ctxtsw);
 
 	hu = ath->hu;
-	tty = hu->tty;
 
 	/* verify and wake up controller */
 	if (test_bit(BT_SLEEPENABLE, &flags))
-		status = ath_wakeup_ar3k(tty);
+		status = ath_wakeup_ar3k();
 	/* Ready to send Data */
 	clear_bit(HCI_UART_SENDING, &hu->tx_state);
 	hci_uart_tx_wakeup(hu);
@@ -176,15 +187,15 @@
 
 static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id)
 {
-	/* schedule a tasklet to handle the change in the host wake line */
-	struct ath_struct *ath = (struct ath_struct *)dev_id;
-
-	schedule_work(&ath->ws_sleep);
+	/* schedule a work to global shared workqueue to handle
+	 * the change in the host wake line
+	 */
+	schedule_work(&ws_sleep);
 
 	return IRQ_HANDLED;
 }
 
-static int ath_bluesleep_gpio_config(struct ath_struct *ath, int on)
+static int ath_bluesleep_gpio_config(int on)
 {
 	int ret = 0;
 
@@ -232,16 +243,16 @@
 	/* Initialize timer */
 	init_timer(&tx_timer);
 	tx_timer.function = bluesleep_tx_timer_expire;
-	tx_timer.data = (u_long)ath->hu;
+	tx_timer.data = 0;
 
 	if (bsi->irq_polarity == POLARITY_LOW) {
 		ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
 				IRQF_DISABLED | IRQF_TRIGGER_FALLING,
-				"bluetooth hostwake", (void *)ath);
+				"bluetooth hostwake", NULL);
 	} else  {
 		ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
 				IRQF_DISABLED | IRQF_TRIGGER_RISING,
-				"bluetooth hostwake", (void *)ath);
+				"bluetooth hostwake", NULL);
 	}
 	if (ret  < 0) {
 		BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ");
@@ -257,7 +268,7 @@
 	return 0;
 
 free_host_wake_irq:
-	free_irq(bsi->host_wake_irq, (void *)ath);
+	free_irq(bsi->host_wake_irq, NULL);
 delete_timer:
 	del_timer(&tx_timer);
 gpio_ext_wake:
@@ -268,26 +279,76 @@
 	return ret;
 }
 
+static int ath_lpm_start(void)
+{
+	BT_DBG("Start LPM mode");
+
+	if (!bsi) {
+		BT_ERR("HCIATH3K bluesleep info does not exist");
+		return -EIO;
+	}
+
+	bsi->uport = msm_hs_get_uart_port(0);
+	if (!bsi->uport) {
+		BT_ERR("UART Port is not available");
+		return -ENODEV;
+	}
+
+	INIT_WORK(&ws_sleep, wakeup_host_work);
+
+	if (ath_bluesleep_gpio_config(1) < 0) {
+		BT_ERR("HCIATH3K GPIO Config failed");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int ath_lpm_stop(void)
+{
+	BT_DBG("Stop LPM mode");
+	cancel_work_sync(&ws_sleep);
+
+	if (bsi) {
+		bsi->uport = NULL;
+		ath_bluesleep_gpio_config(0);
+	}
+
+	return 0;
+}
+
 /* Initialize protocol */
 static int ath_open(struct hci_uart *hu)
 {
 	struct ath_struct *ath;
+	struct uart_state *state;
 
 	BT_DBG("hu %p, bsi %p", hu, bsi);
 
-	if (!bsi)
+	if (!bsi) {
+		BT_ERR("HCIATH3K bluesleep info does not exist");
 		return -EIO;
+	}
 
 	ath = kzalloc(sizeof(*ath), GFP_ATOMIC);
-	if (!ath)
+	if (!ath) {
+		BT_ERR("HCIATH3K Memory not enough to init driver");
 		return -ENOMEM;
+	}
 
 	skb_queue_head_init(&ath->txq);
 
 	hu->priv = ath;
 	ath->hu = hu;
+	state = hu->tty->driver_data;
 
-	if (ath_bluesleep_gpio_config(ath, 1) < 0) {
+	if (!state) {
+		BT_ERR("HCIATH3K tty driver data does not exist");
+		return -ENXIO;
+	}
+	bsi->uport = state->uart_port;
+
+	if (ath_bluesleep_gpio_config(1) < 0) {
 		BT_ERR("HCIATH3K GPIO Config failed");
 		hu->priv = NULL;
 		kfree(ath);
@@ -300,7 +361,7 @@
 		modify_timer_task();
 	}
 	INIT_WORK(&ath->ctxtsw, ath_hci_uart_work);
-	INIT_WORK(&ath->ws_sleep, wakeup_host_work);
+	INIT_WORK(&ws_sleep, wakeup_host_work);
 	return 0;
 }
 
@@ -327,12 +388,13 @@
 
 	cancel_work_sync(&ath->ctxtsw);
 
-	cancel_work_sync(&ath->ws_sleep);
+	cancel_work_sync(&ws_sleep);
 
 	if (bsi)
-		ath_bluesleep_gpio_config(ath, 0);
+		ath_bluesleep_gpio_config(0);
 
 	hu->priv = NULL;
+	bsi->uport = NULL;
 	kfree(ath);
 
 	return 0;
@@ -423,14 +485,13 @@
 
 static void bluesleep_tx_timer_expire(unsigned long data)
 {
-	struct hci_uart *hu = (struct hci_uart *) data;
 
 	if (!test_bit(BT_SLEEPENABLE, &flags))
 		return;
 	BT_INFO("Tx timer expired\n");
 
 	set_bit(BT_TXEXPIRED, &flags);
-	hsuart_serial_clock_off(hu->tty);
+	hsuart_serial_clock_off(bsi->uport);
 }
 
 static struct hci_uart_proto athp = {
@@ -443,6 +504,88 @@
 	.flush = ath_flush,
 };
 
+static int lpm_enabled;
+
+static int bluesleep_lpm_set(const char *val, const struct kernel_param *kp)
+{
+	int ret;
+
+	ret = param_set_int(val, kp);
+
+	if (ret) {
+		BT_ERR("HCIATH3K: lpm enable parameter set failed");
+		return ret;
+	}
+
+	BT_DBG("lpm : %d", lpm_enabled);
+
+	if ((lpm_enabled == 0) && is_lpm_enabled) {
+		ath_lpm_stop();
+		clear_bit(BT_SLEEPENABLE, &flags);
+		is_lpm_enabled = false;
+	} else if ((lpm_enabled == 1) && !is_lpm_enabled) {
+		if (ath_lpm_start() < 0) {
+			BT_ERR("HCIATH3K LPM mode failed");
+			return -EIO;
+		}
+		set_bit(BT_SLEEPENABLE, &flags);
+		is_lpm_enabled = true;
+	} else {
+		BT_ERR("HCIATH3K invalid lpm value");
+		return -EINVAL;
+	}
+	return 0;
+
+}
+
+static struct kernel_param_ops bluesleep_lpm_ops = {
+	.set = bluesleep_lpm_set,
+	.get = param_get_int,
+};
+
+module_param_cb(ath_lpm, &bluesleep_lpm_ops,
+		&lpm_enabled, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ath_lpm, "Enable Atheros LPM sleep Protocol");
+
+static int lpm_btwrite;
+
+static int bluesleep_lpm_btwrite(const char *val, const struct kernel_param *kp)
+{
+	int ret;
+
+	ret = param_set_int(val, kp);
+
+	if (ret) {
+		BT_ERR("HCIATH3K: lpm btwrite parameter set failed");
+		return ret;
+	}
+
+	BT_DBG("btwrite : %d", lpm_btwrite);
+	if (is_lpm_enabled) {
+		if (lpm_btwrite == 0) {
+			/*Setting TXEXPIRED bit to make it
+			compatible with current solution*/
+			set_bit(BT_TXEXPIRED, &flags);
+			hsuart_serial_clock_off(bsi->uport);
+		} else if (lpm_btwrite == 1) {
+			ath_wakeup_ar3k();
+			clear_bit(BT_TXEXPIRED, &flags);
+		} else {
+			BT_ERR("HCIATH3K invalid btwrite value");
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static struct kernel_param_ops bluesleep_lpm_btwrite_ops = {
+	.set = bluesleep_lpm_btwrite,
+	.get = param_get_int,
+};
+
+module_param_cb(ath_btwrite, &bluesleep_lpm_btwrite_ops,
+		&lpm_btwrite, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ath_lpm, "Assert/Deassert the sleep");
 
 static int bluesleep_populate_dt_pinfo(struct platform_device *pdev)
 {
@@ -581,5 +724,6 @@
 int __exit ath_deinit(void)
 {
 	platform_driver_unregister(&bluesleep_driver);
+
 	return hci_uart_unregister_proto(&athp);
 }
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index d3434d8..a01ef3f 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -112,8 +112,6 @@
                 !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC));
 }
 
-static void ion_iommu_release(struct kref *kref);
-
 /* this function should only be called while dev->lock is held */
 static void ion_buffer_add(struct ion_device *dev,
 			   struct ion_buffer *buffer)
@@ -140,61 +138,6 @@
 	rb_insert_color(&buffer->node, &dev->buffers);
 }
 
-static void ion_iommu_add(struct ion_buffer *buffer,
-			  struct ion_iommu_map *iommu)
-{
-	struct rb_node **p = &buffer->iommu_maps.rb_node;
-	struct rb_node *parent = NULL;
-	struct ion_iommu_map *entry;
-
-	while (*p) {
-		parent = *p;
-		entry = rb_entry(parent, struct ion_iommu_map, node);
-
-		if (iommu->key < entry->key) {
-			p = &(*p)->rb_left;
-		} else if (iommu->key > entry->key) {
-			p = &(*p)->rb_right;
-		} else {
-			pr_err("%s: buffer %p already has mapping for domain %d"
-				" and partition %d\n", __func__,
-				buffer,
-				iommu_map_domain(iommu),
-				iommu_map_partition(iommu));
-			BUG();
-		}
-	}
-
-	rb_link_node(&iommu->node, parent, p);
-	rb_insert_color(&iommu->node, &buffer->iommu_maps);
-
-}
-
-static struct ion_iommu_map *ion_iommu_lookup(struct ion_buffer *buffer,
-						unsigned int domain_no,
-						unsigned int partition_no)
-{
-	struct rb_node **p = &buffer->iommu_maps.rb_node;
-	struct rb_node *parent = NULL;
-	struct ion_iommu_map *entry;
-	uint64_t key = domain_no;
-	key = key << 32 | partition_no;
-
-	while (*p) {
-		parent = *p;
-		entry = rb_entry(parent, struct ion_iommu_map, node);
-
-		if (key < entry->key)
-			p = &(*p)->rb_left;
-		else if (key > entry->key)
-			p = &(*p)->rb_right;
-		else
-			return entry;
-	}
-
-	return NULL;
-}
-
 static int ion_buffer_alloc_dirty(struct ion_buffer *buffer);
 
 /* this function should only be called while dev->lock is held */
@@ -275,38 +218,6 @@
 	return ERR_PTR(ret);
 }
 
-/**
- * Check for delayed IOMMU unmapping. Also unmap any outstanding
- * mappings which would otherwise have been leaked.
- */
-static void ion_iommu_delayed_unmap(struct ion_buffer *buffer)
-{
-	struct ion_iommu_map *iommu_map;
-	struct rb_node *node;
-	const struct rb_root *rb = &(buffer->iommu_maps);
-	unsigned long ref_count;
-	unsigned int delayed_unmap;
-
-	mutex_lock(&buffer->lock);
-
-	while ((node = rb_first(rb)) != 0) {
-		iommu_map = rb_entry(node, struct ion_iommu_map, node);
-		ref_count = atomic_read(&iommu_map->ref.refcount);
-		delayed_unmap = iommu_map->flags & ION_IOMMU_UNMAP_DELAYED;
-
-		if ((delayed_unmap && ref_count > 1) || !delayed_unmap) {
-			pr_err("%s: Virtual memory address leak in domain %u, partition %u\n",
-				__func__, iommu_map->domain_info[DI_DOMAIN_NUM],
-				iommu_map->domain_info[DI_PARTITION_NUM]);
-		}
-		/* set ref count to 1 to force release */
-		kref_init(&iommu_map->ref);
-		kref_put(&iommu_map->ref, ion_iommu_release);
-	}
-
-	mutex_unlock(&buffer->lock);
-}
-
 static void ion_delayed_unsecure(struct ion_buffer *buffer)
 {
 	if (buffer->heap->ops->unsecure_buffer)
@@ -323,7 +234,6 @@
 	buffer->heap->ops->unmap_dma(buffer->heap, buffer);
 
 	ion_delayed_unsecure(buffer);
-	ion_iommu_delayed_unmap(buffer);
 	buffer->heap->ops->free(buffer);
 	mutex_lock(&dev->lock);
 	rb_erase(&buffer->node, &dev->buffers);
@@ -654,212 +564,6 @@
 		ion_buffer_kmap_put(buffer);
 }
 
-static struct ion_iommu_map *__ion_iommu_map(struct ion_buffer *buffer,
-		int domain_num, int partition_num, unsigned long align,
-		unsigned long iova_length, unsigned long flags,
-		unsigned long *iova)
-{
-	struct ion_iommu_map *data;
-	int ret;
-
-	data = kmalloc(sizeof(*data), GFP_ATOMIC);
-
-	if (!data)
-		return ERR_PTR(-ENOMEM);
-
-	data->buffer = buffer;
-	iommu_map_domain(data) = domain_num;
-	iommu_map_partition(data) = partition_num;
-
-	ret = buffer->heap->ops->map_iommu(buffer, data,
-						domain_num,
-						partition_num,
-						align,
-						iova_length,
-						flags);
-
-	if (ret)
-		goto out;
-
-	kref_init(&data->ref);
-	*iova = data->iova_addr;
-
-	ion_iommu_add(buffer, data);
-
-	return data;
-
-out:
-	kfree(data);
-	return ERR_PTR(ret);
-}
-
-int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
-			int domain_num, int partition_num, unsigned long align,
-			unsigned long iova_length, unsigned long *iova,
-			unsigned long *buffer_size,
-			unsigned long flags, unsigned long iommu_flags)
-{
-	struct ion_buffer *buffer;
-	struct ion_iommu_map *iommu_map;
-	int ret = 0;
-
-	if (IS_ERR_OR_NULL(client)) {
-		pr_err("%s: client pointer is invalid\n", __func__);
-		return -EINVAL;
-	}
-	if (IS_ERR_OR_NULL(handle)) {
-		pr_err("%s: handle pointer is invalid\n", __func__);
-		return -EINVAL;
-	}
-	if (IS_ERR_OR_NULL(handle->buffer)) {
-		pr_err("%s: buffer pointer is invalid\n", __func__);
-		return -EINVAL;
-	}
-
-	if (ION_IS_CACHED(flags)) {
-		pr_err("%s: Cannot map iommu as cached.\n", __func__);
-		return -EINVAL;
-	}
-
-	mutex_lock(&client->lock);
-	if (!ion_handle_validate(client, handle)) {
-		pr_err("%s: invalid handle passed to map_kernel.\n",
-		       __func__);
-		mutex_unlock(&client->lock);
-		return -EINVAL;
-	}
-
-	buffer = handle->buffer;
-	mutex_lock(&buffer->lock);
-
-	if (!handle->buffer->heap->ops->map_iommu) {
-		pr_err("%s: map_iommu is not implemented by this heap.\n",
-		       __func__);
-		ret = -ENODEV;
-		goto out;
-	}
-
-	/*
-	 * If clients don't want a custom iova length, just use whatever
-	 * the buffer size is
-	 */
-	if (!iova_length)
-		iova_length = buffer->size;
-
-	if (buffer->size > iova_length) {
-		pr_debug("%s: iova length %lx is not at least buffer size"
-			" %x\n", __func__, iova_length, buffer->size);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (buffer->size & ~PAGE_MASK) {
-		pr_debug("%s: buffer size %x is not aligned to %lx", __func__,
-			buffer->size, PAGE_SIZE);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (iova_length & ~PAGE_MASK) {
-		pr_debug("%s: iova_length %lx is not aligned to %lx", __func__,
-			iova_length, PAGE_SIZE);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	iommu_map = ion_iommu_lookup(buffer, domain_num, partition_num);
-	if (!iommu_map) {
-		iommu_map = __ion_iommu_map(buffer, domain_num, partition_num,
-					    align, iova_length, flags, iova);
-		if (!IS_ERR_OR_NULL(iommu_map)) {
-			iommu_map->flags = iommu_flags;
-
-			if (iommu_map->flags & ION_IOMMU_UNMAP_DELAYED)
-				kref_get(&iommu_map->ref);
-		} else {
-			ret = PTR_ERR(iommu_map);
-		}
-	} else {
-		if (iommu_map->flags != iommu_flags) {
-			pr_err("%s: handle %p is already mapped with iommu flags %lx, trying to map with flags %lx\n",
-				__func__, handle,
-				iommu_map->flags, iommu_flags);
-			ret = -EINVAL;
-		} else if (iommu_map->mapped_size != iova_length) {
-			pr_err("%s: handle %p is already mapped with length"
-					" %x, trying to map with length %lx\n",
-				__func__, handle, iommu_map->mapped_size,
-				iova_length);
-			ret = -EINVAL;
-		} else {
-			kref_get(&iommu_map->ref);
-			*iova = iommu_map->iova_addr;
-		}
-	}
-	if (!ret)
-		buffer->iommu_map_cnt++;
-	*buffer_size = buffer->size;
-out:
-	mutex_unlock(&buffer->lock);
-	mutex_unlock(&client->lock);
-	return ret;
-}
-EXPORT_SYMBOL(ion_map_iommu);
-
-static void ion_iommu_release(struct kref *kref)
-{
-	struct ion_iommu_map *map = container_of(kref, struct ion_iommu_map,
-						ref);
-	struct ion_buffer *buffer = map->buffer;
-
-	rb_erase(&map->node, &buffer->iommu_maps);
-	buffer->heap->ops->unmap_iommu(map);
-	kfree(map);
-}
-
-void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
-			int domain_num, int partition_num)
-{
-	struct ion_iommu_map *iommu_map;
-	struct ion_buffer *buffer;
-
-	if (IS_ERR_OR_NULL(client)) {
-		pr_err("%s: client pointer is invalid\n", __func__);
-		return;
-	}
-	if (IS_ERR_OR_NULL(handle)) {
-		pr_err("%s: handle pointer is invalid\n", __func__);
-		return;
-	}
-	if (IS_ERR_OR_NULL(handle->buffer)) {
-		pr_err("%s: buffer pointer is invalid\n", __func__);
-		return;
-	}
-
-	mutex_lock(&client->lock);
-	buffer = handle->buffer;
-
-	mutex_lock(&buffer->lock);
-
-	iommu_map = ion_iommu_lookup(buffer, domain_num, partition_num);
-
-	if (!iommu_map) {
-		WARN(1, "%s: (%d,%d) was never mapped for %p\n", __func__,
-				domain_num, partition_num, buffer);
-		goto out;
-	}
-
-	kref_put(&iommu_map->ref, ion_iommu_release);
-
-	buffer->iommu_map_cnt--;
-out:
-	mutex_unlock(&buffer->lock);
-
-	mutex_unlock(&client->lock);
-
-}
-EXPORT_SYMBOL(ion_unmap_iommu);
-
 void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle)
 {
 	struct ion_buffer *buffer;
@@ -903,52 +607,10 @@
 }
 EXPORT_SYMBOL(ion_unmap_kernel);
 
-int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
-			void *uaddr, unsigned long offset, unsigned long len,
-			unsigned int cmd)
-{
-	struct ion_buffer *buffer;
-	int ret = -EINVAL;
-
-	mutex_lock(&client->lock);
-	if (!ion_handle_validate(client, handle)) {
-		pr_err("%s: invalid handle passed to do_cache_op.\n",
-		       __func__);
-		mutex_unlock(&client->lock);
-		return -EINVAL;
-	}
-	buffer = handle->buffer;
-	mutex_lock(&buffer->lock);
-
-	if (!ION_IS_CACHED(buffer->flags)) {
-		ret = 0;
-		goto out;
-	}
-
-	if (!handle->buffer->heap->ops->cache_op) {
-		pr_err("%s: cache_op is not implemented by this heap.\n",
-		       __func__);
-		ret = -ENODEV;
-		goto out;
-	}
-
-
-	ret = buffer->heap->ops->cache_op(buffer->heap, buffer, uaddr,
-						offset, len, cmd);
-
-out:
-	mutex_unlock(&buffer->lock);
-	mutex_unlock(&client->lock);
-	return ret;
-
-}
-EXPORT_SYMBOL(ion_do_cache_op);
-
 static int ion_debug_client_show(struct seq_file *s, void *unused)
 {
 	struct ion_client *client = s->private;
 	struct rb_node *n;
-	struct rb_node *n2;
 
 	seq_printf(s, "%16.16s: %16.16s : %16.16s : %12.12s : %12.12s : %s\n",
 			"heap_name", "size_in_bytes", "handle refcount",
@@ -973,15 +635,6 @@
 		else
 			seq_printf(s, " : %12s", "N/A");
 
-		for (n2 = rb_first(&handle->buffer->iommu_maps); n2;
-				   n2 = rb_next(n2)) {
-			struct ion_iommu_map *imap =
-				rb_entry(n2, struct ion_iommu_map, node);
-			seq_printf(s, " : [%d,%d] - %8lx",
-					imap->domain_info[DI_DOMAIN_NUM],
-					imap->domain_info[DI_PARTITION_NUM],
-					imap->iova_addr);
-		}
 		seq_printf(s, "\n");
 	}
 	mutex_unlock(&client->lock);
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index aeffb52..0dd3054 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -24,11 +24,9 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/iommu.h>
 #include <linux/seq_file.h>
 #include "ion_priv.h"
 
-#include <mach/iommu_domains.h>
 #include <asm/mach/map.h>
 #include <asm/cacheflush.h>
 #include <linux/msm_ion.h>
@@ -164,91 +162,6 @@
 	return ret_value;
 }
 
-int ion_carveout_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
-			void *vaddr, unsigned int offset, unsigned int length,
-			unsigned int cmd)
-{
-	void (*outer_cache_op)(phys_addr_t, phys_addr_t) = NULL;
-	struct ion_carveout_heap *carveout_heap =
-	     container_of(heap, struct  ion_carveout_heap, heap);
-	unsigned int size_to_vmap, total_size;
-	int i, j;
-	void *ptr = NULL;
-	ion_phys_addr_t buff_phys = buffer->priv_phys;
-
-	if (!vaddr) {
-		/*
-		 * Split the vmalloc space into smaller regions in
-		 * order to clean and/or invalidate the cache.
-		 */
-		size_to_vmap = ((VMALLOC_END - VMALLOC_START)/8);
-		total_size = buffer->size;
-
-		for (i = 0; i < total_size; i += size_to_vmap) {
-			size_to_vmap = min(size_to_vmap, total_size - i);
-			for (j = 0; j < 10 && size_to_vmap; ++j) {
-				ptr = ioremap(buff_phys, size_to_vmap);
-				if (ptr) {
-					switch (cmd) {
-					case ION_IOC_CLEAN_CACHES:
-						dmac_clean_range(ptr,
-							ptr + size_to_vmap);
-						outer_cache_op =
-							outer_clean_range;
-						break;
-					case ION_IOC_INV_CACHES:
-						dmac_inv_range(ptr,
-							ptr + size_to_vmap);
-						outer_cache_op =
-							outer_inv_range;
-						break;
-					case ION_IOC_CLEAN_INV_CACHES:
-						dmac_flush_range(ptr,
-							ptr + size_to_vmap);
-						outer_cache_op =
-							outer_flush_range;
-						break;
-					default:
-						return -EINVAL;
-					}
-					buff_phys += size_to_vmap;
-					break;
-				} else {
-					size_to_vmap >>= 1;
-				}
-			}
-			if (!ptr) {
-				pr_err("Couldn't io-remap the memory\n");
-				return -EINVAL;
-			}
-			iounmap(ptr);
-		}
-	} else {
-		switch (cmd) {
-		case ION_IOC_CLEAN_CACHES:
-			dmac_clean_range(vaddr, vaddr + length);
-			outer_cache_op = outer_clean_range;
-			break;
-		case ION_IOC_INV_CACHES:
-			dmac_inv_range(vaddr, vaddr + length);
-			outer_cache_op = outer_inv_range;
-			break;
-		case ION_IOC_CLEAN_INV_CACHES:
-			dmac_flush_range(vaddr, vaddr + length);
-			outer_cache_op = outer_flush_range;
-			break;
-		default:
-			return -EINVAL;
-		}
-	}
-
-	if (carveout_heap->has_outer_cache) {
-		unsigned long pstart = buffer->priv_phys + offset;
-		outer_cache_op(pstart, pstart + length);
-	}
-	return 0;
-}
-
 static int ion_carveout_print_debug(struct ion_heap *heap, struct seq_file *s,
 				    const struct rb_root *mem_map)
 {
@@ -303,110 +216,6 @@
 	return 0;
 }
 
-int ion_carveout_heap_map_iommu(struct ion_buffer *buffer,
-					struct ion_iommu_map *data,
-					unsigned int domain_num,
-					unsigned int partition_num,
-					unsigned long align,
-					unsigned long iova_length,
-					unsigned long flags)
-{
-	struct iommu_domain *domain;
-	int ret = 0;
-	unsigned long extra;
-	struct scatterlist *sglist = 0;
-	int prot = IOMMU_WRITE | IOMMU_READ;
-	prot |= ION_IS_CACHED(flags) ? IOMMU_CACHE : 0;
-
-	data->mapped_size = iova_length;
-
-	if (!msm_use_iommu()) {
-		data->iova_addr = buffer->priv_phys;
-		return 0;
-	}
-
-	extra = iova_length - buffer->size;
-
-	ret = msm_allocate_iova_address(domain_num, partition_num,
-						data->mapped_size, align,
-						&data->iova_addr);
-
-	if (ret)
-		goto out;
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		ret = -ENOMEM;
-		goto out1;
-	}
-
-	sglist = vmalloc(sizeof(*sglist));
-	if (!sglist)
-		goto out1;
-
-	sg_init_table(sglist, 1);
-	sglist->length = buffer->size;
-	sglist->offset = 0;
-	sglist->dma_address = buffer->priv_phys;
-
-	ret = iommu_map_range(domain, data->iova_addr, sglist,
-			      buffer->size, prot);
-	if (ret) {
-		pr_err("%s: could not map %lx in domain %p\n",
-			__func__, data->iova_addr, domain);
-		goto out1;
-	}
-
-	if (extra) {
-		unsigned long extra_iova_addr = data->iova_addr + buffer->size;
-		unsigned long phys_addr = sg_phys(sglist);
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
-					extra, SZ_4K, prot);
-		if (ret)
-			goto out2;
-	}
-	vfree(sglist);
-	return ret;
-
-out2:
-	iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
-	vfree(sglist);
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				data->mapped_size);
-
-out:
-
-	return ret;
-}
-
-void ion_carveout_heap_unmap_iommu(struct ion_iommu_map *data)
-{
-	unsigned int domain_num;
-	unsigned int partition_num;
-	struct iommu_domain *domain;
-
-	if (!msm_use_iommu())
-		return;
-
-	domain_num = iommu_map_domain(data);
-	partition_num = iommu_map_partition(data);
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
-		return;
-	}
-
-	iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				data->mapped_size);
-
-	return;
-}
-
 static struct ion_heap_ops carveout_heap_ops = {
 	.allocate = ion_carveout_heap_allocate,
 	.free = ion_carveout_heap_free,
@@ -416,10 +225,7 @@
 	.unmap_kernel = ion_carveout_heap_unmap_kernel,
 	.map_dma = ion_carveout_heap_map_dma,
 	.unmap_dma = ion_carveout_heap_unmap_dma,
-	.cache_op = ion_carveout_cache_ops,
 	.print_debug = ion_carveout_print_debug,
-	.map_iommu = ion_carveout_heap_map_iommu,
-	.unmap_iommu = ion_carveout_heap_unmap_iommu,
 };
 
 struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
diff --git a/drivers/gpu/ion/ion_cma_heap.c b/drivers/gpu/ion/ion_cma_heap.c
index 4f12e38..f64ad4d 100644
--- a/drivers/gpu/ion/ion_cma_heap.c
+++ b/drivers/gpu/ion/ion_cma_heap.c
@@ -178,148 +178,6 @@
 	return;
 }
 
-int ion_cma_map_iommu(struct ion_buffer *buffer,
-				struct ion_iommu_map *data,
-				unsigned int domain_num,
-				unsigned int partition_num,
-				unsigned long align,
-				unsigned long iova_length,
-				unsigned long flags)
-{
-	int ret = 0;
-	struct iommu_domain *domain;
-	unsigned long extra;
-	unsigned long extra_iova_addr;
-	struct ion_cma_buffer_info *info = buffer->priv_virt;
-	struct sg_table *table = info->table;
-	int prot = IOMMU_WRITE | IOMMU_READ;
-
-	data->mapped_size = iova_length;
-
-	if (!msm_use_iommu()) {
-		data->iova_addr = info->handle;
-		return 0;
-	}
-
-	extra = iova_length - buffer->size;
-
-	ret = msm_allocate_iova_address(domain_num, partition_num,
-						data->mapped_size, align,
-						&data->iova_addr);
-
-	if (ret)
-		goto out;
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		ret = -EINVAL;
-		goto out1;
-	}
-
-	ret = iommu_map_range(domain, data->iova_addr, table->sgl,
-				buffer->size, prot);
-
-	if (ret) {
-		pr_err("%s: could not map %lx in domain %p\n",
-			__func__, data->iova_addr, domain);
-		goto out1;
-	}
-
-	extra_iova_addr = data->iova_addr + buffer->size;
-	if (extra) {
-		unsigned long phys_addr = sg_phys(table->sgl);
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
-					extra, SZ_4K, prot);
-		if (ret)
-			goto out2;
-	}
-	return ret;
-
-out2:
-	iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				data->mapped_size);
-out:
-	return ret;
-}
-
-
-void ion_cma_unmap_iommu(struct ion_iommu_map *data)
-{
-	unsigned int domain_num;
-	unsigned int partition_num;
-	struct iommu_domain *domain;
-
-	if (!msm_use_iommu())
-		return;
-
-	domain_num = iommu_map_domain(data);
-	partition_num = iommu_map_partition(data);
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
-		return;
-	}
-
-	iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				data->mapped_size);
-
-	return;
-}
-
-int ion_cma_cache_ops(struct ion_heap *heap,
-			struct ion_buffer *buffer, void *vaddr,
-			unsigned int offset, unsigned int length,
-			unsigned int cmd)
-{
-	void (*outer_cache_op)(phys_addr_t, phys_addr_t);
-
-	switch (cmd) {
-	case ION_IOC_CLEAN_CACHES:
-		if (!vaddr)
-			dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_TO_DEVICE);
-		else
-			dmac_clean_range(vaddr, vaddr + length);
-		outer_cache_op = outer_clean_range;
-		break;
-	case ION_IOC_INV_CACHES:
-		if (!vaddr)
-			dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_FROM_DEVICE);
-		else
-			dmac_inv_range(vaddr, vaddr + length);
-		outer_cache_op = outer_inv_range;
-		break;
-	case ION_IOC_CLEAN_INV_CACHES:
-		if (!vaddr) {
-			dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_TO_DEVICE);
-			dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_FROM_DEVICE);
-		} else {
-			dmac_flush_range(vaddr, vaddr + length);
-		}
-		outer_cache_op = outer_flush_range;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (cma_heap_has_outer_cache) {
-		struct ion_cma_buffer_info *info = buffer->priv_virt;
-
-		outer_cache_op(info->handle, info->handle + length);
-	}
-
-	return 0;
-}
-
 static int ion_cma_print_debug(struct ion_heap *heap, struct seq_file *s,
 			const struct rb_root *mem_map)
 {
@@ -358,9 +216,6 @@
 	.map_user = ion_cma_mmap,
 	.map_kernel = ion_cma_map_kernel,
 	.unmap_kernel = ion_cma_unmap_kernel,
-	.map_iommu = ion_cma_map_iommu,
-	.unmap_iommu = ion_cma_unmap_iommu,
-	.cache_op = ion_cma_cache_ops,
 	.print_debug = ion_cma_print_debug,
 };
 
diff --git a/drivers/gpu/ion/ion_cma_secure_heap.c b/drivers/gpu/ion/ion_cma_secure_heap.c
index 0fbcfbf..d622a51 100644
--- a/drivers/gpu/ion/ion_cma_secure_heap.c
+++ b/drivers/gpu/ion/ion_cma_secure_heap.c
@@ -44,7 +44,6 @@
 	bool is_cached;
 };
 
-static int cma_heap_has_outer_cache;
 /*
  * Create scatter-list for the already allocated DMA buffer.
  * This function could be replace by dma_common_get_sgtable
@@ -212,110 +211,6 @@
 	return;
 }
 
-int ion_secure_cma_map_iommu(struct ion_buffer *buffer,
-				struct ion_iommu_map *data,
-				unsigned int domain_num,
-				unsigned int partition_num,
-				unsigned long align,
-				unsigned long iova_length,
-				unsigned long flags)
-{
-	int ret = 0;
-	struct iommu_domain *domain;
-	unsigned long extra;
-	unsigned long extra_iova_addr;
-	struct ion_secure_cma_buffer_info *info = buffer->priv_virt;
-	struct sg_table *table = info->table;
-	int prot = IOMMU_WRITE | IOMMU_READ;
-
-	data->mapped_size = iova_length;
-
-	if (!msm_use_iommu()) {
-		data->iova_addr = info->handle;
-		return 0;
-	}
-
-	extra = iova_length - buffer->size;
-
-	ret = msm_allocate_iova_address(domain_num, partition_num,
-						data->mapped_size, align,
-						&data->iova_addr);
-
-	if (ret)
-		goto out;
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		ret = -EINVAL;
-		goto out1;
-	}
-
-	ret = iommu_map_range(domain, data->iova_addr, table->sgl,
-				buffer->size, prot);
-
-	if (ret) {
-		pr_err("%s: could not map %lx in domain %p\n",
-			__func__, data->iova_addr, domain);
-		goto out1;
-	}
-
-	extra_iova_addr = data->iova_addr + buffer->size;
-	if (extra) {
-		unsigned long phys_addr = sg_phys(table->sgl);
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
-					extra, SZ_4K, prot);
-		if (ret)
-			goto out2;
-	}
-	return ret;
-
-out2:
-	iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				data->mapped_size);
-out:
-	return ret;
-}
-
-
-void ion_secure_cma_unmap_iommu(struct ion_iommu_map *data)
-{
-	unsigned int domain_num;
-	unsigned int partition_num;
-	struct iommu_domain *domain;
-
-	if (!msm_use_iommu())
-		return;
-
-	domain_num = iommu_map_domain(data);
-	partition_num = iommu_map_partition(data);
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
-		return;
-	}
-
-	iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				data->mapped_size);
-
-	return;
-}
-
-int ion_secure_cma_cache_ops(struct ion_heap *heap,
-			struct ion_buffer *buffer, void *vaddr,
-			unsigned int offset, unsigned int length,
-			unsigned int cmd)
-{
-	pr_info("%s: cache operations disallowed from secure heap %s\n",
-		__func__, heap->name);
-	return -EINVAL;
-}
-
 static int ion_secure_cma_print_debug(struct ion_heap *heap, struct seq_file *s,
 			const struct rb_root *mem_map)
 {
@@ -354,9 +249,6 @@
 	.map_user = ion_secure_cma_mmap,
 	.map_kernel = ion_secure_cma_map_kernel,
 	.unmap_kernel = ion_secure_cma_unmap_kernel,
-	.map_iommu = ion_secure_cma_map_iommu,
-	.unmap_iommu = ion_secure_cma_unmap_iommu,
-	.cache_op = ion_secure_cma_cache_ops,
 	.print_debug = ion_secure_cma_print_debug,
 	.secure_buffer = ion_cp_secure_buffer,
 	.unsecure_buffer = ion_cp_unsecure_buffer,
@@ -376,7 +268,6 @@
 	 * used to make the link with reserved CMA memory */
 	heap->priv = data->priv;
 	heap->type = ION_HEAP_TYPE_SECURE_DMA;
-	cma_heap_has_outer_cache = data->has_outer_cache;
 	return heap;
 }
 
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 88addab..f1868a8 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -67,10 +67,6 @@
  *			kernel space (un-cached).
  * @umap_count:	the total number of times this heap has been mapped in
  *		user space.
- * @iommu_iova: saved iova when mapping full heap at once.
- * @iommu_partition: partition used to map full heap.
- * @iommu_map_all:	Indicates whether we should map whole heap into IOMMU.
- * @iommu_2x_map_domain: Indicates the domain to use for overmapping.
  * @has_outer_cache:    set to 1 if outer cache is used, 0 otherwise.
 */
 struct ion_cp_heap {
@@ -90,11 +86,6 @@
 	unsigned long kmap_cached_count;
 	unsigned long kmap_uncached_count;
 	unsigned long umap_count;
-	unsigned long iommu_iova[MAX_DOMAINS];
-	unsigned long iommu_partition[MAX_DOMAINS];
-	void *reserved_vrange;
-	int iommu_map_all;
-	int iommu_2x_map_domain;
 	unsigned int has_outer_cache;
 	atomic_t protect_cnt;
 	void *cpu_addr;
@@ -361,29 +352,6 @@
 	return offset;
 }
 
-static void iommu_unmap_all(unsigned long domain_num,
-			    struct ion_cp_heap *cp_heap)
-{
-	unsigned long left_to_unmap = cp_heap->total_size;
-	unsigned long page_size = SZ_64K;
-
-	struct iommu_domain *domain = msm_get_iommu_domain(domain_num);
-	if (domain) {
-		unsigned long temp_iova = cp_heap->iommu_iova[domain_num];
-
-		while (left_to_unmap) {
-			iommu_unmap(domain, temp_iova, page_size);
-			temp_iova += page_size;
-			left_to_unmap -= page_size;
-		}
-		if (domain_num == cp_heap->iommu_2x_map_domain)
-			msm_iommu_unmap_extra(domain, temp_iova,
-					      cp_heap->total_size, SZ_64K);
-	} else {
-		pr_err("Unable to get IOMMU domain %lu\n", domain_num);
-	}
-}
-
 void ion_cp_free(struct ion_heap *heap, ion_phys_addr_t addr,
 		       unsigned long size)
 {
@@ -401,25 +369,6 @@
 		cp_heap->heap_protected == HEAP_NOT_PROTECTED)
 		ion_on_last_free(heap);
 
-	/* Unmap everything if we previously mapped the whole heap at once. */
-	if (!cp_heap->allocated_bytes) {
-		unsigned int i;
-		for (i = 0; i < MAX_DOMAINS; ++i) {
-			if (cp_heap->iommu_iova[i]) {
-				unsigned long vaddr_len = cp_heap->total_size;
-
-				if (i == cp_heap->iommu_2x_map_domain)
-					vaddr_len <<= 1;
-				iommu_unmap_all(i, cp_heap);
-
-				msm_free_iova_address(cp_heap->iommu_iova[i], i,
-						cp_heap->iommu_partition[i],
-						vaddr_len);
-			}
-			cp_heap->iommu_iova[i] = 0;
-			cp_heap->iommu_partition[i] = 0;
-		}
-	}
 	mutex_unlock(&cp_heap->lock);
 }
 
@@ -674,91 +623,6 @@
 	mutex_unlock(&cp_heap->lock);
 }
 
-int ion_cp_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
-			void *vaddr, unsigned int offset, unsigned int length,
-			unsigned int cmd)
-{
-	void (*outer_cache_op)(phys_addr_t, phys_addr_t) = NULL;
-	struct ion_cp_heap *cp_heap =
-		container_of(heap, struct  ion_cp_heap, heap);
-	unsigned int size_to_vmap, total_size;
-	struct ion_cp_buffer *buf = buffer->priv_virt;
-	int i, j;
-	void *ptr = NULL;
-	ion_phys_addr_t buff_phys = buffer->priv_phys;
-
-	if (!vaddr) {
-		/*
-		 * Split the vmalloc space into smaller regions in
-		 * order to clean and/or invalidate the cache.
-		 */
-		size_to_vmap = (VMALLOC_END - VMALLOC_START)/8;
-		total_size = buffer->size;
-		for (i = 0; i < total_size; i += size_to_vmap) {
-			size_to_vmap = min(size_to_vmap, total_size - i);
-			for (j = 0; j < 10 && size_to_vmap; ++j) {
-				ptr = ioremap(buff_phys, size_to_vmap);
-				if (ptr) {
-					switch (cmd) {
-					case ION_IOC_CLEAN_CACHES:
-						dmac_clean_range(ptr,
-							ptr + size_to_vmap);
-						outer_cache_op =
-							outer_clean_range;
-						break;
-					case ION_IOC_INV_CACHES:
-						dmac_inv_range(ptr,
-							ptr + size_to_vmap);
-						outer_cache_op =
-							outer_inv_range;
-						break;
-					case ION_IOC_CLEAN_INV_CACHES:
-						dmac_flush_range(ptr,
-							ptr + size_to_vmap);
-						outer_cache_op =
-							outer_flush_range;
-						break;
-					default:
-						return -EINVAL;
-					}
-					buff_phys += size_to_vmap;
-					break;
-				} else {
-					size_to_vmap >>= 1;
-				}
-			}
-			if (!ptr) {
-				pr_err("Couldn't io-remap the memory\n");
-				return -EINVAL;
-			}
-			iounmap(ptr);
-		}
-	} else {
-		switch (cmd) {
-		case ION_IOC_CLEAN_CACHES:
-			dmac_clean_range(vaddr, vaddr + length);
-			outer_cache_op = outer_clean_range;
-			break;
-		case ION_IOC_INV_CACHES:
-			dmac_inv_range(vaddr, vaddr + length);
-			outer_cache_op = outer_inv_range;
-			break;
-		case ION_IOC_CLEAN_INV_CACHES:
-			dmac_flush_range(vaddr, vaddr + length);
-			outer_cache_op = outer_flush_range;
-			break;
-		default:
-			return -EINVAL;
-		}
-	}
-
-	if (cp_heap->has_outer_cache) {
-		unsigned long pstart = buf->buffer + offset;
-		outer_cache_op(pstart, pstart + length);
-	}
-	return 0;
-}
-
 static int ion_cp_print_debug(struct ion_heap *heap, struct seq_file *s,
 			      const struct rb_root *mem_map)
 {
@@ -859,205 +723,6 @@
 	return ret_value;
 }
 
-static int iommu_map_all(unsigned long domain_num, struct ion_cp_heap *cp_heap,
-			int partition, unsigned long prot)
-{
-	unsigned long left_to_map = cp_heap->total_size;
-	unsigned long page_size = SZ_64K;
-	int ret_value = 0;
-	unsigned long virt_addr_len = cp_heap->total_size;
-	struct iommu_domain *domain = msm_get_iommu_domain(domain_num);
-
-	/* If we are mapping into the video domain we need to map twice the
-	 * size of the heap to account for prefetch issue in video core.
-	 */
-	if (domain_num == cp_heap->iommu_2x_map_domain)
-		virt_addr_len <<= 1;
-
-	if (cp_heap->total_size & (SZ_64K-1)) {
-		pr_err("Heap size is not aligned to 64K, cannot map into IOMMU\n");
-		ret_value = -EINVAL;
-	}
-	if (cp_heap->base & (SZ_64K-1)) {
-		pr_err("Heap physical address is not aligned to 64K, cannot map into IOMMU\n");
-		ret_value = -EINVAL;
-	}
-	if (!ret_value && domain) {
-		unsigned long temp_phys = cp_heap->base;
-		unsigned long temp_iova;
-
-		ret_value = msm_allocate_iova_address(domain_num, partition,
-						virt_addr_len, SZ_64K,
-						&temp_iova);
-
-		if (ret_value) {
-			pr_err("%s: could not allocate iova from domain %lu, partition %d\n",
-				__func__, domain_num, partition);
-			goto out;
-		}
-		cp_heap->iommu_iova[domain_num] = temp_iova;
-
-		while (left_to_map) {
-			int ret = iommu_map(domain, temp_iova, temp_phys,
-					page_size, prot);
-			if (ret) {
-				pr_err("%s: could not map %lx in domain %p, error: %d\n",
-					__func__, temp_iova, domain, ret);
-				ret_value = -EAGAIN;
-				goto free_iova;
-			}
-			temp_iova += page_size;
-			temp_phys += page_size;
-			left_to_map -= page_size;
-		}
-		if (domain_num == cp_heap->iommu_2x_map_domain)
-			ret_value = msm_iommu_map_extra(domain, temp_iova,
-							cp_heap->base,
-							cp_heap->total_size,
-							SZ_64K, prot);
-		if (ret_value)
-			goto free_iova;
-	} else {
-		pr_err("Unable to get IOMMU domain %lu\n", domain_num);
-		ret_value = -ENOMEM;
-	}
-	goto out;
-
-free_iova:
-	msm_free_iova_address(cp_heap->iommu_iova[domain_num], domain_num,
-			      partition, virt_addr_len);
-out:
-	return ret_value;
-}
-
-static int ion_cp_heap_map_iommu(struct ion_buffer *buffer,
-				struct ion_iommu_map *data,
-				unsigned int domain_num,
-				unsigned int partition_num,
-				unsigned long align,
-				unsigned long iova_length,
-				unsigned long flags)
-{
-	struct iommu_domain *domain;
-	int ret = 0;
-	unsigned long extra;
-	struct ion_cp_heap *cp_heap =
-		container_of(buffer->heap, struct ion_cp_heap, heap);
-	int prot = IOMMU_WRITE | IOMMU_READ;
-	struct ion_cp_buffer *buf = buffer->priv_virt;
-	prot |= ION_IS_CACHED(flags) ? IOMMU_CACHE : 0;
-
-	data->mapped_size = iova_length;
-
-	if (!msm_use_iommu()) {
-		data->iova_addr = buf->buffer;
-		return 0;
-	}
-
-	if (cp_heap->iommu_iova[domain_num]) {
-		/* Already mapped. */
-		unsigned long offset = buf->buffer - cp_heap->base;
-		data->iova_addr = cp_heap->iommu_iova[domain_num] + offset;
-		return 0;
-	} else if (cp_heap->iommu_map_all) {
-		ret = iommu_map_all(domain_num, cp_heap, partition_num, prot);
-		if (!ret) {
-			unsigned long offset =
-					buf->buffer - cp_heap->base;
-			data->iova_addr =
-				cp_heap->iommu_iova[domain_num] + offset;
-			cp_heap->iommu_partition[domain_num] = partition_num;
-			/*
-			clear delayed map flag so that we don't interfere
-			with this feature (we are already delaying).
-			*/
-			data->flags &= ~ION_IOMMU_UNMAP_DELAYED;
-			return 0;
-		} else {
-			cp_heap->iommu_iova[domain_num] = 0;
-			cp_heap->iommu_partition[domain_num] = 0;
-			return ret;
-		}
-	}
-
-	extra = iova_length - buffer->size;
-
-	ret = msm_allocate_iova_address(domain_num, partition_num,
-						data->mapped_size, align,
-						&data->iova_addr);
-
-	if (ret)
-		goto out;
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		ret = -ENOMEM;
-		goto out1;
-	}
-
-	ret = iommu_map_range(domain, data->iova_addr, buffer->sg_table->sgl,
-			      buffer->size, prot);
-	if (ret) {
-		pr_err("%s: could not map %lx in domain %p\n",
-			__func__, data->iova_addr, domain);
-		goto out1;
-	}
-
-	if (extra) {
-		unsigned long extra_iova_addr = data->iova_addr + buffer->size;
-		unsigned long phys_addr = sg_phys(buffer->sg_table->sgl);
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
-					extra, SZ_4K, prot);
-		if (ret)
-			goto out2;
-	}
-	return ret;
-
-out2:
-	iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				data->mapped_size);
-out:
-	return ret;
-}
-
-static void ion_cp_heap_unmap_iommu(struct ion_iommu_map *data)
-{
-	unsigned int domain_num;
-	unsigned int partition_num;
-	struct iommu_domain *domain;
-	struct ion_cp_heap *cp_heap =
-		container_of(data->buffer->heap, struct ion_cp_heap, heap);
-
-	if (!msm_use_iommu())
-		return;
-
-
-	domain_num = iommu_map_domain(data);
-
-	/* If we are mapping everything we'll wait to unmap until everything
-	   is freed. */
-	if (cp_heap->iommu_iova[domain_num])
-		return;
-
-	partition_num = iommu_map_partition(data);
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
-		return;
-	}
-
-	iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				data->mapped_size);
-
-	return;
-}
-
 static struct ion_heap_ops cp_heap_ops = {
 	.allocate = ion_cp_heap_allocate,
 	.free = ion_cp_heap_free,
@@ -1068,12 +733,9 @@
 	.unmap_kernel = ion_cp_heap_unmap_kernel,
 	.map_dma = ion_cp_heap_map_dma,
 	.unmap_dma = ion_cp_heap_unmap_dma,
-	.cache_op = ion_cp_cache_ops,
 	.print_debug = ion_cp_print_debug,
 	.secure_heap = ion_cp_secure_heap,
 	.unsecure_heap = ion_cp_unsecure_heap,
-	.map_iommu = ion_cp_heap_map_iommu,
-	.unmap_iommu = ion_cp_heap_unmap_iommu,
 	.secure_buffer = ion_cp_secure_buffer,
 	.unsecure_buffer = ion_cp_unsecure_buffer,
 };
@@ -1120,10 +782,6 @@
 		if (extra_data->release_region)
 			cp_heap->heap_release_region =
 				extra_data->release_region;
-		cp_heap->iommu_map_all =
-				extra_data->iommu_map_all;
-		cp_heap->iommu_2x_map_domain =
-				extra_data->iommu_2x_map_domain;
 		cp_heap->cma = extra_data->is_cma;
 		cp_heap->allow_non_secure_allocation =
 			extra_data->allow_nonsecure_alloc;
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 512ebf3..ca29016 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -30,7 +30,6 @@
 
 struct ion_iommu_heap {
 	struct ion_heap heap;
-	unsigned int has_outer_cache;
 };
 
 /*
@@ -315,157 +314,6 @@
 	return 0;
 }
 
-int ion_iommu_heap_map_iommu(struct ion_buffer *buffer,
-					struct ion_iommu_map *data,
-					unsigned int domain_num,
-					unsigned int partition_num,
-					unsigned long align,
-					unsigned long iova_length,
-					unsigned long flags)
-{
-	struct iommu_domain *domain;
-	int ret = 0;
-	unsigned long extra;
-	int prot = IOMMU_WRITE | IOMMU_READ;
-	prot |= ION_IS_CACHED(flags) ? IOMMU_CACHE : 0;
-
-	BUG_ON(!msm_use_iommu());
-
-	data->mapped_size = iova_length;
-	extra = iova_length - buffer->size;
-
-	/* Use the biggest alignment to allow bigger IOMMU mappings.
-	 * Use the first entry since the first entry will always be the
-	 * biggest entry. To take advantage of bigger mapping sizes both the
-	 * VA and PA addresses have to be aligned to the biggest size.
-	 */
-	if (buffer->sg_table->sgl->length > align)
-		align = buffer->sg_table->sgl->length;
-
-	ret = msm_allocate_iova_address(domain_num, partition_num,
-						data->mapped_size, align,
-						&data->iova_addr);
-
-	if (ret)
-		goto out;
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		ret = -ENOMEM;
-		goto out1;
-	}
-
-	ret = iommu_map_range(domain, data->iova_addr,
-			      buffer->sg_table->sgl,
-			      buffer->size, prot);
-	if (ret) {
-		pr_err("%s: could not map %lx in domain %p\n",
-			__func__, data->iova_addr, domain);
-		goto out1;
-	}
-
-	if (extra) {
-		unsigned long extra_iova_addr = data->iova_addr + buffer->size;
-		unsigned long phys_addr = sg_phys(buffer->sg_table->sgl);
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
-					extra, SZ_4K, prot);
-		if (ret)
-			goto out2;
-	}
-	return ret;
-
-out2:
-	iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				buffer->size);
-
-out:
-
-	return ret;
-}
-
-void ion_iommu_heap_unmap_iommu(struct ion_iommu_map *data)
-{
-	unsigned int domain_num;
-	unsigned int partition_num;
-	struct iommu_domain *domain;
-
-	BUG_ON(!msm_use_iommu());
-
-	domain_num = iommu_map_domain(data);
-	partition_num = iommu_map_partition(data);
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
-		return;
-	}
-
-	iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				data->mapped_size);
-
-	return;
-}
-
-static int ion_iommu_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
-			void *vaddr, unsigned int offset, unsigned int length,
-			unsigned int cmd)
-{
-	void (*outer_cache_op)(phys_addr_t, phys_addr_t);
-	struct ion_iommu_heap *iommu_heap =
-	     container_of(heap, struct  ion_iommu_heap, heap);
-
-	switch (cmd) {
-	case ION_IOC_CLEAN_CACHES:
-		if (!vaddr)
-			dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_TO_DEVICE);
-		else
-			dmac_clean_range(vaddr, vaddr + length);
-		outer_cache_op = outer_clean_range;
-		break;
-	case ION_IOC_INV_CACHES:
-		if (!vaddr)
-			dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_FROM_DEVICE);
-		else
-			dmac_inv_range(vaddr, vaddr + length);
-		outer_cache_op = outer_inv_range;
-		break;
-	case ION_IOC_CLEAN_INV_CACHES:
-		if (!vaddr) {
-			dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_TO_DEVICE);
-			dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_FROM_DEVICE);
-		} else {
-			dmac_flush_range(vaddr, vaddr + length);
-		}
-		outer_cache_op = outer_flush_range;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (iommu_heap->has_outer_cache) {
-		unsigned long pstart;
-		unsigned int i;
-		struct ion_iommu_priv_data *data = buffer->priv_virt;
-		if (!data)
-			return -ENOMEM;
-
-		for (i = 0; i < data->nrpages; ++i) {
-			pstart = page_to_phys(data->pages[i]);
-			outer_cache_op(pstart, pstart + PAGE_SIZE);
-		}
-	}
-	return 0;
-}
-
 static struct sg_table *ion_iommu_heap_map_dma(struct ion_heap *heap,
 					      struct ion_buffer *buffer)
 {
@@ -483,9 +331,6 @@
 	.map_user = ion_iommu_heap_map_user,
 	.map_kernel = ion_iommu_heap_map_kernel,
 	.unmap_kernel = ion_iommu_heap_unmap_kernel,
-	.map_iommu = ion_iommu_heap_map_iommu,
-	.unmap_iommu = ion_iommu_heap_unmap_iommu,
-	.cache_op = ion_iommu_cache_ops,
 	.map_dma = ion_iommu_heap_map_dma,
 	.unmap_dma = ion_iommu_heap_unmap_dma,
 };
@@ -500,7 +345,6 @@
 
 	iommu_heap->heap.ops = &iommu_heap_ops;
 	iommu_heap->heap.type = ION_HEAP_TYPE_IOMMU;
-	iommu_heap->has_outer_cache = heap_data->has_outer_cache;
 
 	return &iommu_heap->heap;
 }
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 8d45f9d..71527ae 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -65,8 +65,6 @@
 	struct sg_table *sg_table;
 	unsigned long *dirty;
 	struct list_head vmas;
-	unsigned int iommu_map_cnt;
-	struct rb_root iommu_maps;
 	int marked;
 };
 
@@ -98,17 +96,6 @@
 	int (*map_user) (struct ion_heap *mapper, struct ion_buffer *buffer,
 			 struct vm_area_struct *vma);
 	void (*unmap_user) (struct ion_heap *mapper, struct ion_buffer *buffer);
-	int (*cache_op)(struct ion_heap *heap, struct ion_buffer *buffer,
-			void *vaddr, unsigned int offset,
-			unsigned int length, unsigned int cmd);
-	int (*map_iommu)(struct ion_buffer *buffer,
-				struct ion_iommu_map *map_data,
-				unsigned int domain_num,
-				unsigned int partition_num,
-				unsigned long align,
-				unsigned long iova_length,
-				unsigned long flags);
-	void (*unmap_iommu)(struct ion_iommu_map *data);
 	int (*print_debug)(struct ion_heap *heap, struct seq_file *s,
 			   const struct rb_root *mem_map);
 	int (*secure_heap)(struct ion_heap *heap, int version, void *data);
diff --git a/drivers/gpu/ion/ion_removed_heap.c b/drivers/gpu/ion/ion_removed_heap.c
index 4759e40..84d8d37 100644
--- a/drivers/gpu/ion/ion_removed_heap.c
+++ b/drivers/gpu/ion/ion_removed_heap.c
@@ -41,7 +41,6 @@
 	int (*release_region)(void *);
 	atomic_t map_count;
 	void *bus_id;
-	unsigned int has_outer_cache;
 };
 
 ion_phys_addr_t ion_removed_allocate(struct ion_heap *heap,
@@ -233,91 +232,6 @@
 	ion_removed_release_region(removed_heap);
 }
 
-int ion_removed_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
-			void *vaddr, unsigned int offset, unsigned int length,
-			unsigned int cmd)
-{
-	void (*outer_cache_op)(phys_addr_t, phys_addr_t) = NULL;
-	struct ion_removed_heap *removed_heap =
-	     container_of(heap, struct  ion_removed_heap, heap);
-	unsigned int size_to_vmap, total_size;
-	int i, j;
-	void *ptr = NULL;
-	ion_phys_addr_t buff_phys = buffer->priv_phys;
-
-	if (!vaddr) {
-		/*
-		 * Split the vmalloc space into smaller regions in
-		 * order to clean and/or invalidate the cache.
-		 */
-		size_to_vmap = ((VMALLOC_END - VMALLOC_START)/8);
-		total_size = buffer->size;
-
-		for (i = 0; i < total_size; i += size_to_vmap) {
-			size_to_vmap = min(size_to_vmap, total_size - i);
-			for (j = 0; j < 10 && size_to_vmap; ++j) {
-				ptr = ioremap(buff_phys, size_to_vmap);
-				if (ptr) {
-					switch (cmd) {
-					case ION_IOC_CLEAN_CACHES:
-						dmac_clean_range(ptr,
-							ptr + size_to_vmap);
-						outer_cache_op =
-							outer_clean_range;
-						break;
-					case ION_IOC_INV_CACHES:
-						dmac_inv_range(ptr,
-							ptr + size_to_vmap);
-						outer_cache_op =
-							outer_inv_range;
-						break;
-					case ION_IOC_CLEAN_INV_CACHES:
-						dmac_flush_range(ptr,
-							ptr + size_to_vmap);
-						outer_cache_op =
-							outer_flush_range;
-						break;
-					default:
-						return -EINVAL;
-					}
-					buff_phys += size_to_vmap;
-					break;
-				} else {
-					size_to_vmap >>= 1;
-				}
-			}
-			if (!ptr) {
-				pr_err("Couldn't io-remap the memory\n");
-				return -EINVAL;
-			}
-			iounmap(ptr);
-		}
-	} else {
-		switch (cmd) {
-		case ION_IOC_CLEAN_CACHES:
-			dmac_clean_range(vaddr, vaddr + length);
-			outer_cache_op = outer_clean_range;
-			break;
-		case ION_IOC_INV_CACHES:
-			dmac_inv_range(vaddr, vaddr + length);
-			outer_cache_op = outer_inv_range;
-			break;
-		case ION_IOC_CLEAN_INV_CACHES:
-			dmac_flush_range(vaddr, vaddr + length);
-			outer_cache_op = outer_flush_range;
-			break;
-		default:
-			return -EINVAL;
-		}
-	}
-
-	if (removed_heap->has_outer_cache) {
-		unsigned long pstart = buffer->priv_phys + offset;
-		outer_cache_op(pstart, pstart + length);
-	}
-	return 0;
-}
-
 static int ion_removed_print_debug(struct ion_heap *heap, struct seq_file *s,
 				    const struct rb_root *mem_map)
 {
@@ -382,7 +296,6 @@
 	.unmap_kernel = ion_removed_heap_unmap_kernel,
 	.map_dma = ion_removed_heap_map_dma,
 	.unmap_dma = ion_removed_heap_unmap_dma,
-	.cache_op = ion_removed_cache_ops,
 	.print_debug = ion_removed_print_debug,
 };
 
@@ -412,7 +325,6 @@
 	removed_heap->heap.type = ION_HEAP_TYPE_REMOVED;
 	removed_heap->allocated_bytes = 0;
 	removed_heap->total_size = heap_data->size;
-	removed_heap->has_outer_cache = heap_data->has_outer_cache;
 
 	if (heap_data->extra_data) {
 		struct ion_co_heap_pdata *extra_data =
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index ceb30a4..f3f627d 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -24,9 +24,7 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/iommu.h>
 #include <linux/seq_file.h>
-#include <mach/iommu_domains.h>
 #include "ion_priv.h"
 #include <mach/memory.h>
 #include <asm/cacheflush.h>
@@ -35,8 +33,6 @@
 
 static atomic_t system_heap_allocated;
 static atomic_t system_contig_heap_allocated;
-static unsigned int system_heap_has_outer_cache;
-static unsigned int system_heap_contig_has_outer_cache;
 
 struct page_info {
 	struct page *page;
@@ -61,7 +57,7 @@
 			continue;
 		if (split_pages)
 			split_page(page, orders[i]);
-		info = kmap(page);
+		info = kmalloc(sizeof(struct page_info *), GFP_KERNEL);
 		info->page = page;
 		info->order = orders[i];
 		return info;
@@ -122,7 +118,7 @@
 			sg = sg_next(sg);
 		}
 		list_del(&info->list);
-		kunmap(page);
+		kfree(info);
 	}
 
 	dma_sync_sg_for_device(NULL, table->sgl, table->nents,
@@ -141,7 +137,7 @@
 		else
 			__free_pages(info->page, info->order);
 
-		kunmap(info->page);
+		kfree(info);
 	}
 	return -ENOMEM;
 }
@@ -210,32 +206,6 @@
 	vunmap(buffer->vaddr);
 }
 
-void ion_system_heap_unmap_iommu(struct ion_iommu_map *data)
-{
-	unsigned int domain_num;
-	unsigned int partition_num;
-	struct iommu_domain *domain;
-
-	if (!msm_use_iommu())
-		return;
-
-	domain_num = iommu_map_domain(data);
-	partition_num = iommu_map_partition(data);
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
-		return;
-	}
-
-	iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				data->mapped_size);
-
-	return;
-}
-
 int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
 			     struct vm_area_struct *vma)
 {
@@ -262,66 +232,6 @@
 	return 0;
 }
 
-int ion_system_heap_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
-			void *vaddr, unsigned int offset, unsigned int length,
-			unsigned int cmd)
-{
-	void (*outer_cache_op)(phys_addr_t, phys_addr_t);
-
-	switch (cmd) {
-	case ION_IOC_CLEAN_CACHES:
-		if (!vaddr)
-			dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_TO_DEVICE);
-		else
-			dmac_clean_range(vaddr, vaddr + length);
-		outer_cache_op = outer_clean_range;
-		break;
-	case ION_IOC_INV_CACHES:
-		if (!vaddr)
-			dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_FROM_DEVICE);
-		else
-			dmac_inv_range(vaddr, vaddr + length);
-		outer_cache_op = outer_inv_range;
-		break;
-	case ION_IOC_CLEAN_INV_CACHES:
-		if (!vaddr) {
-			dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_TO_DEVICE);
-			dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
-				buffer->sg_table->nents, DMA_FROM_DEVICE);
-		} else {
-			dmac_flush_range(vaddr, vaddr + length);
-		}
-		outer_cache_op = outer_flush_range;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (system_heap_has_outer_cache) {
-		unsigned long pstart;
-		struct sg_table *table = buffer->priv_virt;
-		struct scatterlist *sg;
-		int i;
-		for_each_sg(table->sgl, sg, table->nents, i) {
-			struct page *page = sg_page(sg);
-			pstart = page_to_phys(page);
-			/*
-			 * If page -> phys is returning NULL, something
-			 * has really gone wrong...
-			 */
-			if (!pstart) {
-				WARN(1, "Could not translate virtual address to physical address\n");
-				return -EINVAL;
-			}
-			outer_cache_op(pstart, pstart + PAGE_SIZE);
-		}
-	}
-	return 0;
-}
-
 static int ion_system_print_debug(struct ion_heap *heap, struct seq_file *s,
 				  const struct rb_root *unused)
 {
@@ -331,81 +241,6 @@
 	return 0;
 }
 
-int ion_system_heap_map_iommu(struct ion_buffer *buffer,
-				struct ion_iommu_map *data,
-				unsigned int domain_num,
-				unsigned int partition_num,
-				unsigned long align,
-				unsigned long iova_length,
-				unsigned long flags)
-{
-	int ret = 0;
-	struct iommu_domain *domain;
-	unsigned long extra;
-	unsigned long extra_iova_addr;
-	struct sg_table *table = buffer->priv_virt;
-	int prot = IOMMU_WRITE | IOMMU_READ;
-	prot |= ION_IS_CACHED(flags) ? IOMMU_CACHE : 0;
-
-	if (!ION_IS_CACHED(flags))
-		return -EINVAL;
-
-	if (!msm_use_iommu())
-		return -EINVAL;
-
-	data->mapped_size = iova_length;
-	extra = iova_length - buffer->size;
-
-	/* Use the biggest alignment to allow bigger IOMMU mappings.
-	 * Use the first entry since the first entry will always be the
-	 * biggest entry. To take advantage of bigger mapping sizes both the
-	 * VA and PA addresses have to be aligned to the biggest size.
-	 */
-	if (table->sgl->length > align)
-		align = table->sgl->length;
-
-	ret = msm_allocate_iova_address(domain_num, partition_num,
-						data->mapped_size, align,
-						&data->iova_addr);
-
-	if (ret)
-		goto out;
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		ret = -ENOMEM;
-		goto out1;
-	}
-
-	ret = iommu_map_range(domain, data->iova_addr, table->sgl,
-			      buffer->size, prot);
-
-	if (ret) {
-		pr_err("%s: could not map %lx in domain %p\n",
-			__func__, data->iova_addr, domain);
-		goto out1;
-	}
-
-	extra_iova_addr = data->iova_addr + buffer->size;
-	if (extra) {
-		unsigned long phys_addr = sg_phys(table->sgl);
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
-					extra, SZ_4K, prot);
-		if (ret)
-			goto out2;
-	}
-	return ret;
-
-out2:
-	iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-				data->mapped_size);
-out:
-	return ret;
-}
-
 static struct ion_heap_ops vmalloc_ops = {
 	.allocate = ion_system_heap_allocate,
 	.free = ion_system_heap_free,
@@ -414,10 +249,7 @@
 	.map_kernel = ion_system_heap_map_kernel,
 	.unmap_kernel = ion_system_heap_unmap_kernel,
 	.map_user = ion_system_heap_map_user,
-	.cache_op = ion_system_heap_cache_ops,
 	.print_debug = ion_system_print_debug,
-	.map_iommu = ion_system_heap_map_iommu,
-	.unmap_iommu = ion_system_heap_unmap_iommu,
 };
 
 struct ion_heap *ion_system_heap_create(struct ion_platform_heap *pheap)
@@ -429,7 +261,6 @@
 		return ERR_PTR(-ENOMEM);
 	heap->ops = &vmalloc_ops;
 	heap->type = ION_HEAP_TYPE_SYSTEM;
-	system_heap_has_outer_cache = pheap->has_outer_cache;
 	return heap;
 }
 
@@ -508,46 +339,6 @@
 	}
 }
 
-int ion_system_contig_heap_cache_ops(struct ion_heap *heap,
-			struct ion_buffer *buffer, void *vaddr,
-			unsigned int offset, unsigned int length,
-			unsigned int cmd)
-{
-	void (*outer_cache_op)(phys_addr_t, phys_addr_t);
-
-	switch (cmd) {
-	case ION_IOC_CLEAN_CACHES:
-		dmac_clean_range(vaddr, vaddr + length);
-		outer_cache_op = outer_clean_range;
-		break;
-	case ION_IOC_INV_CACHES:
-		dmac_inv_range(vaddr, vaddr + length);
-		outer_cache_op = outer_inv_range;
-		break;
-	case ION_IOC_CLEAN_INV_CACHES:
-		dmac_flush_range(vaddr, vaddr + length);
-		outer_cache_op = outer_flush_range;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (system_heap_contig_has_outer_cache) {
-		unsigned long pstart;
-
-		pstart = virt_to_phys(buffer->priv_virt) + offset;
-		if (!pstart) {
-			WARN(1, "Could not do virt to phys translation on %p\n",
-				buffer->priv_virt);
-			return -EINVAL;
-		}
-
-		outer_cache_op(pstart, pstart + PAGE_SIZE);
-	}
-
-	return 0;
-}
-
 static int ion_system_contig_print_debug(struct ion_heap *heap,
 					 struct seq_file *s,
 					 const struct rb_root *unused)
@@ -558,84 +349,6 @@
 	return 0;
 }
 
-int ion_system_contig_heap_map_iommu(struct ion_buffer *buffer,
-				struct ion_iommu_map *data,
-				unsigned int domain_num,
-				unsigned int partition_num,
-				unsigned long align,
-				unsigned long iova_length,
-				unsigned long flags)
-{
-	int ret = 0;
-	struct iommu_domain *domain;
-	unsigned long extra;
-	struct scatterlist *sglist = 0;
-	struct page *page = 0;
-	int prot = IOMMU_WRITE | IOMMU_READ;
-	prot |= ION_IS_CACHED(flags) ? IOMMU_CACHE : 0;
-
-	if (!ION_IS_CACHED(flags))
-		return -EINVAL;
-
-	if (!msm_use_iommu()) {
-		data->iova_addr = virt_to_phys(buffer->vaddr);
-		return 0;
-	}
-
-	data->mapped_size = iova_length;
-	extra = iova_length - buffer->size;
-
-	ret = msm_allocate_iova_address(domain_num, partition_num,
-						data->mapped_size, align,
-						&data->iova_addr);
-
-	if (ret)
-		goto out;
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		ret = -ENOMEM;
-		goto out1;
-	}
-	page = virt_to_page(buffer->vaddr);
-
-	sglist = vmalloc(sizeof(*sglist));
-	if (!sglist)
-		goto out1;
-
-	sg_init_table(sglist, 1);
-	sg_set_page(sglist, page, buffer->size, 0);
-
-	ret = iommu_map_range(domain, data->iova_addr, sglist,
-			      buffer->size, prot);
-	if (ret) {
-		pr_err("%s: could not map %lx in domain %p\n",
-			__func__, data->iova_addr, domain);
-		goto out1;
-	}
-
-	if (extra) {
-		unsigned long extra_iova_addr = data->iova_addr + buffer->size;
-		unsigned long phys_addr = sg_phys(sglist);
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
-					extra, SZ_4K, prot);
-		if (ret)
-			goto out2;
-	}
-	vfree(sglist);
-	return ret;
-out2:
-	iommu_unmap_range(domain, data->iova_addr, buffer->size);
-
-out1:
-	vfree(sglist);
-	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
-						data->mapped_size);
-out:
-	return ret;
-}
-
 void *ion_system_contig_heap_map_kernel(struct ion_heap *heap,
 	struct ion_buffer *buffer)
 {
@@ -657,10 +370,7 @@
 	.map_kernel = ion_system_contig_heap_map_kernel,
 	.unmap_kernel = ion_system_contig_heap_unmap_kernel,
 	.map_user = ion_system_contig_heap_map_user,
-	.cache_op = ion_system_contig_heap_cache_ops,
 	.print_debug = ion_system_contig_print_debug,
-	.map_iommu = ion_system_contig_heap_map_iommu,
-	.unmap_iommu = ion_system_heap_unmap_iommu,
 };
 
 struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *pheap)
@@ -672,7 +382,6 @@
 		return ERR_PTR(-ENOMEM);
 	heap->ops = &kmalloc_ops;
 	heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG;
-	system_heap_contig_has_outer_cache = pheap->has_outer_cache;
 	return heap;
 }
 
diff --git a/drivers/gpu/ion/msm/Makefile b/drivers/gpu/ion/msm/Makefile
index 1893405..becdb02 100644
--- a/drivers/gpu/ion/msm/Makefile
+++ b/drivers/gpu/ion/msm/Makefile
@@ -1 +1 @@
-obj-y += msm_ion.o ion_cp_common.o
+obj-y += msm_ion.o ion_cp_common.o ion_iommu_map.o
diff --git a/drivers/gpu/ion/msm/ion_iommu_map.c b/drivers/gpu/ion/msm/ion_iommu_map.c
new file mode 100644
index 0000000..ae4ae37
--- /dev/null
+++ b/drivers/gpu/ion/msm/ion_iommu_map.c
@@ -0,0 +1,538 @@
+/* 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
+ * 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/export.h>
+#include <linux/iommu.h>
+#include <linux/ion.h>
+#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+
+#include <mach/iommu_domains.h>
+
+enum {
+	DI_PARTITION_NUM = 0,
+	DI_DOMAIN_NUM = 1,
+	DI_MAX,
+};
+
+#define iommu_map_domain(__m)           ((__m)->domain_info[1])
+#define iommu_map_partition(__m)        ((__m)->domain_info[0])
+
+/**
+ * struct ion_iommu_map - represents a mapping of an ion buffer to an iommu
+ * @iova_addr - iommu virtual address
+ * @node - rb node to exist in the buffer's tree of iommu mappings
+ * @domain_info - contains the partition number and domain number
+ *		domain_info[1] = domain number
+ *		domain_info[0] = partition number
+ * @ref - for reference counting this mapping
+ * @mapped_size - size of the iova space mapped
+ *		(may not be the same as the buffer size)
+ * @flags - iommu domain/partition specific flags.
+ *
+ * Represents a mapping of one ion buffer to a particular iommu domain
+ * and address range. There may exist other mappings of this buffer in
+ * different domains or address ranges. All mappings will have the same
+ * cacheability and security.
+ */
+struct ion_iommu_map {
+	unsigned long iova_addr;
+	struct rb_node node;
+	union {
+		int domain_info[DI_MAX];
+		uint64_t key;
+	};
+	struct ion_iommu_meta *meta;
+	struct kref ref;
+	int mapped_size;
+	unsigned long flags;
+};
+
+
+struct ion_iommu_meta {
+	struct rb_node node;
+	struct ion_handle *handle;
+	struct rb_root iommu_maps;
+	struct kref ref;
+	struct sg_table *table;
+	unsigned long size;
+	struct mutex lock;
+};
+
+static struct rb_root iommu_root;
+DEFINE_MUTEX(msm_iommu_map_mutex);
+
+static void ion_iommu_meta_add(struct ion_iommu_meta *meta)
+{
+	struct rb_root *root = &iommu_root;
+	struct rb_node **p = &root->rb_node;
+	struct rb_node *parent = NULL;
+	struct ion_iommu_meta *entry;
+
+	while (*p) {
+		parent = *p;
+		entry = rb_entry(parent, struct ion_iommu_meta, node);
+
+		if (meta->handle < entry->handle) {
+			p = &(*p)->rb_left;
+		} else if (meta->handle > entry->handle) {
+			p = &(*p)->rb_right;
+		} else {
+			pr_err("%s: handle %p already exists\n", __func__,
+				entry->handle);
+			BUG();
+		}
+	}
+
+	rb_link_node(&meta->node, parent, p);
+	rb_insert_color(&meta->node, root);
+}
+
+
+static struct ion_iommu_meta *ion_iommu_meta_lookup(struct ion_handle *handle)
+{
+	struct rb_root *root = &iommu_root;
+	struct rb_node **p = &root->rb_node;
+	struct rb_node *parent = NULL;
+	struct ion_iommu_meta *entry = NULL;
+
+	while (*p) {
+		parent = *p;
+		entry = rb_entry(parent, struct ion_iommu_meta, node);
+
+		if (handle < entry->handle)
+			p = &(*p)->rb_left;
+		else if (handle > entry->handle)
+			p = &(*p)->rb_right;
+		else
+			return entry;
+	}
+
+	return NULL;
+}
+
+
+
+static void ion_iommu_add(struct ion_iommu_meta *meta,
+			struct ion_iommu_map *iommu)
+{
+	struct rb_node **p = &meta->iommu_maps.rb_node;
+	struct rb_node *parent = NULL;
+	struct ion_iommu_map *entry;
+
+	while (*p) {
+		parent = *p;
+		entry = rb_entry(parent, struct ion_iommu_map, node);
+
+		if (iommu->key < entry->key) {
+			p = &(*p)->rb_left;
+		} else if (iommu->key > entry->key) {
+			p = &(*p)->rb_right;
+		} else {
+			pr_err("%s: handle %p already has mapping for domain %d and partition %d\n",
+				__func__,
+				meta->handle,
+				iommu_map_domain(iommu),
+				iommu_map_partition(iommu));
+			BUG();
+		}
+	}
+
+	rb_link_node(&iommu->node, parent, p);
+	rb_insert_color(&iommu->node, &meta->iommu_maps);
+}
+
+
+static struct ion_iommu_map *ion_iommu_lookup(
+					struct ion_iommu_meta *meta,
+					unsigned int domain_no,
+					unsigned int partition_no)
+{
+	struct rb_node **p = &meta->iommu_maps.rb_node;
+	struct rb_node *parent = NULL;
+	struct ion_iommu_map *entry;
+	uint64_t key = domain_no;
+	key = key << 32 | partition_no;
+
+	while (*p) {
+		parent = *p;
+		entry = rb_entry(parent, struct ion_iommu_map, node);
+
+		if (key < entry->key)
+			p = &(*p)->rb_left;
+		else if (key > entry->key)
+			p = &(*p)->rb_right;
+		else
+			return entry;
+	}
+
+	return NULL;
+}
+
+static int ion_iommu_map_iommu(struct ion_iommu_meta *meta,
+					struct ion_iommu_map *data,
+					unsigned int domain_num,
+					unsigned int partition_num,
+					unsigned long align,
+					unsigned long iova_length,
+					unsigned long flags)
+{
+	struct iommu_domain *domain;
+	int ret = 0;
+	unsigned long extra, size;
+	struct sg_table *table;
+	int prot = IOMMU_WRITE | IOMMU_READ;
+
+
+	size = meta->size;
+	data->mapped_size = iova_length;
+	extra = iova_length - size;
+	table = meta->table;
+
+	/* Use the biggest alignment to allow bigger IOMMU mappings.
+	 * Use the first entry since the first entry will always be the
+	 * biggest entry. To take advantage of bigger mapping sizes both the
+	 * VA and PA addresses have to be aligned to the biggest size.
+	 */
+	if (table->sgl->length > align)
+		align = table->sgl->length;
+
+	ret = msm_allocate_iova_address(domain_num, partition_num,
+						data->mapped_size, align,
+						&data->iova_addr);
+
+	if (ret)
+		goto out;
+
+	domain = msm_get_iommu_domain(domain_num);
+
+	if (!domain) {
+		ret = -ENOMEM;
+		goto out1;
+	}
+
+	ret = iommu_map_range(domain, data->iova_addr,
+			      table->sgl,
+			      size, prot);
+	if (ret) {
+		pr_err("%s: could not map %lx in domain %p\n",
+			__func__, data->iova_addr, domain);
+		goto out1;
+	}
+
+	if (extra) {
+		unsigned long extra_iova_addr = data->iova_addr + size;
+		unsigned long phys_addr = sg_phys(table->sgl);
+		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
+					extra, SZ_4K, prot);
+		if (ret)
+			goto out2;
+	}
+	return ret;
+
+out2:
+	iommu_unmap_range(domain, data->iova_addr, size);
+out1:
+	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+				size);
+
+out:
+
+	return ret;
+}
+
+static void ion_iommu_heap_unmap_iommu(struct ion_iommu_map *data)
+{
+	unsigned int domain_num;
+	unsigned int partition_num;
+	struct iommu_domain *domain;
+
+	BUG_ON(!msm_use_iommu());
+
+	domain_num = iommu_map_domain(data);
+	partition_num = iommu_map_partition(data);
+
+	domain = msm_get_iommu_domain(domain_num);
+
+	if (!domain) {
+		WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
+		return;
+	}
+
+	iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
+	msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+				data->mapped_size);
+
+	return;
+}
+
+
+
+static struct ion_iommu_map *__ion_iommu_map(struct ion_iommu_meta *meta,
+		int domain_num, int partition_num, unsigned long align,
+		unsigned long iova_length, unsigned long flags,
+		unsigned long *iova)
+{
+	struct ion_iommu_map *data;
+	int ret;
+
+	data = kmalloc(sizeof(*data), GFP_ATOMIC);
+
+	if (!data)
+		return ERR_PTR(-ENOMEM);
+
+	iommu_map_domain(data) = domain_num;
+	iommu_map_partition(data) = partition_num;
+
+	ret = ion_iommu_map_iommu(meta, data,
+						domain_num,
+						partition_num,
+						align,
+						iova_length,
+						flags);
+
+	if (ret)
+		goto out;
+
+	kref_init(&data->ref);
+	*iova = data->iova_addr;
+	data->meta = meta;
+
+	ion_iommu_add(meta, data);
+
+	return data;
+
+out:
+	kfree(data);
+	return ERR_PTR(ret);
+}
+
+static struct ion_iommu_meta *ion_iommu_meta_create(struct ion_handle *handle,
+						struct sg_table *table,
+						unsigned long size)
+{
+	struct ion_iommu_meta *meta;
+
+	meta = kzalloc(sizeof(*meta), GFP_KERNEL);
+
+	if (!meta)
+		return ERR_PTR(-ENOMEM);
+
+	meta->handle = handle;
+	meta->table = table;
+	meta->size = size;
+	kref_init(&meta->ref);
+	mutex_init(&meta->lock);
+	ion_iommu_meta_add(meta);
+
+	return meta;
+}
+
+static void ion_iommu_meta_destroy(struct kref *kref)
+{
+	struct ion_iommu_meta *meta = container_of(kref, struct ion_iommu_meta,
+						ref);
+
+
+	rb_erase(&meta->node, &iommu_root);
+	kfree(meta);
+}
+
+static void ion_iommu_meta_put(struct ion_iommu_meta *meta)
+{
+	/*
+	 * Need to lock here to prevent race against map/unmap
+	 */
+	mutex_lock(&msm_iommu_map_mutex);
+	kref_put(&meta->ref, ion_iommu_meta_destroy);
+	mutex_unlock(&msm_iommu_map_mutex);
+}
+
+int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
+			int domain_num, int partition_num, unsigned long align,
+			unsigned long iova_length, unsigned long *iova,
+			unsigned long *buffer_size,
+			unsigned long flags, unsigned long iommu_flags)
+{
+	struct ion_iommu_map *iommu_map;
+	struct ion_iommu_meta *iommu_meta = NULL;
+	struct sg_table *table;
+	struct scatterlist *sg;
+	int ret = 0;
+	int i;
+	unsigned long size = 0;
+
+	if (IS_ERR_OR_NULL(client)) {
+		pr_err("%s: client pointer is invalid\n", __func__);
+		return -EINVAL;
+	}
+	if (IS_ERR_OR_NULL(handle)) {
+		pr_err("%s: handle pointer is invalid\n", __func__);
+		return -EINVAL;
+	}
+
+	table = ion_sg_table(client, handle);
+
+	if (IS_ERR_OR_NULL(table))
+		return PTR_ERR(table);
+
+	for_each_sg(table->sgl, sg, table->nents, i)
+		size += sg_dma_len(sg);
+
+	if (!msm_use_iommu()) {
+		unsigned long pa = sg_dma_address(table->sgl);
+		if (pa == 0)
+			pa = sg_phys(table->sgl);
+		*iova = pa;
+		*buffer_size = size;
+	}
+	/*
+	 * If clients don't want a custom iova length, just use whatever
+	 * the buffer size is
+	 */
+	if (!iova_length)
+		iova_length = size;
+
+	if (size > iova_length) {
+		pr_debug("%s: iova length %lx is not at least buffer size %lx\n",
+			__func__, iova_length, size);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (size & ~PAGE_MASK) {
+		pr_debug("%s: buffer size %lx is not aligned to %lx", __func__,
+			size, PAGE_SIZE);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (iova_length & ~PAGE_MASK) {
+		pr_debug("%s: iova_length %lx is not aligned to %lx", __func__,
+			iova_length, PAGE_SIZE);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	mutex_lock(&msm_iommu_map_mutex);
+	iommu_meta = ion_iommu_meta_lookup(handle);
+
+	if (!iommu_meta)
+		iommu_meta = ion_iommu_meta_create(handle, table, size);
+	else
+		kref_get(&iommu_meta->ref);
+
+	mutex_unlock(&msm_iommu_map_mutex);
+
+	iommu_map = ion_iommu_lookup(iommu_meta, domain_num, partition_num);
+	if (!iommu_map) {
+		iommu_map = __ion_iommu_map(iommu_meta, domain_num,
+					    partition_num, align, iova_length,
+					    flags, iova);
+		if (!IS_ERR_OR_NULL(iommu_map)) {
+			iommu_map->flags = iommu_flags;
+			ret = 0;
+		} else {
+			ret = PTR_ERR(iommu_map);
+			goto out;
+		}
+	} else {
+		if (iommu_map->flags != iommu_flags) {
+			pr_err("%s: handle %p is already mapped with iommu flags %lx, trying to map with flags %lx\n",
+				__func__, handle,
+				iommu_map->flags, iommu_flags);
+			ret = -EINVAL;
+			goto out;
+		} else if (iommu_map->mapped_size != iova_length) {
+			pr_err("%s: handle %p is already mapped with length %x, trying to map with length %lx\n",
+				__func__, handle, iommu_map->mapped_size,
+				iova_length);
+			ret = -EINVAL;
+			goto out;
+		} else {
+			kref_get(&iommu_map->ref);
+			*iova = iommu_map->iova_addr;
+		}
+	}
+	*buffer_size = size;
+	return ret;
+
+out:
+
+	ion_iommu_meta_put(iommu_meta);
+	return ret;
+}
+EXPORT_SYMBOL(ion_map_iommu);
+
+
+static void ion_iommu_map_release(struct kref *kref)
+{
+	struct ion_iommu_map *map = container_of(kref, struct ion_iommu_map,
+						ref);
+	struct ion_iommu_meta *meta = map->meta;
+
+	rb_erase(&map->node, &meta->iommu_maps);
+	ion_iommu_heap_unmap_iommu(map);
+	kfree(map);
+}
+
+void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
+			int domain_num, int partition_num)
+{
+	struct ion_iommu_map *iommu_map;
+	struct ion_iommu_meta *meta;
+
+	if (IS_ERR_OR_NULL(client)) {
+		pr_err("%s: client pointer is invalid\n", __func__);
+		return;
+	}
+	if (IS_ERR_OR_NULL(handle)) {
+		pr_err("%s: handle pointer is invalid\n", __func__);
+		return;
+	}
+
+
+	mutex_lock(&msm_iommu_map_mutex);
+	meta = ion_iommu_meta_lookup(handle);
+	if (!meta) {
+		WARN(1, "%s: (%d,%d) was never mapped for %p\n", __func__,
+				domain_num, partition_num, handle);
+		mutex_lock(&msm_iommu_map_mutex);
+		goto out;
+
+	}
+	mutex_unlock(&msm_iommu_map_mutex);
+
+	mutex_lock(&meta->lock);
+	iommu_map = ion_iommu_lookup(meta, domain_num, partition_num);
+
+	if (!iommu_map) {
+		WARN(1, "%s: (%d,%d) was never mapped for %p\n", __func__,
+				domain_num, partition_num, handle);
+		mutex_unlock(&meta->lock);
+		goto out;
+	}
+
+	kref_put(&iommu_map->ref, ion_iommu_map_release);
+	mutex_unlock(&meta->lock);
+
+	ion_iommu_meta_put(meta);
+
+out:
+	return;
+}
+EXPORT_SYMBOL(ion_unmap_iommu);
+
+
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index a7dcd19..9259de2 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -26,8 +26,10 @@
 #include <linux/rwsem.h>
 #include <linux/uaccess.h>
 #include <linux/memblock.h>
+#include <linux/dma-mapping.h>
 #include <mach/ion.h>
 #include <mach/msm_memtypes.h>
+#include <asm/cacheflush.h>
 #include "../ion_priv.h"
 #include "ion_cp_common.h"
 
@@ -177,6 +179,210 @@
 }
 EXPORT_SYMBOL(msm_ion_do_cache_op);
 
+static int ion_no_pages_cache_ops(struct ion_client *client,
+			struct ion_handle *handle,
+			void *vaddr,
+			unsigned int offset, unsigned int length,
+			unsigned int cmd)
+{
+	void (*outer_cache_op)(phys_addr_t, phys_addr_t) = NULL;
+	unsigned int size_to_vmap, total_size;
+	int i, j, ret;
+	void *ptr = NULL;
+	ion_phys_addr_t buff_phys = 0;
+	ion_phys_addr_t buff_phys_start = 0;
+	size_t buf_length = 0;
+
+	ret = ion_phys(client, handle, &buff_phys_start, &buf_length);
+	if (ret)
+		return -EINVAL;
+
+	buff_phys = buff_phys_start;
+
+	if (!vaddr) {
+		/*
+		 * Split the vmalloc space into smaller regions in
+		 * order to clean and/or invalidate the cache.
+		 */
+		size_to_vmap = ((VMALLOC_END - VMALLOC_START)/8);
+		total_size = buf_length;
+
+		for (i = 0; i < total_size; i += size_to_vmap) {
+			size_to_vmap = min(size_to_vmap, total_size - i);
+			for (j = 0; j < 10 && size_to_vmap; ++j) {
+				ptr = ioremap(buff_phys, size_to_vmap);
+				if (ptr) {
+					switch (cmd) {
+					case ION_IOC_CLEAN_CACHES:
+						dmac_clean_range(ptr,
+							ptr + size_to_vmap);
+						outer_cache_op =
+							outer_clean_range;
+						break;
+					case ION_IOC_INV_CACHES:
+						dmac_inv_range(ptr,
+							ptr + size_to_vmap);
+						outer_cache_op =
+							outer_inv_range;
+						break;
+					case ION_IOC_CLEAN_INV_CACHES:
+						dmac_flush_range(ptr,
+							ptr + size_to_vmap);
+						outer_cache_op =
+							outer_flush_range;
+						break;
+					default:
+						return -EINVAL;
+					}
+					buff_phys += size_to_vmap;
+					break;
+				} else {
+					size_to_vmap >>= 1;
+				}
+			}
+			if (!ptr) {
+				pr_err("Couldn't io-remap the memory\n");
+				return -EINVAL;
+			}
+			iounmap(ptr);
+		}
+	} else {
+		switch (cmd) {
+		case ION_IOC_CLEAN_CACHES:
+			dmac_clean_range(vaddr, vaddr + length);
+			outer_cache_op = outer_clean_range;
+			break;
+		case ION_IOC_INV_CACHES:
+			dmac_inv_range(vaddr, vaddr + length);
+			outer_cache_op = outer_inv_range;
+			break;
+		case ION_IOC_CLEAN_INV_CACHES:
+			dmac_flush_range(vaddr, vaddr + length);
+			outer_cache_op = outer_flush_range;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	outer_cache_op(buff_phys_start + offset,
+		       buff_phys_start + offset + length);
+
+	return 0;
+}
+
+#ifdef CONFIG_OUTER_CACHE
+static void ion_pages_outer_cache_op(void (*op)(phys_addr_t, phys_addr_t),
+				struct sg_table *table)
+{
+	unsigned long pstart;
+	struct scatterlist *sg;
+	int i;
+	for_each_sg(table->sgl, sg, table->nents, i) {
+		struct page *page = sg_page(sg);
+		pstart = page_to_phys(page);
+		/*
+		 * If page -> phys is returning NULL, something
+		 * has really gone wrong...
+		 */
+		if (!pstart) {
+			WARN(1, "Could not translate virtual address to physical address\n");
+			return;
+		}
+		op(pstart, pstart + PAGE_SIZE);
+	}
+}
+#else
+static void ion_pages_outer_cache_op(void (*op)(phys_addr_t, phys_addr_t),
+					struct sg_table *table)
+{
+
+}
+#endif
+
+static int ion_pages_cache_ops(struct ion_client *client,
+			struct ion_handle *handle,
+			void *vaddr, unsigned int offset, unsigned int length,
+			unsigned int cmd)
+{
+	void (*outer_cache_op)(phys_addr_t, phys_addr_t);
+	struct sg_table *table = NULL;
+
+	table = ion_sg_table(client, handle);
+	if (IS_ERR_OR_NULL(table))
+		return PTR_ERR(table);
+
+	switch (cmd) {
+	case ION_IOC_CLEAN_CACHES:
+		if (!vaddr)
+			dma_sync_sg_for_device(NULL, table->sgl,
+				table->nents, DMA_TO_DEVICE);
+		else
+			dmac_clean_range(vaddr, vaddr + length);
+		outer_cache_op = outer_clean_range;
+		break;
+	case ION_IOC_INV_CACHES:
+		if (!vaddr)
+			dma_sync_sg_for_cpu(NULL, table->sgl,
+				table->nents, DMA_FROM_DEVICE);
+		else
+			dmac_inv_range(vaddr, vaddr + length);
+		outer_cache_op = outer_inv_range;
+		break;
+	case ION_IOC_CLEAN_INV_CACHES:
+		if (!vaddr) {
+			dma_sync_sg_for_device(NULL, table->sgl,
+				table->nents, DMA_TO_DEVICE);
+			dma_sync_sg_for_cpu(NULL, table->sgl,
+				table->nents, DMA_FROM_DEVICE);
+		} else {
+			dmac_flush_range(vaddr, vaddr + length);
+		}
+		outer_cache_op = outer_flush_range;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ion_pages_outer_cache_op(outer_cache_op, table);
+
+	return 0;
+}
+
+int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+			void *uaddr, unsigned long offset, unsigned long len,
+			unsigned int cmd)
+{
+	int ret = -EINVAL;
+	unsigned long flags;
+	struct sg_table *table;
+	struct page *page;
+
+	ret = ion_handle_get_flags(client, handle, &flags);
+	if (ret)
+		return -EINVAL;
+
+	if (!ION_IS_CACHED(flags))
+		return 0;
+
+	table = ion_sg_table(client, handle);
+
+	if (IS_ERR_OR_NULL(table))
+		return PTR_ERR(table);
+
+	page = sg_page(table->sgl);
+
+	if (page)
+		ret = ion_pages_cache_ops(client, handle, uaddr,
+					offset, len, cmd);
+	else
+		ret = ion_no_pages_cache_ops(client, handle, uaddr,
+					offset, len, cmd);
+
+	return ret;
+
+}
+
 static ion_phys_addr_t msm_ion_get_base(unsigned long size, int memory_type,
 				    unsigned int align)
 {
diff --git a/drivers/gpu/ion/msm_ion_priv.h b/drivers/gpu/ion/msm_ion_priv.h
index 2729ce2..2de4e8a 100644
--- a/drivers/gpu/ion/msm_ion_priv.h
+++ b/drivers/gpu/ion/msm_ion_priv.h
@@ -26,42 +26,6 @@
 #include <linux/iommu.h>
 #include <linux/seq_file.h>
 
-enum {
-	DI_PARTITION_NUM = 0,
-	DI_DOMAIN_NUM = 1,
-	DI_MAX,
-};
-
-/**
- * struct ion_iommu_map - represents a mapping of an ion buffer to an iommu
- * @iova_addr - iommu virtual address
- * @node - rb node to exist in the buffer's tree of iommu mappings
- * @domain_info - contains the partition number and domain number
- *		domain_info[1] = domain number
- *		domain_info[0] = partition number
- * @ref - for reference counting this mapping
- * @mapped_size - size of the iova space mapped
- *		(may not be the same as the buffer size)
- * @flags - iommu domain/partition specific flags.
- *
- * Represents a mapping of one ion buffer to a particular iommu domain
- * and address range. There may exist other mappings of this buffer in
- * different domains or address ranges. All mappings will have the same
- * cacheability and security.
- */
-struct ion_iommu_map {
-	unsigned long iova_addr;
-	struct rb_node node;
-	union {
-		int domain_info[DI_MAX];
-		uint64_t key;
-	};
-	struct ion_buffer *buffer;
-	struct kref ref;
-	int mapped_size;
-	unsigned long flags;
-};
-
 /**
  * struct mem_map_data - represents information about the memory map for a heap
  * @node:		rb node used to store in the tree of mem_map_data
@@ -79,9 +43,6 @@
 	const char *client_name;
 };
 
-#define iommu_map_domain(__m)		((__m)->domain_info[1])
-#define iommu_map_partition(__m)	((__m)->domain_info[0])
-
 struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *);
 void ion_iommu_heap_destroy(struct ion_heap *);
 
diff --git a/drivers/iommu/msm_iommu_dev-v0.c b/drivers/iommu/msm_iommu_dev-v0.c
index 549800f..7ae0b21 100644
--- a/drivers/iommu/msm_iommu_dev-v0.c
+++ b/drivers/iommu/msm_iommu_dev-v0.c
@@ -414,6 +414,7 @@
 			pmon_info->iommu.ops = &iommu_access_ops_v0;
 			pmon_info->iommu.hw_ops = iommu_pm_get_hw_ops_v0();
 			pmon_info->iommu.iommu_name = drvdata->name;
+			pmon_info->iommu.always_on = 1;
 			ret = msm_iommu_pm_iommu_register(pmon_info);
 			if (ret) {
 				pr_err("%s iommu register fail\n",
diff --git a/drivers/iommu/msm_iommu_perfmon.c b/drivers/iommu/msm_iommu_perfmon.c
index fee8a4a..a11d794 100644
--- a/drivers/iommu/msm_iommu_perfmon.c
+++ b/drivers/iommu/msm_iommu_perfmon.c
@@ -90,6 +90,19 @@
 	return pos;
 }
 
+static int iommu_pm_event_class_supported(struct iommu_pmon *pmon,
+					  int event_class)
+{
+	unsigned int nevent_cls = pmon->nevent_cls_supported;
+	unsigned int i;
+
+	for (i = 0; i < nevent_cls; ++i) {
+		if (event_class == pmon->event_cls_supported[i])
+			return event_class;
+	}
+	return MSM_IOMMU_PMU_NO_EVENT_CLASS;
+}
+
 static const char *iommu_pm_find_event_class_name(int event_class)
 {
 	size_t array_len;
@@ -113,7 +126,8 @@
 	return event_class_name;
 }
 
-static int iommu_pm_find_event_class(const char *event_class_name)
+static int iommu_pm_find_event_class(struct iommu_pmon *pmon,
+				     const char *event_class_name)
 {
 	size_t array_len;
 	struct event_class *ptr;
@@ -134,6 +148,7 @@
 	}
 
 out:
+	event_class = iommu_pm_event_class_supported(pmon, event_class);
 	return event_class;
 }
 
@@ -389,11 +404,11 @@
 		rv = kstrtol(buf, 10, &value);
 		if (!rv) {
 			counter->current_event_class =
-				iommu_pm_find_event_class(
+				iommu_pm_find_event_class(pmon,
 					iommu_pm_find_event_class_name(value));
 		} else {
 			counter->current_event_class =
-						iommu_pm_find_event_class(buf);
+					iommu_pm_find_event_class(pmon, buf);
 	}	}
 
 	if (current_event_class != counter->current_event_class)
@@ -488,14 +503,17 @@
 		rv = kstrtoul(buf, 10, &cmd);
 		if (!rv && (cmd < 2)) {
 			if (pmon->enabled == 1 && cmd == 0) {
-				if (pmon->iommu_attach_count > 0)
+				if (pmon->iommu.always_on ||
+				    pmon->iommu_attach_count > 0)
 					iommu_pm_off(pmon);
 			} else if (pmon->enabled == 0 && cmd == 1) {
 				/* We can only turn on perf. monitoring if
-				 * iommu is attached. Delay turning on perf.
-				 * monitoring until we are attached.
+				 * iommu is attached (if not always on).
+				 * Delay turning on perf. monitoring until
+				 * we are attached.
 				 */
-				if (pmon->iommu_attach_count > 0)
+				if (pmon->iommu.always_on ||
+				    pmon->iommu_attach_count > 0)
 					iommu_pm_on(pmon);
 				else
 					pmon->enabled = 1;
@@ -788,9 +806,9 @@
 		++pmon->iommu_attach_count;
 		if (pmon->iommu_attach_count == 1) {
 			/* If perf. mon was enabled before we attached we do
-			 * the actual after we attach.
+			 * the actual enabling after we attach.
 			 */
-			if (pmon->enabled)
+			if (pmon->enabled && !pmon->iommu.always_on)
 				iommu_pm_on(pmon);
 		}
 		mutex_unlock(&pmon->lock);
@@ -805,9 +823,9 @@
 		mutex_lock(&pmon->lock);
 		if (pmon->iommu_attach_count == 1) {
 			/* If perf. mon is still enabled we have to disable
-			 * before we do the detach.
+			 * before we do the detach if iommu is not always on.
 			 */
-			if (pmon->enabled)
+			if (pmon->enabled && !pmon->iommu.always_on)
 				iommu_pm_off(pmon);
 		}
 		BUG_ON(pmon->iommu_attach_count == 0);
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index 802349a..71087d9 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -195,9 +195,18 @@
 static int camera_v4l2_reqbufs(struct file *filep, void *fh,
 	struct v4l2_requestbuffers *req)
 {
+	int ret;
+	struct msm_session *session;
 	struct camera_v4l2_private *sp = fh_to_private(fh);
-
-	return vb2_reqbufs(&sp->vb2_q, req);
+	struct msm_video_device *pvdev = video_drvdata(filep);
+	unsigned int session_id = pvdev->vdev->num;
+	session = msm_session_find(session_id);
+	if (WARN_ON(!session))
+		return -EIO;
+	mutex_lock(&session->lock);
+	ret = vb2_reqbufs(&sp->vb2_q, req);
+	mutex_unlock(&session->lock);
+	return ret;
 }
 
 static int camera_v4l2_querybuf(struct file *filep, void *fh,
@@ -209,17 +218,35 @@
 static int camera_v4l2_qbuf(struct file *filep, void *fh,
 	struct v4l2_buffer *pb)
 {
+	int ret;
+	struct msm_session *session;
 	struct camera_v4l2_private *sp = fh_to_private(fh);
-
-	return vb2_qbuf(&sp->vb2_q, pb);
+		struct msm_video_device *pvdev = video_drvdata(filep);
+	unsigned int session_id = pvdev->vdev->num;
+	session = msm_session_find(session_id);
+	if (WARN_ON(!session))
+		return -EIO;
+	mutex_lock(&session->lock);
+	ret = vb2_qbuf(&sp->vb2_q, pb);
+	mutex_unlock(&session->lock);
+	return ret;
 }
 
 static int camera_v4l2_dqbuf(struct file *filep, void *fh,
 	struct v4l2_buffer *pb)
 {
+	int ret;
+	struct msm_session *session;
 	struct camera_v4l2_private *sp = fh_to_private(fh);
-
-	return vb2_dqbuf(&sp->vb2_q, pb, filep->f_flags & O_NONBLOCK);
+		struct msm_video_device *pvdev = video_drvdata(filep);
+	unsigned int session_id = pvdev->vdev->num;
+	session = msm_session_find(session_id);
+	if (WARN_ON(!session))
+		return -EIO;
+	mutex_lock(&session->lock);
+	ret = vb2_dqbuf(&sp->vb2_q, pb, filep->f_flags & O_NONBLOCK);
+	mutex_unlock(&session->lock);
+	return ret;
 }
 
 static int camera_v4l2_streamon(struct file *filep, void *fh,
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index b9ca017..9f1c81a 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -30,69 +30,6 @@
 #include "msm_vb2.h"
 #include "msm_sd.h"
 
-struct msm_queue_head {
-	struct list_head list;
-	spinlock_t lock;
-	int len;
-	int max;
-};
-
-/** msm_event:
- *
- *  event sent by imaging server
- **/
-struct msm_event {
-	struct video_device *vdev;
-	atomic_t on_heap;
-};
-
-struct msm_command {
-	struct list_head list;
-	struct v4l2_event event;
-	atomic_t on_heap;
-};
-
-/** struct msm_command_ack
- *
- *  Object of command_ack_q, which is
- *  created per open operation
- *
- *  contains struct msm_command
- **/
-struct msm_command_ack {
-	struct list_head list;
-	struct msm_queue_head command_q;
-	wait_queue_head_t wait;
-	int stream_id;
-};
-
-struct msm_v4l2_subdev {
-	/* FIXME: for session close and error handling such
-	 * as daemon shutdown */
-	int    close_sequence;
-};
-
-struct msm_session {
-	struct list_head list;
-
-	/* session index */
-	unsigned int session_id;
-
-	/* event queue sent by imaging server */
-	struct msm_event event_q;
-
-	/* ACK by imaging server. Object type of
-	 * struct msm_command_ack per open,
-	 * assumption is application can send
-	 * command on every opened video node */
-	struct msm_queue_head command_ack_q;
-
-	/* real streams(either data or metadate) owned by one
-	 * session struct msm_stream */
-	struct msm_queue_head stream_q;
-	struct mutex lock;
-};
-
 static struct v4l2_device *msm_v4l2_dev;
 
 static struct msm_queue_head *msm_session_q;
@@ -248,6 +185,17 @@
 	return (ack->stream_id == *(unsigned int *)d2) ? 1 : 0;
 }
 
+
+struct msm_session *msm_session_find(unsigned int session_id)
+{
+	struct msm_session *session;
+	session = msm_queue_find(msm_session_q, struct msm_session,
+		list, __msm_queue_find_session, &session_id);
+	if (WARN_ON(!session))
+		return NULL;
+	return session;
+}
+
 int msm_create_stream(unsigned int session_id,
 	unsigned int stream_id, struct vb2_queue *q)
 {
@@ -492,7 +440,7 @@
 		list_for_each_entry(sd, &msm_v4l2_dev->subdevs, list)
 			__msm_sd_close_session_streams(sd, sd_close);
 	spin_unlock_irqrestore(&msm_v4l2_dev->lock, flags);
-
+	INIT_LIST_HEAD(&stream->queued_list);
 	return 0;
 }
 
diff --git a/drivers/media/platform/msm/camera_v2/msm.h b/drivers/media/platform/msm/camera_v2/msm.h
index 39901ad..d57cf8d 100644
--- a/drivers/media/platform/msm/camera_v2/msm.h
+++ b/drivers/media/platform/msm/camera_v2/msm.h
@@ -38,6 +38,69 @@
 	atomic_t opened;
 };
 
+struct msm_queue_head {
+	struct list_head list;
+	spinlock_t lock;
+	int len;
+	int max;
+};
+
+/** msm_event:
+ *
+ *  event sent by imaging server
+ **/
+struct msm_event {
+	struct video_device *vdev;
+	atomic_t on_heap;
+};
+
+struct msm_command {
+	struct list_head list;
+	struct v4l2_event event;
+	atomic_t on_heap;
+};
+
+/** struct msm_command_ack
+ *
+ *  Object of command_ack_q, which is
+ *  created per open operation
+ *
+ *  contains struct msm_command
+ **/
+struct msm_command_ack {
+	struct list_head list;
+	struct msm_queue_head command_q;
+	wait_queue_head_t wait;
+	int stream_id;
+};
+
+struct msm_v4l2_subdev {
+	/* FIXME: for session close and error handling such
+	 * as daemon shutdown */
+	int    close_sequence;
+};
+
+struct msm_session {
+	struct list_head list;
+
+	/* session index */
+	unsigned int session_id;
+
+	/* event queue sent by imaging server */
+	struct msm_event event_q;
+
+	/* ACK by imaging server. Object type of
+	 * struct msm_command_ack per open,
+	 * assumption is application can send
+	 * command on every opened video node */
+	struct msm_queue_head command_ack_q;
+
+	/* real streams(either data or metadate) owned by one
+	 * session struct msm_stream */
+	struct msm_queue_head stream_q;
+	struct mutex lock;
+};
+
 int msm_post_event(struct v4l2_event *event, int timeout);
 int  msm_create_session(unsigned int session, struct video_device *vdev);
 int msm_destroy_session(unsigned int session_id);
@@ -52,5 +115,5 @@
 struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id,
 	unsigned int stream_id);
 struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q);
-
+struct msm_session *msm_session_find(unsigned int session_id);
 #endif /*_MSM_H */
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
index 29262af..8fa8f8d 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
@@ -48,7 +48,6 @@
 	}
 	msm_vb2_buf = container_of(vb, struct msm_vb2_buffer, vb2_buf);
 	msm_vb2_buf->in_freeq = 0;
-	msm_vb2_buf->stream = stream;
 
 	return 0;
 }
@@ -66,7 +65,7 @@
 		return;
 	}
 
-	stream = msm_vb2->stream;
+	stream = msm_get_stream_from_vb2q(vb->vb2_queue);
 	if (!stream) {
 		pr_err("%s:%d] NULL stream", __func__, __LINE__);
 		return;
@@ -91,7 +90,7 @@
 		return -EINVAL;
 	}
 
-	stream = msm_vb2->stream;
+	stream = msm_get_stream_from_vb2q(vb->vb2_queue);
 	if (!stream) {
 		pr_err("%s:%d] NULL stream", __func__, __LINE__);
 		return -EINVAL;
@@ -122,7 +121,7 @@
 		return;
 	}
 
-	stream = msm_vb2->stream;
+	stream = msm_get_stream_from_vb2q(vb->vb2_queue);
 	if (!stream) {
 		pr_err("%s:%d] NULL stream", __func__, __LINE__);
 		return;
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
index 027d344..7082f85 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
@@ -42,7 +42,6 @@
 	struct vb2_buffer vb2_buf;
 	struct list_head list;
 	int in_freeq;
-	struct msm_stream *stream;
 };
 
 struct msm_vb2_private_data {
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 3c181fe..f458a0a 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -241,7 +241,7 @@
 static u32 get_frame_size_compressed(int plane,
 					u32 height, u32 width)
 {
-	return (width * height * 3/2)/2;
+	return (width * height * 3/2)/4;
 }
 
 struct msm_vidc_format vdec_formats[] = {
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index e011d8f..046faac 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -34,8 +34,6 @@
 #define SLIMBUS_PRESENT_TIMEOUT 100
 
 #define MAX_WCD9XXX_DEVICE	4
-#define TABLA_I2C_MODE	0x03
-#define SITAR_I2C_MODE	0x01
 #define CODEC_DT_MAX_PROP_SIZE   40
 #define WCD9XXX_I2C_GSBI_SLAVE_ID "3-000d"
 #define WCD9XXX_I2C_TOP_SLAVE_ADDR	0x0d
@@ -59,18 +57,9 @@
 	int mod_id;
 };
 
-static char *taiko_supplies[] = {
-	WCD9XXX_SUPPLY_BUCK_NAME, "cdc-vdd-tx-h", "cdc-vdd-rx-h", "cdc-vddpx-1",
-	"cdc-vdd-a-1p2v", "cdc-vddcx-1", "cdc-vddcx-2",
-};
-
-static char *tapan_supplies[] = {
-	WCD9XXX_SUPPLY_BUCK_NAME, "cdc-vdd-h", "cdc-vdd-px",
-	"cdc-vdd-a-1p2v", "cdc-vdd-cx"
-};
-
 static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
-	struct wcd9xxx_regulator *vreg, const char *vreg_name);
+				      struct wcd9xxx_regulator *vreg,
+				      const char *vreg_name, bool ondemand);
 static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
 	struct wcd9xxx_micbias_setting *micbias);
 static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev);
@@ -292,49 +281,60 @@
 	},
 };
 
-static struct wcd9xx_codec_type {
-	u8 byte[4];
-	struct mfd_cell *dev;
-	int size;
-	int num_irqs;
-	int version; /* -1 to retrive version from chip version register */
-	enum wcd9xxx_slim_slave_addr_type slim_slave_type;
-} wcd9xxx_codecs[] = {
+
+enum wcd9xxx_chipid_major {
+	TABLA_MAJOR = cpu_to_le16(0x100),
+	SITAR_MAJOR = cpu_to_le16(0x101),
+	TAIKO_MAJOR = cpu_to_le16(0x102),
+	TAPAN_MAJOR = cpu_to_le16(0x103),
+};
+
+static const struct wcd9xxx_codec_type wcd9xxx_codecs[] = {
 	{
-	 {0x2, 0x0, 0x0, 0x1}, tabla_devs, ARRAY_SIZE(tabla_devs),
-	 TABLA_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+		TABLA_MAJOR, cpu_to_le16(0x1), tabla1x_devs,
+		ARRAY_SIZE(tabla1x_devs), TABLA_NUM_IRQS, -1,
+		WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x03,
 	},
 	{
-	 {0x1, 0x0, 0x0, 0x1}, tabla1x_devs, ARRAY_SIZE(tabla1x_devs),
-	 TABLA_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
-	},
-	{ /* wcd9320 version 1 */
-	 {0x0, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs),
-	  TAIKO_NUM_IRQS, 1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
-	},
-	{ /* wcd9320 version 2 */
-	 {0x1, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs),
-	 TAIKO_NUM_IRQS, 2, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
+		TABLA_MAJOR, cpu_to_le16(0x2), tabla_devs,
+		ARRAY_SIZE(tabla_devs), TABLA_NUM_IRQS, -1,
+		WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x03
 	},
 	{
-	 {0x0, 0x0, 0x3, 0x1}, tapan_devs, ARRAY_SIZE(tapan_devs),
-	 TAPAN_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
+		/* Siter version 1 has same major chip id with Tabla */
+		TABLA_MAJOR, cpu_to_le16(0x0), sitar_devs,
+		ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
+		WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
 	},
 	{
-	 {0x1, 0x0, 0x3, 0x1}, tapan_devs, ARRAY_SIZE(tapan_devs),
-	 TAPAN_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
+		SITAR_MAJOR, cpu_to_le16(0x1), sitar_devs,
+		ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
+		WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
 	},
 	{
-	 {0x0, 0x0, 0x0, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
-	 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+		SITAR_MAJOR, cpu_to_le16(0x2), sitar_devs,
+		ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
+		WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
 	},
 	{
-	 {0x1, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
-	 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+		TAIKO_MAJOR, cpu_to_le16(0x0), taiko_devs,
+		ARRAY_SIZE(taiko_devs), TAIKO_NUM_IRQS, 1,
+		WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x01
 	},
 	{
-	 {0x2, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
-	 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+		TAIKO_MAJOR, cpu_to_le16(0x1), taiko_devs,
+		ARRAY_SIZE(taiko_devs), TAIKO_NUM_IRQS, 2,
+		WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x01
+	},
+	{
+		TAPAN_MAJOR, cpu_to_le16(0x0), tapan_devs,
+		ARRAY_SIZE(tapan_devs), TAPAN_NUM_IRQS, -1,
+		WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x03
+	},
+	{
+		TAPAN_MAJOR, cpu_to_le16(0x1), tapan_devs,
+		ARRAY_SIZE(tapan_devs), TAPAN_NUM_IRQS, -1,
+		WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x03
 	},
 };
 
@@ -384,65 +384,80 @@
 		wcd9xxx->reset_gpio = 0;
 	}
 }
-static int wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx,
-				    struct mfd_cell **wcd9xxx_dev,
-				    int *wcd9xxx_dev_size,
-				    int *wcd9xxx_dev_num_irqs)
+
+static const struct wcd9xxx_codec_type
+*wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx, u8 *version)
 {
-	int i;
-	int ret;
-	i = WCD9XXX_A_CHIP_ID_BYTE_0;
-	while (i <= WCD9XXX_A_CHIP_ID_BYTE_3) {
-		ret = wcd9xxx_reg_read(wcd9xxx, i);
-		if (ret < 0)
-			goto exit;
-		wcd9xxx->idbyte[i-WCD9XXX_A_CHIP_ID_BYTE_0] = (u8)ret;
-		pr_debug("%s: wcd9xx read = %x, byte = %x\n", __func__, ret,
-			i);
-		i++;
+	int i, rc;
+	const struct wcd9xxx_codec_type *c, *d = NULL;
+
+	rc = wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0,
+			       sizeof(wcd9xxx->id_minor),
+			       (u8 *)&wcd9xxx->id_minor);
+	if (rc < 0)
+		goto exit;
+
+	rc = wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2,
+			       sizeof(wcd9xxx->id_major),
+			       (u8 *)&wcd9xxx->id_major);
+	if (rc < 0)
+		goto exit;
+	dev_dbg(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
+		__func__, wcd9xxx->id_major, wcd9xxx->id_minor);
+
+	for (i = 0, c = &wcd9xxx_codecs[0]; i < ARRAY_SIZE(wcd9xxx_codecs);
+	     i++, c++) {
+		if (c->id_major == wcd9xxx->id_major) {
+			if (c->id_minor == wcd9xxx->id_minor) {
+				d = c;
+				dev_dbg(wcd9xxx->dev,
+					"%s: exact match %s\n", __func__,
+					d->dev->name);
+				break;
+			} else if (!d) {
+				d = c;
+			} else {
+				if ((d->id_minor < c->id_minor) ||
+				    (d->id_minor == c->id_minor &&
+				     d->version < c->version))
+					d = c;
+			}
+			dev_dbg(wcd9xxx->dev,
+				"%s: best match %s, major 0x%x, minor 0x%x\n",
+				__func__, d->dev->name, d->id_major,
+				d->id_minor);
+		}
 	}
 
-	/* Read codec version */
-	ret = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
-	if (ret < 0)
-		goto exit;
-	wcd9xxx->version = (u8)ret & 0x1F;
-	i = 0;
-	while (i < ARRAY_SIZE(wcd9xxx_codecs)) {
-		if ((wcd9xxx_codecs[i].byte[0] == wcd9xxx->idbyte[0]) &&
-		    (wcd9xxx_codecs[i].byte[1] == wcd9xxx->idbyte[1]) &&
-		    (wcd9xxx_codecs[i].byte[2] == wcd9xxx->idbyte[2]) &&
-		    (wcd9xxx_codecs[i].byte[3] == wcd9xxx->idbyte[3])) {
-			pr_info("%s: codec is %s", __func__,
-				wcd9xxx_codecs[i].dev->name);
-			*wcd9xxx_dev = wcd9xxx_codecs[i].dev;
-			*wcd9xxx_dev_size = wcd9xxx_codecs[i].size;
-			*wcd9xxx_dev_num_irqs = wcd9xxx_codecs[i].num_irqs;
-			wcd9xxx->slim_slave_type =
-			    wcd9xxx_codecs[i].slim_slave_type;
-			if (wcd9xxx_codecs[i].version > -1)
-				wcd9xxx->version = wcd9xxx_codecs[i].version;
-			break;
+	if (!d) {
+		dev_warn(wcd9xxx->dev,
+			 "%s: driver for id major 0x%x, minor 0x%x not found\n",
+			 __func__, wcd9xxx->id_major, wcd9xxx->id_minor);
+	} else {
+		if (d->version > -1) {
+			*version = d->version;
+		} else {
+			rc = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
+			if (rc < 0) {
+				d = NULL;
+				goto exit;
+			}
+			*version = (u8)rc & 0x1F;
 		}
-		i++;
+		dev_info(wcd9xxx->dev,
+			 "%s: detected %s, major 0x%x, minor 0x%x, ver 0x%x\n",
+			 __func__, d->dev->name, d->id_major, d->id_minor,
+			 *version);
 	}
-	if (*wcd9xxx_dev == NULL || *wcd9xxx_dev_size == 0)
-		ret = -ENODEV;
-	pr_info("%s: Read codec idbytes & version\n"
-		"byte_0[%08x] byte_1[%08x] byte_2[%08x]\n"
-		" byte_3[%08x] version = %x\n", __func__,
-		wcd9xxx->idbyte[0], wcd9xxx->idbyte[1],
-		wcd9xxx->idbyte[2], wcd9xxx->idbyte[3],
-		wcd9xxx->version);
 exit:
-	return ret;
+	return d;
 }
 
 static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
 {
 	int ret;
-	struct mfd_cell *wcd9xxx_dev = NULL;
-	int wcd9xxx_dev_size = 0;
+	u8 version;
+	const struct wcd9xxx_codec_type *found;
 
 	mutex_init(&wcd9xxx->io_lock);
 	mutex_init(&wcd9xxx->xfer_lock);
@@ -458,10 +473,14 @@
 
 	wcd9xxx_bring_up(wcd9xxx);
 
-	ret = wcd9xxx_check_codec_type(wcd9xxx, &wcd9xxx_dev, &wcd9xxx_dev_size,
-				       &wcd9xxx->num_irqs);
-	if (ret < 0)
+	found = wcd9xxx_check_codec_type(wcd9xxx, &version);
+	if (!found) {
+		ret = -ENODEV;
 		goto err_irq;
+	} else {
+		wcd9xxx->codec_type = found;
+		wcd9xxx->version = version;
+	}
 
 	if (wcd9xxx->irq != -1) {
 		ret = wcd9xxx_irq_init(wcd9xxx);
@@ -471,7 +490,7 @@
 		}
 	}
 
-	ret = mfd_add_devices(wcd9xxx->dev, -1, wcd9xxx_dev, wcd9xxx_dev_size,
+	ret = mfd_add_devices(wcd9xxx->dev, -1, found->dev, found->size,
 			      NULL, 0);
 	if (ret != 0) {
 		dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
@@ -605,8 +624,8 @@
 };
 #endif
 
-static int wcd9xxx_enable_supplies(struct wcd9xxx *wcd9xxx,
-				struct wcd9xxx_pdata *pdata)
+static int wcd9xxx_init_supplies(struct wcd9xxx *wcd9xxx,
+				 struct wcd9xxx_pdata *pdata)
 {
 	int ret;
 	int i;
@@ -620,7 +639,7 @@
 
 	wcd9xxx->num_of_supplies = 0;
 
-	if (ARRAY_SIZE(pdata->regulator) > MAX_REGULATOR) {
+	if (ARRAY_SIZE(pdata->regulator) > WCD9XXX_MAX_REGULATOR) {
 		pr_err("%s: Array Size out of bound\n", __func__);
 		ret = -EINVAL;
 		goto err;
@@ -642,8 +661,12 @@
 	}
 
 	for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
+		if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
+		    0)
+			continue;
 		ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
-			pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
+					    pdata->regulator[i].min_uV,
+					    pdata->regulator[i].max_uV);
 		if (ret) {
 			pr_err("%s: Setting regulator voltage failed for "
 				"regulator %s err = %d\n", __func__,
@@ -652,30 +675,19 @@
 		}
 
 		ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
-			pdata->regulator[i].optimum_uA);
+						pdata->regulator[i].optimum_uA);
 		if (ret < 0) {
 			pr_err("%s: Setting regulator optimum mode failed for "
 				"regulator %s err = %d\n", __func__,
 				wcd9xxx->supplies[i].supply, ret);
 			goto err_get;
+		} else {
+			ret = 0;
 		}
 	}
 
-	ret = regulator_bulk_enable(wcd9xxx->num_of_supplies,
-				    wcd9xxx->supplies);
-	if (ret != 0) {
-		dev_err(wcd9xxx->dev, "Failed to enable supplies: err = %d\n",
-				ret);
-		goto err_configure;
-	}
 	return ret;
 
-err_configure:
-	for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
-		regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
-			pdata->regulator[i].max_uV);
-		regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
-	}
 err_get:
 	regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
 err_supplies:
@@ -684,6 +696,33 @@
 	return ret;
 }
 
+static int wcd9xxx_enable_static_supplies(struct wcd9xxx *wcd9xxx,
+					  struct wcd9xxx_pdata *pdata)
+{
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
+		if (pdata->regulator[i].ondemand)
+			continue;
+		ret = regulator_enable(wcd9xxx->supplies[i].consumer);
+		if (ret) {
+			pr_err("%s: Failed to enable %s\n", __func__,
+			       wcd9xxx->supplies[i].supply);
+			break;
+		} else {
+			pr_debug("%s: Enabled regulator %s\n", __func__,
+				 wcd9xxx->supplies[i].supply);
+		}
+	}
+
+	while (ret && --i)
+		if (!pdata->regulator[i].ondemand)
+			regulator_disable(wcd9xxx->supplies[i].consumer);
+
+	return ret;
+}
+
 static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx,
 				     struct wcd9xxx_pdata *pdata)
 {
@@ -692,8 +731,11 @@
 	regulator_bulk_disable(wcd9xxx->num_of_supplies,
 				    wcd9xxx->supplies);
 	for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
+		if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
+		    0)
+			continue;
 		regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
-			pdata->regulator[i].max_uV);
+				      pdata->regulator[i].max_uV);
 		regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
 	}
 	regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
@@ -856,7 +898,6 @@
 	struct wcd9xxx_pdata *pdata = NULL;
 	int val = 0;
 	int ret = 0;
-	int i2c_mode = 0;
 	int wcd9xx_index = 0;
 	struct device *dev;
 
@@ -913,18 +954,26 @@
 		wcd9xxx->slim_device_bootup = true;
 		if (client->dev.of_node)
 			wcd9xxx->mclk_rate = pdata->mclk_rate;
-		ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
+
+		ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
 		if (ret) {
 			pr_err("%s: Fail to enable Codec supplies\n",
 			       __func__);
 			goto err_codec;
 		}
 
+		ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
+		if (ret) {
+			pr_err("%s: Fail to enable Codec pre-reset supplies\n",
+			       __func__);
+			goto err_codec;
+		}
 		usleep_range(5, 5);
+
 		ret = wcd9xxx_reset(wcd9xxx);
 		if (ret) {
 			pr_err("%s: Resetting Codec failed\n", __func__);
-		goto err_supplies;
+			goto err_supplies;
 		}
 
 		ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
@@ -948,18 +997,14 @@
 			goto err_device_init;
 		}
 
-		if ((wcd9xxx->idbyte[0] == 0x2) || (wcd9xxx->idbyte[0] == 0x1))
-			i2c_mode = TABLA_I2C_MODE;
-		else if (wcd9xxx->idbyte[0] == 0x0)
-			i2c_mode = SITAR_I2C_MODE;
-
 		ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
+		if (ret < 0)
+			pr_err("%s: failed to read the wcd9xxx status (%d)\n",
+			       __func__, ret);
+		if (val != wcd9xxx->codec_type->i2c_chip_status)
+			pr_err("%s: unknown chip status 0x%x\n", __func__, val);
 
-		if ((ret < 0) || (val != i2c_mode))
-			pr_err("failed to read the wcd9xxx status ret = %d\n",
-			       ret);
-
-	wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
+		wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
 
 		return ret;
 	} else
@@ -988,7 +1033,9 @@
 }
 
 static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
-	struct wcd9xxx_regulator *vreg, const char *vreg_name)
+				      struct wcd9xxx_regulator *vreg,
+				      const char *vreg_name,
+				      bool ondemand)
 {
 	int len, ret = 0;
 	const __be32 *prop;
@@ -1006,6 +1053,7 @@
 		return -ENODEV;
 	}
 	vreg->name = vreg_name;
+	vreg->ondemand = ondemand;
 
 	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
 		"qcom,%s-voltage", vreg_name);
@@ -1014,7 +1062,7 @@
 	if (!prop || (len != (2 * sizeof(__be32)))) {
 		dev_err(dev, "%s %s property\n",
 				prop ? "invalid format" : "no", prop_name);
-		return -ENODEV;
+		return -EINVAL;
 	} else {
 		vreg->min_uV = be32_to_cpup(&prop[0]);
 		vreg->max_uV = be32_to_cpup(&prop[1]);
@@ -1027,12 +1075,12 @@
 	if (ret) {
 		dev_err(dev, "Looking up %s property in node %s failed",
 				prop_name, dev->of_node->full_name);
-		return -ENODEV;
+		return -EFAULT;
 	}
 	vreg->optimum_uA = prop_val;
 
-	dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
-		vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
+	dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n", vreg->name,
+		vreg->min_uV, vreg->max_uV, vreg->optimum_uA, vreg->ondemand);
 	return 0;
 }
 
@@ -1150,40 +1198,66 @@
 static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
 {
 	struct wcd9xxx_pdata *pdata;
-	int ret, i;
-	char **codec_supplies;
-	u32 num_of_supplies = 0;
+	int ret, static_cnt, ond_cnt, idx, i;
+	const char *name = NULL;
 	u32 mclk_rate = 0;
 	u32 dmic_sample_rate = 0;
+	const char *static_prop_name = "qcom,cdc-static-supplies";
+	const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
 		dev_err(dev, "could not allocate memory for platform data\n");
 		return NULL;
 	}
-	if (!strcmp(dev_name(dev), "taiko-slim-pgd") ||
-		(!strcmp(dev_name(dev), WCD9XXX_I2C_GSBI_SLAVE_ID))) {
-		codec_supplies = taiko_supplies;
-		num_of_supplies = ARRAY_SIZE(taiko_supplies);
-	} else if (!strcmp(dev_name(dev), "tapan-slim-pgd")) {
-		codec_supplies = tapan_supplies;
-		num_of_supplies = ARRAY_SIZE(tapan_supplies);
-	} else {
-		dev_err(dev, "%s unsupported device %s\n",
-				__func__, dev_name(dev));
+
+	static_cnt = of_property_count_strings(dev->of_node, static_prop_name);
+	if (IS_ERR_VALUE(static_cnt)) {
+		dev_err(dev, "%s: Failed to get static supplies %d\n", __func__,
+			static_cnt);
 		goto err;
 	}
 
-	if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
+	/* On-demand supply list is an optional property */
+	ond_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
+	if (IS_ERR_VALUE(ond_cnt))
+		ond_cnt = 0;
+
+	BUG_ON(static_cnt <= 0 || ond_cnt < 0);
+	if ((static_cnt + ond_cnt) > ARRAY_SIZE(pdata->regulator)) {
 		dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
-		      __func__, num_of_supplies, ARRAY_SIZE(pdata->regulator));
-
+			__func__, static_cnt, ARRAY_SIZE(pdata->regulator));
 		goto err;
 	}
 
-	for (i = 0; i < num_of_supplies; i++) {
-		ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[i],
-			codec_supplies[i]);
+	for (idx = 0; idx < static_cnt; idx++) {
+		ret = of_property_read_string_index(dev->of_node,
+						    static_prop_name, idx,
+						    &name);
+		if (ret) {
+			dev_err(dev, "%s: of read string %s idx %d error %d\n",
+				__func__, static_prop_name, idx, ret);
+			goto err;
+		}
+
+		dev_dbg(dev, "%s: Found static cdc supply %s\n", __func__,
+			name);
+		ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[idx],
+						 name, false);
+		if (ret)
+			goto err;
+	}
+
+	for (i = 0; i < ond_cnt; i++, idx++) {
+		ret = of_property_read_string_index(dev->of_node, ond_prop_name,
+						    i, &name);
+		if (ret)
+			goto err;
+
+		dev_dbg(dev, "%s: Found on-demand cdc supply %s\n", __func__,
+			name);
+		ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[idx],
+						 name, true);
 		if (ret)
 			goto err;
 	}
@@ -1325,9 +1399,17 @@
 	wcd9xxx->mclk_rate = pdata->mclk_rate;
 	wcd9xxx->slim_device_bootup = true;
 
-	ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
-	if (ret)
+	ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
+	if (ret) {
+		pr_err("%s: Fail to init Codec supplies %d\n", __func__, ret);
 		goto err_codec;
+	}
+	ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
+	if (ret) {
+		pr_err("%s: Fail to enable Codec pre-reset supplies\n",
+		       __func__);
+		goto err_codec;
+	}
 	usleep_range(5, 5);
 
 	ret = wcd9xxx_reset(wcd9xxx);
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index f2c3959..356aecb 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.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
@@ -218,7 +218,8 @@
 
 static int wcd9xxx_num_irq_regs(const struct wcd9xxx *wcd9xxx)
 {
-	return (wcd9xxx->num_irqs / 8) + ((wcd9xxx->num_irqs % 8) ? 1 : 0);
+	return (wcd9xxx->codec_type->num_irqs / 8) +
+		((wcd9xxx->codec_type->num_irqs % 8) ? 1 : 0);
 }
 
 static irqreturn_t wcd9xxx_irq_thread(int irq, void *data)
@@ -266,7 +267,8 @@
 		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i))
 			wcd9xxx_irq_dispatch(wcd9xxx, i);
 	}
-	for (i = WCD9XXX_IRQ_BG_PRECHARGE; i < wcd9xxx->num_irqs; i++) {
+	for (i = WCD9XXX_IRQ_BG_PRECHARGE; i < wcd9xxx->codec_type->num_irqs;
+	     i++) {
 		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i))
 			wcd9xxx_irq_dispatch(wcd9xxx, i);
 	}
@@ -301,7 +303,7 @@
 
 	pr_debug("%s: enter\n", __func__);
 
-	for (irq = 0; irq < wcd9xxx->num_irqs; irq++) {
+	for (irq = 0; irq < wcd9xxx->codec_type->num_irqs; irq++) {
 		/* Map OF irq */
 		virq = wcd9xxx_map_irq(wcd9xxx, irq);
 		pr_debug("%s: irq %d -> %d\n", __func__, irq, virq);
@@ -365,7 +367,7 @@
 
 	/* mask all the interrupts */
 	memset(irq_level, 0, wcd9xxx_num_irq_regs(wcd9xxx));
-	for (i = 0; i < wcd9xxx->num_irqs; i++) {
+	for (i = 0; i < wcd9xxx->codec_type->num_irqs; i++) {
 		wcd9xxx->irq_masks_cur[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
 		wcd9xxx->irq_masks_cache[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
 		irq_level[BIT_BYTE(i)] |=
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index f2d71b6..81262b58 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -31,7 +31,8 @@
 
 static int wcd9xxx_configure_ports(struct wcd9xxx *wcd9xxx)
 {
-	if (wcd9xxx->slim_slave_type == WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA) {
+	if (wcd9xxx->codec_type->slim_slave_type ==
+	    WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA) {
 		sh_ch.rx_port_ch_reg_base = 0x180;
 		sh_ch.port_rx_cfg_reg_base = 0x040;
 		sh_ch.port_tx_cfg_reg_base = 0x040;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 188ac32..05a15b1 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1,5 +1,3 @@
-
-
 /*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
  *
  * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
@@ -53,6 +51,7 @@
 #define QSEE_VERSION_01			0x401000
 #define QSEE_VERSION_02			0x402000
 #define QSEE_VERSION_03			0x403000
+#define QSEE_VERSION_04			0x404000
 
 
 #define QSEOS_CHECK_VERSION_CMD		0x00001803
@@ -62,6 +61,12 @@
 #define QSEECOM_MAX_SG_ENTRY	512
 #define QSEECOM_DISK_ENCRYTPION_KEY_ID 0
 
+/* Save partition image hash for authentication check */
+#define	SCM_SAVE_PARTITION_HASH_ID	0x01
+
+/* Check if enterprise security is activate */
+#define	SCM_IS_ACTIVATED_ID		0x02
+
 enum qseecom_clk_definitions {
 	CLK_DFAB = 0,
 	CLK_SFPB,
@@ -74,6 +79,11 @@
 	QSEECOM_GENERIC,
 };
 
+enum qseecom_ce_hw_instance {
+	CLK_QSEE = 0,
+	CLK_CE_DRV,
+};
+
 static struct class *driver_class;
 static dev_t qseecom_device_no;
 static struct cdev qseecom_cdev;
@@ -85,6 +95,7 @@
 
 static DEFINE_MUTEX(qsee_bw_mutex);
 static DEFINE_MUTEX(app_access_lock);
+static DEFINE_MUTEX(clk_access_lock);
 
 struct qseecom_registered_listener_list {
 	struct list_head                 list;
@@ -117,10 +128,12 @@
 };
 
 struct qseecom_clk {
+	enum qseecom_ce_hw_instance instance;
 	struct clk *ce_core_clk;
 	struct clk *ce_clk;
 	struct clk *ce_core_src_clk;
 	struct clk *ce_bus_clk;
+	uint32_t clk_access_cnt;
 };
 
 struct qseecom_control {
@@ -148,6 +161,7 @@
 
 	uint32_t qsee_perf_client;
 	struct qseecom_clk qsee;
+	struct qseecom_clk ce_drv;
 };
 
 struct qseecom_client_handle {
@@ -157,8 +171,6 @@
 	uint32_t user_virt_sb_base;
 	size_t sb_length;
 	struct ion_handle *ihandle;		/* Retrieve phy addr */
-	bool  perf_enabled;
-	bool  fast_load_enabled;
 };
 
 struct qseecom_listener_handle {
@@ -177,6 +189,8 @@
 	int               abort;
 	wait_queue_head_t abort_wq;
 	atomic_t          ioctl_count;
+	bool  perf_enabled;
+	bool  fast_load_enabled;
 };
 
 enum qseecom_set_clear_key_flag {
@@ -1789,9 +1803,9 @@
 		pr_err("Unable to find the handle, exiting\n");
 	else
 		ret = qseecom_unload_app(data);
-	if (data->client.fast_load_enabled == true)
+	if (data->fast_load_enabled == true)
 		qsee_disable_clock_vote(data, CLK_SFPB);
-	if (data->client.perf_enabled == true)
+	if (data->perf_enabled == true)
 		qsee_disable_clock_vote(data, CLK_DFAB);
 	if (ret == 0) {
 		kzfree(data);
@@ -1891,12 +1905,23 @@
 	return 0;
 }
 
-static int __qseecom_enable_clk(void)
+static int __qseecom_enable_clk(enum qseecom_ce_hw_instance ce)
 {
 	int rc = 0;
 	struct qseecom_clk *qclk;
 
+	if (ce == CLK_QSEE)
 		qclk = &qseecom.qsee;
+	else
+		qclk = &qseecom.ce_drv;
+
+	mutex_lock(&clk_access_lock);
+	if (qclk->clk_access_cnt > 0) {
+		qclk->clk_access_cnt++;
+		mutex_unlock(&clk_access_lock);
+		return rc;
+	}
+
 	/* Enable CE core clk */
 	rc = clk_prepare_enable(qclk->ce_core_clk);
 	if (rc) {
@@ -1915,6 +1940,8 @@
 		pr_err("Unable to enable/prepare CE bus clk\n");
 		goto ce_bus_clk_err;
 	}
+	qclk->clk_access_cnt++;
+	mutex_unlock(&clk_access_lock);
 	return 0;
 
 ce_bus_clk_err:
@@ -1922,20 +1949,30 @@
 ce_clk_err:
 	clk_disable_unprepare(qclk->ce_core_clk);
 err:
+	mutex_unlock(&clk_access_lock);
 	return -EIO;
 }
 
-static void __qseecom_disable_clk(void)
+static void __qseecom_disable_clk(enum qseecom_ce_hw_instance ce)
 {
 	struct qseecom_clk *qclk;
 
-	qclk = &qseecom.qsee;
-	if (qclk->ce_clk != NULL)
-		clk_disable_unprepare(qclk->ce_clk);
-	if (qclk->ce_core_clk != NULL)
-		clk_disable_unprepare(qclk->ce_core_clk);
-	if (qclk->ce_bus_clk != NULL)
-		clk_disable_unprepare(qclk->ce_bus_clk);
+	if (ce == CLK_QSEE)
+		qclk = &qseecom.qsee;
+	else
+		qclk = &qseecom.ce_drv;
+
+	mutex_lock(&clk_access_lock);
+	if (qclk->clk_access_cnt == 1) {
+		if (qclk->ce_clk != NULL)
+			clk_disable_unprepare(qclk->ce_clk);
+		if (qclk->ce_core_clk != NULL)
+			clk_disable_unprepare(qclk->ce_core_clk);
+		if (qclk->ce_bus_clk != NULL)
+			clk_disable_unprepare(qclk->ce_bus_clk);
+	}
+	qclk->clk_access_cnt--;
+	mutex_unlock(&clk_access_lock);
 }
 
 static int qsee_vote_for_clock(struct qseecom_dev_handle *data,
@@ -1957,14 +1994,14 @@
 					qseecom.qsee_perf_client, 3);
 			else {
 				if (qclk->ce_core_src_clk != NULL)
-					ret = __qseecom_enable_clk();
+					ret = __qseecom_enable_clk(CLK_QSEE);
 				if (!ret) {
 					ret =
 					msm_bus_scale_client_update_request(
 						qseecom.qsee_perf_client, 1);
 					if ((ret) &&
 						(qclk->ce_core_src_clk != NULL))
-						__qseecom_disable_clk();
+						__qseecom_disable_clk(CLK_QSEE);
 				}
 			}
 			if (ret)
@@ -1972,11 +2009,11 @@
 								ret);
 			else {
 				qseecom.qsee_bw_count++;
-				data->client.perf_enabled = true;
+				data->perf_enabled = true;
 			}
 		} else {
 			qseecom.qsee_bw_count++;
-			data->client.perf_enabled = true;
+			data->perf_enabled = true;
 		}
 		mutex_unlock(&qsee_bw_mutex);
 		break;
@@ -1988,14 +2025,14 @@
 					qseecom.qsee_perf_client, 3);
 			else {
 				if (qclk->ce_core_src_clk != NULL)
-					ret = __qseecom_enable_clk();
+					ret = __qseecom_enable_clk(CLK_QSEE);
 				if (!ret) {
 					ret =
 					msm_bus_scale_client_update_request(
 						qseecom.qsee_perf_client, 2);
 					if ((ret) &&
 						(qclk->ce_core_src_clk != NULL))
-						__qseecom_disable_clk();
+						__qseecom_disable_clk(CLK_QSEE);
 				}
 			}
 
@@ -2004,11 +2041,11 @@
 								ret);
 			else {
 				qseecom.qsee_sfpb_bw_count++;
-				data->client.fast_load_enabled = true;
+				data->fast_load_enabled = true;
 			}
 		} else {
 			qseecom.qsee_sfpb_bw_count++;
-			data->client.fast_load_enabled = true;
+			data->fast_load_enabled = true;
 		}
 		mutex_unlock(&qsee_bw_mutex);
 		break;
@@ -2046,18 +2083,18 @@
 				ret = msm_bus_scale_client_update_request(
 						qseecom.qsee_perf_client, 0);
 				if ((!ret) && (qclk->ce_core_src_clk != NULL))
-					__qseecom_disable_clk();
+					__qseecom_disable_clk(CLK_QSEE);
 			}
 			if (ret)
 				pr_err("SFPB Bandwidth req fail (%d)\n",
 								ret);
 			else {
 				qseecom.qsee_bw_count--;
-				data->client.perf_enabled = false;
+				data->perf_enabled = false;
 			}
 		} else {
 			qseecom.qsee_bw_count--;
-			data->client.perf_enabled = false;
+			data->perf_enabled = false;
 		}
 		mutex_unlock(&qsee_bw_mutex);
 		break;
@@ -2076,18 +2113,18 @@
 				ret = msm_bus_scale_client_update_request(
 						qseecom.qsee_perf_client, 0);
 				if ((!ret) && (qclk->ce_core_src_clk != NULL))
-					__qseecom_disable_clk();
+					__qseecom_disable_clk(CLK_QSEE);
 			}
 			if (ret)
 				pr_err("SFPB Bandwidth req fail (%d)\n",
 								ret);
 			else {
 				qseecom.qsee_sfpb_bw_count--;
-				data->client.fast_load_enabled = false;
+				data->fast_load_enabled = false;
 			}
 		} else {
 			qseecom.qsee_sfpb_bw_count--;
-			data->client.fast_load_enabled = false;
+			data->fast_load_enabled = false;
 		}
 		mutex_unlock(&qsee_bw_mutex);
 		break;
@@ -2345,11 +2382,13 @@
 	memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
 	ireq.flags = flags;
 
+	__qseecom_enable_clk(CLK_QSEE);
 	ret = scm_call(SCM_SVC_CRYPTO, QSEOS_GENERATE_KEY,
 				&ireq, sizeof(struct qseecom_key_generate_ireq),
 				&resp, sizeof(resp));
 	if (ret) {
 		pr_err("scm call to generate key failed : %d\n", ret);
+		__qseecom_disable_clk(CLK_QSEE);
 		return ret;
 	}
 
@@ -2367,6 +2406,7 @@
 		ret = -EINVAL;
 		break;
 	}
+	__qseecom_disable_clk(CLK_QSEE);
 	return ret;
 }
 
@@ -2386,11 +2426,13 @@
 	memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
 	ireq.flags = flags;
 
+	__qseecom_enable_clk(CLK_QSEE);
 	ret = scm_call(SCM_SVC_CRYPTO, QSEOS_DELETE_KEY,
 				&ireq, sizeof(struct qseecom_key_delete_ireq),
 				&resp, sizeof(struct qseecom_command_scm_resp));
 	if (ret) {
 		pr_err("scm call to delete key failed : %d\n", ret);
+		__qseecom_disable_clk(CLK_QSEE);
 		return ret;
 	}
 
@@ -2409,6 +2451,7 @@
 		ret = -EINVAL;
 		break;
 	}
+	__qseecom_disable_clk(CLK_QSEE);
 	return ret;
 }
 
@@ -2424,6 +2467,12 @@
 			pr_err("Error:: unsupported usage %d\n", usage);
 			return -EFAULT;
 	}
+
+	if (qseecom.qsee.instance == qseecom.ce_drv.instance)
+		__qseecom_enable_clk(CLK_QSEE);
+	else
+		__qseecom_enable_clk(CLK_CE_DRV);
+
 	memcpy(ireq.key_id, set_key_para->key_id, QSEECOM_KEY_ID_SIZE);
 	ireq.ce = set_key_para->ce_hw;
 	ireq.pipe = set_key_para->pipe;
@@ -2459,6 +2508,11 @@
 		break;
 	}
 
+	if (qseecom.qsee.instance == qseecom.ce_drv.instance)
+		__qseecom_disable_clk(CLK_QSEE);
+	else
+		__qseecom_disable_clk(CLK_CE_DRV);
+
 	return ret;
 }
 
@@ -2570,6 +2624,70 @@
 	return ret;
 }
 
+static int qseecom_is_es_activated(void __user *argp)
+{
+	struct qseecom_is_es_activated_req req;
+	int ret;
+	int resp_buf;
+
+	if (qseecom.qsee_version < QSEE_VERSION_04) {
+		pr_err("invalid qsee version");
+		return -ENODEV;
+	}
+
+	if (argp == NULL) {
+		pr_err("arg is null");
+		return -EINVAL;
+	}
+
+	ret = scm_call(SCM_SVC_ES, SCM_IS_ACTIVATED_ID, NULL, 0,
+		       (void *) &resp_buf, sizeof(resp_buf));
+	if (ret) {
+		pr_err("scm_call failed");
+		return ret;
+	}
+
+	req.is_activated = resp_buf;
+	ret = copy_to_user(argp, &req, sizeof(req));
+	if (ret) {
+		pr_err("copy_to_user failed");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int qseecom_save_partition_hash(void __user *argp)
+{
+	struct qseecom_save_partition_hash_req req;
+	int ret;
+
+	if (qseecom.qsee_version < QSEE_VERSION_04) {
+		pr_err("invalid qsee version ");
+		return -ENODEV;
+	}
+
+	if (argp == NULL) {
+		pr_err("arg is null");
+		return -EINVAL;
+	}
+
+	ret = copy_from_user(&req, argp, sizeof(req));
+	if (ret) {
+		pr_err("copy_from_user failed");
+		return ret;
+	}
+
+	ret = scm_call(SCM_SVC_ES, SCM_SAVE_PARTITION_HASH_ID,
+		       (void *) &req, sizeof(req), NULL, 0);
+	if (ret) {
+		pr_err("scm_call failed");
+		return ret;
+	}
+
+	return 0;
+}
+
 static long qseecom_ioctl(struct file *file, unsigned cmd,
 		unsigned long arg)
 {
@@ -2782,6 +2900,24 @@
 		mutex_unlock(&app_access_lock);
 		break;
 	}
+	case QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ: {
+		data->released = true;
+		mutex_lock(&app_access_lock);
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_save_partition_hash(argp);
+		atomic_dec(&data->ioctl_count);
+		mutex_unlock(&app_access_lock);
+		break;
+	}
+	case QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ: {
+		data->released = true;
+		mutex_lock(&app_access_lock);
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_is_es_activated(argp);
+		atomic_dec(&data->ioctl_count);
+		mutex_unlock(&app_access_lock);
+		break;
+	}
 	default:
 		return -EINVAL;
 	}
@@ -2853,9 +2989,9 @@
 		}
 	}
 
-	if (data->client.fast_load_enabled == true)
+	if (data->fast_load_enabled == true)
 		qsee_disable_clock_vote(data, CLK_SFPB);
-	if (data->client.perf_enabled == true)
+	if (data->perf_enabled == true)
 		qsee_disable_clock_vote(data, CLK_DFAB);
 
 	if (qseecom.qseos_version == QSEOS_VERSION_13) {
@@ -2877,18 +3013,43 @@
 		.release = qseecom_release
 };
 
-static int __qseecom_init_clk(void)
+static int __qseecom_init_clk(enum qseecom_ce_hw_instance ce)
 {
 	int rc = 0;
 	struct device *pdev;
 	struct qseecom_clk *qclk;
+	char *core_clk_src = NULL;
+	char *core_clk = NULL;
+	char *iface_clk = NULL;
+	char *bus_clk = NULL;
 
-	qclk = &qseecom.qsee;
-
+	switch (ce) {
+	case CLK_QSEE: {
+		core_clk_src = "core_clk_src";
+		core_clk = "core_clk";
+		iface_clk = "iface_clk";
+		bus_clk = "bus_clk";
+		qclk = &qseecom.qsee;
+		qclk->instance = CLK_QSEE;
+		break;
+	};
+	case CLK_CE_DRV: {
+		core_clk_src = "ce_drv_core_clk_src";
+		core_clk = "ce_drv_core_clk";
+		iface_clk = "ce_drv_iface_clk";
+		bus_clk = "ce_drv_bus_clk";
+		qclk = &qseecom.ce_drv;
+		qclk->instance = CLK_CE_DRV;
+		break;
+	};
+	default:
+		pr_err("Invalid ce hw instance: %d!\n", ce);
+		return -EIO;
+	}
 	pdev = qseecom.pdev;
-	/* Get CE3 src core clk. */
 
-	qclk->ce_core_src_clk = clk_get(pdev, "core_clk_src");
+	/* Get CE3 src core clk. */
+	qclk->ce_core_src_clk = clk_get(pdev, core_clk_src);
 	if (!IS_ERR(qclk->ce_core_src_clk)) {
 		/* Set the core src clk @100Mhz */
 		rc = clk_set_rate(qclk->ce_core_src_clk, QSEE_CE_CLK_100MHZ);
@@ -2903,7 +3064,7 @@
 	}
 
 	/* Get CE core clk */
-	qclk->ce_core_clk = clk_get(pdev, "core_clk");
+	qclk->ce_core_clk = clk_get(pdev, core_clk);
 	if (IS_ERR(qclk->ce_core_clk)) {
 		rc = PTR_ERR(qclk->ce_core_clk);
 		pr_err("Unable to get CE core clk\n");
@@ -2913,7 +3074,7 @@
 	}
 
 	/* Get CE Interface clk */
-	qclk->ce_clk = clk_get(pdev, "iface_clk");
+	qclk->ce_clk = clk_get(pdev, iface_clk);
 	if (IS_ERR(qclk->ce_clk)) {
 		rc = PTR_ERR(qclk->ce_clk);
 		pr_err("Unable to get CE interface clk\n");
@@ -2924,7 +3085,7 @@
 	}
 
 	/* Get CE AXI clk */
-	qclk->ce_bus_clk = clk_get(pdev, "bus_clk");
+	qclk->ce_bus_clk = clk_get(pdev, bus_clk);
 	if (IS_ERR(qclk->ce_bus_clk)) {
 		rc = PTR_ERR(qclk->ce_bus_clk);
 		pr_err("Unable to get CE BUS interface clk\n");
@@ -2937,11 +3098,14 @@
 	return rc;
 }
 
-static void __qseecom_deinit_clk(void)
+static void __qseecom_deinit_clk(enum qseecom_ce_hw_instance ce)
 {
 	struct qseecom_clk *qclk;
 
-	qclk = &qseecom.qsee;
+	if (ce == CLK_QSEE)
+		qclk = &qseecom.qsee;
+	else
+		qclk = &qseecom.ce_drv;
 
 	if (qclk->ce_clk != NULL) {
 		clk_put(qclk->ce_clk);
@@ -2979,6 +3143,11 @@
 	qseecom.qsee.ce_core_src_clk = NULL;
 	qseecom.qsee.ce_bus_clk = NULL;
 
+	qseecom.ce_drv.ce_core_clk = NULL;
+	qseecom.ce_drv.ce_clk = NULL;
+	qseecom.ce_drv.ce_core_src_clk = NULL;
+	qseecom.ce_drv.ce_bus_clk = NULL;
+
 	rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV);
 	if (rc < 0) {
 		pr_err("alloc_chrdev_region failed %d\n", rc);
@@ -3053,6 +3222,7 @@
 
 	/* register client for bus scaling */
 	if (pdev->dev.of_node) {
+
 		if (of_property_read_u32((&pdev->dev)->of_node,
 				"qcom,disk-encrypt-pipe-pair",
 				&qseecom.ce_info.disk_encrypt_pipe)) {
@@ -3089,10 +3259,29 @@
 			qseecom.ce_info.hlos_ce_hw_instance);
 		}
 
-		ret = __qseecom_init_clk();
+		qseecom.qsee.instance = qseecom.ce_info.qsee_ce_hw_instance;
+		qseecom.ce_drv.instance = qseecom.ce_info.hlos_ce_hw_instance;
+
+		ret = __qseecom_init_clk(CLK_QSEE);
 		if (ret)
 			goto err;
 
+		if (qseecom.qsee.instance != qseecom.ce_drv.instance) {
+			ret = __qseecom_init_clk(CLK_CE_DRV);
+			if (ret) {
+				__qseecom_deinit_clk(CLK_QSEE);
+				goto err;
+			}
+		} else {
+			struct qseecom_clk *qclk;
+
+			qclk = &qseecom.qsee;
+			qseecom.ce_drv.ce_core_clk = qclk->ce_core_clk;
+			qseecom.ce_drv.ce_clk = qclk->ce_clk;
+			qseecom.ce_drv.ce_core_src_clk = qclk->ce_core_src_clk;
+			qseecom.ce_drv.ce_bus_clk = qclk->ce_bus_clk;
+		}
+
 		qseecom_platform_support = (struct msm_bus_scale_pdata *)
 						msm_bus_cl_get_pdata(pdev);
 		if (qseecom.qsee_version >= (QSEE_VERSION_02)) {
@@ -3203,9 +3392,11 @@
 		msm_bus_scale_client_update_request(qseecom.qsee_perf_client,
 									0);
 	/* register client for bus scaling */
-	if (pdev->dev.of_node)
-		__qseecom_deinit_clk();
-
+	if (pdev->dev.of_node) {
+		__qseecom_deinit_clk(CLK_QSEE);
+		if (qseecom.qsee.instance != qseecom.ce_drv.instance)
+			__qseecom_deinit_clk(CLK_CE_DRV);
+	}
 	return ret;
 };
 
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 6b392b9..a27353f 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2188,6 +2188,8 @@
 	host->quirks2 |= SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK;
 	host->quirks2 |= SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING;
 	host->quirks2 |= SDHCI_QUIRK2_USE_MAX_DISCARD_SIZE;
+	host->quirks2 |= SDHCI_QUIRK2_IGNORE_DATATOUT_FOR_R1BCMD;
+	host->quirks2 |= SDHCI_QUIRK2_BROKEN_PRESET_VALUE;
 
 	host_version = readl_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
 	dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index bd9a960..c9b7d75 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2089,6 +2089,9 @@
 	if (host->version < SDHCI_SPEC_300)
 		return;
 
+	if (host->quirks2 & SDHCI_QUIRK2_BROKEN_PRESET_VALUE)
+		return;
+
 	spin_lock_irqsave(&host->lock, flags);
 
 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
@@ -2363,7 +2366,6 @@
 		sdhci_finish_command(host);
 }
 
-#ifdef CONFIG_MMC_DEBUG
 static void sdhci_show_adma_error(struct sdhci_host *host)
 {
 	const char *name = mmc_hostname(host->mmc);
@@ -2379,7 +2381,7 @@
 		len = (__le16 *)(desc + 2);
 		attr = *desc;
 
-		DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
+		pr_info("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
 		    name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr);
 
 		desc += 8;
@@ -2388,9 +2390,6 @@
 			break;
 	}
 }
-#else
-static void sdhci_show_adma_error(struct sdhci_host *host) { }
-#endif
 
 static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
 {
@@ -2420,6 +2419,9 @@
 				sdhci_finish_command(host);
 				return;
 			}
+			if (host->quirks2 &
+				SDHCI_QUIRK2_IGNORE_DATATOUT_FOR_R1BCMD)
+				return;
 		}
 
 		pr_err("%s: Got data interrupt 0x%08x even "
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index db7f7f0..5cc5d46 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -41,6 +41,7 @@
 #define IPA_DMA_POOL_SIZE (512)
 #define IPA_DMA_POOL_ALIGNMENT (4)
 #define IPA_DMA_POOL_BOUNDARY (1024)
+#define IPA_NUM_DESC_PER_SW_TX (2)
 #define IPA_ROUTING_RULE_BYTE_SIZE (4)
 #define IPA_BAM_CNFG_BITS_VAL (0x7FFFE004)
 
@@ -1761,15 +1762,20 @@
 	 * This is an issue with IPA HW v1.0 only.
 	 */
 	if (ipa_ctx->ipa_hw_type == IPA_HW_v1_0) {
-		ipa_ctx->one_kb_no_straddle_pool = dma_pool_create("ipa_1k",
+		ipa_ctx->dma_pool = dma_pool_create("ipa_1k",
 				NULL,
 				IPA_DMA_POOL_SIZE, IPA_DMA_POOL_ALIGNMENT,
 				IPA_DMA_POOL_BOUNDARY);
-		if (!ipa_ctx->one_kb_no_straddle_pool) {
-			IPAERR("cannot setup 1kb alloc DMA pool.\n");
-			result = -ENOMEM;
-			goto fail_dma_pool;
-		}
+	} else {
+		ipa_ctx->dma_pool = dma_pool_create("ipa_tx", NULL,
+			IPA_NUM_DESC_PER_SW_TX * sizeof(struct sps_iovec),
+			0, 0);
+	}
+
+	if (!ipa_ctx->dma_pool) {
+		IPAERR("cannot alloc DMA pool.\n");
+		result = -ENOMEM;
+		goto fail_dma_pool;
 	}
 
 	ipa_ctx->glob_flt_tbl[IPA_IP_v4].in_sys = !ipa_ctx->ip4_flt_tbl_lcl;
@@ -1976,7 +1982,7 @@
 	 * DMA pool need to be released only for IPA HW v1.0 only.
 	 */
 	if (ipa_ctx->ipa_hw_type == IPA_HW_v1_0)
-		dma_pool_destroy(ipa_ctx->one_kb_no_straddle_pool);
+		dma_pool_destroy(ipa_ctx->dma_pool);
 fail_dma_pool:
 	kmem_cache_destroy(ipa_ctx->tree_node_cache);
 fail_tree_node_cache:
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index 5f7f3d9..2555c6b 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -42,7 +42,7 @@
  *   the order for sent packet is the same as expected
  * - delete all the tx packet descriptors from the system
  *   pipe context (not needed anymore)
- * - return the tx buffer back to one_kb_no_straddle_pool
+ * - return the tx buffer back to dma_pool
  */
 void ipa_wq_write_done(struct work_struct *work)
 {
@@ -80,7 +80,7 @@
 		list_del(&tx_pkt->link);
 		spin_unlock_irqrestore(&tx_pkt->sys->spinlock, irq_flags);
 		if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0)) {
-			dma_pool_free(ipa_ctx->one_kb_no_straddle_pool,
+			dma_pool_free(ipa_ctx->dma_pool,
 					tx_pkt->bounce,
 					tx_pkt->mem.phys_base);
 		} else {
@@ -97,7 +97,7 @@
 	}
 
 	if (mult.phys_base)
-		dma_free_coherent(NULL, mult.size, mult.base, mult.phys_base);
+		dma_pool_free(ipa_ctx->dma_pool, mult.base, mult.phys_base);
 }
 
 /**
@@ -144,7 +144,7 @@
 		 * does not cross a 1KB boundary
 		 */
 		tx_pkt->bounce = dma_pool_alloc(
-					ipa_ctx->one_kb_no_straddle_pool,
+					ipa_ctx->dma_pool,
 					mem_flag, &dma_address);
 		if (!tx_pkt->bounce) {
 			dma_address = 0;
@@ -208,7 +208,7 @@
 	list_del(&tx_pkt->link);
 	spin_unlock_irqrestore(&sys->spinlock, irq_flags);
 	if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
-		dma_pool_free(ipa_ctx->one_kb_no_straddle_pool, tx_pkt->bounce,
+		dma_pool_free(ipa_ctx->dma_pool, tx_pkt->bounce,
 				dma_address);
 	else
 		dma_unmap_single(NULL, dma_address, desc->len, DMA_TO_DEVICE);
@@ -259,7 +259,7 @@
 	if (unlikely(!in_atomic))
 		mem_flag = GFP_KERNEL;
 
-	transfer.iovec = dma_alloc_coherent(NULL, size, &dma_addr, mem_flag);
+	transfer.iovec = dma_pool_alloc(ipa_ctx->dma_pool, mem_flag, &dma_addr);
 	transfer.iovec_phys = dma_addr;
 	transfer.iovec_count = num_desc;
 	spin_lock_irqsave(&sys->spinlock, irq_flags);
@@ -306,7 +306,7 @@
 			 * packet does not cross a 1KB boundary
 			 */
 			tx_pkt->bounce =
-			   dma_pool_alloc(ipa_ctx->one_kb_no_straddle_pool,
+			   dma_pool_alloc(ipa_ctx->dma_pool,
 					   mem_flag,
 					   &tx_pkt->mem.phys_base);
 			if (!tx_pkt->bounce) {
@@ -377,7 +377,7 @@
 		next_pkt = list_next_entry(tx_pkt, link);
 		list_del(&tx_pkt->link);
 		if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
-			dma_pool_free(ipa_ctx->one_kb_no_straddle_pool,
+			dma_pool_free(ipa_ctx->dma_pool,
 					tx_pkt->bounce,
 					tx_pkt->mem.phys_base);
 		else
@@ -392,7 +392,7 @@
 		if (fail_dma_wrap)
 			kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
 	if (transfer.iovec_phys)
-		dma_free_coherent(NULL, size, transfer.iovec,
+		dma_pool_free(ipa_ctx->dma_pool, transfer.iovec,
 				  transfer.iovec_phys);
 failure_coherent:
 	spin_unlock_irqrestore(&sys->spinlock, irq_flags);
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index ca5740d..cb67514 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -585,7 +585,7 @@
  * @ip6_flt_tbl_lcl: where ip6 flt tables reside 1-local; 0-system
  * @empty_rt_tbl_mem: empty routing tables memory
  * @pipe_mem_pool: pipe memory pool
- * @one_kb_no_straddle_pool: one kb no straddle pool
+ * @dma_pool: special purpose DMA pool
  * @ipa_hw_type: type of IPA HW type (e.g. IPA 1.0, IPA 1.1 etc')
  * @ipa_hw_mode: mode of IPA HW mode (e.g. Normal, Virtual or over PCIe)
  *
@@ -643,7 +643,7 @@
 	bool ip6_flt_tbl_lcl;
 	struct ipa_mem_buffer empty_rt_tbl_mem;
 	struct gen_pool *pipe_mem_pool;
-	struct dma_pool *one_kb_no_straddle_pool;
+	struct dma_pool *dma_pool;
 	atomic_t ipa_active_clients;
 	u32 clnt_hdl_cmd;
 	u32 clnt_hdl_data_in;
diff --git a/drivers/platform/msm/ipa/ipa_intf.c b/drivers/platform/msm/ipa/ipa_intf.c
index 0f41d2c..5ee1929 100644
--- a/drivers/platform/msm/ipa/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_intf.c
@@ -432,6 +432,7 @@
 			}
 			IPA_STATS_INC_CNT(
 				ipa_ctx->stats.msg_r[msg->meta.msg_type]);
+			kfree(msg);
 		}
 
 		ret = -EAGAIN;
diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c
index 1d88280..fc5f668 100644
--- a/drivers/platform/msm/ipa/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_rt.c
@@ -505,6 +505,8 @@
 			IPAERR("failed to add to tree\n");
 			WARN_ON(1);
 		}
+	} else {
+		kmem_cache_free(ipa_ctx->tree_node_cache, node);
 	}
 
 	return entry;
diff --git a/drivers/platform/msm/qpnp-pwm.c b/drivers/platform/msm/qpnp-pwm.c
index 1729b49..52c523e 100644
--- a/drivers/platform/msm/qpnp-pwm.c
+++ b/drivers/platform/msm/qpnp-pwm.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
@@ -463,7 +463,7 @@
 	int			i, pwm_size, rc = 0;
 	int			burst_size = SPMI_MAX_BUF_LEN;
 	int			list_len = lut->list_len << 1;
-	int			offset = lut->lo_index << 1;
+	int			offset = (lut->lo_index << 1) - 2;
 
 	pwm_size = QPNP_GET_PWM_SIZE(
 			chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]) &
@@ -1024,8 +1024,8 @@
 		raw_lut = 1;
 
 	lut_config->list_len = len;
-	lut_config->lo_index = start_idx;
-	lut_config->hi_index = start_idx + len - 1;
+	lut_config->lo_index = start_idx + 1;
+	lut_config->hi_index = start_idx + len;
 
 	rc = qpnp_lpg_change_table(pwm, duty_pct, raw_lut);
 	if (rc) {
@@ -1041,13 +1041,13 @@
 
 	QPNP_SET_PAUSE_CNT(lut_config->lut_pause_lo_cnt,
 			lut_params.lut_pause_lo, ramp_step_ms);
-	if (lut_config->lut_pause_lo_cnt > PM_PWM_LUT_PAUSE_MAX)
-		lut_config->lut_pause_lo_cnt = PM_PWM_LUT_PAUSE_MAX;
+	if (lut_config->lut_pause_lo_cnt > PM_PWM_MAX_PAUSE_CNT)
+		lut_config->lut_pause_lo_cnt = PM_PWM_MAX_PAUSE_CNT;
 
 	QPNP_SET_PAUSE_CNT(lut_config->lut_pause_hi_cnt,
 			lut_params.lut_pause_hi, ramp_step_ms);
-	if (lut_config->lut_pause_hi_cnt > PM_PWM_LUT_PAUSE_MAX)
-			lut_config->lut_pause_hi_cnt = PM_PWM_LUT_PAUSE_MAX;
+	if (lut_config->lut_pause_hi_cnt > PM_PWM_MAX_PAUSE_CNT)
+			lut_config->lut_pause_hi_cnt = PM_PWM_MAX_PAUSE_CNT;
 
 	lut_config->ramp_step_ms = ramp_step_ms;
 
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index e9cf973..459ab1d 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -4574,12 +4574,12 @@
 	int rc;
 	struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
 
-	pm8921_chg_force_19p2mhz_clk(chip);
-
 	rc = pm8921_chg_set_lpm(chip, 0);
 	if (rc)
 		pr_err("Failed to set lpm rc=%d\n", rc);
 
+	pm8921_chg_force_19p2mhz_clk(chip);
+
 	rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
 						VREF_BATT_THERM_FORCE_ON);
 	if (rc)
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 331c7f1..6cc27c2 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1737,7 +1737,7 @@
 	}
 
 	/* Get the vddmax property */
-	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddmax-mv",
+	rc = of_property_read_u32(spmi->dev.of_node, "qcom,vddmax-mv",
 						&chip->max_voltage_mv);
 	if (rc) {
 		pr_err("Error reading vddmax property %d\n", rc);
@@ -1745,7 +1745,7 @@
 	}
 
 	/* Get the vinmin property */
-	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vinmin-mv",
+	rc = of_property_read_u32(spmi->dev.of_node, "qcom,vinmin-mv",
 						&chip->min_voltage_mv);
 	if (rc) {
 		pr_err("Error reading vddmax property %d\n", rc);
@@ -1753,7 +1753,7 @@
 	}
 
 	/* Get the vddmax property */
-	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddsafe-mv",
+	rc = of_property_read_u32(spmi->dev.of_node, "qcom,vddsafe-mv",
 						&chip->safe_voltage_mv);
 	if (rc) {
 		pr_err("Error reading vddsave property %d\n", rc);
@@ -1762,7 +1762,7 @@
 
 	/* Get the vbatdet-delta property */
 	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-vbatdet-delta-mv",
+				"qcom,vbatdet-delta-mv",
 				&chip->resume_delta_mv);
 	if (rc && rc != -EINVAL) {
 		pr_err("Error reading vbatdet-delta property %d\n", rc);
@@ -1771,7 +1771,7 @@
 
 	/* Get the ibatsafe property */
 	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-ibatsafe-ma",
+				"qcom,ibatsafe-ma",
 				&chip->safe_current);
 	if (rc) {
 		pr_err("Error reading ibatsafe property %d\n", rc);
@@ -1780,7 +1780,7 @@
 
 	/* Get the ibatterm property */
 	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-ibatterm-ma",
+				"qcom,ibatterm-ma",
 				&chip->term_current);
 	if (rc && rc != -EINVAL) {
 		pr_err("Error reading ibatterm property %d\n", rc);
@@ -1788,7 +1788,7 @@
 	}
 
 	/* Get the ibatmax property */
-	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-ibatmax-ma",
+	rc = of_property_read_u32(spmi->dev.of_node, "qcom,ibatmax-ma",
 						&chip->max_bat_chg_current);
 	if (rc) {
 		pr_err("Error reading ibatmax property %d\n", rc);
@@ -1797,7 +1797,7 @@
 
 	/* Get the maxinput-dc-ma property */
 	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-maxinput-dc-ma",
+				"qcom,maxinput-dc-ma",
 				&chip->maxinput_dc_ma);
 	if (rc && rc != -EINVAL) {
 		pr_err("Error reading maxinput-dc-ma property %d\n", rc);
@@ -1806,7 +1806,7 @@
 
 	/* Get the maxinput-usb-ma property */
 	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-maxinput-usb-ma",
+				"qcom,maxinput-usb-ma",
 				&chip->maxinput_usb_ma);
 	if (rc && rc != -EINVAL) {
 		pr_err("Error reading maxinput-usb-ma property %d\n", rc);
@@ -1815,11 +1815,11 @@
 
 	/* Get the charging-disabled property */
 	chip->charging_disabled = of_property_read_bool(spmi->dev.of_node,
-					"qcom,chg-charging-disabled");
+					"qcom,charging-disabled");
 
 	/* Get the warm-bat-degc property */
 	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-warm-bat-decidegc",
+				"qcom,warm-bat-decidegc",
 				&chip->warm_bat_decidegc);
 	if (rc && rc != -EINVAL) {
 		pr_err("Error reading warm-bat-degc property %d\n", rc);
@@ -1828,7 +1828,7 @@
 
 	/* Get the cool-bat-degc property */
 	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-cool-bat-decidegc",
+				"qcom,cool-bat-decidegc",
 				&chip->cool_bat_decidegc);
 	if (rc && rc != -EINVAL) {
 		pr_err("Error reading cool-bat-degc property %d\n", rc);
@@ -1844,7 +1844,7 @@
 
 		/* Get the ibatmax-warm property */
 		rc = of_property_read_u32(spmi->dev.of_node,
-					"qcom,chg-ibatmax-warm-ma",
+					"qcom,ibatmax-warm-ma",
 					&chip->warm_bat_chg_ma);
 		if (rc) {
 			pr_err("Error reading ibatmax-warm-ma %d\n", rc);
@@ -1853,7 +1853,7 @@
 
 		/* Get the ibatmax-cool property */
 		rc = of_property_read_u32(spmi->dev.of_node,
-					"qcom,chg-ibatmax-cool-ma",
+					"qcom,ibatmax-cool-ma",
 					&chip->cool_bat_chg_ma);
 		if (rc) {
 			pr_err("Error reading ibatmax-cool-ma %d\n", rc);
@@ -1861,7 +1861,7 @@
 		}
 		/* Get the cool-bat-mv property */
 		rc = of_property_read_u32(spmi->dev.of_node,
-					"qcom,chg-cool-bat-mv",
+					"qcom,cool-bat-mv",
 					&chip->cool_bat_mv);
 		if (rc) {
 			pr_err("Error reading cool-bat-mv property %d\n", rc);
@@ -1870,7 +1870,7 @@
 
 		/* Get the warm-bat-mv property */
 		rc = of_property_read_u32(spmi->dev.of_node,
-					"qcom,chg-warm-bat-mv",
+					"qcom,warm-bat-mv",
 					&chip->warm_bat_mv);
 		if (rc) {
 			pr_err("Error reading warm-bat-mv property %d\n", rc);
@@ -1880,9 +1880,9 @@
 
 	/* Get the fake-batt-values property */
 	chip->use_default_batt_values = of_property_read_bool(spmi->dev.of_node,
-					"qcom,chg-use-default-batt-values");
+					"qcom,use-default-batt-values");
 
-	of_get_property(spmi->dev.of_node, "qcom,chg-thermal-mitigation",
+	of_get_property(spmi->dev.of_node, "qcom,thermal-mitigation",
 		&(chip->thermal_levels));
 
 	if (chip->thermal_levels > sizeof(int)) {
@@ -1897,10 +1897,10 @@
 
 		chip->thermal_levels /= sizeof(int);
 		rc = of_property_read_u32_array(spmi->dev.of_node,
-				"qcom,chg-thermal-mitigation",
+				"qcom,thermal-mitigation",
 				chip->thermal_mitigation, chip->thermal_levels);
 		if (rc) {
-			pr_err("qcom,chg-thermal-mitigation missing in dt\n");
+			pr_err("qcom,thermal-mitigation missing in dt\n");
 			goto fail_chg_enable;
 		}
 	}
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 706fba7..9a4ea63 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -58,6 +58,17 @@
 
 	  If unsure, say N.
 
+config SCSI_UFSHCD_PLATFORM
+	tristate "Platform bus based UFS Controller support"
+	depends on SCSI_UFSHCD
+	---help---
+	This selects the UFS host controller support. Select this if
+	you have an UFS controller on Platform bus.
+
+	If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
+
 config SCSI_UFS_TEST
 	tristate "Universal Flash Storage host controller driver unit-tests"
 	depends on SCSI_UFSHCD && IOSCHED_TEST
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index bbcc202..8d6665b 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,4 +1,5 @@
 # UFSHCD makefile
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
+obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
 obj-$(CONFIG_SCSI_UFS_TEST) += ufs_test.o
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
new file mode 100644
index 0000000..03319ac
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -0,0 +1,217 @@
+/*
+ * Universal Flash Storage Host controller Platform bus based glue driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c
+ * Copyright (C) 2011-2013 Samsung India Software Operations
+ *
+ * Authors:
+ *	Santosh Yaraganavi <santosh.sy@samsung.com>
+ *	Vinayak Holikatti <h.vinayak@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ *
+ * 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.
+ *
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
+ */
+
+#include "ufshcd.h"
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_PM
+/**
+ * ufshcd_pltfrm_suspend - suspend power management function
+ * @dev: pointer to device handle
+ *
+ *
+ * Returns 0
+ */
+static int ufshcd_pltfrm_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+	/*
+	 * TODO:
+	 * 1. Call ufshcd_suspend
+	 * 2. Do bus specific power management
+	 */
+
+	disable_irq(hba->irq);
+
+	return 0;
+}
+
+/**
+ * ufshcd_pltfrm_resume - resume power management function
+ * @dev: pointer to device handle
+ *
+ * Returns 0
+ */
+static int ufshcd_pltfrm_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+	/*
+	 * TODO:
+	 * 1. Call ufshcd_resume.
+	 * 2. Do bus specific wake up
+	 */
+
+	enable_irq(hba->irq);
+
+	return 0;
+}
+#else
+#define ufshcd_pltfrm_suspend	NULL
+#define ufshcd_pltfrm_resume	NULL
+#endif
+
+/**
+ * ufshcd_pltfrm_probe - probe routine of the driver
+ * @pdev: pointer to Platform device handle
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int ufshcd_pltfrm_probe(struct platform_device *pdev)
+{
+	struct ufs_hba *hba;
+	void __iomem *mmio_base;
+	struct resource *mem_res;
+	struct resource *irq_res;
+	resource_size_t mem_size;
+	int err;
+	struct device *dev = &pdev->dev;
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem_res) {
+		dev_err(&pdev->dev,
+			"Memory resource not available\n");
+		err = -ENODEV;
+		goto out_error;
+	}
+
+	mem_size = resource_size(mem_res);
+	if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) {
+		dev_err(&pdev->dev,
+			"Cannot reserve the memory resource\n");
+		err = -EBUSY;
+		goto out_error;
+	}
+
+	mmio_base = ioremap_nocache(mem_res->start, mem_size);
+	if (!mmio_base) {
+		dev_err(&pdev->dev, "memory map failed\n");
+		err = -ENOMEM;
+		goto out_release_regions;
+	}
+
+	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq_res) {
+		dev_err(&pdev->dev, "IRQ resource not available\n");
+		err = -ENODEV;
+		goto out_iounmap;
+	}
+
+	err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
+	if (err) {
+		dev_err(&pdev->dev, "set dma mask failed\n");
+		goto out_iounmap;
+	}
+
+	err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
+	if (err) {
+		dev_err(&pdev->dev, "Intialization failed\n");
+		goto out_iounmap;
+	}
+
+	platform_set_drvdata(pdev, hba);
+
+	return 0;
+
+out_iounmap:
+	iounmap(mmio_base);
+out_release_regions:
+	release_mem_region(mem_res->start, mem_size);
+out_error:
+	return err;
+}
+
+/**
+ * ufshcd_pltfrm_remove - remove platform driver routine
+ * @pdev: pointer to platform device handle
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int ufshcd_pltfrm_remove(struct platform_device *pdev)
+{
+	struct resource *mem_res;
+	resource_size_t mem_size;
+	struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+	disable_irq(hba->irq);
+
+	/* Some buggy controllers raise interrupt after
+	 * the resources are removed. So first we unregister the
+	 * irq handler and then the resources used by driver
+	 */
+
+	free_irq(hba->irq, hba);
+	ufshcd_remove(hba);
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem_res)
+		dev_err(&pdev->dev, "ufshcd: Memory resource not available\n");
+	else {
+		mem_size = resource_size(mem_res);
+		release_mem_region(mem_res->start, mem_size);
+	}
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static const struct of_device_id ufs_of_match[] = {
+	{ .compatible = "jedec,ufs-1.1"},
+};
+
+static const struct dev_pm_ops ufshcd_dev_pm_ops = {
+	.suspend	= ufshcd_pltfrm_suspend,
+	.resume		= ufshcd_pltfrm_resume,
+};
+
+static struct platform_driver ufshcd_pltfrm_driver = {
+	.probe	= ufshcd_pltfrm_probe,
+	.remove	= ufshcd_pltfrm_remove,
+	.driver	= {
+		.name	= "ufshcd",
+		.owner	= THIS_MODULE,
+		.pm	= &ufshcd_dev_pm_ops,
+		.of_match_table = ufs_of_match,
+	},
+};
+
+module_platform_driver(ufshcd_pltfrm_driver);
+
+MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
+MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
+MODULE_DESCRIPTION("UFS host controller Pltform bus based glue driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 60fd40c..c32a478 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -478,7 +478,7 @@
 		ucd_cmd_ptr->header.dword_2 = 0;
 
 		ucd_cmd_ptr->exp_data_transfer_len =
-			cpu_to_be32(lrbp->cmd->transfersize);
+			cpu_to_be32(lrbp->cmd->sdb.length);
 
 		memcpy(ucd_cmd_ptr->cdb,
 		       lrbp->cmd->cmnd,
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 5aca48d..12ac3bc 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -23,17 +23,447 @@
 #include <linux/msm_thermal.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
 #include <mach/cpufreq.h>
+#include <mach/rpm-regulator.h>
+#include <mach/rpm-regulator-smd.h>
+#include <linux/regulator/consumer.h>
 
-static int enabled;
+#define MAX_RAILS 5
+
 static struct msm_thermal_data msm_thermal_info;
 static uint32_t limited_max_freq = MSM_CPUFREQ_NO_LIMIT;
 static struct delayed_work check_temp_work;
+static bool core_control_enabled;
+static uint32_t cpus_offlined;
+static DEFINE_MUTEX(core_control_mutex);
 
+static int enabled;
+static int rails_cnt;
+static int psm_rails_cnt;
 static int limit_idx;
 static int limit_idx_low;
 static int limit_idx_high;
+static int max_tsens_num;
 static struct cpufreq_frequency_table *table;
+static uint32_t usefreq;
+static int freq_table_get;
+static bool vdd_rstr_enabled;
+static bool vdd_rstr_nodes_called;
+static bool vdd_rstr_probed;
+static bool psm_enabled;
+static bool psm_nodes_called;
+static bool psm_probed;
+static DEFINE_MUTEX(vdd_rstr_mutex);
+static DEFINE_MUTEX(psm_mutex);
+
+struct rail {
+	const char *name;
+	uint32_t freq_req;
+	uint32_t min_level;
+	uint32_t num_levels;
+	uint32_t curr_level;
+	uint32_t levels[3];
+	struct kobj_attribute value_attr;
+	struct kobj_attribute level_attr;
+	struct regulator *reg;
+	struct attribute_group attr_gp;
+};
+
+struct psm_rail {
+	const char *name;
+	uint8_t init;
+	uint8_t mode;
+	struct kobj_attribute mode_attr;
+	struct rpm_regulator *reg;
+	struct attribute_group attr_gp;
+};
+
+static struct psm_rail *psm_rails;
+static struct rail *rails;
+
+struct vdd_rstr_enable {
+	struct kobj_attribute ko_attr;
+	uint32_t enabled;
+};
+
+/* For SMPS only*/
+enum PMIC_SW_MODE {
+	PMIC_AUTO_MODE  = RPM_REGULATOR_MODE_AUTO,
+	PMIC_IPEAK_MODE = RPM_REGULATOR_MODE_IPEAK,
+	PMIC_PWM_MODE   = RPM_REGULATOR_MODE_HPM,
+};
+
+#define VDD_RES_RO_ATTRIB(_rail, ko_attr, j, _name) \
+	ko_attr.attr.name = __stringify(_name); \
+	ko_attr.attr.mode = 444; \
+	ko_attr.show = vdd_rstr_reg_##_name##_show; \
+	ko_attr.store = NULL; \
+	_rail.attr_gp.attrs[j] = &ko_attr.attr;
+
+#define VDD_RES_RW_ATTRIB(_rail, ko_attr, j, _name) \
+	ko_attr.attr.name = __stringify(_name); \
+	ko_attr.attr.mode = 644; \
+	ko_attr.show = vdd_rstr_reg_##_name##_show; \
+	ko_attr.store = vdd_rstr_reg_##_name##_store; \
+	_rail.attr_gp.attrs[j] = &ko_attr.attr;
+
+#define VDD_RSTR_ENABLE_FROM_ATTRIBS(attr) \
+	(container_of(attr, struct vdd_rstr_enable, ko_attr));
+
+#define VDD_RSTR_REG_VALUE_FROM_ATTRIBS(attr) \
+	(container_of(attr, struct rail, value_attr));
+
+#define VDD_RSTR_REG_LEVEL_FROM_ATTRIBS(attr) \
+	(container_of(attr, struct rail, level_attr));
+
+#define PSM_RW_ATTRIB(_rail, ko_attr, j, _name) \
+	ko_attr.attr.name = __stringify(_name); \
+	ko_attr.attr.mode = 644; \
+	ko_attr.show = psm_reg_##_name##_show; \
+	ko_attr.store = psm_reg_##_name##_store; \
+	_rail.attr_gp.attrs[j] = &ko_attr.attr;
+
+#define PSM_REG_MODE_FROM_ATTRIBS(attr) \
+	(container_of(attr, struct psm_rail, mode_attr));
+/* If freq table exists, then we can send freq request */
+static int check_freq_table(void)
+{
+	int ret = 0;
+	struct cpufreq_frequency_table *table = NULL;
+
+	table = cpufreq_frequency_get_table(0);
+	if (!table) {
+		pr_debug("%s: error reading cpufreq table\n", __func__);
+		return -EINVAL;
+	}
+	freq_table_get = 1;
+
+	return ret;
+}
+
+static int update_cpu_min_freq_all(uint32_t min)
+{
+	int cpu = 0;
+	int ret = 0;
+
+	if (!freq_table_get) {
+		ret = check_freq_table();
+		if (ret) {
+			pr_err("%s:Fail to get freq table\n", __func__);
+			return ret;
+		}
+	}
+	/* If min is larger than allowed max */
+	if (min != MSM_CPUFREQ_NO_LIMIT &&
+			min > table[limit_idx_high].frequency)
+		min = table[limit_idx_high].frequency;
+
+	for_each_possible_cpu(cpu) {
+		ret = msm_cpufreq_set_freq_limits(cpu, min, limited_max_freq);
+
+		if (ret) {
+			pr_err("%s:Fail to set limits for cpu%d\n",
+					__func__, cpu);
+			return ret;
+		}
+
+		if (cpufreq_update_policy(cpu))
+			pr_debug("%s: Cannot update policy for cpu%d\n",
+					__func__, cpu);
+	}
+
+	return ret;
+}
+
+static int vdd_restriction_apply_freq(struct rail *r, int level)
+{
+	int ret = 0;
+
+	/* level = -1: disable, level = 0,1,2..n: enable */
+	if (level == -1) {
+		ret = update_cpu_min_freq_all(r->min_level);
+		if (ret)
+			return ret;
+		else
+			r->curr_level = -1;
+	} else if (level >= 0 && level < (r->num_levels)) {
+		ret = update_cpu_min_freq_all(r->levels[level]);
+		if (ret)
+			return ret;
+		else
+			r->curr_level = level;
+	} else {
+		pr_err("level input:%d is not within range\n", level);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int vdd_restriction_apply_voltage(struct rail *r, int level)
+{
+	int ret = 0;
+
+	if (r->reg == NULL) {
+		pr_info("Do not have regulator handle:%s, can't apply vdd\n",
+				r->name);
+		return -EFAULT;
+	}
+	/* level = -1: disable, level = 0,1,2..n: enable */
+	if (level == -1) {
+		ret = regulator_set_voltage(r->reg, r->min_level,
+			r->levels[r->num_levels - 1]);
+		if (!ret)
+			r->curr_level = -1;
+	} else if (level >= 0 && level < (r->num_levels)) {
+		ret = regulator_set_voltage(r->reg, r->levels[level],
+			r->levels[r->num_levels - 1]);
+		if (!ret)
+			r->curr_level = level;
+	} else {
+		pr_err("level input:%d is not within range\n", level);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+/* 1:enable, 0:disable */
+static int vdd_restriction_apply_all(int en)
+{
+	int i = 0;
+	int fail_cnt = 0;
+	int ret = 0;
+
+	for (i = 0; i < rails_cnt; i++) {
+		if (rails[i].freq_req == 1 && freq_table_get)
+			ret = vdd_restriction_apply_freq(&rails[i],
+					en ? 0 : -1);
+		else
+			ret = vdd_restriction_apply_voltage(&rails[i],
+					en ? 0 : -1);
+		if (ret) {
+			pr_err("Cannot set voltage for %s", rails[i].name);
+			fail_cnt++;
+		}
+	}
+	/* Check fail_cnt again to make sure all of the rails are applied
+	 * restriction successfully or not */
+	if (fail_cnt)
+		return -EFAULT;
+
+	return ret;
+}
+
+/* Setting all rails the same mode */
+static int psm_set_mode_all(int mode)
+{
+	int i = 0;
+	int fail_cnt = 0;
+	int ret = 0;
+
+	for (i = 0; i < psm_rails_cnt; i++) {
+		if (psm_rails[i].mode != mode) {
+			ret = rpm_regulator_set_mode(psm_rails[i].reg, mode);
+			if (ret) {
+				pr_err("Cannot set mode:%d for %s",
+					mode, psm_rails[i].name);
+				fail_cnt++;
+			} else
+				psm_rails[i].mode = mode;
+		}
+	}
+
+	return fail_cnt ? (-EFAULT) : ret;
+}
+
+static int vdd_rstr_en_show(
+	struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	struct vdd_rstr_enable *en = VDD_RSTR_ENABLE_FROM_ATTRIBS(attr);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", en->enabled);
+}
+
+static ssize_t vdd_rstr_en_store(struct kobject *kobj,
+	struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	int ret = 0;
+	int i = 0;
+	uint8_t en_cnt = 0;
+	uint8_t dis_cnt = 0;
+	uint32_t val = 0;
+	struct kernel_param kp;
+	struct vdd_rstr_enable *en = VDD_RSTR_ENABLE_FROM_ATTRIBS(attr);
+
+	mutex_lock(&vdd_rstr_mutex);
+	kp.arg = &val;
+	ret = param_set_bool(buf, &kp);
+	if (ret) {
+		pr_err("Invalid input %s for enabled\n", buf);
+		goto done_vdd_rstr_en;
+	}
+
+	if ((val == 0) && (en->enabled == 0))
+		goto done_vdd_rstr_en;
+
+	for (i = 0; i < rails_cnt; i++) {
+		if (rails[i].freq_req == 1 && freq_table_get)
+			ret = vdd_restriction_apply_freq(&rails[i],
+					(val) ? 0 : -1);
+		else
+			ret = vdd_restriction_apply_voltage(&rails[i],
+			(val) ? 0 : -1);
+
+		/* Even if fail to set one rail, still try to set the
+		 * others. Continue the loop */
+		if (ret)
+			pr_err("Set vdd restriction for %s failed\n",
+					rails[i].name);
+		else {
+			if (val)
+				en_cnt++;
+			else
+				dis_cnt++;
+		}
+	}
+	/* As long as one rail is enabled, vdd rstr is enabled */
+	if (val && en_cnt)
+		en->enabled = 1;
+	else if (!val && (dis_cnt == rails_cnt))
+		en->enabled = 0;
+
+done_vdd_rstr_en:
+	mutex_unlock(&vdd_rstr_mutex);
+	return count;
+}
+
+static struct vdd_rstr_enable vdd_rstr_en = {
+	.ko_attr.attr.name = __stringify(enabled),
+	.ko_attr.attr.mode = 644,
+	.ko_attr.show = vdd_rstr_en_show,
+	.ko_attr.store = vdd_rstr_en_store,
+	.enabled = 1,
+};
+
+static struct attribute *vdd_rstr_en_attribs[] = {
+	&vdd_rstr_en.ko_attr.attr,
+	NULL,
+};
+
+static struct attribute_group vdd_rstr_en_attribs_gp = {
+	.attrs  = vdd_rstr_en_attribs,
+};
+
+static int vdd_rstr_reg_value_show(
+	struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	int val = 0;
+	struct rail *reg = VDD_RSTR_REG_VALUE_FROM_ATTRIBS(attr);
+	/* -1:disabled, -2:fail to get regualtor handle */
+	if (reg->curr_level < 0)
+		val = reg->curr_level;
+	else
+		val = reg->levels[reg->curr_level];
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", reg->levels[reg->curr_level]);
+}
+
+static int vdd_rstr_reg_level_show(
+	struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	struct rail *reg = VDD_RSTR_REG_LEVEL_FROM_ATTRIBS(attr);
+	return snprintf(buf, PAGE_SIZE, "%d\n", reg->curr_level);
+}
+
+static ssize_t vdd_rstr_reg_level_store(struct kobject *kobj,
+	struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	int ret = 0;
+	int val = 0;
+
+	struct rail *reg = VDD_RSTR_REG_LEVEL_FROM_ATTRIBS(attr);
+
+	mutex_lock(&vdd_rstr_mutex);
+	if (vdd_rstr_en.enabled == 0)
+		goto done_store_level;
+
+	ret = kstrtoint(buf, 10, &val);
+	if (ret) {
+		pr_err("Invalid input %s for level\n", buf);
+		goto done_store_level;
+	}
+
+	if (val < 0 || val > reg->num_levels - 1) {
+		pr_err(" Invalid number %d for level\n", val);
+		goto done_store_level;
+	}
+
+	if (val != reg->curr_level) {
+		if (reg->freq_req == 1 && freq_table_get)
+			update_cpu_min_freq_all(reg->levels[val]);
+		else {
+			ret = vdd_restriction_apply_voltage(reg, val);
+			if (ret) {
+				pr_err( \
+				"Set vdd restriction for regulator %s failed\n",
+				reg->name);
+				goto done_store_level;
+			}
+		}
+		reg->curr_level = val;
+	}
+
+done_store_level:
+	mutex_unlock(&vdd_rstr_mutex);
+	return count;
+}
+
+static int psm_reg_mode_show(
+	struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	struct psm_rail *reg = PSM_REG_MODE_FROM_ATTRIBS(attr);
+	return snprintf(buf, PAGE_SIZE, "%d\n", reg->mode);
+}
+
+static ssize_t psm_reg_mode_store(struct kobject *kobj,
+	struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	int ret = 0;
+	int val = 0;
+	struct psm_rail *reg = PSM_REG_MODE_FROM_ATTRIBS(attr);
+
+	mutex_lock(&psm_mutex);
+	ret = kstrtoint(buf, 10, &val);
+	if (ret) {
+		pr_err("Invalid input %s for mode\n", buf);
+		goto done_psm_store;
+	}
+
+	if ((val != PMIC_PWM_MODE) && (val != PMIC_AUTO_MODE)) {
+		pr_err(" Invalid number %d for mode\n", val);
+		goto done_psm_store;
+	}
+
+	if (val != reg->mode) {
+		ret = rpm_regulator_set_mode(reg->reg, val);
+		if (ret) {
+			pr_err( \
+			"Fail to set PMIC SW Mode:%d for %s\n",
+			val, reg->name);
+			goto done_psm_store;
+		}
+		reg->mode = val;
+	}
+
+done_psm_store:
+	mutex_unlock(&psm_mutex);
+	return count;
+}
 
 static int msm_thermal_get_freq_table(void)
 {
@@ -42,7 +472,7 @@
 
 	table = cpufreq_frequency_get_table(0);
 	if (table == NULL) {
-		pr_debug("%s: error reading cpufreq table\n", __func__);
+		pr_debug("%s: error reading cpufreq table\n", KBUILD_MODNAME);
 		ret = -EINVAL;
 		goto fail;
 	}
@@ -67,17 +497,166 @@
 
 	limited_max_freq = max_freq;
 	if (max_freq != MSM_CPUFREQ_NO_LIMIT)
-		pr_info("msm_thermal: Limiting cpu%d max frequency to %d\n",
-				cpu, max_freq);
+		pr_info("%s: Limiting cpu%d max frequency to %d\n",
+				KBUILD_MODNAME, cpu, max_freq);
 	else
-		pr_info("msm_thermal: Max frequency reset for cpu%d\n", cpu);
+		pr_info("%s: Max frequency reset for cpu%d\n",
+				KBUILD_MODNAME, cpu);
 
 	ret = cpufreq_update_policy(cpu);
 
 	return ret;
 }
 
-static void check_temp(struct work_struct *work)
+static void __cpuinit do_core_control(long temp)
+{
+	int i = 0;
+	int ret = 0;
+
+	if (!core_control_enabled)
+		return;
+
+	mutex_lock(&core_control_mutex);
+	if (msm_thermal_info.core_control_mask &&
+		temp >= msm_thermal_info.core_limit_temp_degC) {
+		for (i = num_possible_cpus(); i > 0; i--) {
+			if (!(msm_thermal_info.core_control_mask & BIT(i)))
+				continue;
+			if (cpus_offlined & BIT(i) && !cpu_online(i))
+				continue;
+			pr_info("%s: Set Offline: CPU%d Temp: %ld\n",
+					KBUILD_MODNAME, i, temp);
+			ret = cpu_down(i);
+			if (ret)
+				pr_err("%s: Error %d offline core %d\n",
+					KBUILD_MODNAME, ret, i);
+			cpus_offlined |= BIT(i);
+			break;
+		}
+	} else if (msm_thermal_info.core_control_mask && cpus_offlined &&
+		temp <= (msm_thermal_info.core_limit_temp_degC -
+			msm_thermal_info.core_temp_hysteresis_degC)) {
+		for (i = 0; i < num_possible_cpus(); i++) {
+			if (!(cpus_offlined & BIT(i)))
+				continue;
+			cpus_offlined &= ~BIT(i);
+			pr_info("%s: Allow Online CPU%d Temp: %ld\n",
+					KBUILD_MODNAME, i, temp);
+			/* If this core is already online, then bring up the
+			 * next offlined core.
+			 */
+			if (cpu_online(i))
+				continue;
+			ret = cpu_up(i);
+			if (ret)
+				pr_err("%s: Error %d online core %d\n",
+						KBUILD_MODNAME, ret, i);
+			break;
+		}
+	}
+	mutex_unlock(&core_control_mutex);
+}
+
+static int do_vdd_restriction(void)
+{
+	struct tsens_device tsens_dev;
+	long temp = 0;
+	int ret = 0;
+	int i = 0;
+	int dis_cnt = 0;
+
+	if (!vdd_rstr_enabled)
+		return ret;
+
+	if (usefreq && !freq_table_get) {
+		if (check_freq_table())
+			return ret;
+	}
+
+	mutex_lock(&vdd_rstr_mutex);
+	for (i = 0; i < max_tsens_num; i++) {
+		tsens_dev.sensor_num = i;
+		ret = tsens_get_temp(&tsens_dev, &temp);
+		if (ret) {
+			pr_debug("%s: Unable to read TSENS sensor %d\n",
+					__func__, tsens_dev.sensor_num);
+			dis_cnt++;
+			continue;
+		}
+		if (temp <=  msm_thermal_info.vdd_rstr_temp_hyst_degC &&
+				vdd_rstr_en.enabled == 0) {
+			ret = vdd_restriction_apply_all(1);
+			if (ret) {
+				pr_err( \
+				"Enable vdd rstr votlage for all failed\n");
+				goto exit;
+			}
+			vdd_rstr_en.enabled = 1;
+			goto exit;
+		} else if (temp > msm_thermal_info.vdd_rstr_temp_degC &&
+				vdd_rstr_en.enabled == 1)
+			dis_cnt++;
+	}
+	if (dis_cnt == max_tsens_num) {
+		ret = vdd_restriction_apply_all(0);
+		if (ret) {
+			pr_err("Disable vdd rstr votlage for all failed\n");
+			goto exit;
+		}
+		vdd_rstr_en.enabled = 0;
+	}
+exit:
+	mutex_unlock(&vdd_rstr_mutex);
+	return ret;
+}
+
+static int do_psm(void)
+{
+	struct tsens_device tsens_dev;
+	long temp = 0;
+	int ret = 0;
+	int i = 0;
+	int auto_cnt = 0;
+
+	mutex_lock(&psm_mutex);
+	for (i = 0; i < max_tsens_num; i++) {
+		tsens_dev.sensor_num = i;
+		ret = tsens_get_temp(&tsens_dev, &temp);
+		if (ret) {
+			pr_debug("%s: Unable to read TSENS sensor %d\n",
+					__func__, tsens_dev.sensor_num);
+			auto_cnt++;
+			continue;
+		}
+
+		/* As long as one sensor is above the threshold, set PWM mode
+		 * on all rails, and loop stops. Set auto mode when all rails
+		 * are below thershold */
+		if (temp >  msm_thermal_info.psm_temp_degC) {
+			ret = psm_set_mode_all(PMIC_PWM_MODE);
+			if (ret) {
+				pr_err("Set pwm mode for all failed\n");
+				goto exit;
+			}
+			break;
+		} else if (temp <= msm_thermal_info.psm_temp_hyst_degC)
+			auto_cnt++;
+	}
+
+	if (auto_cnt == max_tsens_num) {
+		ret = psm_set_mode_all(PMIC_AUTO_MODE);
+		if (ret) {
+			pr_err("Set auto mode for all failed\n");
+			goto exit;
+		}
+	}
+
+exit:
+	mutex_unlock(&psm_mutex);
+	return ret;
+}
+
+static void __cpuinit check_temp(struct work_struct *work)
 {
 	static int limit_init;
 	struct tsens_device tsens_dev;
@@ -85,12 +664,11 @@
 	uint32_t max_freq = limited_max_freq;
 	int cpu = 0;
 	int ret = 0;
-
 	tsens_dev.sensor_num = msm_thermal_info.sensor_id;
 	ret = tsens_get_temp(&tsens_dev, &temp);
 	if (ret) {
-		pr_debug("msm_thermal: Unable to read TSENS sensor %d\n",
-				tsens_dev.sensor_num);
+		pr_debug("%s: Unable to read TSENS sensor %d\n",
+				KBUILD_MODNAME, tsens_dev.sensor_num);
 		goto reschedule;
 	}
 
@@ -102,6 +680,10 @@
 			limit_init = 1;
 	}
 
+	do_core_control(temp);
+	do_vdd_restriction();
+	do_psm();
+
 	if (temp >= msm_thermal_info.limit_temp_degC) {
 		if (limit_idx == limit_idx_low)
 			goto reschedule;
@@ -129,8 +711,9 @@
 	for_each_possible_cpu(cpu) {
 		ret = update_cpu_max_freq(cpu, max_freq);
 		if (ret)
-			pr_debug("Unable to limit cpu%d max freq to %d\n",
-					cpu, max_freq);
+			pr_debug(
+			"%s: Unable to limit cpu%d max freq to %d\n",
+					KBUILD_MODNAME, cpu, max_freq);
 	}
 
 reschedule:
@@ -139,7 +722,36 @@
 				msecs_to_jiffies(msm_thermal_info.poll_ms));
 }
 
-static void disable_msm_thermal(void)
+static int __cpuinit msm_thermal_cpu_callback(struct notifier_block *nfb,
+		unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+
+	if (action == CPU_UP_PREPARE || action == CPU_UP_PREPARE_FROZEN) {
+		if (core_control_enabled &&
+			(msm_thermal_info.core_control_mask & BIT(cpu)) &&
+			(cpus_offlined & BIT(cpu))) {
+			pr_info(
+			"%s: Preventing cpu%d from coming online.\n",
+				KBUILD_MODNAME, cpu);
+			return NOTIFY_BAD;
+		}
+	}
+
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __refdata msm_thermal_cpu_notifier = {
+	.notifier_call = msm_thermal_cpu_callback,
+};
+
+/**
+ * We will reset the cpu frequencies limits here. The core online/offline
+ * status will be carried over to the process stopping the msm_thermal, as
+ * we dont want to online a core and bring in the thermal issues.
+ */
+static void __cpuinit disable_msm_thermal(void)
 {
 	int cpu = 0;
 
@@ -155,7 +767,7 @@
 	}
 }
 
-static int set_enabled(const char *val, const struct kernel_param *kp)
+static int __cpuinit set_enabled(const char *val, const struct kernel_param *kp)
 {
 	int ret = 0;
 
@@ -163,9 +775,10 @@
 	if (!enabled)
 		disable_msm_thermal();
 	else
-		pr_info("msm_thermal: no action for enabled = %d\n", enabled);
+		pr_info("%s: no action for enabled = %d\n",
+				KBUILD_MODNAME, enabled);
 
-	pr_info("msm_thermal: enabled = %d\n", enabled);
+	pr_info("%s: enabled = %d\n", KBUILD_MODNAME, enabled);
 
 	return ret;
 }
@@ -178,18 +791,561 @@
 module_param_cb(enabled, &module_ops, &enabled, 0644);
 MODULE_PARM_DESC(enabled, "enforce thermal limit on cpu");
 
+
+/* Call with core_control_mutex locked */
+static int __cpuinit update_offline_cores(int val)
+{
+	int cpu = 0;
+	int ret = 0;
+
+	cpus_offlined = msm_thermal_info.core_control_mask & val;
+	if (!core_control_enabled)
+		return 0;
+
+	for_each_possible_cpu(cpu) {
+		if (!(cpus_offlined & BIT(cpu)))
+			continue;
+		if (!cpu_online(cpu))
+			continue;
+		ret = cpu_down(cpu);
+		if (ret)
+			pr_err("%s: Unable to offline cpu%d\n",
+				KBUILD_MODNAME, cpu);
+	}
+	return ret;
+}
+
+static ssize_t show_cc_enabled(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", core_control_enabled);
+}
+
+static ssize_t __cpuinit store_cc_enabled(struct kobject *kobj,
+		struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	int ret = 0;
+	int val = 0;
+
+	mutex_lock(&core_control_mutex);
+	ret = kstrtoint(buf, 10, &val);
+	if (ret) {
+		pr_err("%s: Invalid input %s\n", KBUILD_MODNAME, buf);
+		goto done_store_cc;
+	}
+
+	if (core_control_enabled == !!val)
+		goto done_store_cc;
+
+	core_control_enabled = !!val;
+	if (core_control_enabled) {
+		pr_info("%s: Core control enabled\n", KBUILD_MODNAME);
+		register_cpu_notifier(&msm_thermal_cpu_notifier);
+		update_offline_cores(cpus_offlined);
+	} else {
+		pr_info("%s: Core control disabled\n", KBUILD_MODNAME);
+		unregister_cpu_notifier(&msm_thermal_cpu_notifier);
+	}
+
+done_store_cc:
+	mutex_unlock(&core_control_mutex);
+	return count;
+}
+
+static ssize_t show_cpus_offlined(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", cpus_offlined);
+}
+
+static ssize_t __cpuinit store_cpus_offlined(struct kobject *kobj,
+		struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	int ret = 0;
+	uint32_t val = 0;
+
+	mutex_lock(&core_control_mutex);
+	ret = kstrtouint(buf, 10, &val);
+	if (ret) {
+		pr_err("%s: Invalid input %s\n", KBUILD_MODNAME, buf);
+		goto done_cc;
+	}
+
+	if (enabled) {
+		pr_err("%s: Ignoring request; polling thread is enabled.\n",
+				KBUILD_MODNAME);
+		goto done_cc;
+	}
+
+	if (cpus_offlined == val)
+		goto done_cc;
+
+	update_offline_cores(val);
+done_cc:
+	mutex_unlock(&core_control_mutex);
+	return count;
+}
+
+static __cpuinitdata struct kobj_attribute cc_enabled_attr =
+__ATTR(enabled, 0644, show_cc_enabled, store_cc_enabled);
+
+static __cpuinitdata struct kobj_attribute cpus_offlined_attr =
+__ATTR(cpus_offlined, 0644, show_cpus_offlined, store_cpus_offlined);
+
+static __cpuinitdata struct attribute *cc_attrs[] = {
+	&cc_enabled_attr.attr,
+	&cpus_offlined_attr.attr,
+	NULL,
+};
+
+static __cpuinitdata struct attribute_group cc_attr_group = {
+	.attrs = cc_attrs,
+};
+
+static __init int msm_thermal_add_cc_nodes(void)
+{
+	struct kobject *module_kobj = NULL;
+	struct kobject *cc_kobj = NULL;
+	int ret = 0;
+
+	module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+	if (!module_kobj) {
+		pr_err("%s: cannot find kobject for module\n",
+			KBUILD_MODNAME);
+		ret = -ENOENT;
+		goto done_cc_nodes;
+	}
+
+	cc_kobj = kobject_create_and_add("core_control", module_kobj);
+	if (!cc_kobj) {
+		pr_err("%s: cannot create core control kobj\n",
+				KBUILD_MODNAME);
+		ret = -ENOMEM;
+		goto done_cc_nodes;
+	}
+
+	ret = sysfs_create_group(cc_kobj, &cc_attr_group);
+	if (ret) {
+		pr_err("%s: cannot create group\n", KBUILD_MODNAME);
+		goto done_cc_nodes;
+	}
+
+	return 0;
+
+done_cc_nodes:
+	if (cc_kobj)
+		kobject_del(cc_kobj);
+	return ret;
+}
+
 int __devinit msm_thermal_init(struct msm_thermal_data *pdata)
 {
 	int ret = 0;
 
 	BUG_ON(!pdata);
-	BUG_ON(pdata->sensor_id >= TSENS_MAX_SENSORS);
+	tsens_get_max_sensor_num(&max_tsens_num);
+	BUG_ON(msm_thermal_info.sensor_id >= max_tsens_num);
 	memcpy(&msm_thermal_info, pdata, sizeof(struct msm_thermal_data));
 
 	enabled = 1;
+	core_control_enabled = 1;
 	INIT_DELAYED_WORK(&check_temp_work, check_temp);
 	schedule_delayed_work(&check_temp_work, 0);
 
+	register_cpu_notifier(&msm_thermal_cpu_notifier);
+
+	return ret;
+}
+
+static int vdd_restriction_reg_init(struct platform_device *pdev)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < rails_cnt; i++) {
+		if (rails[i].freq_req == 1) {
+			usefreq |= BIT(i);
+			check_freq_table();
+			/* Restrict frequency by default until we have made
+			 * our first temp reading */
+			if (freq_table_get)
+				ret = vdd_restriction_apply_freq(&rails[i], 0);
+			else
+				pr_info("%s:Defer vdd rstr freq init\n",
+						__func__);
+		} else {
+			rails[i].reg = devm_regulator_get(&pdev->dev,
+					rails[i].name);
+			if (IS_ERR_OR_NULL(rails[i].reg)) {
+				ret = PTR_ERR(rails[i].reg);
+				if (ret != -EPROBE_DEFER) {
+					pr_err( \
+					"%s, could not get regulator: %s\n",
+					rails[i].name, __func__);
+					rails[i].reg = NULL;
+					rails[i].curr_level = -2;
+					return ret;
+				}
+				return ret;
+			}
+			/* Restrict votlage by default until we have made
+			 * our first temp reading */
+			ret = vdd_restriction_apply_voltage(&rails[i], 0);
+		}
+	}
+
+	return ret;
+}
+
+static int psm_reg_init(struct platform_device *pdev)
+{
+	int ret = 0;
+	int i = 0;
+	int j = 0;
+
+	for (i = 0; i < psm_rails_cnt; i++) {
+		psm_rails[i].reg = rpm_regulator_get(&pdev->dev,
+				psm_rails[i].name);
+		if (IS_ERR_OR_NULL(psm_rails[i].reg)) {
+			ret = PTR_ERR(psm_rails[i].reg);
+			if (ret != -EPROBE_DEFER) {
+				pr_err("%s, could not get rpm regulator: %s\n",
+					psm_rails[i].name, __func__);
+				psm_rails[i].reg = NULL;
+				goto psm_reg_exit;
+			}
+			return ret;
+		}
+		/* Apps default vote for PWM mode */
+		psm_rails[i].init = PMIC_PWM_MODE;
+		ret = rpm_regulator_set_mode(psm_rails[i].reg,
+				psm_rails[i].init);
+		if (ret) {
+			pr_err("%s: Cannot set PMIC PWM mode\n", __func__);
+			return ret;
+		} else
+			psm_rails[i].mode = PMIC_PWM_MODE;
+	}
+
+	return ret;
+
+psm_reg_exit:
+	if (ret) {
+		for (j = 0; j < i; j++) {
+			if (psm_rails[j].reg != NULL)
+				rpm_regulator_put(psm_rails[j].reg);
+		}
+	}
+
+	return ret;
+}
+
+static int msm_thermal_add_vdd_rstr_nodes(void)
+{
+	struct kobject *module_kobj = NULL;
+	struct kobject *vdd_rstr_kobj = NULL;
+	struct kobject *vdd_rstr_reg_kobj[MAX_RAILS] = {0};
+	int rc = 0;
+	int i = 0;
+
+	if (!vdd_rstr_probed) {
+		vdd_rstr_nodes_called = true;
+		return rc;
+	}
+
+	if (vdd_rstr_probed && rails_cnt == 0)
+		return rc;
+
+	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 thermal_sysfs_add_exit;
+	}
+
+	vdd_rstr_kobj = kobject_create_and_add("vdd_restriction", module_kobj);
+	if (!vdd_rstr_kobj) {
+		pr_err("%s: cannot create vdd_restriction kobject\n", __func__);
+		rc = -ENOMEM;
+		goto thermal_sysfs_add_exit;
+	}
+
+	rc = sysfs_create_group(vdd_rstr_kobj, &vdd_rstr_en_attribs_gp);
+	if (rc) {
+		pr_err("%s: cannot create kobject attribute group\n", __func__);
+		rc = -ENOMEM;
+		goto thermal_sysfs_add_exit;
+	}
+
+	for (i = 0; i < rails_cnt; i++) {
+		vdd_rstr_reg_kobj[i] = kobject_create_and_add(rails[i].name,
+					vdd_rstr_kobj);
+		if (!vdd_rstr_reg_kobj[i]) {
+			pr_err("%s: cannot create for kobject for %s\n",
+					__func__, rails[i].name);
+			rc = -ENOMEM;
+			goto thermal_sysfs_add_exit;
+		}
+
+		rails[i].attr_gp.attrs = kzalloc(sizeof(struct attribute *) * 3,
+					GFP_KERNEL);
+		if (!rails[i].attr_gp.attrs) {
+			rc = -ENOMEM;
+			goto thermal_sysfs_add_exit;
+		}
+
+		VDD_RES_RW_ATTRIB(rails[i], rails[i].level_attr, 0, level);
+		VDD_RES_RO_ATTRIB(rails[i], rails[i].value_attr, 1, value);
+		rails[i].attr_gp.attrs[2] = NULL;
+
+		rc = sysfs_create_group(vdd_rstr_reg_kobj[i],
+				&rails[i].attr_gp);
+		if (rc) {
+			pr_err("%s: cannot create attribute group for %s\n",
+					__func__, rails[i].name);
+			goto thermal_sysfs_add_exit;
+		}
+	}
+
+	return rc;
+
+thermal_sysfs_add_exit:
+	if (rc) {
+		for (i = 0; i < rails_cnt; i++) {
+			kobject_del(vdd_rstr_reg_kobj[i]);
+			kfree(rails[i].attr_gp.attrs);
+		}
+		if (vdd_rstr_kobj)
+			kobject_del(vdd_rstr_kobj);
+	}
+	return rc;
+}
+
+static int msm_thermal_add_psm_nodes(void)
+{
+	struct kobject *module_kobj = NULL;
+	struct kobject *psm_kobj = NULL;
+	struct kobject *psm_reg_kobj[MAX_RAILS] = {0};
+	int rc = 0;
+	int i = 0;
+
+	if (!psm_probed) {
+		psm_nodes_called = true;
+		return rc;
+	}
+
+	if (psm_probed && psm_rails_cnt == 0)
+		return rc;
+
+	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 psm_node_exit;
+	}
+
+	psm_kobj = kobject_create_and_add("pmic_sw_mode", module_kobj);
+	if (!psm_kobj) {
+		pr_err("%s: cannot create psm kobject\n", KBUILD_MODNAME);
+		rc = -ENOMEM;
+		goto psm_node_exit;
+	}
+
+	for (i = 0; i < psm_rails_cnt; i++) {
+		psm_reg_kobj[i] = kobject_create_and_add(psm_rails[i].name,
+					psm_kobj);
+		if (!psm_reg_kobj[i]) {
+			pr_err("%s: cannot create for kobject for %s\n",
+					KBUILD_MODNAME, psm_rails[i].name);
+			rc = -ENOMEM;
+			goto psm_node_exit;
+		}
+		psm_rails[i].attr_gp.attrs = kzalloc( \
+				sizeof(struct attribute *) * 2, GFP_KERNEL);
+		if (!psm_rails[i].attr_gp.attrs) {
+			rc = -ENOMEM;
+			goto psm_node_exit;
+		}
+
+		PSM_RW_ATTRIB(psm_rails[i], psm_rails[i].mode_attr, 0, mode);
+		psm_rails[i].attr_gp.attrs[1] = NULL;
+
+		rc = sysfs_create_group(psm_reg_kobj[i], &psm_rails[i].attr_gp);
+		if (rc) {
+			pr_err("%s: cannot create attribute group for %s\n",
+					KBUILD_MODNAME, psm_rails[i].name);
+			goto psm_node_exit;
+		}
+	}
+
+	return rc;
+
+psm_node_exit:
+	if (rc) {
+		for (i = 0; i < psm_rails_cnt; i++) {
+			kobject_del(psm_reg_kobj[i]);
+			kfree(psm_rails[i].attr_gp.attrs);
+		}
+		if (psm_kobj)
+			kobject_del(psm_kobj);
+	}
+	return rc;
+}
+
+static int probe_vdd_rstr(struct device_node *node,
+		struct msm_thermal_data *data, struct platform_device *pdev)
+{
+	int ret = 0;
+	int i = 0;
+	int arr_size;
+	char *key = NULL;
+	struct device_node *child_node = NULL;
+
+	key = "qcom,vdd-restriction-temp";
+	ret = of_property_read_u32(node, key, &data->vdd_rstr_temp_degC);
+	if (ret)
+		goto read_node_fail;
+
+	key = "qcom,vdd-restriction-temp-hysteresis";
+	ret = of_property_read_u32(node, key, &data->vdd_rstr_temp_hyst_degC);
+	if (ret)
+		goto read_node_fail;
+
+	for_each_child_of_node(node, child_node) {
+		rails_cnt++;
+	}
+
+	if (rails_cnt == 0)
+		goto read_node_fail;
+	if (rails_cnt >= MAX_RAILS) {
+		pr_err("%s: Too many rails.\n", __func__);
+		return -EFAULT;
+	}
+
+	rails = kzalloc(sizeof(struct rail) * rails_cnt,
+				GFP_KERNEL);
+	if (!rails) {
+		pr_err("%s: Fail to allocate memory for rails.\n", __func__);
+		return -ENOMEM;
+	}
+
+	i = 0;
+	for_each_child_of_node(node, child_node) {
+		key = "qcom,vdd-rstr-reg";
+		ret = of_property_read_string(child_node, key, &rails[i].name);
+		if (ret)
+			goto read_node_fail;
+
+		key = "qcom,levels";
+		if (!of_get_property(child_node, key, &arr_size))
+			goto read_node_fail;
+		rails[i].num_levels = arr_size/sizeof(__be32);
+		if (rails[i].num_levels >
+			sizeof(rails[i].levels)/sizeof(uint32_t)) {
+			pr_err("%s: Array size too large\n", __func__);
+			return -EFAULT;
+		}
+		ret = of_property_read_u32_array(child_node, key,
+				rails[i].levels, rails[i].num_levels);
+		if (ret)
+			goto read_node_fail;
+
+		key = "qcom,min-level";
+		ret = of_property_read_u32(child_node, key,
+				&rails[i].min_level);
+		if (ret)
+			goto read_node_fail;
+
+		key = "qcom,freq-req";
+		rails[i].freq_req = of_property_read_bool(child_node, key);
+
+		if (ret)
+			goto read_node_fail;
+		rails[i].curr_level = 0;
+		rails[i].reg = NULL;
+		i++;
+	}
+
+	if (rails_cnt) {
+		ret = vdd_restriction_reg_init(pdev);
+		if (ret) {
+			pr_info("%s:Failed to get regulators. KTM continues.\n",
+				__func__);
+			goto read_node_fail;
+		}
+		vdd_rstr_enabled = true;
+	}
+read_node_fail:
+	vdd_rstr_probed = true;
+	if (ret) {
+		dev_info(&pdev->dev,
+			"%s:Failed reading node=%s, key=%s. KTM continues\n",
+			__func__, node->full_name, key);
+		kfree(rails);
+		rails_cnt = 0;
+	}
+	if (ret == -EPROBE_DEFER)
+		vdd_rstr_probed = false;
+	return ret;
+}
+
+static int probe_psm(struct device_node *node, struct msm_thermal_data *data,
+		struct platform_device *pdev)
+{
+	int ret = 0;
+	int j = 0;
+	char *key = NULL;
+
+	key = "qcom,pmic-sw-mode-temp";
+	ret = of_property_read_u32(node, key, &data->psm_temp_degC);
+	if (ret)
+		goto read_node_fail;
+
+	key = "qcom,pmic-sw-mode-temp-hysteresis";
+	ret = of_property_read_u32(node, key, &data->psm_temp_hyst_degC);
+	if (ret)
+		goto read_node_fail;
+
+	key = "qcom,pmic-sw-mode-regs";
+	psm_rails_cnt = of_property_count_strings(node, key);
+	psm_rails = kzalloc(sizeof(struct psm_rail) * psm_rails_cnt,
+			GFP_KERNEL);
+	if (!psm_rails) {
+		pr_err("%s: Fail to allocate memory for psm rails\n", __func__);
+		psm_rails_cnt = 0;
+		return -ENOMEM;
+	}
+
+	for (j = 0; j < psm_rails_cnt; j++) {
+		ret = of_property_read_string_index(node, key, j,
+				&psm_rails[j].name);
+		if (ret)
+			goto read_node_fail;
+	}
+
+	if (psm_rails_cnt) {
+		ret = psm_reg_init(pdev);
+		if (ret) {
+			pr_info("%s:Failed to get regulators. KTM continues.\n",
+					__func__);
+			goto read_node_fail;
+		}
+		psm_enabled = true;
+	}
+
+read_node_fail:
+	psm_probed = true;
+	if (ret) {
+		dev_info(&pdev->dev,
+			"%s:Failed reading node=%s, key=%s. KTM continues\n",
+			__func__, node->full_name, key);
+		kfree(psm_rails);
+		psm_rails_cnt = 0;
+	}
+	if (ret == -EPROBE_DEFER)
+		psm_probed = false;
 	return ret;
 }
 
@@ -198,14 +1354,15 @@
 	int ret = 0;
 	char *key = NULL;
 	struct device_node *node = pdev->dev.of_node;
+
 	struct msm_thermal_data data;
 
 	memset(&data, 0, sizeof(struct msm_thermal_data));
+
 	key = "qcom,sensor-id";
 	ret = of_property_read_u32(node, key, &data.sensor_id);
 	if (ret)
 		goto fail;
-	WARN_ON(data.sensor_id >= TSENS_MAX_SENSORS);
 
 	key = "qcom,poll-ms";
 	ret = of_property_read_u32(node, key, &data.poll_ms);
@@ -224,17 +1381,50 @@
 
 	key = "qcom,freq-step";
 	ret = of_property_read_u32(node, key, &data.freq_step);
+	if (ret)
+		goto fail;
 
+	key = "qcom,core-limit-temp";
+	ret = of_property_read_u32(node, key, &data.core_limit_temp_degC);
+
+	key = "qcom,core-temp-hysteresis";
+	ret = of_property_read_u32(node, key, &data.core_temp_hysteresis_degC);
+
+	key = "qcom,core-control-mask";
+	ret = of_property_read_u32(node, key, &data.core_control_mask);
+
+	/* Probe optional properties below. Call probe_psm before
+	 * probe_vdd_rstr because rpm_regulator_get has to be called
+	 * before devm_regulator_get*/
+	ret = probe_psm(node, &data, pdev);
+	if (ret == -EPROBE_DEFER)
+		goto fail;
+	ret = probe_vdd_rstr(node, &data, pdev);
+	if (ret == -EPROBE_DEFER)
+		goto fail;
+
+	/* In case sysfs add nodes get called before probe function.
+	 * Need to make sure sysfs node is created again */
+	if (psm_nodes_called) {
+		msm_thermal_add_psm_nodes();
+		psm_nodes_called = false;
+	}
+	if (vdd_rstr_nodes_called) {
+		msm_thermal_add_vdd_rstr_nodes();
+		vdd_rstr_nodes_called = false;
+	}
+	ret = msm_thermal_init(&data);
+
+	return ret;
 fail:
 	if (ret)
 		pr_err("%s: Failed reading node=%s, key=%s\n",
-		       __func__, node->full_name, key);
-	else
-		ret = msm_thermal_init(&data);
+			__func__, node->full_name, key);
 
 	return ret;
 }
 
+
 static struct of_device_id msm_thermal_match_table[] = {
 	{.compatible = "qcom,msm-thermal"},
 	{},
@@ -253,3 +1443,14 @@
 {
 	return platform_driver_register(&msm_thermal_device_driver);
 }
+
+int __init msm_thermal_late_init(void)
+{
+	msm_thermal_add_cc_nodes();
+	msm_thermal_add_psm_nodes();
+	msm_thermal_add_vdd_rstr_nodes();
+
+	return 0;
+}
+late_initcall(msm_thermal_late_init);
+
diff --git a/drivers/thermal/pm8xxx-tm.c b/drivers/thermal/pm8xxx-tm.c
index 4568933..99a9454 100644
--- a/drivers/thermal/pm8xxx-tm.c
+++ b/drivers/thermal/pm8xxx-tm.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -682,6 +682,13 @@
 	return 0;
 }
 
+static void pm8xxx_tm_shutdown(struct platform_device *pdev)
+{
+	struct pm8xxx_tm_chip *chip = platform_get_drvdata(pdev);
+
+	pm8xxx_tm_write_pwm(chip, TEMP_ALARM_PWM_EN_NEVER);
+}
+
 #ifdef CONFIG_PM
 static int pm8xxx_tm_suspend(struct device *dev)
 {
@@ -719,6 +726,7 @@
 static struct platform_driver pm8xxx_tm_driver = {
 	.probe	= pm8xxx_tm_probe,
 	.remove	= __devexit_p(pm8xxx_tm_remove),
+	.shutdown = pm8xxx_tm_shutdown,
 	.driver	= {
 		.name = PM8XXX_TM_DEV_NAME,
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 569f200..3cad3ce 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -98,6 +98,32 @@
 	}
 }
 
+static void ci13xxx_msm_reset(void)
+{
+	struct ci13xxx *udc = _udc;
+	struct usb_phy *phy = udc->transceiver;
+	struct device *dev = udc->gadget.dev.parent;
+
+	writel_relaxed(0, USB_AHBBURST);
+	writel_relaxed(0x08, USB_AHBMODE);
+
+	if (phy && (phy->flags & ENABLE_SECONDARY_PHY)) {
+		int	temp;
+
+		dev_dbg(dev, "using secondary hsphy\n");
+		temp = readl_relaxed(USB_PHY_CTRL2);
+		temp |= (1<<16);
+		writel_relaxed(temp, USB_PHY_CTRL2);
+
+		/*
+		 * Add memory barrier to make sure above LINK writes are
+		 * complete before moving ahead with USB peripheral mode
+		 * enumeration.
+		 */
+		mb();
+	}
+}
+
 static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
 {
 	struct device *dev = udc->gadget.dev.parent;
@@ -105,8 +131,7 @@
 	switch (event) {
 	case CI13XXX_CONTROLLER_RESET_EVENT:
 		dev_info(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
-		writel(0, USB_AHBBURST);
-		writel_relaxed(0x08, USB_AHBMODE);
+		ci13xxx_msm_reset();
 		break;
 	case CI13XXX_CONTROLLER_DISCONNECT_EVENT:
 		dev_info(dev, "CI13XXX_CONTROLLER_DISCONNECT_EVENT received\n");
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index 5a3d753..22f8dc9 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -1703,6 +1703,7 @@
 		ntb_parameters.dwNtbInMaxSize =
 		cpu_to_le32(NTB_DEFAULT_IN_SIZE_IPA);
 		ntb_parameters.dwNtbOutMaxSize = cpu_to_le32(NTB_OUT_SIZE_IPA);
+		ntb_parameters.wNdpInDivisor = 1;
 	}
 
 	INIT_LIST_HEAD(&mbim->cpkt_req_q);
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 2dccca8..f095efb 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -301,6 +301,7 @@
 	int	ret;
 	int	port_idx;
 	int	i;
+	u8 base;
 
 	pr_debug("%s: bam ports: %u bam2bam ports: %u data hsic ports: %u data hsuart ports: %u"
 		" smd ports: %u ctrl hsic ports: %u ctrl hsuart ports: %u"
@@ -317,9 +318,13 @@
 	}
 
 	if (no_ctrl_smd_ports) {
-		ret = gsmd_ctrl_setup(no_ctrl_smd_ports);
+		ret = gsmd_ctrl_setup(FRMNET_CTRL_CLIENT,
+				no_ctrl_smd_ports, &base);
 		if (ret)
 			return ret;
+		for (i = 0; i < nr_rmnet_ports; i++)
+			if (rmnet_ports[i].port)
+				rmnet_ports[i].port->port_num += base;
 	}
 
 	if (no_data_hsic_ports) {
diff --git a/drivers/usb/gadget/u_rmnet.h b/drivers/usb/gadget/u_rmnet.h
index a9cca50..98307d3 100644
--- a/drivers/usb/gadget/u_rmnet.h
+++ b/drivers/usb/gadget/u_rmnet.h
@@ -46,6 +46,12 @@
 	void (*connect)(struct grmnet *g);
 };
 
+enum ctrl_client {
+	FRMNET_CTRL_CLIENT,
+
+	NR_CTRL_CLIENTS
+};
+
 int gbam_setup(unsigned int no_bam_port, unsigned int no_bam2bam_port);
 int gbam_connect(struct grmnet *gr, u8 port_num,
 	enum transport_type trans, u8 src_connection_idx,
@@ -56,7 +62,8 @@
 void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans);
 int gsmd_ctrl_connect(struct grmnet *gr, int port_num);
 void gsmd_ctrl_disconnect(struct grmnet *gr, u8 port_num);
-int gsmd_ctrl_setup(unsigned int count);
+int gsmd_ctrl_setup(enum ctrl_client client_num, unsigned int count,
+					u8 *first_port_idx);
 int gqti_ctrl_connect(struct grmnet *gr);
 void gqti_ctrl_disconnect(struct grmnet *gr);
 
diff --git a/drivers/usb/gadget/u_rmnet_ctrl_smd.c b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
index 161634e..9b824bb 100644
--- a/drivers/usb/gadget/u_rmnet_ctrl_smd.c
+++ b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
@@ -24,11 +24,15 @@
 
 #include "u_rmnet.h"
 
-#define NR_CTRL_SMD_PORTS	3
-static int n_rmnet_ctrl_ports;
-static char *rmnet_ctrl_names[] = {"DATA40_CNTL", "DATA39_CNTL", "DATA38_CNTL"};
+#define MAX_CTRL_PER_CLIENT	3
+#define MAX_CTRL_PORT		(MAX_CTRL_PER_CLIENT * NR_CTRL_CLIENTS)
+static char *ctrl_names[NR_CTRL_CLIENTS][MAX_CTRL_PER_CLIENT] = {
+	{"DATA40_CNTL", "DATA39_CNTL", "DATA38_CNTL"},
+};
 static struct workqueue_struct *grmnet_ctrl_wq;
 
+u8 online_clients;
+
 #define SMD_CH_MAX_LEN	20
 #define CH_OPENED	0
 #define CH_READY	1
@@ -68,7 +72,7 @@
 static struct rmnet_ctrl_ports {
 	struct rmnet_ctrl_port *port;
 	struct platform_driver pdrv;
-} ctrl_smd_ports[NR_CTRL_SMD_PORTS];
+} ctrl_smd_ports[MAX_CTRL_PORT];
 
 
 /*---------------misc functions---------------- */
@@ -172,6 +176,15 @@
 	}
 	spin_unlock_irqrestore(&port->port_lock, flags);
 }
+static int is_legal_port_num(u8 portno)
+{
+	if (portno >= MAX_CTRL_PORT)
+		return false;
+	if (ctrl_smd_ports[portno].port == NULL)
+		return false;
+
+	return true;
+}
 
 static int
 grmnet_ctrl_smd_send_cpkt_tomodem(u8 portno,
@@ -182,7 +195,7 @@
 	struct smd_ch_info	*c;
 	struct rmnet_ctrl_pkt *cpkt;
 
-	if (portno >= n_rmnet_ctrl_ports) {
+	if (!is_legal_port_num(portno)) {
 		pr_err("%s: Invalid portno#%d\n", __func__, portno);
 		return -ENODEV;
 	}
@@ -225,7 +238,7 @@
 	int			clear_bits = 0;
 	int			temp = 0;
 
-	if (portno >= n_rmnet_ctrl_ports) {
+	if (!is_legal_port_num(portno)) {
 		pr_err("%s: Invalid portno#%d\n", __func__, portno);
 		return;
 	}
@@ -375,8 +388,8 @@
 
 	pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num);
 
-	if (port_num >= n_rmnet_ctrl_ports) {
-		pr_err("%s: invalid portno#%d\n", __func__, port_num);
+	if (!is_legal_port_num(port_num)) {
+		pr_err("%s: Invalid port_num#%d\n", __func__, port_num);
 		return -ENODEV;
 	}
 
@@ -431,8 +444,8 @@
 
 	pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num);
 
-	if (port_num >= n_rmnet_ctrl_ports) {
-		pr_err("%s: invalid portno#%d\n", __func__, port_num);
+	if (!is_legal_port_num(port_num)) {
+		pr_err("%s: Invalid port_num#%d\n", __func__, port_num);
 		return;
 	}
 
@@ -478,7 +491,10 @@
 
 	pr_debug("%s: name:%s\n", __func__, pdev->name);
 
-	for (i = 0; i < n_rmnet_ctrl_ports; i++) {
+	for (i = 0; i < MAX_CTRL_PORT; i++) {
+		if (!ctrl_smd_ports[i].port)
+			continue;
+
 		port = ctrl_smd_ports[i].port;
 		c = &port->ctrl_ch;
 
@@ -508,7 +524,10 @@
 
 	pr_debug("%s: name:%s\n", __func__, pdev->name);
 
-	for (i = 0; i < n_rmnet_ctrl_ports; i++) {
+	for (i = 0; i < MAX_CTRL_PORT; i++) {
+		if (!ctrl_smd_ports[i].port)
+			continue;
+
 		port = ctrl_smd_ports[i].port;
 		c = &port->ctrl_ch;
 
@@ -555,7 +574,8 @@
 	INIT_DELAYED_WORK(&port->disconnect_w, grmnet_ctrl_smd_disconnect_w);
 
 	c = &port->ctrl_ch;
-	c->name = rmnet_ctrl_names[portno];
+	c->name = ctrl_names[portno / MAX_CTRL_PER_CLIENT]
+						[portno % MAX_CTRL_PER_CLIENT];
 	c->port = port;
 	init_waitqueue_head(&c->wait);
 	INIT_LIST_HEAD(&c->tx_q);
@@ -575,44 +595,54 @@
 	return 0;
 }
 
-int gsmd_ctrl_setup(unsigned int count)
+int gsmd_ctrl_setup(enum ctrl_client client_num, unsigned int count,
+					u8 *first_port_idx)
 {
-	int	i;
+	int	i, start_port, allocated_ports;
 	int	ret;
 
 	pr_debug("%s: requested ports:%d\n", __func__, count);
 
-	if (!count || count > NR_CTRL_SMD_PORTS) {
+	if (!count || count > MAX_CTRL_PER_CLIENT) {
 		pr_err("%s: Invalid num of ports count:%d\n",
 				__func__, count);
 		return -EINVAL;
 	}
 
-	grmnet_ctrl_wq = alloc_workqueue("gsmd_ctrl",
-				WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
-	if (!grmnet_ctrl_wq) {
-		pr_err("%s: Unable to create workqueue grmnet_ctrl\n",
-				__func__);
-		return -ENOMEM;
+	if (!online_clients) {
+		grmnet_ctrl_wq = alloc_workqueue("gsmd_ctrl",
+			WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+		if (!grmnet_ctrl_wq) {
+			pr_err("%s: Unable to create workqueue grmnet_ctrl\n",
+					__func__);
+			return -ENOMEM;
+		}
 	}
+	online_clients++;
 
-	for (i = 0; i < count; i++) {
-		n_rmnet_ctrl_ports++;
+	start_port = MAX_CTRL_PER_CLIENT * client_num;
+	allocated_ports = 0;
+	for (i = start_port; i < count + start_port; i++) {
+		allocated_ports++;
 		ret = grmnet_ctrl_smd_port_alloc(i);
 		if (ret) {
 			pr_err("%s: Unable to alloc port:%d\n", __func__, i);
-			n_rmnet_ctrl_ports--;
+			allocated_ports--;
 			goto free_ctrl_smd_ports;
 		}
 	}
-
+	if (first_port_idx)
+		*first_port_idx = start_port;
 	return 0;
 
 free_ctrl_smd_ports:
-	for (i = 0; i < n_rmnet_ctrl_ports; i++)
-		grmnet_ctrl_smd_port_free(i);
+	for (i = 0; i < allocated_ports; i++)
+		grmnet_ctrl_smd_port_free(start_port + i);
 
-	destroy_workqueue(grmnet_ctrl_wq);
+
+	online_clients--;
+	if (!online_clients)
+		destroy_workqueue(grmnet_ctrl_wq);
 
 	return ret;
 }
@@ -634,10 +664,11 @@
 	if (!buf)
 		return -ENOMEM;
 
-	for (i = 0; i < n_rmnet_ctrl_ports; i++) {
-		port = ctrl_smd_ports[i].port;
-		if (!port)
+	for (i = 0; i < MAX_CTRL_PORT; i++) {
+		if (!ctrl_smd_ports[i].port)
 			continue;
+		port = ctrl_smd_ports[i].port;
+
 		spin_lock_irqsave(&port->port_lock, flags);
 
 		c = &port->ctrl_ch;
@@ -677,10 +708,10 @@
 	int			i;
 	unsigned long		flags;
 
-	for (i = 0; i < n_rmnet_ctrl_ports; i++) {
-		port = ctrl_smd_ports[i].port;
-		if (!port)
+	for (i = 0; i < MAX_CTRL_PORT; i++) {
+		if (!ctrl_smd_ports[i].port)
 			continue;
+		port = ctrl_smd_ports[i].port;
 
 		spin_lock_irqsave(&port->port_lock, flags);
 
@@ -727,6 +758,7 @@
 static int __init gsmd_ctrl_init(void)
 {
 	gsmd_ctrl_debugfs_init();
+	online_clients = 0;
 
 	return 0;
 }
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index cae2c17..4865b03 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -478,6 +478,7 @@
 	u32 val;
 	int ret;
 	int retries;
+	struct msm_otg_platform_data *pdata = motg->pdata;
 
 	ret = msm_otg_link_clk_reset(motg, 1);
 	if (ret)
@@ -496,6 +497,9 @@
 	if (ret)
 		return ret;
 
+	if (pdata && pdata->enable_sec_phy)
+		writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
+							USB_PHY_CTRL2);
 	val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
 	writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
 
@@ -535,6 +539,7 @@
 static int msm_otg_link_reset(struct msm_otg *motg)
 {
 	int cnt = 0;
+	struct msm_otg_platform_data *pdata = motg->pdata;
 
 	writel_relaxed(USBCMD_RESET, USB_USBCMD);
 	while (cnt < LINK_RESET_TIMEOUT_USEC) {
@@ -551,6 +556,9 @@
 	writel_relaxed(0x0, USB_AHBBURST);
 	writel_relaxed(0x08, USB_AHBMODE);
 
+	if (pdata && pdata->enable_sec_phy)
+		writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
+								USB_PHY_CTRL2);
 	return 0;
 }
 
@@ -3784,8 +3792,6 @@
 				&pdata->default_mode);
 	of_property_read_u32(node, "qcom,hsusb-otg-phy-type",
 				&pdata->phy_type);
-	of_property_read_u32(node, "qcom,hsusb-otg-pmic-id-irq",
-				&pdata->pmic_id_irq);
 	pdata->disable_reset_on_disconnect = of_property_read_bool(node,
 				"qcom,hsusb-otg-disable-reset");
 	pdata->pnoc_errata_fix = of_property_read_bool(node,
@@ -3798,6 +3804,12 @@
 				"qcom,hsusb-otg-delay-lpm");
 	pdata->dp_manual_pullup = of_property_read_bool(node,
 				"qcom,dp-manual-pullup");
+	pdata->enable_sec_phy = of_property_read_bool(node,
+					"qcom,usb2-enable-hsphy2");
+
+	pdata->pmic_id_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
+	if (pdata->pmic_id_irq < 0)
+		pdata->pmic_id_irq = 0;
 
 	return pdata;
 }
@@ -4093,6 +4105,9 @@
 	if (pdata->dp_manual_pullup)
 		phy->flags |= ENABLE_DP_MANUAL_PULLUP;
 
+	if (pdata->enable_sec_phy)
+		phy->flags |= ENABLE_SECONDARY_PHY;
+
 	ret = usb_set_transceiver(&motg->phy);
 	if (ret) {
 		dev_err(&pdev->dev, "usb_set_transceiver failed\n");
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index 0b2a7c0..0918db1 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -286,6 +286,96 @@
 	return -ENODEV;
 }
 
+
+static int mdss_debug_stat_open(struct inode *inode, struct file *file)
+{
+	/* non-seekable */
+	file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static int mdss_debug_stat_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int mdss_debug_stat_ctl_dump(struct mdss_mdp_ctl *ctl,
+		char *bp, int len)
+{
+	int tot = 0;
+
+	if (!ctl->ref_cnt)
+		return 0;
+
+	if (ctl->intf_num) {
+		tot = scnprintf(bp, len,
+			"intf%d: play: %08u \tvsync: %08u \tunderrun: %08u\n",
+				ctl->intf_num, ctl->play_cnt,
+				ctl->vsync_cnt, ctl->underrun_cnt);
+	} else {
+		tot = scnprintf(bp, len, "wb: \tmode=%x \tplay: %08u\n",
+				ctl->opmode, ctl->play_cnt);
+	}
+
+	return tot;
+}
+
+static ssize_t mdss_debug_stat_read(struct file *file, char __user *buff,
+		size_t count, loff_t *ppos)
+{
+	struct mdss_data_type *mdata = file->private_data;
+	struct mdss_mdp_pipe *pipe;
+	int i, len, tot;
+	char bp[512];
+
+	if (*ppos)
+		return 0;	/* the end */
+
+	len = sizeof(bp);
+
+	tot = scnprintf(bp, len, "\nmdp:\n");
+
+	for (i = 0; i < mdata->nctl; i++)
+		tot += mdss_debug_stat_ctl_dump(mdata->ctl_off + i,
+				bp + tot, len - tot);
+	tot += scnprintf(bp + tot, len - tot, "\n");
+
+	for (i = 0; i < mdata->nvig_pipes; i++) {
+		pipe = mdata->vig_pipes + i;
+		tot += scnprintf(bp + tot, len - tot,
+			"VIG%d :   %08u\t", i, pipe->play_cnt);
+	}
+	tot += scnprintf(bp + tot, len - tot, "\n");
+
+	for (i = 0; i < mdata->nrgb_pipes; i++) {
+		pipe = mdata->rgb_pipes + i;
+		tot += scnprintf(bp + tot, len - tot,
+			"RGB%d :   %08u\t", i, pipe->play_cnt);
+	}
+	tot += scnprintf(bp + tot, len - tot, "\n");
+
+	for (i = 0; i < mdata->ndma_pipes; i++) {
+		pipe = mdata->dma_pipes + i;
+		tot += scnprintf(bp + tot, len - tot,
+			"DMA%d :   %08u\t", i, pipe->play_cnt);
+	}
+	tot += scnprintf(bp + tot, len - tot, "\n");
+
+	if (copy_to_user(buff, bp, tot))
+		return -EFAULT;
+
+	*ppos += tot;	/* increase offset */
+
+	return tot;
+}
+
+static const struct file_operations mdss_stat_fops = {
+	.open = mdss_debug_stat_open,
+	.release = mdss_debug_stat_release,
+	.read = mdss_debug_stat_read,
+};
+
 static int mdss_debugfs_cleanup(struct mdss_debug_data *mdd)
 {
 	struct mdss_debug_base *base, *tmp;
@@ -330,6 +420,7 @@
 		mdss_debugfs_cleanup(mdd);
 		return -ENODEV;
 	}
+	debugfs_create_file("stat", 0644, mdd->root, mdata, &mdss_stat_fops);
 
 	debugfs_create_u32("min_mdp_clk", 0644, mdd->root,
 		(u32 *)&mdata->min_mdp_clk);
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 51776db..baedd03 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -878,6 +878,7 @@
 {
 	int i, j;
 	char *offset;
+	struct mdss_mdp_pipe *vig;
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 	mdata->mdp_rev = MDSS_MDP_REG_READ(MDSS_MDP_REG_HW_VERSION);
@@ -899,7 +900,16 @@
 			writel_relaxed(j, offset);
 
 		/* swap */
-		writel_relaxed(i, offset + 4);
+		writel_relaxed(1, offset + 4);
+	}
+	vig = mdata->vig_pipes;
+	for (i = 0; i < mdata->nvig_pipes; i++) {
+		offset = vig[i].base +
+			MDSS_MDP_REG_VIG_HIST_LUT_BASE;
+		for (j = 0; j < ENHIST_LUT_ENTRIES; j++)
+			writel_relaxed(j, offset);
+		/* swap */
+		writel_relaxed(1, offset + 16);
 	}
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 	pr_debug("MDP hw init done\n");
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 07b083a..175a07f 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -122,6 +122,7 @@
 	u32 flush_bits;
 
 	u32 play_cnt;
+	u32 vsync_cnt;
 	u32 underrun_cnt;
 
 	u16 width;
@@ -217,6 +218,21 @@
 	struct mdss_mdp_img_data p[MAX_PLANES];
 };
 
+struct pp_hist_col_info {
+	u32 col_state;
+	u32 col_en;
+	u32 read_request;
+	u32 hist_cnt_read;
+	u32 hist_cnt_sent;
+	u32 hist_cnt_time;
+	u32 frame_cnt;
+	u32 is_kick_ready;
+	struct completion comp;
+	u32 data[HIST_V_SIZE];
+	struct mutex hist_mutex;
+	spinlock_t hist_lock;
+};
+
 struct pp_sts_type {
 	u32 pa_sts;
 	u32 pcc_sts;
@@ -233,6 +249,8 @@
 struct mdss_pipe_pp_res {
 	u32 igc_c0_c1[IGC_LUT_ENTRIES];
 	u32 igc_c2[IGC_LUT_ENTRIES];
+	u32 hist_lut[ENHIST_LUT_ENTRIES];
+	struct pp_hist_col_info hist;
 	struct pp_sts_type pp_sts;
 };
 
@@ -421,13 +439,14 @@
 				struct mdp_histogram_start_req *req);
 int mdss_mdp_histogram_stop(struct mdss_mdp_ctl *ctl, u32 block);
 int mdss_mdp_hist_collect(struct mdss_mdp_ctl *ctl,
-				struct mdp_histogram_data *hist,
-				u32 *hist_data_addr);
+				struct mdp_histogram_data *hist);
 void mdss_mdp_hist_intr_done(u32 isr);
 
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(struct mdss_mdp_mixer *mixer,
 					  u32 type);
 struct mdss_mdp_pipe *mdss_mdp_pipe_get(struct mdss_data_type *mdata, u32 ndx);
+struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
+						  u32 ndx);
 int mdss_mdp_pipe_map(struct mdss_mdp_pipe *pipe);
 void mdss_mdp_pipe_unmap(struct mdss_mdp_pipe *pipe);
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_dma(struct mdss_mdp_mixer *mixer);
@@ -449,6 +468,8 @@
 			     struct mdss_mdp_plane_sizes *ps, u32 bwc_mode);
 int mdss_mdp_get_rau_strides(u32 w, u32 h, struct mdss_mdp_format_params *fmt,
 			       struct mdss_mdp_plane_sizes *ps);
+void mdss_mdp_data_calc_offset(struct mdss_mdp_data *data, u16 x, u16 y,
+	struct mdss_mdp_plane_sizes *ps, struct mdss_mdp_format_params *fmt);
 struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format);
 int mdss_mdp_put_img(struct mdss_mdp_img_data *data);
 int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 4e51100..03a33cd 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -279,8 +279,6 @@
 		return -EINVAL;
 	}
 
-	mutex_lock(&mdss_mdp_ctl_lock);
-	ctl->ref_cnt--;
 	if (ctl->mixer_left) {
 		mdss_mdp_mixer_free(ctl->mixer_left);
 		ctl->mixer_left = NULL;
@@ -289,6 +287,8 @@
 		mdss_mdp_mixer_free(ctl->mixer_right);
 		ctl->mixer_right = NULL;
 	}
+	mutex_lock(&mdss_mdp_ctl_lock);
+	ctl->ref_cnt--;
 	ctl->power_on = false;
 	ctl->start_fnc = NULL;
 	ctl->stop_fnc = NULL;
@@ -437,7 +437,6 @@
 	if (ctl->stop_fnc)
 		ctl->stop_fnc(ctl);
 
-	mdss_mdp_mixer_free(mixer);
 	mdss_mdp_ctl_free(ctl);
 
 	mdss_mdp_ctl_perf_commit(ctl->mdata, MDSS_MDP_PERF_UPDATE_ALL);
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index d6b0fb2..006a8dd 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -180,6 +180,7 @@
 	pr_debug("%s: ctl=%d intf_num=%d\n", __func__, ctl->num, ctl->intf_num);
 
 	vsync_time = ktime_get();
+	ctl->vsync_cnt++;
 
 	spin_lock(&ctx->vsync_lock);
 	if (ctx->vsync_handler)
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 0426784..6e631e9 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -282,8 +282,9 @@
 	}
 
 	vsync_time = ktime_get();
+	ctl->vsync_cnt++;
 
-	pr_debug("intr ctl=%d\n", ctl->num);
+	pr_debug("intr ctl=%d vsync cnt=%u\n", ctl->num, ctl->vsync_cnt);
 
 	complete_all(&ctx->vsync_comp);
 	spin_lock(&ctx->vsync_lock);
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index 7fbb031..b3f15a7 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -33,9 +33,11 @@
 	u32 intf_num;
 
 	u32 opmode;
-	u32 format;
+	struct mdss_mdp_format_params *dst_fmt;
 	u16 width;
 	u16 height;
+	struct mdss_mdp_img_rect dst_rect;
+
 	u8 rot90;
 	u32 bwc_mode;
 	int initialized;
@@ -81,48 +83,55 @@
 }
 
 static int mdss_mdp_writeback_addr_setup(struct mdss_mdp_writeback_ctx *ctx,
-					 struct mdss_mdp_data *data)
+					 const struct mdss_mdp_data *in_data)
 {
 	int ret;
+	struct mdss_mdp_data data;
 
-	if (!data)
+	if (!in_data)
 		return -EINVAL;
+	data = *in_data;
 
-	pr_debug("wb_num=%d addr=0x%x\n", ctx->wb_num, data->p[0].addr);
+	pr_debug("wb_num=%d addr=0x%x\n", ctx->wb_num, data.p[0].addr);
 
 	if (ctx->bwc_mode)
-		data->bwc_enabled = 1;
+		data.bwc_enabled = 1;
 
-	ret = mdss_mdp_data_check(data, &ctx->dst_planes);
+	ret = mdss_mdp_data_check(&data, &ctx->dst_planes);
 	if (ret)
 		return ret;
 
-	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST0_ADDR, data->p[0].addr);
-	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST1_ADDR, data->p[1].addr);
-	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST2_ADDR, data->p[2].addr);
-	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST3_ADDR, data->p[3].addr);
+	mdss_mdp_data_calc_offset(&data, ctx->dst_rect.x, ctx->dst_rect.y,
+			&ctx->dst_planes, ctx->dst_fmt);
+
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST0_ADDR, data.p[0].addr);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST1_ADDR, data.p[1].addr);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST2_ADDR, data.p[2].addr);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST3_ADDR, data.p[3].addr);
 
 	return 0;
 }
 
-static int mdss_mdp_writeback_format_setup(struct mdss_mdp_writeback_ctx *ctx)
+static int mdss_mdp_writeback_format_setup(struct mdss_mdp_writeback_ctx *ctx,
+		u32 format)
 {
 	struct mdss_mdp_format_params *fmt;
 	u32 dst_format, pattern, ystride0, ystride1, outsize, chroma_samp;
 	u32 opmode = ctx->opmode;
 	struct mdss_data_type *mdata;
 
-	pr_debug("wb_num=%d format=%d\n", ctx->wb_num, ctx->format);
+	pr_debug("wb_num=%d format=%d\n", ctx->wb_num, format);
 
-	mdss_mdp_get_plane_sizes(ctx->format, ctx->width, ctx->height,
+	mdss_mdp_get_plane_sizes(format, ctx->width, ctx->height,
 				 &ctx->dst_planes,
 				 ctx->opmode & MDSS_MDP_OP_BWC_EN);
 
-	fmt = mdss_mdp_get_format_params(ctx->format);
+	fmt = mdss_mdp_get_format_params(format);
 	if (!fmt) {
-		pr_err("wb format=%d not supported\n", ctx->format);
+		pr_err("wb format=%d not supported\n", format);
 		return -EINVAL;
 	}
+	ctx->dst_fmt = fmt;
 
 	chroma_samp = fmt->chroma_sample;
 
@@ -190,7 +199,7 @@
 		   (ctx->dst_planes.ystride[1] << 16);
 	ystride1 = (ctx->dst_planes.ystride[2]) |
 		   (ctx->dst_planes.ystride[3] << 16);
-	outsize = (ctx->height << 16) | ctx->width;
+	outsize = (ctx->dst_rect.h << 16) | ctx->dst_rect.w;
 
 	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST_FORMAT, dst_format);
 	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST_OP_MODE, opmode);
@@ -217,11 +226,14 @@
 	pr_debug("wfd setup ctl=%d\n", ctl->num);
 
 	ctx->opmode = 0;
-	ctx->format = ctl->dst_format;
 	ctx->width = ctl->width;
 	ctx->height = ctl->height;
+	ctx->dst_rect.x = 0;
+	ctx->dst_rect.y = 0;
+	ctx->dst_rect.w = ctx->width;
+	ctx->dst_rect.h = ctx->height;
 
-	ret = mdss_mdp_writeback_format_setup(ctx);
+	ret = mdss_mdp_writeback_format_setup(ctx, ctl->dst_format);
 	if (ret) {
 		pr_err("format setup failed\n");
 		return ret;
@@ -237,6 +249,7 @@
 	struct mdss_mdp_writeback_ctx *ctx;
 	struct mdss_mdp_writeback_arg *wb_args;
 	struct mdss_mdp_rotator_session *rot;
+	u32 format;
 
 	ctx = (struct mdss_mdp_writeback_ctx *) ctl->priv_data;
 	if (!ctx)
@@ -259,24 +272,26 @@
 	ctx->bwc_mode = rot->bwc_mode;
 	ctx->opmode |= ctx->bwc_mode;
 
-	ctx->width = rot->src_rect.w;
-	ctx->height = rot->src_rect.h;
-
-	ctx->format = rot->format;
+	ctx->width = rot->dst.w;
+	ctx->height = rot->dst.h;
+	ctx->dst_rect.x = rot->dst.x;
+	ctx->dst_rect.y = rot->dst.y;
+	ctx->dst_rect.w = rot->src_rect.w;
+	ctx->dst_rect.h = rot->src_rect.h;
 
 	ctx->rot90 = !!(rot->flags & MDP_ROT_90);
 
 	if (ctx->bwc_mode || ctx->rot90)
-		ctx->format = mdss_mdp_get_rotator_dst_format(rot->format);
+		format = mdss_mdp_get_rotator_dst_format(rot->format);
 	else
-		ctx->format = rot->format;
+		format = rot->format;
 
 	if (ctx->rot90) {
 		ctx->opmode |= BIT(5); /* ROT 90 */
-		swap(ctx->width, ctx->height);
+		swap(ctx->dst_rect.w, ctx->dst_rect.h);
 	}
 
-	return mdss_mdp_writeback_format_setup(ctx);
+	return mdss_mdp_writeback_format_setup(ctx, format);
 }
 
 static int mdss_mdp_writeback_stop(struct mdss_mdp_ctl *ctl)
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index dae3e05..3cce4f9 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -92,8 +92,7 @@
 		return -EOVERFLOW;
 	}
 
-	if (req->dst_rect.w < min_dst_size || req->dst_rect.h < min_dst_size ||
-	    req->dst_rect.w > MAX_DST_W || req->dst_rect.h > MAX_DST_H) {
+	if (req->dst_rect.w < min_dst_size || req->dst_rect.h < min_dst_size) {
 		pr_err("invalid destination resolution (%dx%d)",
 		       req->dst_rect.w, req->dst_rect.h);
 		return -EOVERFLOW;
@@ -227,9 +226,13 @@
 		rot->src_rect.h /= 2;
 	}
 
-	rot->params_changed++;
-
-	req->id = rot->session_id;
+	ret = mdss_mdp_rotator_setup(rot);
+	if (ret == 0) {
+		req->id = rot->session_id;
+	} else {
+		pr_err("Unable to setup rotator session\n");
+		mdss_mdp_rotator_release(rot->session_id);
+	}
 
 	return ret;
 }
@@ -243,11 +246,23 @@
 	struct mdss_mdp_mixer *mixer = NULL;
 	u32 pipe_type, mixer_mux, len, src_format;
 	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+	struct mdp_histogram_start_req hist;
 	int ret;
 
 	if (mdp5_data->ctl == NULL)
 		return -ENODEV;
 
+	if (req->flags & MDP_ROT_90) {
+		pr_err("unsupported inline rotation\n");
+		return -ENOTSUPP;
+	}
+
+	if ((req->dst_rect.w > MAX_DST_W) || (req->dst_rect.h > MAX_DST_H)) {
+		pr_err("exceeded max mixer supported resolution %dx%d\n",
+				req->dst_rect.w, req->dst_rect.h);
+		return -EOVERFLOW;
+	}
+
 	if (req->flags & MDSS_MDP_RIGHT_MIXER)
 		mixer_mux = MDSS_MDP_MIXER_MUX_RIGHT;
 	else
@@ -256,11 +271,6 @@
 	pr_debug("pipe ctl=%u req id=%x mux=%d\n", mdp5_data->ctl->num, req->id,
 			mixer_mux);
 
-	if (req->flags & MDP_ROT_90) {
-		pr_err("unsupported inline rotation\n");
-		return -ENOTSUPP;
-	}
-
 	src_format = req->src.format;
 	if (req->flags & (MDP_SOURCE_ROTATED_90 | MDP_BWC_EN))
 		src_format = mdss_mdp_get_rotator_dst_format(src_format);
@@ -365,7 +375,8 @@
 	pipe->is_fg = req->is_fg;
 	pipe->alpha = req->alpha;
 	pipe->transp = req->transp_mask;
-	pipe->overfetch_disable = fmt->is_yuv;
+	pipe->overfetch_disable = fmt->is_yuv &&
+			!(pipe->flags & MDP_SOURCE_ROTATED_90);
 
 	pipe->req_data = *req;
 
@@ -389,6 +400,31 @@
 							pipe->pp_res.igc_c0_c1;
 			pipe->pp_cfg.igc_cfg.c2_data = pipe->pp_res.igc_c2;
 		}
+		if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_HIST_CFG) {
+			if (pipe->pp_cfg.hist_cfg.ops & MDP_PP_OPS_ENABLE) {
+				hist.block = pipe->pp_cfg.hist_cfg.block;
+				hist.frame_cnt =
+					pipe->pp_cfg.hist_cfg.frame_cnt;
+				hist.bit_mask = pipe->pp_cfg.hist_cfg.bit_mask;
+				hist.num_bins = pipe->pp_cfg.hist_cfg.num_bins;
+				mdss_mdp_histogram_start(pipe->mixer->ctl,
+									&hist);
+			} else if (pipe->pp_cfg.hist_cfg.ops &
+							MDP_PP_OPS_DISABLE) {
+				mdss_mdp_histogram_stop(pipe->mixer->ctl,
+						pipe->pp_cfg.hist_cfg.block);
+			}
+		}
+		len = pipe->pp_cfg.hist_lut_cfg.len;
+		if ((pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_HIST_LUT_CFG) &&
+						(len == ENHIST_LUT_ENTRIES)) {
+			ret = copy_from_user(pipe->pp_res.hist_lut,
+					pipe->pp_cfg.hist_lut_cfg.data,
+					sizeof(uint32_t) * len);
+			if (ret)
+				return -ENOMEM;
+			pipe->pp_cfg.hist_lut_cfg.data = pipe->pp_res.hist_lut;
+		}
 	}
 
 	if (pipe->flags & MDP_DEINTERLACE) {
@@ -1457,7 +1493,7 @@
 	int ret = -ENOSYS;
 	struct mdp_histogram_data hist;
 	struct mdp_histogram_start_req hist_req;
-	u32 block, hist_data_addr = 0;
+	u32 block;
 	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
 
 	switch (cmd) {
@@ -1488,15 +1524,9 @@
 		if (ret)
 			return ret;
 
-		ret = mdss_mdp_hist_collect(mdp5_data->ctl, &hist,
-					&hist_data_addr);
-		if ((ret == 0) && hist_data_addr) {
-			ret = copy_to_user(hist.c0, (u32 *)hist_data_addr,
-				sizeof(u32) * hist.bin_cnt);
-			if (ret == 0)
-				ret = copy_to_user(argp, &hist,
-						   sizeof(hist));
-		}
+		ret = mdss_mdp_hist_collect(mdp5_data->ctl, &hist);
+		if (!ret)
+			ret = copy_to_user(argp, &hist, sizeof(hist));
 		break;
 	default:
 		break;
@@ -1583,10 +1613,8 @@
 				ret = copy_to_user(argp, &req, sizeof(req));
 		}
 
-		if (ret) {
+		if (ret)
 			pr_debug("OVERLAY_GET failed (%d)\n", ret);
-			ret = -EFAULT;
-		}
 		break;
 
 	case MSMFB_OVERLAY_SET:
@@ -1597,10 +1625,8 @@
 			if (!IS_ERR_VALUE(ret))
 				ret = copy_to_user(argp, &req, sizeof(req));
 		}
-		if (ret) {
+		if (ret)
 			pr_debug("OVERLAY_SET failed (%d)\n", ret);
-			ret = -EFAULT;
-		}
 		break;
 
 
@@ -1629,10 +1655,8 @@
 					mdss_fb_update_backlight(mfd);
 			}
 
-			if (ret) {
+			if (ret)
 				pr_debug("OVERLAY_PLAY failed (%d)\n", ret);
-				ret = -EFAULT;
-			}
 		} else {
 			ret = 0;
 		}
@@ -1646,10 +1670,8 @@
 			if (!ret)
 				ret = mdss_mdp_overlay_play_wait(mfd, &data);
 
-			if (ret) {
+			if (ret)
 				pr_err("OVERLAY_PLAY_WAIT failed (%d)\n", ret);
-				ret = -EFAULT;
-			}
 		} else {
 			ret = 0;
 		}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index b169c43..242972b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -27,8 +27,6 @@
 static DEFINE_MUTEX(mdss_mdp_smp_lock);
 static DECLARE_BITMAP(mdss_mdp_smp_mmb_pool, MDSS_MDP_SMP_MMB_BLOCKS);
 
-static struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
-						  u32 ndx);
 static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
 
 static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
@@ -257,9 +255,11 @@
 		pipe = NULL;
 	}
 
-	if (pipe)
-		pr_debug("type=%x   pnum=%d\n", pipe->type, pipe->num);
-	else
+	if (pipe) {
+		pr_info("type=%x   pnum=%d\n", pipe->type, pipe->num);
+		mutex_init(&pipe->pp_res.hist.hist_mutex);
+		spin_lock_init(&pipe->pp_res.hist.hist_lock);
+	} else
 		pr_err("no %d type pipes available\n", type);
 
 	return pipe;
@@ -318,7 +318,7 @@
 	return pipe;
 }
 
-static struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
+struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
 						  u32 ndx)
 {
 	u32 i;
@@ -487,28 +487,6 @@
 	return 0;
 }
 
-static void mdss_mdp_addr_add_offset(struct mdss_mdp_pipe *pipe,
-				    struct mdss_mdp_data *data)
-{
-	data->p[0].addr += pipe->src.x +
-		(pipe->src.y * pipe->src_planes.ystride[0]);
-	if (data->num_planes > 1) {
-		u8 hmap[] = { 1, 2, 1, 2 };
-		u8 vmap[] = { 1, 1, 2, 2 };
-		u16 xoff = pipe->src.x / hmap[pipe->src_fmt->chroma_sample];
-		u16 yoff = pipe->src.y / vmap[pipe->src_fmt->chroma_sample];
-
-		if (data->num_planes == 2) /* pseudo planar */
-			xoff *= 2;
-		data->p[1].addr += xoff + (yoff * pipe->src_planes.ystride[1]);
-
-		if (data->num_planes > 2) { /* planar */
-			data->p[2].addr += xoff +
-				(yoff * pipe->src_planes.ystride[2]);
-		}
-	}
-}
-
 int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata, u32 *offsets,
 				u32 *ftch_id, u32 type, u32 num_base, u32 len)
 {
@@ -571,7 +549,8 @@
 		return ret;
 
 	if (pipe->overfetch_disable)
-		mdss_mdp_addr_add_offset(pipe, data);
+		mdss_mdp_data_calc_offset(data, pipe->src.x, pipe->src.y,
+			&pipe->src_planes, pipe->src_fmt);
 
 	/* planar format expects YCbCr, swap chroma planes if YCrCb */
 	if (!is_rot && (pipe->src_fmt->fetch_planes == MDSS_MDP_PLANE_PLANAR) &&
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 2c0d5e0..cf9a8b6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -78,7 +78,7 @@
 
 #define MDSS_BLOCK_DISP_NUM	(MDP_BLOCK_MAX - MDP_LOGICAL_BLOCK_DISP_0)
 
-#define HIST_WAIT_TIMEOUT(frame) ((60 * HZ * (frame)) / 1000)
+#define HIST_WAIT_TIMEOUT(frame) ((75 * HZ * (frame)) / 1000)
 /* hist collect state */
 enum {
 	HIST_UNKNOWN,
@@ -88,18 +88,6 @@
 	HIST_READY,
 };
 
-struct pp_hist_col_info {
-	u32 col_state;
-	u32 col_en;
-	u32 read_request;
-	u32 hist_cnt_read;
-	u32 hist_cnt_sent;
-	u32 frame_cnt;
-	u32 is_kick_ready;
-	struct completion comp;
-	u32 data[HIST_V_SIZE];
-};
-
 static u32 dither_matrix[16] = {
 	15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10};
 static u32 dither_depth_map[9] = {
@@ -166,11 +154,13 @@
 };
 
 static DEFINE_MUTEX(mdss_pp_mutex);
-static DEFINE_SPINLOCK(mdss_hist_lock);
-static DEFINE_MUTEX(mdss_mdp_hist_mutex);
 static struct mdss_pp_res_type *mdss_pp_res;
 
-static void pp_hist_read(u32 v_base, struct pp_hist_col_info *hist_info);
+static void pp_hist_read(char __iomem *v_base,
+				struct pp_hist_col_info *hist_info);
+static int pp_histogram_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix);
+static int pp_histogram_disable(struct pp_hist_col_info *hist_info,
+					u32 done_bit, char __iomem *ctl_base);
 static void pp_update_pcc_regs(u32 offset,
 				struct mdp_pcc_cfg_data *cfg_ptr);
 static void pp_update_igc_lut(struct mdp_igc_lut_data *cfg,
@@ -179,7 +169,8 @@
 				struct mdp_ar_gc_lut_data *lut_data);
 static void pp_update_argc_lut(u32 offset,
 				struct mdp_pgc_lut_data *config);
-static void pp_update_hist_lut(u32 offset, struct mdp_hist_lut_data *cfg);
+static void pp_update_hist_lut(char __iomem *base,
+				struct mdp_hist_lut_data *cfg);
 static void pp_pa_config(unsigned long flags, u32 base,
 				struct pp_sts_type *pp_sts,
 				struct mdp_pa_cfg *pa_config);
@@ -190,7 +181,7 @@
 				struct pp_sts_type *pp_sts,
 				struct mdp_igc_lut_data *igc_config,
 				u32 pipe_num);
-static void pp_enhist_config(unsigned long flags, u32 base,
+static void pp_enhist_config(unsigned long flags, char __iomem *base,
 				struct pp_sts_type *pp_sts,
 				struct mdp_hist_lut_data *enhist_cfg);
 static void pp_sharp_config(char __iomem *offset,
@@ -391,7 +382,7 @@
 	}
 }
 
-static void pp_enhist_config(unsigned long flags, u32 base,
+static void pp_enhist_config(unsigned long flags, char __iomem *base,
 				struct pp_sts_type *pp_sts,
 				struct mdp_hist_lut_data *enhist_cfg)
 {
@@ -431,6 +422,7 @@
 {
 	u32 opmode = 0, base = 0;
 	unsigned long flags = 0;
+	char __iomem *offset;
 
 	pr_debug("pnum=%x\n", pipe->num);
 
@@ -464,6 +456,8 @@
 		}
 	}
 
+	pp_histogram_setup(&opmode, MDSS_PP_SSPP_CFG | pipe->num, pipe->mixer);
+
 	if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) {
 		if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_PA_CFG) {
 			flags = PP_FLAGS_DIRTY_PA;
@@ -475,6 +469,26 @@
 			if (pipe->pp_res.pp_sts.pa_sts & PP_STS_ENABLE)
 				opmode |= (1 << 4); /* PA_EN */
 		}
+
+		if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_HIST_LUT_CFG) {
+			pp_enhist_config(PP_FLAGS_DIRTY_ENHIST,
+				pipe->base + MDSS_MDP_REG_VIG_HIST_LUT_BASE,
+				&pipe->pp_res.pp_sts,
+				&pipe->pp_cfg.hist_lut_cfg);
+		}
+	}
+
+	if (pipe->pp_res.pp_sts.enhist_sts & PP_STS_ENABLE) {
+		/* Enable HistLUT and PA */
+		opmode |= BIT(10) | BIT(4);
+		if (!(pipe->pp_res.pp_sts.pa_sts & PP_STS_ENABLE)) {
+			/* Program default value */
+			offset = pipe->base + MDSS_MDP_REG_VIG_PA_BASE;
+			writel_relaxed(0, offset);
+			writel_relaxed(0, offset + 4);
+			writel_relaxed(0, offset + 8);
+			writel_relaxed(0, offset + 12);
+		}
 	}
 
 	*op = opmode;
@@ -704,6 +718,17 @@
 
 void mdss_mdp_pipe_sspp_term(struct mdss_mdp_pipe *pipe)
 {
+	u32 done_bit;
+	struct pp_hist_col_info *hist_info;
+	char __iomem *ctl_base;
+
+	if (!pipe && pipe->pp_res.hist.col_en) {
+		done_bit = 3 << (pipe->num * 4);
+		hist_info = &pipe->pp_res.hist;
+		ctl_base = pipe->base +
+			MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+		pp_histogram_disable(hist_info, done_bit, ctl_base);
+	}
 	memset(&pipe->pp_cfg, 0, sizeof(struct mdp_overlay_pp_params));
 	memset(&pipe->pp_res, 0, sizeof(struct mdss_pipe_pp_res));
 }
@@ -796,16 +821,86 @@
 	return 0;
 }
 
+static char __iomem *mdss_mdp_get_dspp_addr_off(u32 dspp_num)
+{
+	struct mdss_data_type *mdata;
+	struct mdss_mdp_mixer *mixer;
+
+	mdata = mdss_mdp_get_mdata();
+	if (mdata->nmixers_intf <= dspp_num) {
+		pr_err("Invalid dspp_num=%d", dspp_num);
+		return ERR_PTR(-EINVAL);
+	}
+	mixer = mdata->mixer_intf + dspp_num;
+	return mixer->dspp_base;
+}
+
+/* Assumes that function will be called from within clock enabled space*/
+static int pp_histogram_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix)
+{
+	int ret = -EINVAL;
+	char __iomem *base;
+	u32 op_flags, kick_base, col_state;
+	struct mdss_data_type *mdata;
+	struct mdss_mdp_pipe *pipe;
+	struct pp_hist_col_info *hist_info;
+	unsigned long flag;
+
+	if (mix && (PP_LOCAT(block) == MDSS_PP_DSPP_CFG)) {
+		/* HIST_EN & AUTO_CLEAR */
+		op_flags = BIT(16) | BIT(17);
+		hist_info = &mdss_pp_res->dspp_hist[mix->num];
+		base = mdss_mdp_get_dspp_addr_off(PP_BLOCK(block));
+		kick_base = MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
+	} else if (PP_LOCAT(block) == MDSS_PP_SSPP_CFG) {
+		mdata = mdss_mdp_get_mdata();
+		pipe = mdss_mdp_pipe_get(mdata, BIT(PP_BLOCK(block)));
+		if (IS_ERR_OR_NULL(pipe)) {
+			pr_debug("pipe DNE (%d)", (u32) BIT(PP_BLOCK(block)));
+			ret = -ENODEV;
+			goto error;
+		}
+		/* HIST_EN & AUTO_CLEAR */
+		op_flags = BIT(8) + BIT(9);
+		hist_info = &pipe->pp_res.hist;
+		base = pipe->base;
+		kick_base = MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+		mdss_mdp_pipe_unmap(pipe);
+	} else {
+		pr_warn("invalid histogram location (%d)", block);
+		goto error;
+	}
+
+	if (hist_info->col_en) {
+		*op |= op_flags;
+		mutex_lock(&hist_info->hist_mutex);
+		spin_lock_irqsave(&hist_info->hist_lock, flag);
+		col_state = hist_info->col_state;
+		if (hist_info->is_kick_ready &&
+			((col_state == HIST_IDLE) ||
+			((false == hist_info->read_request) &&
+				col_state == HIST_READY))) {
+			/* Kick off collection */
+			writel_relaxed(1, base + kick_base);
+			hist_info->col_state = HIST_START;
+		}
+		spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+		mutex_unlock(&hist_info->hist_mutex);
+	}
+	ret = 0;
+error:
+	return ret;
+}
+
 static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
 				struct mdss_mdp_mixer *mixer)
 {
 	u32 flags, base, offset, dspp_num, opmode = 0;
 	struct mdp_dither_cfg_data *dither_cfg;
-	struct pp_hist_col_info *hist_info;
 	struct mdp_pgc_lut_data *pgc_config;
 	struct pp_sts_type *pp_sts;
-	u32 data, col_state;
-	unsigned long flag;
+	u32 data;
+	char __iomem *basel;
 	int i, ret = 0;
 
 	if (!mixer || !ctl)
@@ -817,28 +912,13 @@
 		(dspp_num >= MDSS_MDP_MAX_DSPP))
 		return -EINVAL;
 	base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num);
-	hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+	basel = mdss_mdp_get_dspp_addr_off(dspp_num);
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 
-	if (hist_info->col_en) {
-		/* HIST_EN & AUTO_CLEAR */
-		opmode |= (1 << 16) | (1 << 17);
-		mutex_lock(&mdss_mdp_hist_mutex);
-		spin_lock_irqsave(&mdss_hist_lock, flag);
-		col_state = hist_info->col_state;
-		if (hist_info->is_kick_ready &&
-				((col_state == HIST_IDLE) ||
-				((false == hist_info->read_request) &&
-						col_state == HIST_READY))) {
-			/* Kick off collection */
-			MDSS_MDP_REG_WRITE(base +
-				MDSS_MDP_REG_DSPP_HIST_CTL_BASE, 1);
-			hist_info->col_state = HIST_START;
-		}
-		spin_unlock_irqrestore(&mdss_hist_lock, flag);
-		mutex_unlock(&mdss_mdp_hist_mutex);
-	}
+	ret = pp_histogram_setup(&opmode, MDSS_PP_DSPP_CFG | dspp_num, mixer);
+	if (ret)
+		goto dspp_exit;
 
 	if (disp_num < MDSS_BLOCK_DISP_NUM)
 		flags = mdss_pp_res->pp_disp_flags[disp_num];
@@ -846,7 +926,7 @@
 		flags = 0;
 
 	/* nothing to update */
-	if ((!flags) && (!(hist_info->col_en)))
+	if ((!flags) && (!(opmode)))
 		goto dspp_exit;
 
 	pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
@@ -860,7 +940,7 @@
 	pp_igc_config(flags, MDSS_MDP_REG_IGC_DSPP_BASE, pp_sts,
 				&mdss_pp_res->igc_disp_cfg[disp_num], dspp_num);
 
-	pp_enhist_config(flags, base + MDSS_MDP_REG_DSPP_HIST_LUT_BASE,
+	pp_enhist_config(flags, basel + MDSS_MDP_REG_DSPP_HIST_LUT_BASE,
 			pp_sts, &mdss_pp_res->enhist_disp_cfg[disp_num]);
 
 	if (pp_sts->pa_sts & PP_STS_ENABLE)
@@ -934,7 +1014,7 @@
 	if (pp_sts->pgc_sts & PP_STS_ENABLE)
 		opmode |= (1 << 22);
 
-	MDSS_MDP_REG_WRITE(base + MDSS_MDP_REG_DSPP_OP_MODE, opmode);
+	writel_relaxed(opmode, basel + MDSS_MDP_REG_DSPP_OP_MODE);
 	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, BIT(13 + dspp_num));
 	wmb();
 dspp_exit:
@@ -1068,7 +1148,9 @@
 
 int mdss_mdp_pp_init(struct device *dev)
 {
-	int ret = 0;
+	int i, ret = 0;
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+	struct mdss_mdp_pipe *vig;
 
 	mutex_lock(&mdss_pp_mutex);
 	if (!mdss_pp_res) {
@@ -1078,6 +1160,18 @@
 			pr_err("%s mdss_pp_res allocation failed!", __func__);
 			ret = -ENOMEM;
 		}
+
+		for (i = 0; i < MDSS_MDP_MAX_DSPP; i++) {
+			mutex_init(&mdss_pp_res->dspp_hist[i].hist_mutex);
+			spin_lock_init(&mdss_pp_res->dspp_hist[i].hist_lock);
+		}
+	}
+	if (mdata) {
+		vig = mdata->vig_pipes;
+		for (i = 0; i < mdata->nvig_pipes; i++) {
+			mutex_init(&vig[i].pp_res.hist.hist_mutex);
+			spin_lock_init(&vig[i].pp_res.hist.hist_lock);
+		}
 	}
 	mutex_unlock(&mdss_pp_mutex);
 	return ret;
@@ -1545,13 +1639,17 @@
 }
 
 /* Note: Assumes that its inputs have been checked by calling function */
-static void pp_update_hist_lut(u32 offset, struct mdp_hist_lut_data *cfg)
+static void pp_update_hist_lut(char __iomem *offset,
+				struct mdp_hist_lut_data *cfg)
 {
 	int i;
 	for (i = 0; i < ENHIST_LUT_ENTRIES; i++)
-		MDSS_MDP_REG_WRITE(offset, cfg->data[i]);
+		writel_relaxed(cfg->data[i], offset);
 	/* swap */
-	MDSS_MDP_REG_WRITE(offset + 4, 1);
+	if (PP_LOCAT(cfg->block) == MDSS_PP_DSPP_CFG)
+		writel_relaxed(1, offset + 4);
+	else
+		writel_relaxed(1, offset + 16);
 }
 
 int mdss_mdp_argc_config(struct mdss_mdp_ctl *ctl,
@@ -1574,7 +1672,7 @@
 	mutex_lock(&mdss_pp_mutex);
 
 	disp_num = PP_BLOCK(config->block) - MDP_LOGICAL_BLOCK_DISP_0;
-	switch (config->block & MDSS_PP_LOCATION_MASK) {
+	switch (PP_LOCAT(config->block)) {
 	case MDSS_PP_LM_CFG:
 		argc_offset = MDSS_MDP_REG_LM_OFFSET(dspp_num) +
 			MDSS_MDP_REG_LM_GC_LUT_BASE;
@@ -1670,12 +1768,12 @@
 	if (!ctl)
 		return -EINVAL;
 
-	if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
-		(config->block >= MDP_BLOCK_MAX))
+	if ((PP_BLOCK(config->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(PP_BLOCK(config->block) >= MDP_BLOCK_MAX))
 		return -EINVAL;
 
 	mutex_lock(&mdss_pp_mutex);
-	disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+	disp_num = PP_BLOCK(config->block) - MDP_LOGICAL_BLOCK_DISP_0;
 
 	if (config->ops & MDP_PP_OPS_READ) {
 		ret = pp_get_dspp_num(disp_num, &dspp_num);
@@ -1833,124 +1931,205 @@
 		mdss_mdp_pp_setup(ctl);
 	return ret;
 }
-static void pp_hist_read(u32 v_base, struct pp_hist_col_info *hist_info)
+static void pp_hist_read(char __iomem *v_base,
+				struct pp_hist_col_info *hist_info)
 {
 	int i, i_start;
 	u32 data;
-	data = MDSS_MDP_REG_READ(v_base);
+	data = readl_relaxed(v_base);
 	i_start = data >> 24;
 	hist_info->data[i_start] = data & 0xFFFFFF;
 	for (i = i_start + 1; i < HIST_V_SIZE; i++)
-		hist_info->data[i] = MDSS_MDP_REG_READ(v_base) & 0xFFFFFF;
+		hist_info->data[i] = readl_relaxed(v_base) & 0xFFFFFF;
 	for (i = 0; i < i_start - 1; i++)
-		hist_info->data[i] = MDSS_MDP_REG_READ(v_base) & 0xFFFFFF;
+		hist_info->data[i] = readl_relaxed(v_base) & 0xFFFFFF;
 	hist_info->hist_cnt_read++;
 }
 
-int mdss_mdp_histogram_start(struct mdss_mdp_ctl *ctl,
-					struct mdp_histogram_start_req *req)
+/* Assumes that relevant clocks are enabled */
+static int pp_histogram_enable(struct pp_hist_col_info *hist_info,
+				struct mdp_histogram_start_req *req,
+				u32 shift_bit, char __iomem *ctl_base)
 {
-	u32 ctl_base, done_shift_bit;
+	unsigned long flag;
+	int ret = 0;
+	mutex_lock(&hist_info->hist_mutex);
+	/* check if it is idle */
+	if (hist_info->col_en) {
+		pr_info("%s Hist collection has already been enabled %d",
+			__func__, (u32) ctl_base);
+		ret = -EINVAL;
+		goto exit;
+	}
+	hist_info->frame_cnt = req->frame_cnt;
+	init_completion(&hist_info->comp);
+	hist_info->hist_cnt_read = 0;
+	hist_info->hist_cnt_sent = 0;
+	hist_info->hist_cnt_time = 0;
+	spin_lock_irqsave(&hist_info->hist_lock, flag);
+	hist_info->read_request = false;
+	hist_info->col_state = HIST_RESET;
+	hist_info->col_en = true;
+	spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+	hist_info->is_kick_ready = false;
+	mdss_mdp_hist_irq_enable(3 << shift_bit);
+	writel_relaxed(req->frame_cnt, ctl_base + 8);
+	/* Kick out reset start */
+	writel_relaxed(1, ctl_base + 4);
+exit:
+	mutex_unlock(&hist_info->hist_mutex);
+	return ret;
+}
+
+int mdss_mdp_histogram_start(struct mdss_mdp_ctl *ctl,
+				struct mdp_histogram_start_req *req)
+{
+	u32 done_shift_bit;
+	char __iomem *ctl_base;
 	struct pp_hist_col_info *hist_info;
 	int i, ret = 0;
 	u32 disp_num, dspp_num = 0;
 	u32 mixer_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
-	unsigned long flag;
-
+	struct mdss_mdp_pipe *pipe;
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
 	if (!ctl)
 		return -EINVAL;
 
-	if ((req->block < MDP_LOGICAL_BLOCK_DISP_0) ||
-		(req->block >= MDP_BLOCK_MAX))
+	if ((PP_BLOCK(req->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(PP_BLOCK(req->block) >= MDP_BLOCK_MAX))
 		return -EINVAL;
 
-	mutex_lock(&mdss_mdp_hist_mutex);
-	disp_num = req->block - MDP_LOGICAL_BLOCK_DISP_0;
+	disp_num = PP_BLOCK(req->block) - MDP_LOGICAL_BLOCK_DISP_0;
 	mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
 
 	if (!mixer_cnt) {
 		pr_err("%s, no dspp connects to disp %d",
 			__func__, disp_num);
 		ret = -EPERM;
-		goto hist_start_exit;
+		goto hist_exit;
 	}
 	if (mixer_cnt >= MDSS_MDP_MAX_DSPP) {
 		pr_err("%s, Too many dspp connects to disp %d",
 			__func__, mixer_cnt);
 		ret = -EPERM;
-		goto hist_start_exit;
+		goto hist_exit;
 	}
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-	for (i = 0; i < mixer_cnt; i++) {
-		dspp_num = mixer_id[i];
-		hist_info = &mdss_pp_res->dspp_hist[dspp_num];
-		done_shift_bit = (dspp_num * 4) + 12;
-		/* check if it is idle */
-		if (hist_info->col_en) {
-			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
-			pr_info("%s Hist collection has already been enabled %d",
-				__func__, dspp_num);
-			goto hist_start_exit;
+
+	if (PP_LOCAT(req->block) == MDSS_PP_SSPP_CFG) {
+		i = MDSS_PP_ARG_MASK & req->block;
+		if (!i) {
+			ret = -EINVAL;
+			pr_warn("Must pass pipe arguments, %d", i);
+			goto hist_exit;
 		}
-		spin_lock_irqsave(&mdss_hist_lock, flag);
-		hist_info->frame_cnt = req->frame_cnt;
-		init_completion(&hist_info->comp);
-		hist_info->hist_cnt_read = 0;
-		hist_info->hist_cnt_sent = 0;
-		hist_info->read_request = false;
-		hist_info->col_state = HIST_RESET;
-		hist_info->col_en = true;
-		hist_info->is_kick_ready = false;
-		spin_unlock_irqrestore(&mdss_hist_lock, flag);
-		mdss_pp_res->hist_col[disp_num][i] =
-			&mdss_pp_res->dspp_hist[dspp_num];
-		mdss_mdp_hist_irq_enable(3 << done_shift_bit);
-		ctl_base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
-			  MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
-		MDSS_MDP_REG_WRITE(ctl_base + 8, req->frame_cnt);
-		/* Kick out reset start */
-		MDSS_MDP_REG_WRITE(ctl_base + 4, 1);
+
+		for (i = 0; i < MDSS_PP_ARG_NUM; i++) {
+			if (!PP_ARG(i, req->block))
+				continue;
+			pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+			if (IS_ERR_OR_NULL(pipe))
+				continue;
+			if (!pipe || pipe->num > MDSS_MDP_SSPP_VIG2) {
+				ret = -EINVAL;
+				pr_warn("Invalid Hist pipe (%d)", i);
+				goto hist_exit;
+			}
+			done_shift_bit = (pipe->num * 4);
+			hist_info = &pipe->pp_res.hist;
+			ctl_base = pipe->base +
+				MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+			ret = pp_histogram_enable(hist_info, req,
+						done_shift_bit,	ctl_base);
+			mdss_mdp_pipe_unmap(pipe);
+		}
+	} else if (PP_LOCAT(req->block) == MDSS_PP_DSPP_CFG) {
+		for (i = 0; i < mixer_cnt; i++) {
+			dspp_num = mixer_id[i];
+			done_shift_bit = (dspp_num * 4) + 12;
+			hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+			ctl_base = mdss_mdp_get_dspp_addr_off(dspp_num) +
+				MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
+			ret = pp_histogram_enable(hist_info, req,
+						done_shift_bit,	ctl_base);
+			mdss_pp_res->pp_disp_flags[disp_num] |=
+							PP_FLAGS_DIRTY_HIST_COL;
+		}
 	}
-	for (i = mixer_cnt; i < MDSS_MDP_MAX_DSPP; i++)
-		mdss_pp_res->hist_col[disp_num][i] = 0;
-	mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_HIST_COL;
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
-hist_start_exit:
-	mutex_unlock(&mdss_mdp_hist_mutex);
-	if (!ret) {
+
+hist_exit:
+	if (!ret && (PP_LOCAT(req->block) == MDSS_PP_DSPP_CFG)) {
 		mdss_mdp_pp_setup(ctl);
 		/* wait for a frame to let histrogram enable itself */
+		/* TODO add hysteresis value to be able to remove this sleep */
 		usleep(41666);
 		for (i = 0; i < mixer_cnt; i++) {
 			dspp_num = mixer_id[i];
 			hist_info = &mdss_pp_res->dspp_hist[dspp_num];
-			mutex_lock(&mdss_mdp_hist_mutex);
-			spin_lock_irqsave(&mdss_hist_lock, flag);
+			mutex_lock(&hist_info->hist_mutex);
 			hist_info->is_kick_ready = true;
-			spin_unlock_irqrestore(&mdss_hist_lock, flag);
-			mutex_unlock(&mdss_mdp_hist_mutex);
+			mutex_unlock(&hist_info->hist_mutex);
+		}
+	} else if (!ret) {
+		for (i = 0; i < MDSS_PP_ARG_NUM; i++) {
+			if (!PP_ARG(i, req->block))
+				continue;
+			pr_info("PP_ARG(%d) = %d", i, PP_ARG(i, req->block));
+			pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+			if (IS_ERR_OR_NULL(pipe))
+				continue;
+			hist_info = &pipe->pp_res.hist;
+			hist_info->is_kick_ready = true;
+			mdss_mdp_pipe_unmap(pipe);
 		}
 	}
 	return ret;
 }
 
+static int pp_histogram_disable(struct pp_hist_col_info *hist_info,
+					u32 done_bit, char __iomem *ctl_base)
+{
+	int ret = 0;
+	unsigned long flag;
+	mutex_lock(&hist_info->hist_mutex);
+	if (hist_info->col_en == false) {
+		pr_debug("Histogram already disabled (%d)", (u32) ctl_base);
+		ret = -EINVAL;
+		goto exit;
+	}
+	complete_all(&hist_info->comp);
+	spin_lock_irqsave(&hist_info->hist_lock, flag);
+	hist_info->col_en = false;
+	hist_info->col_state = HIST_UNKNOWN;
+	spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+	hist_info->is_kick_ready = false;
+	mdss_mdp_hist_irq_disable(done_bit);
+	writel_relaxed(BIT(1), ctl_base);/* cancel */
+	ret = 0;
+exit:
+	mutex_unlock(&hist_info->hist_mutex);
+	return ret;
+}
+
 int mdss_mdp_histogram_stop(struct mdss_mdp_ctl *ctl, u32 block)
 {
 	int i, ret = 0;
-	u32 dspp_num, disp_num, ctl_base, done_bit;
+	char __iomem *ctl_base;
+	u32 dspp_num, disp_num, done_bit;
 	struct pp_hist_col_info *hist_info;
 	u32 mixer_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
-	unsigned long flag;
+	struct mdss_mdp_pipe *pipe;
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
 
 	if (!ctl)
 		return -EINVAL;
 
-	if ((block < MDP_LOGICAL_BLOCK_DISP_0) ||
-		(block >= MDP_BLOCK_MAX))
+	if ((PP_BLOCK(block) < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(PP_BLOCK(block) >= MDP_BLOCK_MAX))
 		return -EINVAL;
 
-	mutex_lock(&mdss_mdp_hist_mutex);
-	disp_num = block - MDP_LOGICAL_BLOCK_DISP_0;
+	disp_num = PP_BLOCK(block) - MDP_LOGICAL_BLOCK_DISP_0;
 	mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
 
 	if (!mixer_cnt) {
@@ -1966,162 +2145,312 @@
 		goto hist_stop_exit;
 	}
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-	for (i = 0; i < mixer_cnt; i++) {
-		dspp_num = mixer_id[i];
-		hist_info = &mdss_pp_res->dspp_hist[dspp_num];
-		done_bit = 3 << ((dspp_num * 4) + 12);
-		ctl_base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
-			  MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
-		if (hist_info->col_en == false) {
-			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+	if (PP_LOCAT(block) == MDSS_PP_SSPP_CFG) {
+		i = MDSS_PP_ARG_MASK & block;
+		if (!i) {
+			pr_warn("Must pass pipe arguments, %d", i);
 			goto hist_stop_exit;
 		}
-		complete_all(&hist_info->comp);
-		spin_lock_irqsave(&mdss_hist_lock, flag);
-		hist_info->col_en = false;
-		hist_info->col_state = HIST_UNKNOWN;
-		hist_info->is_kick_ready = false;
-		spin_unlock_irqrestore(&mdss_hist_lock, flag);
-		mdss_mdp_hist_irq_disable(done_bit);
-		MDSS_MDP_REG_WRITE(ctl_base, (1 << 1));/* cancel */
+
+		for (i = 0; i < MDSS_PP_ARG_NUM; i++) {
+			if (!PP_ARG(i, block))
+				continue;
+			pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+			if (IS_ERR_OR_NULL(pipe) ||
+					pipe->num > MDSS_MDP_SSPP_VIG2) {
+				pr_warn("Invalid Hist pipe (%d)", i);
+				continue;
+			}
+			done_bit = 3 << (pipe->num * 4);
+			hist_info = &pipe->pp_res.hist;
+			ctl_base = pipe->base +
+				MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+			ret = pp_histogram_disable(hist_info, done_bit,
+								ctl_base);
+			mdss_mdp_pipe_unmap(pipe);
+			if (ret)
+				goto hist_stop_exit;
+		}
+	} else if (PP_LOCAT(block) == MDSS_PP_DSPP_CFG) {
+		for (i = 0; i < mixer_cnt; i++) {
+			dspp_num = mixer_id[i];
+			done_bit = 3 << ((dspp_num * 4) + 12);
+			hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+			ctl_base = mdss_mdp_get_dspp_addr_off(dspp_num) +
+				  MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
+			ret = pp_histogram_disable(hist_info, done_bit,
+								ctl_base);
+			if (ret)
+				goto hist_stop_exit;
+			mdss_pp_res->pp_disp_flags[disp_num] |=
+							PP_FLAGS_DIRTY_HIST_COL;
+		}
 	}
-	for (i = 0; i < MDSS_MDP_MAX_DSPP; i++)
-		mdss_pp_res->hist_col[disp_num][i] = 0;
-	mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_HIST_COL;
-	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 hist_stop_exit:
-	mutex_unlock(&mdss_mdp_hist_mutex);
-	if (!ret)
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+	if (!ret && (PP_LOCAT(block) == MDSS_PP_DSPP_CFG))
 		mdss_mdp_pp_setup(ctl);
 	return ret;
 }
 
-int mdss_mdp_hist_collect(struct mdss_mdp_ctl *ctl,
-					struct mdp_histogram_data *hist,
-					u32 *hist_data_addr)
+static int pp_hist_collect(struct mdss_mdp_ctl *ctl,
+				struct mdp_histogram_data *hist,
+				struct pp_hist_col_info *hist_info,
+				char __iomem *ctl_base)
 {
-	int i, j, wait_ret, ret = 0;
-	u32 timeout, v_base;
-	struct pp_hist_col_info *hist_info;
-	u32 dspp_num, disp_num, ctl_base;
-	u32 mixer_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
+	int wait_ret, ret = 0;
+	u32 timeout;
+	char __iomem *v_base;
 	unsigned long flag;
+	struct mdss_pipe_pp_res *res;
+	struct mdss_mdp_pipe *pipe;
+
+	mutex_lock(&hist_info->hist_mutex);
+	if ((hist_info->col_en == 0) ||
+			(hist_info->col_state == HIST_UNKNOWN)) {
+		ret = -EINVAL;
+		goto hist_collect_exit;
+	}
+	spin_lock_irqsave(&hist_info->hist_lock, flag);
+	/* wait for hist done if cache has no data */
+	if (hist_info->col_state != HIST_READY) {
+		hist_info->read_request = true;
+		spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+		timeout = HIST_WAIT_TIMEOUT(hist_info->frame_cnt);
+		mutex_unlock(&hist_info->hist_mutex);
+		/* flush updates before wait*/
+		if (PP_LOCAT(hist->block) == MDSS_PP_DSPP_CFG)
+			mdss_mdp_pp_setup(ctl);
+		if (PP_LOCAT(hist->block) == MDSS_PP_SSPP_CFG) {
+			res = container_of(hist_info, struct mdss_pipe_pp_res,
+						hist);
+			pipe = container_of(res, struct mdss_mdp_pipe, pp_res);
+			pipe->params_changed++;
+		}
+		wait_ret = wait_for_completion_killable_timeout(
+				&(hist_info->comp), timeout);
+
+		mutex_lock(&hist_info->hist_mutex);
+		if (wait_ret == 0) {
+			ret = -ETIMEDOUT;
+			spin_lock_irqsave(&hist_info->hist_lock, flag);
+			pr_debug("bin collection timedout, state %d",
+					hist_info->col_state);
+			/*
+			 * When the histogram has timed out (usually
+			 * underrun) change the SW state back to idle
+			 * since histogram hardware will have done the
+			 * same. Histogram data also needs to be
+			 * cleared in this case, which is done by the
+			 * histogram being read (triggered by READY
+			 * state, which also moves the histogram SW back
+			 * to IDLE).
+			 */
+			hist_info->hist_cnt_time++;
+			hist_info->col_state = HIST_READY;
+			spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+		} else if (wait_ret < 0) {
+			ret = -EINTR;
+			pr_debug("%s: bin collection interrupted",
+					__func__);
+			goto hist_collect_exit;
+		}
+		if (hist_info->col_state != HIST_READY) {
+			ret = -ENODATA;
+			pr_debug("%s: state is not ready: %d",
+					__func__, hist_info->col_state);
+			goto hist_collect_exit;
+		}
+	} else {
+		spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+	}
+	spin_lock_irqsave(&hist_info->hist_lock, flag);
+	if (hist_info->col_state == HIST_READY) {
+		spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+		v_base = ctl_base + 0x1C;
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+		pp_hist_read(v_base, hist_info);
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+		spin_lock_irqsave(&hist_info->hist_lock, flag);
+		hist_info->read_request = false;
+		hist_info->col_state = HIST_IDLE;
+	}
+	spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+hist_collect_exit:
+	mutex_unlock(&hist_info->hist_mutex);
+	return ret;
+}
+
+int mdss_mdp_hist_collect(struct mdss_mdp_ctl *ctl,
+					struct mdp_histogram_data *hist)
+{
+	int i, j, off, ret = 0;
+	struct pp_hist_col_info *hist_info;
+	u32 dspp_num, disp_num;
+	char __iomem *ctl_base;
+	u32 hist_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
+	u32 *hist_concat = NULL;
+	u32 *hist_data_addr;
+	u32 pipe_cnt = 0;
+	u32 pipe_num = MDSS_MDP_SSPP_VIG0;
+	struct mdss_mdp_pipe *pipe;
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
 
 	if (!ctl)
 		return -EINVAL;
 
-	if ((hist->block < MDP_LOGICAL_BLOCK_DISP_0) ||
-		(hist->block >= MDP_BLOCK_MAX))
+	if ((PP_BLOCK(hist->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(PP_BLOCK(hist->block) >= MDP_BLOCK_MAX))
 		return -EINVAL;
 
-	mutex_lock(&mdss_mdp_hist_mutex);
-	disp_num = hist->block - MDP_LOGICAL_BLOCK_DISP_0;
-	mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
+	disp_num = PP_BLOCK(hist->block) - MDP_LOGICAL_BLOCK_DISP_0;
+	hist_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
 
-	if (!mixer_cnt) {
+	if (!hist_cnt) {
 		pr_err("%s, no dspp connects to disp %d",
 			__func__, disp_num);
 		ret = -EPERM;
 		goto hist_collect_exit;
 	}
-	if (mixer_cnt >= MDSS_MDP_MAX_DSPP) {
+	if (hist_cnt >= MDSS_MDP_MAX_DSPP) {
 		pr_err("%s, Too many dspp connects to disp %d",
-			__func__, mixer_cnt);
+			__func__, hist_cnt);
 		ret = -EPERM;
 		goto hist_collect_exit;
 	}
-	hist_info = &mdss_pp_res->dspp_hist[0];
-	for (i = 0; i < mixer_cnt; i++) {
-		dspp_num = mixer_id[i];
-		hist_info = &mdss_pp_res->dspp_hist[dspp_num];
-		ctl_base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
-			  MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
-		if ((hist_info->col_en == 0) ||
-			(hist_info->col_state == HIST_UNKNOWN)) {
-			ret = -EINVAL;
-			goto hist_collect_exit;
-		}
-		spin_lock_irqsave(&mdss_hist_lock, flag);
-		/* wait for hist done if cache has no data */
-		if (hist_info->col_state != HIST_READY) {
-			hist_info->read_request = true;
-			spin_unlock_irqrestore(&mdss_hist_lock, flag);
-			timeout = HIST_WAIT_TIMEOUT(hist_info->frame_cnt);
-			mutex_unlock(&mdss_mdp_hist_mutex);
-			/* flush updates before wait*/
-			mdss_mdp_pp_setup(ctl);
-			wait_ret = wait_for_completion_killable_timeout(
-					&(hist_info->comp), timeout);
-
-			mutex_lock(&mdss_mdp_hist_mutex);
-			if (wait_ret == 0) {
-				ret = -ETIMEDOUT;
-				spin_lock_irqsave(&mdss_hist_lock, flag);
-				pr_debug("bin collection timedout, state %d",
-							hist_info->col_state);
-				/*
-				 * When the histogram has timed out (usually
-				 * underrun) change the SW state back to idle
-				 * since histogram hardware will have done the
-				 * same. Histogram data also needs to be
-				 * cleared in this case, which is done by the
-				 * histogram being read (triggered by READY
-				 * state, which also moves the histogram SW back
-				 * to IDLE).
-				 */
-				hist_info->col_state = HIST_READY;
-				spin_unlock_irqrestore(&mdss_hist_lock, flag);
-			} else if (wait_ret < 0) {
-				ret = -EINTR;
-				pr_debug("%s: bin collection interrupted",
-						__func__);
-				goto hist_collect_exit;
-			}
-			if (hist_info->col_state != HIST_READY) {
-				ret = -ENODATA;
-				pr_debug("%s: state is not ready: %d",
-					__func__, hist_info->col_state);
-				goto hist_collect_exit;
-			}
-		} else {
-			spin_unlock_irqrestore(&mdss_hist_lock, flag);
-		}
-		spin_lock_irqsave(&mdss_hist_lock, flag);
-		if (hist_info->col_state == HIST_READY) {
-			spin_unlock_irqrestore(&mdss_hist_lock, flag);
-			v_base = ctl_base + 0x1C;
-			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-			pp_hist_read(v_base, hist_info);
-			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
-			spin_lock_irqsave(&mdss_hist_lock, flag);
-			hist_info->read_request = false;
-			hist_info->col_state = HIST_IDLE;
-		}
-		spin_unlock_irqrestore(&mdss_hist_lock, flag);
-	}
-	if (mixer_cnt > 1) {
-		memset(&mdss_pp_res->hist_data[disp_num][0],
-			0, HIST_V_SIZE * sizeof(u32));
-		for (i = 0; i < mixer_cnt; i++) {
+	if (PP_LOCAT(hist->block) == MDSS_PP_DSPP_CFG) {
+		hist_info = &mdss_pp_res->dspp_hist[disp_num];
+		for (i = 0; i < hist_cnt; i++) {
 			dspp_num = mixer_id[i];
 			hist_info = &mdss_pp_res->dspp_hist[dspp_num];
-			for (j = 0; j < HIST_V_SIZE; j++)
-				mdss_pp_res->hist_data[disp_num][i] +=
-					hist_info->data[i];
+			ctl_base = mdss_mdp_get_dspp_addr_off(dspp_num) +
+				MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
+			ret = pp_hist_collect(ctl, hist, hist_info, ctl_base);
+			if (ret)
+				goto hist_collect_exit;
 		}
-		*hist_data_addr = (u32)&mdss_pp_res->hist_data[disp_num][0];
+		if (hist_cnt > 1) {
+			if (hist->bin_cnt != HIST_V_SIZE) {
+				pr_err("User not expecting size %d output",
+								HIST_V_SIZE);
+				ret = -EINVAL;
+				goto hist_collect_exit;
+			}
+			hist_concat = kmalloc(HIST_V_SIZE * sizeof(u32),
+								GFP_KERNEL);
+			if (!hist_concat) {
+				ret = -ENOMEM;
+				goto hist_collect_exit;
+			}
+			memset(hist_concat, 0, HIST_V_SIZE * sizeof(u32));
+			for (i = 0; i < hist_cnt; i++) {
+				dspp_num = mixer_id[i];
+				hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+				mutex_lock(&hist_info->hist_mutex);
+				for (j = 0; j < HIST_V_SIZE; j++)
+					hist_concat[i] += hist_info->data[i];
+				mutex_unlock(&hist_info->hist_mutex);
+			}
+			hist_data_addr = hist_concat;
+		} else {
+			hist_data_addr = hist_info->data;
+		}
+		hist_info = &mdss_pp_res->dspp_hist[disp_num];
+		hist_info->hist_cnt_sent++;
+	} else if (PP_LOCAT(hist->block) == MDSS_PP_SSPP_CFG) {
+
+		hist_cnt = MDSS_PP_ARG_MASK & hist->block;
+		if (!hist_cnt) {
+			pr_warn("Must pass pipe arguments, %d", hist_cnt);
+			goto hist_collect_exit;
+		}
+
+		/* Find the first pipe requested */
+		for (i = 0; i < MDSS_PP_ARG_NUM; i++) {
+			if (PP_ARG(i, hist_cnt)) {
+				pipe_num = i;
+				break;
+			}
+		}
+
+		pipe = mdss_mdp_pipe_get(mdata, BIT(pipe_num));
+		if (IS_ERR_OR_NULL(pipe)) {
+			pr_warn("Invalid starting hist pipe, %d", pipe_num);
+			ret = -ENODEV;
+			goto hist_collect_exit;
+		}
+		hist_info  = &pipe->pp_res.hist;
+		mdss_mdp_pipe_unmap(pipe);
+		for (i = pipe_num; i < MDSS_PP_ARG_NUM; i++) {
+			if (!PP_ARG(i, hist->block))
+				continue;
+			pipe_cnt++;
+			pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+			if (IS_ERR_OR_NULL(pipe) ||
+					pipe->num > MDSS_MDP_SSPP_VIG2) {
+				pr_warn("Invalid Hist pipe (%d)", i);
+				continue;
+			}
+			hist_info = &pipe->pp_res.hist;
+			ctl_base = pipe->base +
+				MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+			ret = pp_hist_collect(ctl, hist, hist_info, ctl_base);
+			mdss_mdp_pipe_unmap(pipe);
+			if (ret)
+				goto hist_collect_exit;
+		}
+		if (pipe_cnt > 1) {
+			if (hist->bin_cnt != (HIST_V_SIZE * pipe_cnt)) {
+				pr_err("User not expecting size %d output",
+							pipe_cnt * HIST_V_SIZE);
+				ret = -EINVAL;
+				goto hist_collect_exit;
+			}
+			hist_concat = kmalloc(HIST_V_SIZE * pipe_cnt *
+						sizeof(u32), GFP_KERNEL);
+			if (!hist_concat) {
+				ret = -ENOMEM;
+				goto hist_collect_exit;
+			}
+
+			memset(hist_concat, 0, pipe_cnt * HIST_V_SIZE *
+								sizeof(u32));
+			for (i = pipe_num; i < MDSS_PP_ARG_NUM; i++) {
+				if (!PP_ARG(i, hist->block))
+					continue;
+				pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+				hist_info  = &pipe->pp_res.hist;
+				off = HIST_V_SIZE * i;
+				mutex_lock(&hist_info->hist_mutex);
+				for (j = off; j < off + HIST_V_SIZE; j++)
+					hist_concat[j] =
+						hist_info->data[j - off];
+				hist_info->hist_cnt_sent++;
+				mutex_unlock(&hist_info->hist_mutex);
+				mdss_mdp_pipe_unmap(pipe);
+			}
+
+			hist_data_addr = hist_concat;
+		} else {
+			hist_data_addr = hist_info->data;
+		}
 	} else {
-		*hist_data_addr = (u32)hist_info->data;
+		pr_info("No Histogram at location %d", PP_LOCAT(hist->block));
+		goto hist_collect_exit;
 	}
-	hist_info->hist_cnt_sent++;
+	ret = copy_to_user(hist->c0, hist_data_addr, sizeof(u32) *
+								hist->bin_cnt);
 hist_collect_exit:
-	mutex_unlock(&mdss_mdp_hist_mutex);
+	kfree(hist_concat);
+
 	return ret;
 }
 void mdss_mdp_hist_intr_done(u32 isr)
 {
 	u32 isr_blk, blk_idx;
-	struct pp_hist_col_info *hist_info;
+	struct pp_hist_col_info *hist_info = NULL;
+	struct mdss_mdp_pipe *pipe;
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
 	isr &= 0x333333;
 	while (isr != 0) {
 		if (isr & 0xFFF000) {
@@ -2141,36 +2470,40 @@
 			hist_info = &mdss_pp_res->dspp_hist[blk_idx];
 		} else {
 			if (isr & 0x3) {
-				blk_idx = 0;
+				blk_idx = MDSS_MDP_SSPP_VIG0;
 				isr_blk = isr & 0x3;
 				isr &= ~0x3;
 			} else if (isr & 0x30) {
-				blk_idx = 1;
+				blk_idx = MDSS_MDP_SSPP_VIG1;
 				isr_blk = (isr >> 4) & 0x3;
 				isr &= ~0x30;
 			} else {
-				blk_idx = 2;
+				blk_idx = MDSS_MDP_SSPP_VIG2;
 				isr_blk = (isr >> 8) & 0x3;
 				isr &= ~0x300;
 			}
-			/* SSPP block, not support yet*/
-			continue;
+			pipe = mdss_mdp_pipe_search(mdata, BIT(blk_idx));
+			if (IS_ERR_OR_NULL(pipe)) {
+				pr_debug("pipe DNE, %d", blk_idx);
+				continue;
+			}
+			hist_info = &pipe->pp_res.hist;
 		}
 		/* Histogram Done Interrupt */
-		if ((isr_blk & 0x1) &&
+		if (hist_info && (isr_blk & 0x1) &&
 			(hist_info->col_en)) {
-			spin_lock(&mdss_hist_lock);
+			spin_lock(&hist_info->hist_lock);
 			hist_info->col_state = HIST_READY;
-			spin_unlock(&mdss_hist_lock);
+			spin_unlock(&hist_info->hist_lock);
 			if (hist_info->read_request)
 				complete(&hist_info->comp);
 		}
 		/* Histogram Reset Done Interrupt */
 		if ((isr_blk & 0x2) &&
 			(hist_info->col_en)) {
-				spin_lock(&mdss_hist_lock);
+				spin_lock(&hist_info->hist_lock);
 				hist_info->col_state = HIST_IDLE;
-				spin_unlock(&mdss_hist_lock);
+				spin_unlock(&hist_info->hist_lock);
 		}
 	};
 }
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 5711653..ce4c28f 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -27,6 +27,8 @@
 static struct mdss_mdp_rotator_session rotator_session[MAX_ROTATOR_SESSIONS];
 static LIST_HEAD(rotator_queue);
 
+static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot);
+
 struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void)
 {
 	struct mdss_mdp_rotator_session *rot;
@@ -166,27 +168,21 @@
 	return 0;
 }
 
-int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot,
+static int mdss_mdp_rotator_queue_sub(struct mdss_mdp_rotator_session *rot,
 			   struct mdss_mdp_data *src_data,
 			   struct mdss_mdp_data *dst_data)
 {
 	struct mdss_mdp_pipe *rot_pipe = NULL;
 	struct mdss_mdp_ctl *ctl;
-	int ret, need_wait = false;
+	int ret;
 
-	ret = mutex_lock_interruptible(&rotator_lock);
-	if (ret)
-		return ret;
-
-	if (!rot || !rot->ref_cnt) {
-		mutex_unlock(&rotator_lock);
-		return -ENODEV;
-	}
+	if (!rot || !rot->ref_cnt)
+		return -ENOENT;
 
 	ret = mdss_mdp_rotator_pipe_dequeue(rot);
 	if (ret) {
 		pr_err("unable to acquire rotator\n");
-		goto done;
+		return ret;
 	}
 
 	rot_pipe = rot->pipe;
@@ -203,31 +199,141 @@
 		rot_pipe->img_height = rot->img_height;
 		rot_pipe->src = rot->src_rect;
 		rot_pipe->dst = rot->src_rect;
+		rot_pipe->dst.x = 0;
+		rot_pipe->dst.y = 0;
 		rot_pipe->params_changed++;
 	}
 
 	ret = mdss_mdp_pipe_queue_data(rot->pipe, src_data);
 	if (ret) {
 		pr_err("unable to queue rot data\n");
-		goto done;
+		return ret;
 	}
 
 	ret = mdss_mdp_rotator_kickoff(ctl, rot, dst_data);
 
-	if (ret == 0 && !rot->no_wait)
-		need_wait = true;
-done:
+	return ret;
+}
+
+int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot,
+			   struct mdss_mdp_data *src_data,
+			   struct mdss_mdp_data *dst_data)
+{
+	int ret;
+	struct mdss_mdp_rotator_session *tmp = rot;
+
+	ret = mutex_lock_interruptible(&rotator_lock);
+	if (ret)
+		return ret;
+
+	pr_debug("rotator session=%x start\n", rot->session_id);
+
+	for (ret = 0, tmp = rot; ret == 0 && tmp; tmp = tmp->next)
+		ret = mdss_mdp_rotator_queue_sub(tmp, src_data, dst_data);
+
 	mutex_unlock(&rotator_lock);
 
-	if (need_wait)
-		mdss_mdp_rotator_busy_wait(rot);
+	if (ret) {
+		pr_err("rotation failed %d for rot=%d\n", ret, rot->session_id);
+		return ret;
+	}
 
-	if (rot_pipe)
-		pr_debug("end of rotator pnum=%d enqueue\n", rot_pipe->num);
+	for (tmp = rot; tmp; tmp = tmp->next)
+		mdss_mdp_rotator_busy_wait(tmp);
+
+	pr_debug("rotator session=%x queue done\n", rot->session_id);
 
 	return ret;
 }
 
+int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot)
+{
+
+	rot->dst = rot->src_rect;
+	/*
+	 * by default, rotator output should be placed directly on
+	 * output buffer address without any offset.
+	 */
+	rot->dst.x = 0;
+	rot->dst.y = 0;
+
+	if (rot->flags & MDP_ROT_90)
+		swap(rot->dst.w, rot->dst.h);
+
+	if (rot->src_rect.w > MAX_MIXER_WIDTH) {
+		struct mdss_mdp_rotator_session *tmp;
+		u32 width;
+
+		if (rot->bwc_mode) {
+			pr_err("Unable to do split rotation with bwc set\n");
+			return -EINVAL;
+		}
+
+		width = rot->src_rect.w;
+
+		pr_debug("setting up split rotation src=%dx%d\n",
+			rot->src_rect.w, rot->src_rect.h);
+
+		if (width > (MAX_MIXER_WIDTH * 2)) {
+			pr_err("unsupported source width %d\n", width);
+			return -EOVERFLOW;
+		}
+
+		if (!rot->next) {
+			tmp = mdss_mdp_rotator_session_alloc();
+			if (!tmp) {
+				pr_err("unable to allocate rot dual session\n");
+				return -ENOMEM;
+			}
+			rot->next = tmp;
+		}
+		tmp = rot->next;
+
+		tmp->session_id = rot->session_id & ~MDSS_MDP_ROT_SESSION_MASK;
+		tmp->flags = rot->flags;
+		tmp->format = rot->format;
+		tmp->img_width = rot->img_width;
+		tmp->img_height = rot->img_height;
+		tmp->src_rect = rot->src_rect;
+
+		tmp->src_rect.w = width / 2;
+		width -= tmp->src_rect.w;
+		tmp->src_rect.x += width;
+
+		tmp->dst = rot->dst;
+		rot->src_rect.w = width;
+
+		if (rot->flags & MDP_ROT_90) {
+			/*
+			 * If rotated by 90 first half should be on top.
+			 * But if horizontally flipped should be on bottom.
+			 */
+			if (rot->flags & MDP_FLIP_LR)
+				rot->dst.y = tmp->src_rect.w;
+			else
+				tmp->dst.y = rot->src_rect.w;
+		} else {
+			/*
+			 * If not rotated, first half should be the left part
+			 * of the frame, unless horizontally flipped
+			 */
+			if (rot->flags & MDP_FLIP_LR)
+				rot->dst.x = tmp->src_rect.w;
+			else
+				tmp->dst.x = rot->src_rect.w;
+		}
+
+		tmp->params_changed++;
+	} else if (rot->next) {
+		mdss_mdp_rotator_finish(rot->next);
+		rot->next = NULL;
+	}
+
+	rot->params_changed++;
+
+	return 0;
+}
+
 static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot)
 {
 	struct mdss_mdp_pipe *rot_pipe;
@@ -237,6 +343,9 @@
 
 	pr_debug("finish rot id=%x\n", rot->session_id);
 
+	if (rot->next)
+		mdss_mdp_rotator_finish(rot->next);
+
 	rot_pipe = rot->pipe;
 	if (rot_pipe) {
 		mdss_mdp_rotator_busy_wait(rot);
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.h b/drivers/video/msm/mdss/mdss_mdp_rotator.h
index 21ee9bb..c50d710 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.h
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.h
@@ -30,6 +30,7 @@
 	u16 img_width;
 	u16 img_height;
 	struct mdss_mdp_img_rect src_rect;
+	struct mdss_mdp_img_rect dst;
 
 	u32 bwc_mode;
 	struct mdss_mdp_pipe *pipe;
@@ -40,6 +41,7 @@
 	u8 no_wait;
 
 	struct list_head head;
+	struct mdss_mdp_rotator_session *next;
 };
 
 static inline u32 mdss_mdp_get_rotator_dst_format(u32 in_format)
@@ -61,6 +63,7 @@
 struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void);
 struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_get(u32 session_id);
 
+int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot);
 int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot,
 			   struct mdss_mdp_data *src_data,
 			   struct mdss_mdp_data *dst_data);
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 5915f61..4de6d03 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -387,6 +387,31 @@
 	return 0;
 }
 
+void mdss_mdp_data_calc_offset(struct mdss_mdp_data *data, u16 x, u16 y,
+	struct mdss_mdp_plane_sizes *ps, struct mdss_mdp_format_params *fmt)
+{
+	if ((x == 0) && (y == 0))
+		return;
+
+	data->p[0].addr += y * ps->ystride[0];
+
+	if (data->num_planes == 1) {
+		data->p[0].addr += x * fmt->bpp;
+	} else {
+		u8 hmap[] = { 1, 2, 1, 2 };
+		u8 vmap[] = { 1, 1, 2, 2 };
+		u16 xoff = x / hmap[fmt->chroma_sample];
+		u16 yoff = y / vmap[fmt->chroma_sample];
+
+		data->p[0].addr += x;
+		data->p[1].addr += xoff + (yoff * ps->ystride[1]);
+		if (data->num_planes == 2) /* pseudo planar */
+			data->p[1].addr += xoff;
+		else /* planar */
+			data->p[2].addr += xoff + (yoff * ps->ystride[2]);
+	}
+}
+
 int mdss_mdp_put_img(struct mdss_mdp_img_data *data)
 {
 	struct ion_client *iclient = mdss_get_ionclient();
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 969b400..2f77d29 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -118,10 +118,10 @@
 /* This needs to be modified manually now, when we add
  a new RANGE of SSIDs to the msg_mask_tbl */
 #define MSG_MASK_TBL_CNT		24
-#define EVENT_LAST_ID			0x09AB
+#define EVENT_LAST_ID			0x09B2
 
 #define MSG_SSID_0			0
-#define MSG_SSID_0_LAST			94
+#define MSG_SSID_0_LAST			97
 #define MSG_SSID_1			500
 #define MSG_SSID_1_LAST			506
 #define MSG_SSID_2			1000
@@ -287,6 +287,9 @@
 	MSG_LVL_LOW,
 	MSG_LVL_LOW,
 	MSG_LVL_HIGH,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL,
 	MSG_LVL_LOW
 };
 
@@ -722,7 +725,7 @@
 /* LOG CODES */
 
 #define LOG_0	0x0
-#define LOG_1	0x1755
+#define LOG_1	0x17F4
 #define LOG_2	0x0
 #define LOG_3	0x0
 #define LOG_4	0x4910
diff --git a/include/linux/memory_alloc.h b/include/linux/memory_alloc.h
index b649451..8097949 100644
--- a/include/linux/memory_alloc.h
+++ b/include/linux/memory_alloc.h
@@ -20,7 +20,7 @@
 struct mem_pool {
 	struct mutex pool_mutex;
 	struct gen_pool *gpool;
-	unsigned long paddr;
+	phys_addr_t paddr;
 	unsigned long size;
 	unsigned long free;
 	unsigned int id;
@@ -28,29 +28,34 @@
 
 struct alloc {
 	struct rb_node rb_node;
-	void *vaddr;
-	unsigned long paddr;
+	/*
+	 * The physical address may be used for lookup in the tree so the
+	 * 'virtual address' needs to be able to accomodate larger physical
+	 * addresses.
+	 */
+	phys_addr_t vaddr;
+	phys_addr_t paddr;
 	struct mem_pool *mpool;
 	unsigned long len;
 	void *caller;
 };
 
-struct mem_pool *initialize_memory_pool(unsigned long start,
+struct mem_pool *initialize_memory_pool(phys_addr_t start,
 	unsigned long size, int mem_type);
 
 void *allocate_contiguous_memory(unsigned long size,
 	int mem_type, unsigned long align, int cached);
 
-unsigned long _allocate_contiguous_memory_nomap(unsigned long size,
+phys_addr_t _allocate_contiguous_memory_nomap(unsigned long size,
 	int mem_type, unsigned long align, void *caller);
 
-unsigned long allocate_contiguous_memory_nomap(unsigned long size,
+phys_addr_t allocate_contiguous_memory_nomap(unsigned long size,
 	int mem_type, unsigned long align);
 
 void free_contiguous_memory(void *addr);
-void free_contiguous_memory_by_paddr(unsigned long paddr);
+void free_contiguous_memory_by_paddr(phys_addr_t paddr);
 
-unsigned long memory_pool_node_paddr(void *vaddr);
+phys_addr_t memory_pool_node_paddr(void *vaddr);
 
 unsigned long memory_pool_node_len(void *vaddr);
 
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 37a12fb..3a9b1b9 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -150,6 +150,17 @@
 #define WCD9XXX_CH(xport, xshift) \
 	{.port = xport, .shift = xshift}
 
+struct wcd9xxx_codec_type {
+	u16 id_major;
+	u16 id_minor;
+	struct mfd_cell *dev;
+	int size;
+	int num_irqs;
+	int version; /* -1 to retrive version from chip version register */
+	enum wcd9xxx_slim_slave_addr_type slim_slave_type;
+	u16 i2c_chip_status;
+};
+
 struct wcd9xxx {
 	struct device *dev;
 	struct slim_device *slim;
@@ -181,14 +192,14 @@
 	struct pm_qos_request pm_qos_req;
 	int wlock_holders;
 
-	u8 idbyte[4];
+	u16 id_minor;
+	u16 id_major;
 
 	unsigned int irq_base;
 	unsigned int irq;
 	u8 irq_masks_cur[WCD9XXX_NUM_IRQ_REGS];
 	u8 irq_masks_cache[WCD9XXX_NUM_IRQ_REGS];
 	bool irq_level_high[WCD9XXX_MAX_NUM_IRQS];
-	int num_irqs;
 	/* Slimbus or I2S port */
 	u32 num_rx_port;
 	u32 num_tx_port;
@@ -196,7 +207,7 @@
 	struct wcd9xxx_ch *tx_chs;
 	u32 mclk_rate;
 
-	enum wcd9xxx_slim_slave_addr_type slim_slave_type;
+	const struct wcd9xxx_codec_type *codec_type;
 };
 
 int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index 813cac3..c6e4ab3 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -136,7 +136,7 @@
 	unsigned int	hph_ocp_limit:3; /* Headphone OCP current limit */
 };
 
-#define MAX_REGULATOR	7
+#define WCD9XXX_MAX_REGULATOR	8
 /*
  *      format : TABLA_<POWER_SUPPLY_PIN_NAME>_CUR_MAX
  *
@@ -151,11 +151,14 @@
 #define  WCD9XXX_VDDD_CDC_D_CUR_MAX       5000
 #define  WCD9XXX_VDDD_CDC_A_CUR_MAX       5000
 
+#define WCD9XXX_VDD_SPKDRV_NAME "cdc-vdd-spkdrv"
+
 struct wcd9xxx_regulator {
 	const char *name;
 	int min_uV;
 	int max_uV;
 	int optimum_uA;
+	bool ondemand;
 	struct regulator *regulator;
 };
 
@@ -168,7 +171,7 @@
 	struct slim_device slimbus_slave_device;
 	struct wcd9xxx_micbias_setting micbias;
 	struct wcd9xxx_ocp_setting ocp;
-	struct wcd9xxx_regulator regulator[MAX_REGULATOR];
+	struct wcd9xxx_regulator regulator[WCD9XXX_MAX_REGULATOR];
 	u32 mclk_rate;
 	u32 dmic_sample_rate;
 };
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 538185f..d74cd3b 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -122,6 +122,19 @@
  * secure discard kind of operations to complete.
  */
 #define SDHCI_QUIRK2_USE_MAX_DISCARD_SIZE		(1<<5)
+/*
+ * Ignore data timeout error for R1B commands as there will be no
+ * data associated and the busy timeout value for these commands
+ * could be lager than the maximum timeout value that controller
+ * can handle.
+ */
+#define SDHCI_QUIRK2_IGNORE_DATATOUT_FOR_R1BCMD		(1<<6)
+/*
+ * The preset value registers are not properly initialized by
+ * some hardware and hence preset value must not be enabled for
+ * such controllers.
+ */
+#define SDHCI_QUIRK2_BROKEN_PRESET_VALUE		(1<<7)
 
 	int irq;		/* Device IRQ */
 	void __iomem *ioaddr;	/* Mapped address */
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index f932494..b9d4a6f 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -289,14 +289,19 @@
 #define MDP_PP_IGC_FLAG_ROM0	0x10
 #define MDP_PP_IGC_FLAG_ROM1	0x20
 
-#define MDSS_PP_DSPP_CFG	0x0000
-#define MDSS_PP_SSPP_CFG	0x4000
-#define MDSS_PP_LM_CFG	0x8000
-#define MDSS_PP_WB_CFG	0xC000
+#define MDSS_PP_DSPP_CFG	0x000
+#define MDSS_PP_SSPP_CFG	0x100
+#define MDSS_PP_LM_CFG	0x200
+#define MDSS_PP_WB_CFG	0x300
 
-#define MDSS_PP_LOCATION_MASK	0xC000
-#define MDSS_PP_LOGICAL_MASK	0x3FFF
+#define MDSS_PP_ARG_MASK	0x3C00
+#define MDSS_PP_ARG_NUM		4
+#define MDSS_PP_ARG_SHIFT	10
+#define MDSS_PP_LOCATION_MASK	0x0300
+#define MDSS_PP_LOGICAL_MASK	0x00FF
 
+#define MDSS_PP_ADD_ARG(var, arg) ((var) | (0x1 << (MDSS_PP_ARG_SHIFT + (arg))))
+#define PP_ARG(x, var) ((var) & (0x1 << (MDSS_PP_ARG_SHIFT + (x))))
 #define PP_LOCAT(var) ((var) & MDSS_PP_LOCATION_MASK)
 #define PP_BLOCK(var) ((var) & MDSS_PP_LOGICAL_MASK)
 
@@ -326,6 +331,8 @@
 #define MDP_OVERLAY_PP_PA_CFG          0x4
 #define MDP_OVERLAY_PP_IGC_CFG         0x8
 #define MDP_OVERLAY_PP_SHARP_CFG       0x10
+#define MDP_OVERLAY_PP_HIST_CFG        0x20
+#define MDP_OVERLAY_PP_HIST_LUT_CFG    0x40
 
 #define MDP_CSC_FLAG_ENABLE	0x1
 #define MDP_CSC_FLAG_YUV_IN	0x2
@@ -361,6 +368,21 @@
 	uint32_t *c2_data;
 };
 
+struct mdp_histogram_cfg {
+	uint32_t ops;
+	uint32_t block;
+	uint8_t frame_cnt;
+	uint8_t bit_mask;
+	uint16_t num_bins;
+};
+
+struct mdp_hist_lut_data {
+	uint32_t block;
+	uint32_t ops;
+	uint32_t len;
+	uint32_t *data;
+};
+
 struct mdp_overlay_pp_params {
 	uint32_t config_ops;
 	struct mdp_csc_cfg csc_cfg;
@@ -368,6 +390,8 @@
 	struct mdp_pa_cfg pa_cfg;
 	struct mdp_igc_lut_data igc_cfg;
 	struct mdp_sharp_cfg sharp_cfg;
+	struct mdp_histogram_cfg hist_cfg;
+	struct mdp_hist_lut_data hist_lut_cfg;
 };
 
 struct mdp_overlay {
@@ -433,7 +457,7 @@
 	MDP_BLOCK_DMA_S,
 	MDP_BLOCK_DMA_E,
 	MDP_BLOCK_OVERLAY_2,
-	MDP_LOGICAL_BLOCK_DISP_0 = 0x1000,
+	MDP_LOGICAL_BLOCK_DISP_0 = 0x10,
 	MDP_LOGICAL_BLOCK_DISP_1,
 	MDP_LOGICAL_BLOCK_DISP_2,
 	MDP_BLOCK_MAX,
@@ -502,13 +526,6 @@
 };
 
 
-struct mdp_hist_lut_data {
-	uint32_t block;
-	uint32_t ops;
-	uint32_t len;
-	uint32_t *data;
-};
-
 struct mdp_lut_cfg_data {
 	uint32_t lut_type;
 	union {
diff --git a/include/linux/msm_thermal.h b/include/linux/msm_thermal.h
index 2c9a613..f14cc52 100644
--- a/include/linux/msm_thermal.h
+++ b/include/linux/msm_thermal.h
@@ -1,5 +1,5 @@
 /*
- * 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,9 +17,16 @@
 struct msm_thermal_data {
 	uint32_t sensor_id;
 	uint32_t poll_ms;
-	uint32_t limit_temp_degC;
-	uint32_t temp_hysteresis_degC;
+	int32_t limit_temp_degC;
+	int32_t temp_hysteresis_degC;
 	uint32_t freq_step;
+	int32_t core_limit_temp_degC;
+	int32_t core_temp_hysteresis_degC;
+	uint32_t core_control_mask;
+	int32_t vdd_rstr_temp_degC;
+	int32_t vdd_rstr_temp_hyst_degC;
+	int32_t psm_temp_degC;
+	int32_t psm_temp_hyst_degC;
 };
 
 #ifdef CONFIG_THERMAL_MONITOR
diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h
index c399b81..294c881 100644
--- a/include/linux/qseecom.h
+++ b/include/linux/qseecom.h
@@ -138,6 +138,25 @@
 	enum qseecom_key_management_usage_type usage;
 };
 
+#define SHA256_DIGEST_LENGTH	(256/8)
+/*
+ * struct qseecom_save_partition_hash_req
+ * @partition_id - partition id.
+ * @hash[SHA256_DIGEST_LENGTH] -  sha256 digest.
+ */
+struct qseecom_save_partition_hash_req {
+	int partition_id; /* in */
+	char digest[SHA256_DIGEST_LENGTH]; /* in */
+};
+
+/*
+ * struct qseecom_is_es_activated_req
+ * @is_activated - 1=true , 0=false
+ */
+struct qseecom_is_es_activated_req {
+	int is_activated; /* out */
+};
+
 #define QSEECOM_IOC_MAGIC    0x97
 
 
@@ -195,5 +214,10 @@
 #define QSEECOM_IOCTL_WIPE_KEY_REQ \
 	_IOWR(QSEECOM_IOC_MAGIC, 18, struct qseecom_wipe_key_req)
 
+#define QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 19, struct qseecom_save_partition_hash_req)
+
+#define QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 20, struct qseecom_is_es_activated_req)
 
 #endif /* __QSEECOM_H_ */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index c8a20da..5e73bd9 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -201,6 +201,7 @@
  *              USB enters LPM.
  * @delay_lpm_on_disconnect: Use a delay before entering LPM
  *              upon USB cable disconnection.
+ * @enable_sec_phy: Use second HSPHY with USB2 core
  * @bus_scale_table: parameters for bus bandwidth requirements
  * @mhl_dev_name: MHL device name used to register with MHL driver.
  */
@@ -222,12 +223,14 @@
 	bool core_clk_always_on_workaround;
 	bool delay_lpm_on_disconnect;
 	bool dp_manual_pullup;
+	bool enable_sec_phy;
 	struct msm_bus_scale_pdata *bus_scale_table;
 	const char *mhl_dev_name;
 };
 
 /* phy related flags */
 #define ENABLE_DP_MANUAL_PULLUP		BIT(0)
+#define ENABLE_SECONDARY_PHY		BIT(1)
 
 /* Timeout (in msec) values (min - max) associated with OTG timers */
 
diff --git a/lib/memory_alloc.c b/lib/memory_alloc.c
index cc7424f..03f1944 100644
--- a/lib/memory_alloc.c
+++ b/lib/memory_alloc.c
@@ -67,7 +67,7 @@
 	struct rb_node *r = p;
 	struct alloc *node = rb_entry(r, struct alloc, rb_node);
 
-	seq_printf(m, "0x%lx 0x%p %ld %u %pS\n", node->paddr, node->vaddr,
+	seq_printf(m, "0x%pa 0x%pa %ld %u %pS\n", &node->paddr, &node->vaddr,
 		   node->len, node->mpool->id, node->caller);
 	return 0;
 }
@@ -84,7 +84,7 @@
 	return seq_open(file, &mempool_op);
 }
 
-static struct alloc *find_alloc(void *addr)
+static struct alloc *find_alloc(phys_addr_t addr)
 {
 	struct rb_root *root = &alloc_root;
 	struct rb_node *p = root->rb_node;
@@ -126,7 +126,7 @@
 		else if (node->vaddr > tmp->vaddr)
 			p = &(*p)->rb_right;
 		else {
-			WARN(1, "memory at %p already allocated", tmp->vaddr);
+			WARN(1, "memory at %pa already allocated", &tmp->vaddr);
 			mutex_unlock(&alloc_mutex);
 			return -EINVAL;
 		}
@@ -149,7 +149,7 @@
 	return 0;
 }
 
-static struct gen_pool *initialize_gpool(unsigned long start,
+static struct gen_pool *initialize_gpool(phys_addr_t start,
 	unsigned long size)
 {
 	struct gen_pool *gpool;
@@ -194,7 +194,12 @@
 	if (!vaddr)
 		goto out_kfree;
 
-	node->vaddr = vaddr;
+	/*
+	 * Just cast to an unsigned long to avoid warnings about casting from a
+	 * pointer to an integer of different size. The pointer is only 32-bits
+	 * so we lose no data.
+	 */
+	node->vaddr = (unsigned long)vaddr;
 	node->paddr = paddr;
 	node->len = aligned_size;
 	node->mpool = mpool;
@@ -216,13 +221,19 @@
 
 static void __free(void *vaddr, bool unmap)
 {
-	struct alloc *node = find_alloc(vaddr);
+	struct alloc *node = find_alloc((unsigned long)vaddr);
 
 	if (!node)
 		return;
 
 	if (unmap)
-		iounmap(node->vaddr);
+		/*
+		 * We need the double cast because otherwise gcc complains about
+		 * cast to pointer of different size. This is technically a down
+		 * cast but if unmap is being called, this had better be an
+		 * actual 32-bit pointer anyway.
+		 */
+		iounmap((void *)(unsigned long)node->vaddr);
 
 	gen_pool_free(node->mpool->gpool, node->paddr, node->len);
 	node->mpool->free += node->len;
@@ -248,7 +259,7 @@
 	return mpool;
 }
 
-struct mem_pool *initialize_memory_pool(unsigned long start,
+struct mem_pool *initialize_memory_pool(phys_addr_t start,
 	unsigned long size, int mem_type)
 {
 	int id = mem_type;
@@ -264,8 +275,8 @@
 	mpools[id].id = id;
 	mutex_unlock(&mpools[id].pool_mutex);
 
-	pr_info("memory pool %d (start %lx size %lx) initialized\n",
-		id, start, size);
+	pr_info("memory pool %d (start %pa size %lx) initialized\n",
+		id, &start, size);
 	return &mpools[id];
 }
 EXPORT_SYMBOL_GPL(initialize_memory_pool);
@@ -285,10 +296,10 @@
 }
 EXPORT_SYMBOL_GPL(allocate_contiguous_memory);
 
-unsigned long _allocate_contiguous_memory_nomap(unsigned long size,
+phys_addr_t _allocate_contiguous_memory_nomap(unsigned long size,
 	int mem_type, unsigned long align, void *caller)
 {
-	unsigned long paddr;
+	phys_addr_t paddr;
 	unsigned long aligned_size;
 
 	struct alloc *node;
@@ -317,7 +328,7 @@
 	 * are disjoint, so there won't be any chance of
 	 * a duplicate node->vaddr value.
 	 */
-	node->vaddr = (void *)paddr;
+	node->vaddr = paddr;
 	node->len = aligned_size;
 	node->mpool = mpool;
 	node->caller = caller;
@@ -334,7 +345,7 @@
 }
 EXPORT_SYMBOL_GPL(_allocate_contiguous_memory_nomap);
 
-unsigned long allocate_contiguous_memory_nomap(unsigned long size,
+phys_addr_t allocate_contiguous_memory_nomap(unsigned long size,
 	int mem_type, unsigned long align)
 {
 	return _allocate_contiguous_memory_nomap(size, mem_type, align,
@@ -351,18 +362,18 @@
 }
 EXPORT_SYMBOL_GPL(free_contiguous_memory);
 
-void free_contiguous_memory_by_paddr(unsigned long paddr)
+void free_contiguous_memory_by_paddr(phys_addr_t paddr)
 {
 	if (!paddr)
 		return;
-	__free((void *)paddr, false);
+	__free((void *)(unsigned long)paddr, false);
 	return;
 }
 EXPORT_SYMBOL_GPL(free_contiguous_memory_by_paddr);
 
-unsigned long memory_pool_node_paddr(void *vaddr)
+phys_addr_t memory_pool_node_paddr(void *vaddr)
 {
-	struct alloc *node = find_alloc(vaddr);
+	struct alloc *node = find_alloc((unsigned long)vaddr);
 
 	if (!node)
 		return -EINVAL;
@@ -373,7 +384,7 @@
 
 unsigned long memory_pool_node_len(void *vaddr)
 {
-	struct alloc *node = find_alloc(vaddr);
+	struct alloc *node = find_alloc((unsigned long)vaddr);
 
 	if (!node)
 		return -EINVAL;
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index fd3e0dc..a7069a6 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -193,6 +193,7 @@
 	s32 dmic_5_6_clk_cnt;
 
 	u32 anc_slot;
+	bool anc_func;
 
 	/*track tapan interface type*/
 	u8 intf_type;
@@ -348,6 +349,58 @@
 	return 0;
 }
 
+static int tapan_get_anc_func(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = (tapan->anc_func == true ? 1 : 0);
+	return 0;
+}
+
+static int tapan_put_anc_func(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+	mutex_lock(&dapm->codec->mutex);
+	tapan->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
+
+	dev_err(codec->dev, "%s: anc_func %x", __func__, tapan->anc_func);
+
+	if (tapan->anc_func == true) {
+		pr_info("enable anc virtual widgets");
+		snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
+		snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
+		snd_soc_dapm_enable_pin(dapm, "ANC HEADPHONE");
+		snd_soc_dapm_enable_pin(dapm, "ANC EAR PA");
+		snd_soc_dapm_enable_pin(dapm, "ANC EAR");
+		snd_soc_dapm_disable_pin(dapm, "HPHR");
+		snd_soc_dapm_disable_pin(dapm, "HPHL");
+		snd_soc_dapm_disable_pin(dapm, "HEADPHONE");
+		snd_soc_dapm_disable_pin(dapm, "EAR PA");
+		snd_soc_dapm_disable_pin(dapm, "EAR");
+	} else {
+		pr_info("disable anc virtual widgets");
+		snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+		snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+		snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+		snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
+		snd_soc_dapm_disable_pin(dapm, "ANC EAR");
+		snd_soc_dapm_enable_pin(dapm, "HPHR");
+		snd_soc_dapm_enable_pin(dapm, "HPHL");
+		snd_soc_dapm_enable_pin(dapm, "HEADPHONE");
+		snd_soc_dapm_enable_pin(dapm, "EAR PA");
+		snd_soc_dapm_enable_pin(dapm, "EAR");
+	}
+	snd_soc_dapm_sync(dapm);
+	mutex_unlock(&dapm->codec->mutex);
+	return 0;
+}
+
 static int tapan_pa_gain_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -713,6 +766,10 @@
 		SOC_ENUM_SINGLE_EXT(2, tapan_ear_pa_gain_text),
 };
 
+static const char *const tapan_anc_func_text[] = {"OFF", "ON"};
+static const struct soc_enum tapan_anc_func_enum =
+		SOC_ENUM_SINGLE_EXT(2, tapan_anc_func_text);
+
 /*cut of frequency for high pass filter*/
 static const char * const cf_text[] = {
 	"MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
@@ -770,11 +827,11 @@
 	SOC_SINGLE_TLV("SPK DRV Volume", TAPAN_A_SPKR_DRV_GAIN, 3, 7, 1,
 		line_gain),
 
-	SOC_SINGLE_TLV("ADC1 Volume", TAPAN_A_TX_1_EN, 2, 13, 0, analog_gain),
-	SOC_SINGLE_TLV("ADC2 Volume", TAPAN_A_TX_2_EN, 2, 13, 0, analog_gain),
-	SOC_SINGLE_TLV("ADC3 Volume", TAPAN_A_TX_3_EN, 2, 13, 0, analog_gain),
-	SOC_SINGLE_TLV("ADC4 Volume", TAPAN_A_TX_4_EN, 2, 13, 0, analog_gain),
-	SOC_SINGLE_TLV("ADC5 Volume", TAPAN_A_TX_5_EN, 2, 13, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC1 Volume", TAPAN_A_TX_1_EN, 2, 19, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC2 Volume", TAPAN_A_TX_2_EN, 2, 19, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC3 Volume", TAPAN_A_TX_3_EN, 2, 19, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC4 Volume", TAPAN_A_TX_4_EN, 2, 19, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC5 Volume", TAPAN_A_TX_5_EN, 2, 19, 0, analog_gain),
 
 	SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL,
 		-84, 40, digital_gain),
@@ -803,9 +860,10 @@
 	SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAPAN_A_CDC_IIR1_GAIN_B4_CTL, -84,
 		40, digital_gain),
 
-	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, tapan_get_anc_slot,
+	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tapan_get_anc_slot,
 		tapan_put_anc_slot),
-
+	SOC_ENUM_EXT("ANC Function", tapan_anc_func_enum, tapan_get_anc_func,
+		tapan_put_anc_func),
 	SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
 	SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
 	SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
@@ -943,6 +1001,10 @@
 	"RSVD", "RSVD"
 };
 
+static const char * const anc1_fb_mux_text[] = {
+	"ZERO", "EAR_HPH_L", "EAR_LINE_1",
+};
+
 static const char * const iir1_inp1_text[] = {
 	"ZERO", "DEC1", "DEC2", "DEC3", "DEC4",
 	"RX1", "RX2", "RX3", "RX4", "RX5"
@@ -1031,6 +1093,9 @@
 static const struct soc_enum anc2_mux_enum =
 	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_ANC_B1_CTL, 4, 15, anc_mux_text);
 
+static const struct soc_enum anc1_fb_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
+
 static const struct soc_enum iir1_inp1_mux_enum =
 	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_EQ1_B1_CTL, 0, 10, iir1_inp1_text);
 
@@ -1200,6 +1265,9 @@
 static const struct snd_kcontrol_new anc2_mux =
 	SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
 
+static const struct snd_kcontrol_new anc1_fb_mux =
+	SOC_DAPM_ENUM("ANC1 FB MUX Mux", anc1_fb_mux_enum);
+
 static const struct snd_kcontrol_new dac1_switch[] = {
 	SOC_DAPM_SINGLE("Switch", TAPAN_A_RX_EAR_EN, 5, 1, 0)
 };
@@ -1322,11 +1390,11 @@
 			return 0;
 		}
 		break;
-		default:
-			dev_err(codec->dev, "Unknown AIF %d\n", dai_id);
-			mutex_unlock(&codec->mutex);
-			return -EINVAL;
-		}
+	default:
+		dev_err(codec->dev, "Unknown AIF %d\n", dai_id);
+		mutex_unlock(&codec->mutex);
+		return -EINVAL;
+	}
 	dev_dbg(codec->dev, "%s: name %s sname %s updated value %u shift %d\n",
 		 __func__, widget->name, widget->sname,
 		 widget->value, widget->shift);
@@ -1392,14 +1460,14 @@
 	break;
 	case 2:
 		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tapan_p->dai[AIF1_PB].wcd9xxx_ch_list))
+			&tapan_p->dai[AIF2_PB].wcd9xxx_ch_list))
 			goto pr_err;
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tapan_p->dai[AIF2_PB].wcd9xxx_ch_list);
 	break;
 	case 3:
 		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tapan_p->dai[AIF1_PB].wcd9xxx_ch_list))
+			&tapan_p->dai[AIF3_PB].wcd9xxx_ch_list))
 			goto pr_err;
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tapan_p->dai[AIF3_PB].wcd9xxx_ch_list);
@@ -1668,9 +1736,11 @@
 	int anc_size_remaining;
 	u32 *anc_ptr;
 	u16 reg;
-	u8 mask, val;
+	u8 mask, val, old_val;
 
 	dev_dbg(codec->dev, "%s %d\n", __func__, event);
+	if (tapan->anc_func == 0)
+		return 0;
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 
@@ -1737,14 +1807,21 @@
 		for (i = 0; i < anc_writes_size; i++) {
 			TAPAN_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
 				mask, val);
-			snd_soc_write(codec, reg, val);
+			old_val = snd_soc_read(codec, reg);
+			snd_soc_write(codec, reg, (old_val & ~mask) |
+					(val & mask));
 		}
 		release_firmware(fw);
 
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		snd_soc_write(codec, TAPAN_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
+		msleep(40);
+		snd_soc_update_bits(codec, TAPAN_A_CDC_ANC1_B1_CTL, 0x01, 0x00);
+		snd_soc_update_bits(codec, TAPAN_A_CDC_ANC2_B1_CTL, 0x02, 0x00);
+		msleep(20);
+		snd_soc_write(codec, TAPAN_A_CDC_CLK_ANC_RESET_CTL, 0x0F);
 		snd_soc_write(codec, TAPAN_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
+		snd_soc_write(codec, TAPAN_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
 		break;
 	}
 	return 0;
@@ -2137,12 +2214,12 @@
 
 	dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
 	if (w->shift == 5) {
-		e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
-		e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
-		req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
-	} else if (w->shift == 4) {
 		e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
 		e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
+		req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
+	} else if (w->shift == 4) {
+		e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
+		e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
 		req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
 	} else {
 		pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
@@ -2182,6 +2259,46 @@
 	return 0;
 }
 
+static int tapan_codec_enable_anc_hph(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	int ret = 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = tapan_hph_pa_event(w, kcontrol, event);
+		if (w->shift == 4) {
+			ret |= tapan_codec_enable_anc(w, kcontrol, event);
+			msleep(50);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		if (w->shift == 4) {
+			snd_soc_update_bits(codec,
+					TAPAN_A_RX_HPH_CNP_EN, 0x30, 0x30);
+			msleep(30);
+		}
+		ret = tapan_hph_pa_event(w, kcontrol, event);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (w->shift == 5) {
+			snd_soc_update_bits(codec,
+					TAPAN_A_RX_HPH_CNP_EN, 0x30, 0x00);
+			msleep(40);
+		}
+		if (w->shift == 5) {
+			snd_soc_update_bits(codec,
+					TAPAN_A_TX_7_MBHC_EN, 0x80, 00);
+			ret |= tapan_codec_enable_anc(w, kcontrol, event);
+		}
+	case SND_SOC_DAPM_POST_PMD:
+		ret = tapan_hph_pa_event(w, kcontrol, event);
+		break;
+	}
+	return ret;
+}
+
 static const struct snd_soc_dapm_widget tapan_dapm_i2s_widgets[] = {
 	SND_SOC_DAPM_SUPPLY("I2S_CLK", TAPAN_A_CDC_CLK_I2S_CTL,
 	4, 0, NULL, 0),
@@ -2296,6 +2413,11 @@
 	{"EAR_PA_MIXER", NULL, "DAC1"},
 	{"DAC1", NULL, "RX_BIAS"},
 
+	{"ANC EAR", NULL, "ANC EAR PA"},
+	{"ANC EAR PA", NULL, "EAR_PA_MIXER"},
+	{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
+	{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
+
 	/* Headset (RX MIX1 and RX MIX2) */
 	{"HEADPHONE", NULL, "HPHL"},
 	{"HEADPHONE", NULL, "HPHR"},
@@ -2308,6 +2430,33 @@
 	{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
 	{"HPHR DAC", NULL, "RX_BIAS"},
 
+	{"ANC HEADPHONE", NULL, "ANC HPHL"},
+	{"ANC HEADPHONE", NULL, "ANC HPHR"},
+
+	{"ANC HPHL", NULL, "HPHL_PA_MIXER"},
+	{"ANC HPHR", NULL, "HPHR_PA_MIXER"},
+
+	{"ANC1 MUX", "ADC1", "ADC1"},
+	{"ANC1 MUX", "ADC2", "ADC2"},
+	{"ANC1 MUX", "ADC3", "ADC3"},
+	{"ANC1 MUX", "ADC4", "ADC4"},
+	{"ANC1 MUX", "ADC5", "ADC5"},
+	{"ANC1 MUX", "DMIC1", "DMIC1"},
+	{"ANC1 MUX", "DMIC2", "DMIC2"},
+	{"ANC1 MUX", "DMIC3", "DMIC3"},
+	{"ANC1 MUX", "DMIC4", "DMIC4"},
+	{"ANC2 MUX", "ADC1", "ADC1"},
+	{"ANC2 MUX", "ADC2", "ADC2"},
+	{"ANC2 MUX", "ADC3", "ADC3"},
+	{"ANC2 MUX", "ADC4", "ADC4"},
+	{"ANC2 MUX", "ADC5", "ADC5"},
+	{"ANC2 MUX", "DMIC1", "DMIC1"},
+	{"ANC2 MUX", "DMIC2", "DMIC2"},
+	{"ANC2 MUX", "DMIC3", "DMIC3"},
+	{"ANC2 MUX", "DMIC4", "DMIC4"},
+
+	{"ANC HPHR", NULL, "CDC_CONN"},
+
 	{"DAC1", "Switch", "CLASS_H_DSM MUX"},
 	{"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
 	{"HPHR DAC", NULL, "RX2 CHAIN"},
@@ -2336,6 +2485,8 @@
 	{"RX1 CHAIN", NULL, "RX1 MIX2"},
 	{"RX2 CHAIN", NULL, "RX2 MIX2"},
 	{"CLASS_H_DSM MUX", "RX_HPHL", "RX1 CHAIN"},
+	{"RX1 MIX2", NULL, "ANC1 MUX"},
+	{"RX2 MIX2", NULL, "ANC2 MUX"},
 
 	{"LINEOUT1 DAC", NULL, "RX_BIAS"},
 	{"LINEOUT2 DAC", NULL, "RX_BIAS"},
@@ -2564,6 +2715,14 @@
 		(reg <= TAPAN_A_CDC_IIR2_COEF_B2_CTL))
 		return 1;
 
+	/* ANC filter registers are not cacheable */
+	if ((reg >= TAPAN_A_CDC_ANC1_IIR_B1_CTL) &&
+		(reg <= TAPAN_A_CDC_ANC1_LPF_B2_CTL))
+		return 1;
+	if ((reg >= TAPAN_A_CDC_ANC2_IIR_B1_CTL) &&
+		(reg <= TAPAN_A_CDC_ANC2_LPF_B2_CTL))
+		return 1;
+
 	/* Digital gain register is not cacheable so we have to write
 	 * the setting even it is the same
 	 */
@@ -2850,7 +3009,7 @@
 					tapan->comp_fs[comp_rx_path[j]]
 					= compander_fs;
 			}
-			if (j <= 2)
+			if (j <= 1)
 				rx_mix_1_reg_1 += 3;
 			else
 				rx_mix_1_reg_1 += 2;
@@ -3419,6 +3578,33 @@
 	return 0;
 }
 
+static int tapan_codec_enable_anc_ear(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	int ret = 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = tapan_codec_enable_anc(w, kcontrol, event);
+		msleep(50);
+		snd_soc_update_bits(codec, TAPAN_A_RX_EAR_EN, 0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		ret = tapan_codec_enable_ear_pa(w, kcontrol, event);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, TAPAN_A_RX_EAR_EN, 0x10, 0x00);
+		msleep(40);
+		ret |= tapan_codec_enable_anc(w, kcontrol, event);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = tapan_codec_enable_ear_pa(w, kcontrol, event);
+		break;
+	}
+	return ret;
+}
+
 
 /* Todo: Have seperate dapm widgets for I2S and Slimbus.
  * Might Need to have callbacks registered only for slimbus
@@ -3695,9 +3881,21 @@
 	SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
 	SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
 
-	SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
-		tapan_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
+	SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 5, 0, NULL, 0,
+		tapan_codec_enable_anc_hph,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 4, 0, NULL, 0,
+		tapan_codec_enable_anc_hph, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_OUTPUT("ANC EAR"),
+	SND_SOC_DAPM_PGA_E("ANC EAR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
+		tapan_codec_enable_anc_ear,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
 
 	SND_SOC_DAPM_INPUT("AMIC2"),
 	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TAPAN_A_MICB_2_CTL, 7, 0,
@@ -4304,6 +4502,14 @@
 	(void) tapan_setup_irqs(tapan);
 
 	atomic_set(&kp_tapan_priv, (unsigned long)tapan);
+	mutex_lock(&dapm->codec->mutex);
+	snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+	snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+	snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+	snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
+	snd_soc_dapm_disable_pin(dapm, "ANC EAR");
+	snd_soc_dapm_sync(dapm);
+	mutex_unlock(&dapm->codec->mutex);
 
 	codec->ignore_pmdown_time = 1;
 	return ret;
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index cc1e8eb..fef7100 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -24,6 +24,7 @@
 #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
 #include <linux/mfd/wcd9xxx/wcd9320_registers.h>
 #include <linux/mfd/wcd9xxx/pdata.h>
+#include <linux/regulator/consumer.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
@@ -394,6 +395,7 @@
 	u8 aux_r_gain;
 
 	bool spkr_pa_widget_on;
+	struct regulator *spkdrv_reg;
 
 	struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;
 
@@ -404,7 +406,6 @@
 
 	/* class h specific data */
 	struct wcd9xxx_clsh_cdc_data clsh_d;
-
 };
 
 static const u32 comp_shift[] = {
@@ -1082,13 +1083,6 @@
 		40, digital_gain),
 	SOC_SINGLE_S8_TLV("IIR2 INP4 Volume", TAIKO_A_CDC_IIR2_GAIN_B4_CTL, -84,
 		40, digital_gain),
-	SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
-	SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
-	SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
-	SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
-	SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
-	SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
-
 
 	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
 		taiko_put_anc_slot),
@@ -2707,10 +2701,20 @@
 	int ret = 0;
 	struct snd_soc_codec *codec = w->codec;
 	struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+	struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
 
 	pr_debug("%s: %d %s\n", __func__, event, w->name);
+
+	WARN_ONCE(!priv->spkdrv_reg, "SPKDRV supply %s isn't defined\n",
+		  WCD9XXX_VDD_SPKDRV_NAME);
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
+		if (priv->spkdrv_reg) {
+			ret = regulator_enable(priv->spkdrv_reg);
+			if (ret)
+				pr_err("%s: Failed to enable spkdrv_reg %s\n",
+				       __func__, WCD9XXX_VDD_SPKDRV_NAME);
+		}
 		if (spkr_drv_wrnd > 0) {
 			WARN_ON(!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
 				  0x80));
@@ -2731,6 +2735,12 @@
 			snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
 					    0x80);
 		}
+		if (priv->spkdrv_reg) {
+			ret = regulator_disable(priv->spkdrv_reg);
+			if (ret)
+				pr_err("%s: Failed to disable spkdrv_reg %s\n",
+				       __func__, WCD9XXX_VDD_SPKDRV_NAME);
+		}
 		break;
 	}
 
@@ -5378,7 +5388,8 @@
 	}
 
 	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
-		if (!strncmp(pdata->regulator[i].name, "CDC_VDDA_RX", 11)) {
+		if (pdata->regulator[i].name &&
+		    !strncmp(pdata->regulator[i].name, "CDC_VDDA_RX", 11)) {
 			if (pdata->regulator[i].min_uV == 1800000 &&
 			    pdata->regulator[i].max_uV == 1800000) {
 				snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
@@ -5945,6 +5956,21 @@
 			   SND_SOC_DAPM_POST_PMU),
 };
 
+static struct regulator *taiko_codec_find_regulator(struct snd_soc_codec *codec,
+						    const char *name)
+{
+	int i;
+	struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+
+	for (i = 0; i < core->num_of_supplies; i++) {
+		if (core->supplies[i].supply &&
+		    !strcmp(core->supplies[i].supply, name))
+			return core->supplies[i].consumer;
+	}
+
+	return NULL;
+}
+
 static int taiko_codec_probe(struct snd_soc_codec *codec)
 {
 	struct wcd9xxx *control;
@@ -6023,6 +6049,9 @@
 		goto err_pdata;
 	}
 
+	taiko->spkdrv_reg = taiko_codec_find_regulator(codec,
+						       WCD9XXX_VDD_SPKDRV_NAME);
+
 	if (spkr_drv_wrnd > 0) {
 		WCD9XXX_BCL_LOCK(&taiko->resmgr);
 		wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
@@ -6127,6 +6156,8 @@
 	/* cleanup resmgr */
 	wcd9xxx_resmgr_deinit(&taiko->resmgr);
 
+	taiko->spkdrv_reg = NULL;
+
 	kfree(taiko);
 	return 0;
 }
diff --git a/sound/soc/msm/mdm9625.c b/sound/soc/msm/mdm9625.c
index 2bef1b7..f3ccb33 100644
--- a/sound/soc/msm/mdm9625.c
+++ b/sound/soc/msm/mdm9625.c
@@ -761,6 +761,21 @@
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
 	},
 	{
+		.name = "MDM9625 Media2",
+		.stream_name = "MultiMedia2",
+		.cpu_dai_name   = "MultiMedia2",
+		.platform_name  = "msm-pcm-dsp.0",
+		.dynamic = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+	},
+	{
 		.name = "MSM VoIP",
 		.stream_name = "VoIP",
 		.cpu_dai_name = "VoIP",
diff --git a/sound/soc/msm/qdsp6v2/audio_ocmem.c b/sound/soc/msm/qdsp6v2/audio_ocmem.c
index c14cb74..ad96ae3 100644
--- a/sound/soc/msm/qdsp6v2/audio_ocmem.c
+++ b/sound/soc/msm/qdsp6v2/audio_ocmem.c
@@ -20,18 +20,58 @@
 #include <linux/platform_device.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <linux/of_device.h>
+#include <linux/memory_alloc.h>
 #include <asm/mach-types.h>
 #include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
 #include <mach/ocmem.h>
+#include <mach/subsystem_notif.h>
+#include <mach/subsystem_restart.h>
+#include <mach/msm_memtypes.h>
+#include <mach/ramdump.h>
 #include "q6core.h"
 #include "audio_ocmem.h"
 
+
 #define AUDIO_OCMEM_BUF_SIZE (512 * SZ_1K)
 
+/**
+ * Exercise OCMEM Dump if audio OCMEM state is
+ * one of the following. All other states indicate
+ * audio data is not mapped from DDR to OCMEM and
+ * therefore no need of dump.
+ */
+#define _DO_OCMEM_DUMP_BIT_MASK_\
+		((1 << OCMEM_STATE_MAP_COMPL) |\
+		(1 << OCMEM_STATE_MAP_TRANSITION) |\
+		(1 << OCMEM_STATE_UNMAP_TRANSITION) |\
+		(1 << OCMEM_STATE_SHRINK) |\
+		(1 << OCMEM_STATE_GROW))
+
+/**
+ * Wait for OCMEM driver to process and respond for
+ * ongoing map/unmap request before calling OCMEM dump.
+ */
+#define _WAIT_BFR_DUMP_BIT_MASK_\
+		((1 << OCMEM_STATE_MAP_COMPL) |\
+		(1 << OCMEM_STATE_UNMAP_COMPL) |\
+		(1 << OCMEM_STATE_MAP_FAIL) |\
+		(1 << OCMEM_STATE_UNMAP_FAIL))
+
+#define _MAP_RESPONSE_BIT_MASK_\
+		((1 << OCMEM_STATE_MAP_COMPL) |\
+		(1 << OCMEM_STATE_MAP_FAIL))
+
+
+#define _UNMAP_RESPONSE_BIT_MASK_\
+		((1 << OCMEM_STATE_UNMAP_COMPL) |\
+		(1 << OCMEM_STATE_UNMAP_FAIL))
+
 #define _BIT_MASK_\
-		((1 << OCMEM_STATE_EXIT) |\
+		((1 << OCMEM_STATE_SSR) |\
+		(1 << OCMEM_STATE_EXIT) |\
 		(1 << OCMEM_STATE_GROW) |\
 		(1 << OCMEM_STATE_SHRINK))
 
@@ -89,6 +129,10 @@
 	struct workqueue_struct *audio_ocmem_workqueue;
 	struct workqueue_struct *voice_ocmem_workqueue;
 	bool ocmem_en;
+	bool audio_ocmem_running;
+	void *ocmem_ramdump_dev;
+	struct ramdump_segment ocmem_ramdump_segment;
+	unsigned long ocmem_dump_addr;
 };
 
 static struct audio_ocmem_prv audio_ocmem_lcl;
@@ -114,7 +158,9 @@
 		break;
 	case OCMEM_MAP_FAIL:
 		pr_debug("%s: map fail\n", __func__);
-		atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_MAP_FAIL);
+		clear_bit_pos(audio_ocmem_lcl.audio_state,
+				OCMEM_STATE_MAP_TRANSITION);
+		set_bit_pos(audio_ocmem_lcl.audio_state, OCMEM_STATE_MAP_FAIL);
 		break;
 	case OCMEM_UNMAP_DONE:
 		pr_debug("%s: unmap done\n", __func__);
@@ -125,8 +171,10 @@
 		break;
 	case OCMEM_UNMAP_FAIL:
 		pr_debug("%s: unmap fail\n", __func__);
-		atomic_set(&audio_ocmem_lcl.audio_state,
-				OCMEM_STATE_UNMAP_FAIL);
+		clear_bit_pos(audio_ocmem_lcl.audio_state,
+				OCMEM_STATE_UNMAP_TRANSITION);
+		set_bit_pos(audio_ocmem_lcl.audio_state,
+			    OCMEM_STATE_UNMAP_FAIL);
 		break;
 	case OCMEM_ALLOC_GROW:
 		rbuf = data;
@@ -170,6 +218,9 @@
 	} else if (test_bit_pos((*state), OCMEM_STATE_EXIT)) {
 		pr_debug("%s: returning exit state\n", __func__);
 		return OCMEM_STATE_EXIT;
+	} else if (test_bit_pos((*state), OCMEM_STATE_SSR)) {
+		pr_debug("%s: returning ssr state\n", __func__);
+		return OCMEM_STATE_SSR;
 	} else
 		return -EINVAL;
 
@@ -278,8 +329,8 @@
 	}
 
 	wait_event_interruptible(audio_ocmem_lcl.audio_wait,
-			test_bit_pos(audio_ocmem_lcl.audio_state,
-				OCMEM_STATE_MAP_COMPL) != 0);
+			(atomic_read(&audio_ocmem_lcl.audio_state) &
+					_MAP_RESPONSE_BIT_MASK_) != 0);
 	atomic_set(&audio_ocmem_lcl.audio_cond, 1);
 
 	mutex_unlock(&audio_ocmem_lcl.protect_lock);
@@ -322,8 +373,9 @@
 			}
 
 			wait_event_interruptible(audio_ocmem_lcl.audio_wait,
-				test_bit_pos(audio_ocmem_lcl.audio_state,
-					OCMEM_STATE_UNMAP_COMPL) != 0);
+				(atomic_read(&audio_ocmem_lcl.audio_state) &
+					     _UNMAP_RESPONSE_BIT_MASK_)
+					     != 0);
 			ret = ocmem_shrink(cid, audio_ocmem_lcl.buf, 0);
 			if (ret) {
 				pr_err("%s: ocmem_shrink failed, state[%d]\n",
@@ -353,8 +405,8 @@
 				goto fail_cmd;
 			}
 			wait_event_interruptible(audio_ocmem_lcl.audio_wait,
-				test_bit_pos(audio_ocmem_lcl.audio_state,
-					OCMEM_STATE_MAP_COMPL) != 0);
+				(atomic_read(&audio_ocmem_lcl.audio_state) &
+						_MAP_RESPONSE_BIT_MASK_) != 0);
 
 			clear_bit_pos(audio_ocmem_lcl.audio_state,
 					OCMEM_STATE_GROW);
@@ -377,8 +429,8 @@
 				}
 				wait_event_interruptible(
 				audio_ocmem_lcl.audio_wait,
-				test_bit_pos(audio_ocmem_lcl.audio_state,
-					OCMEM_STATE_UNMAP_COMPL) != 0);
+				(atomic_read(&audio_ocmem_lcl.audio_state) &
+				_UNMAP_RESPONSE_BIT_MASK_) != 0);
 			}
 
 			if (test_bit_pos(audio_ocmem_lcl.audio_state,
@@ -434,14 +486,15 @@
 				goto fail_cmd;
 			}
 			pr_debug("%s: ocmem_free success\n", __func__);
+		/* Fall through */
+		case OCMEM_STATE_SSR:
 			msm_bus_scale_client_update_request(
 				audio_ocmem_lcl.audio_ocmem_bus_client,
 				0);
 			set_bit_pos(audio_ocmem_lcl.audio_state,
-						OCMEM_STATE_DISABLE);
+					OCMEM_STATE_DISABLE);
 			break;
 
-
 		case -EINVAL:
 			pr_info("%s: audio_cond[%d] audio_state[0x%x]\n",
 				__func__,
@@ -453,6 +506,7 @@
 	ret = 0;
 fail_cmd:
 	pr_debug("%s: exit\n", __func__);
+	audio_ocmem_lcl.audio_ocmem_running = false;
 	return ret;
 }
 
@@ -470,8 +524,11 @@
 	pr_debug("%s: audio_cond[0x%x], audio_state[0x%x]\n", __func__,
 			 atomic_read(&audio_ocmem_lcl.audio_cond),
 			 atomic_read(&audio_ocmem_lcl.audio_state));
-	set_bit_pos(audio_ocmem_lcl.audio_state,
-				OCMEM_STATE_EXIT);
+	if (!test_bit_pos(audio_ocmem_lcl.audio_state,
+			  OCMEM_STATE_SSR))
+		set_bit_pos(audio_ocmem_lcl.audio_state,
+			    OCMEM_STATE_EXIT);
+
 	wake_up(&audio_ocmem_lcl.audio_wait);
 
 	mutex_unlock(&audio_ocmem_lcl.protect_lock);
@@ -652,6 +709,7 @@
 		}
 		workdata->id = id;
 		workdata->en = enable;
+		audio_ocmem_lcl.audio_ocmem_running = true;
 
 		INIT_WORK(&workdata->work, audio_ocmem_process_workdata);
 		queue_work(audio_ocmem_lcl.audio_ocmem_workqueue,
@@ -684,12 +742,130 @@
 
 	return 0;
 }
+
+static void do_ocmem_ramdump(void)
+{
+	int ret = 0;
+	void *virt = NULL;
+
+	virt = ioremap(audio_ocmem_lcl.ocmem_dump_addr, AUDIO_OCMEM_BUF_SIZE);
+	ret = ocmem_dump(OCMEM_LP_AUDIO,
+			 audio_ocmem_lcl.buf,
+			 (unsigned long)virt);
+	iounmap(virt);
+
+	if (ret)
+		pr_err("%s: ocmem_dump failed\n", __func__);
+
+	audio_ocmem_lcl.ocmem_ramdump_segment.address
+			= (unsigned long)audio_ocmem_lcl.ocmem_dump_addr;
+	audio_ocmem_lcl.ocmem_ramdump_segment.size
+						= AUDIO_OCMEM_BUF_SIZE;
+	ret = do_ramdump(audio_ocmem_lcl.ocmem_ramdump_dev,
+			 &audio_ocmem_lcl.ocmem_ramdump_segment,
+			 1);
+	if (ret < 0)
+		pr_err("%s: do_ramdump failed\n", __func__);
+}
+
+static void process_ocmem_dump(void)
+{
+	int ret = 0;
+
+	set_bit_pos(audio_ocmem_lcl.audio_state, OCMEM_STATE_SSR);
+
+	if (atomic_read(&audio_ocmem_lcl.audio_state) &
+	    _DO_OCMEM_DUMP_BIT_MASK_) {
+
+		wait_event_interruptible(audio_ocmem_lcl.audio_wait,
+				(atomic_read(&audio_ocmem_lcl.audio_state) &
+				 _WAIT_BFR_DUMP_BIT_MASK_) != 0);
+
+		if (test_bit_pos(audio_ocmem_lcl.audio_state,
+				 OCMEM_STATE_MAP_COMPL) ||
+		    test_bit_pos(audio_ocmem_lcl.audio_state,
+				 OCMEM_STATE_UNMAP_FAIL)) {
+
+			if (audio_ocmem_lcl.ocmem_dump_addr &&
+			    audio_ocmem_lcl.ocmem_ramdump_dev)
+				do_ocmem_ramdump();
+			else
+				pr_err("%s: Error calling ocmem ramdump\n",
+					__func__);
+
+			ret = ocmem_drop(OCMEM_LP_AUDIO, audio_ocmem_lcl.buf,
+					 &audio_ocmem_lcl.mlist);
+			if (ret)
+				pr_err("%s: ocmem_drop failed\n", __func__);
+		}
+	}
+
+	ret = ocmem_free(OCMEM_LP_AUDIO, audio_ocmem_lcl.buf);
+	if (ret)
+		pr_err("%s: ocmem_free failed\n", __func__);
+}
+
+static int lpass_notifier_cb(struct notifier_block *this, unsigned long code,
+			     void *_cmd)
+{
+	int ret = NOTIFY_DONE;
+
+	switch (code) {
+	case SUBSYS_BEFORE_SHUTDOWN:
+	pr_debug("AO-Notify: Shutdown started\n");
+		break;
+	case SUBSYS_AFTER_SHUTDOWN:
+	pr_debug("AO-Notify: Shutdown Completed\n");
+		break;
+	case SUBSYS_RAMDUMP_NOTIFICATION:
+		pr_debug("AO-Notify: OCMEM dump\n");
+		if (audio_ocmem_lcl.ocmem_en &&
+		    audio_ocmem_lcl.audio_ocmem_running)
+			process_ocmem_dump();
+		pr_debug("AO-Notify: OCMEM dump done\n");
+		break;
+	case SUBSYS_BEFORE_POWERUP:
+		pr_debug("AO-Notify: Powerup started\n");
+		break;
+	case SUBSYS_AFTER_POWERUP:
+		pr_debug("AO-Notify: Powerup completed\n");
+		break;
+	default:
+		pr_err("AO-Notify: Generel: %lu\n", code);
+		break;
+	}
+	return ret;
+}
+
+static struct notifier_block anb = {
+	.notifier_call = lpass_notifier_cb,
+};
+
 static int ocmem_audio_client_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct msm_bus_scale_pdata *audio_ocmem_bus_scale_pdata = NULL;
 
 	pr_debug("%s\n", __func__);
+
+	subsys_notif_register_notifier("adsp", &anb);
+
+	audio_ocmem_lcl.ocmem_dump_addr =
+		allocate_contiguous_memory_nomap(AUDIO_OCMEM_BUF_SIZE,
+						 MEMTYPE_EBI1,
+						 AUDIO_OCMEM_BUF_SIZE);
+
+	if (audio_ocmem_lcl.ocmem_dump_addr) {
+		audio_ocmem_lcl.ocmem_ramdump_dev =
+			create_ramdump_device("audio-ocmem", &pdev->dev);
+
+		if (!audio_ocmem_lcl.ocmem_ramdump_dev)
+			pr_err("%s: audio-ocmem ramdump device failed\n",
+				__func__);
+	} else {
+		pr_err("%s: ocmem dump memory alloc failed\n", __func__);
+	}
+
 	audio_ocmem_lcl.audio_ocmem_workqueue =
 		alloc_workqueue("ocmem_audio_client_driver_audio",
 					WQ_NON_REENTRANT | WQ_UNBOUND, 0);
@@ -715,6 +891,7 @@
 	spin_lock_init(&audio_ocmem_lcl.audio_lock);
 	mutex_init(&audio_ocmem_lcl.protect_lock);
 	audio_ocmem_lcl.ocmem_en = true;
+	audio_ocmem_lcl.audio_ocmem_running = false;
 
 	/* populate platform data */
 	ret = audio_ocmem_platform_data_populate(pdev);
@@ -753,6 +930,7 @@
 	msm_bus_cl_clear_pdata(audio_ocmem_bus_scale_pdata);
 	ocmem_notifier_unregister(audio_ocmem_lcl.audio_hdl,
 					&audio_ocmem_client_nb);
+	free_contiguous_memory_by_paddr(audio_ocmem_lcl.ocmem_dump_addr);
 	return 0;
 }
 static const struct of_device_id msm_ocmem_audio_dt_match[] = {
@@ -771,11 +949,9 @@
 	.remove = ocmem_audio_client_remove,
 };
 
-
 static int __init ocmem_audio_client_init(void)
 {
 	int rc;
-
 	rc = platform_driver_register(&audio_ocmem_driver);
 
 	if (rc)
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 9d6896e..63af271 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -56,6 +56,10 @@
 #define TIMEOUT_MS 1000
 #define Q6AFE_MAX_VOLUME 0x3FFF
 
+static int pcm_afe_instance[2];
+static int proxy_afe_instance[2];
+bool afe_close_done[2] = {true, true};
+
 #define SIZEOF_CFG_CMD(y) \
 		(sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
 
@@ -943,7 +947,7 @@
 	int i;
 
 	i = port_id - SLIMBUS_0_RX;
-	if (i < 0 || i > ARRAY_SIZE(afe_ports_mad_type)) {
+	if (i < 0 || i >= ARRAY_SIZE(afe_ports_mad_type)) {
 		pr_debug("%s: Non Slimbus port_id 0x%x\n", __func__, port_id);
 		return MAD_HW_NONE;
 	}
@@ -1061,11 +1065,30 @@
 	}
 
 	if ((port_id == RT_PROXY_DAI_001_RX) ||
-		(port_id == RT_PROXY_DAI_002_TX))
-		return 0;
-	if ((port_id == RT_PROXY_DAI_002_RX) ||
-		(port_id == RT_PROXY_DAI_001_TX))
+		(port_id == RT_PROXY_DAI_002_TX)) {
+		pr_debug("%s: before incrementing pcm_afe_instance %d"\
+			" port_id %d\n", __func__,
+			pcm_afe_instance[port_id & 0x1], port_id);
 		port_id = VIRTUAL_ID_TO_PORTID(port_id);
+		pcm_afe_instance[port_id & 0x1]++;
+		return 0;
+	}
+	if ((port_id == RT_PROXY_DAI_002_RX) ||
+			(port_id == RT_PROXY_DAI_001_TX)) {
+		pr_debug("%s: before incrementing proxy_afe_instance %d"\
+			" port_id %d\n", __func__,
+			proxy_afe_instance[port_id & 0x1], port_id);
+
+		if (!afe_close_done[port_id & 0x1]) {
+			/*close pcm dai corresponding to the proxy dai*/
+			afe_close(port_id - 0x10);
+			pcm_afe_instance[port_id & 0x1]++;
+			pr_debug("%s: reconfigure afe port again\n", __func__);
+		}
+		proxy_afe_instance[port_id & 0x1]++;
+		afe_close_done[port_id & 0x1] = false;
+		port_id = VIRTUAL_ID_TO_PORTID(port_id);
+	}
 
 	pr_debug("%s: port id: %#x\n", __func__, port_id);
 
@@ -2618,6 +2641,31 @@
 		goto fail_cmd;
 	}
 	pr_debug("%s: port_id=%d\n", __func__, port_id);
+	if ((port_id == RT_PROXY_DAI_001_RX) ||
+			(port_id == RT_PROXY_DAI_002_TX)) {
+		pr_debug("%s: before decrementing pcm_afe_instance %d\n",
+			__func__, pcm_afe_instance[port_id & 0x1]);
+		port_id = VIRTUAL_ID_TO_PORTID(port_id);
+		pcm_afe_instance[port_id & 0x1]--;
+		if (!(pcm_afe_instance[port_id & 0x1] == 0 &&
+			proxy_afe_instance[port_id & 0x1] == 0))
+			return 0;
+		else
+			afe_close_done[port_id & 0x1] = true;
+	}
+
+	if ((port_id == RT_PROXY_DAI_002_RX) ||
+		(port_id == RT_PROXY_DAI_001_TX)) {
+		pr_debug("%s: before decrementing proxy_afe_instance %d\n",
+			__func__, proxy_afe_instance[port_id & 0x1]);
+		port_id = VIRTUAL_ID_TO_PORTID(port_id);
+		proxy_afe_instance[port_id & 0x1]--;
+		if (!(pcm_afe_instance[port_id & 0x1] == 0 &&
+			proxy_afe_instance[port_id & 0x1] == 0))
+			return 0;
+		else
+			afe_close_done[port_id & 0x1] = true;
+	}
 
 	port_id = q6audio_convert_virtual_to_portid(port_id);
 	index = q6audio_get_port_index(port_id);