Merge "msm: pm-8x60: Remove enum from devicetree"
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index b0a5d9a..45000f0 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -158,6 +158,17 @@
 		not enabled to wake up the system from sleep states, this
 		attribute is not present.
 
+What:		/sys/devices/.../power/wakeup_prevent_sleep_time_ms
+Date:		February 2012
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/devices/.../wakeup_prevent_sleep_time_ms attribute
+		contains the total time the device has been preventing
+		opportunistic transitions to sleep states from occuring.
+		This attribute is read-only.  If the device is not enabled to
+		wake up the system from sleep states, this attribute is not
+		present.
+
 What:		/sys/devices/.../power/autosuspend_delay_ms
 Date:		September 2010
 Contact:	Alan Stern <stern@rowland.harvard.edu>
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index b464d12..31725ff 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -172,3 +172,62 @@
 
 		Reading from this file will display the current value, which is
 		set to 1 MB by default.
+
+What:		/sys/power/autosleep
+Date:		April 2012
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/power/autosleep file can be written one of the strings
+		returned by reads from /sys/power/state.  If that happens, a
+		work item attempting to trigger a transition of the system to
+		the sleep state represented by that string is queued up.  This
+		attempt will only succeed if there are no active wakeup sources
+		in the system at that time.  After every execution, regardless
+		of whether or not the attempt to put the system to sleep has
+		succeeded, the work item requeues itself until user space
+		writes "off" to /sys/power/autosleep.
+
+		Reading from this file causes the last string successfully
+		written to it to be returned.
+
+What:		/sys/power/wake_lock
+Date:		February 2012
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/power/wake_lock file allows user space to create
+		wakeup source objects and activate them on demand (if one of
+		those wakeup sources is active, reads from the
+		/sys/power/wakeup_count file block or return false).  When a
+		string without white space is written to /sys/power/wake_lock,
+		it will be assumed to represent a wakeup source name.  If there
+		is a wakeup source object with that name, it will be activated
+		(unless active already).  Otherwise, a new wakeup source object
+		will be registered, assigned the given name and activated.
+		If a string written to /sys/power/wake_lock contains white
+		space, the part of the string preceding the white space will be
+		regarded as a wakeup source name and handled as descrived above.
+		The other part of the string will be regarded as a timeout (in
+		nanoseconds) such that the wakeup source will be automatically
+		deactivated after it has expired.  The timeout, if present, is
+		set regardless of the current state of the wakeup source object
+		in question.
+
+		Reads from this file return a string consisting of the names of
+		wakeup sources created with the help of it that are active at
+		the moment, separated with spaces.
+
+
+What:		/sys/power/wake_unlock
+Date:		February 2012
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/power/wake_unlock file allows user space to deactivate
+		wakeup sources created with the help of /sys/power/wake_lock.
+		When a string is written to /sys/power/wake_unlock, it will be
+		assumed to represent the name of a wakeup source to deactivate.
+		If a wakeup source object of that name exists and is active at
+		the moment, it will be deactivated.
+
+		Reads from this file return a string consisting of the names of
+		wakeup sources created with the help of /sys/power/wake_lock
+		that are inactive at the moment, separated with spaces.
diff --git a/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt b/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt
index e62b9ec..9ac1cbd 100644
--- a/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt
+++ b/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt
@@ -1,4 +1,4 @@
-* MSM Timetick counter (mpm-v2)
+* MSM MPM sleep counter (mpm-v2)
 
 The MPM provides a timetick that starts when the device is powered up and
 is not reset by any of the boot loaders or the HLOS. The MPM timetick counter
@@ -6,12 +6,14 @@
 
 The required nodes for the MPM timetick counter driver are:
 
-- compatible: "qcom,mpm-counter"
+- compatible: "qcom,mpm2-sleep-counter"
 - reg: Specifies the physical address of the timetick count register.
+- clock-frequency: the physical counter frequency.
 
 Example:
-	qcom,mpm-counter@fc4a3000 {
-		compatible = "qcom,mpm-counter";
+	qcom,mpm2-sleep-counter@fc4a3000 {
+		compatible = "qcom,mpm2-sleep-counter";
 		reg = <0xfc4a3000 0x1000>;
+		clock-frequency = <32768>;
 	};
 
diff --git a/Documentation/devicetree/bindings/arm/msm/pmu.txt b/Documentation/devicetree/bindings/arm/msm/pmu.txt
new file mode 100644
index 0000000..0bd5e58
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/pmu.txt
@@ -0,0 +1,40 @@
+* Qcom Performance Monitor Units
+Qcom cores have several PMUs for counting CPU side, L2 and bus side events.
+
+For the L1CC PMU:
+In most cases the L1 cache controller PMU is a per cpu unit. The irq-is-percpu
+flag becomes a requirement if this is the case.
+
+Required Properties:
+
+- compatible : Should be "qcom,krait-pmu"
+- interrupts : 1 combined interrupt or 1 per core. See the devicetree/bindings/gic.txt for more details on this format.
+
+Optional:
+
+- qcom,irq-is-percpu: 	Define this if the IRQ of the PMU is a PPI. This will tell perf to use
+			the per_cpu IRQ API for request and free.
+
+Example:
+
+ arm-pmu {
+                compatible = "qcom,krait-pmu";
+                qcom,irq-is-percpu;
+                interrupts = <1 7 0xf00>;
+        };
+
+For the L2CC PMU:
+If the L2 cache controller PMU is available, its DT bindings should be defined as
+follows.
+
+Required Properties:
+
+- compatible: Should be "qcom,l2-pmu"
+- interrupts : 1 combined interrupt.
+
+Example:
+
+  l2-pmu {
+                compatible = "qcom,l2-pmu";
+                interrupts = <0 1 0>;
+        };
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index a432fb5..9a7fa90 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -39,8 +39,7 @@
 Required properties:
 - compatible : should be "qcom" followed by sensor name
     - "qcom,s5k3l1yx"
-- reg : should contain i2c slave address of the camera sensor and
-    length of data field which is 0x0
+- reg : should contain i2c slave address of the device
 - qcom,slave-id : should contain i2c slave address, device id address
     and expected id read value
 - qcom,csiphy-sd-index : should contain csiphy instance that will used to
@@ -176,14 +175,14 @@
 
         actuator0: qcom,actuator@18 {
                 cell-index = <0>;
-                reg = <0x18 0x0>;
+                reg = <0x18>;
                 compatible = "qcom,actuator";
                 qcom,cci-master = <0>;
         };
 
        qcom,s5k3l1yx@6e {
                compatible = "qcom,s5k3l1yx";
-               reg = <0x6e 0x0>;
+               reg = <0x6e>;
                qcom,slave-id = <0x6e 0x0 0x3121>;
                qcom,csiphy-sd-index = <2>;
                qcom,csid-sd-index = <0>;
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index a0c7037..d5937cf 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -20,6 +20,24 @@
 Optional Properties:
 	- interrupt-names - "status_irq". This status_irq will be used for card
 			     detection.
+	- cd-gpios: specify GPIO for card detection. If this property is
+		    defined, then it means SDHC device has more than one interrupt
+		    parent and hence, it is required to define the following properties
+		    to configure interrupts from multiple parents -
+
+		    interrupt-parent - This must provide reference to the current
+				       device node.
+		    #address-cells - Should provide a value of 0.
+		    interrupts - Should be <0 1 2> and it is an index to the
+				 interrupt-map.
+		    #interrupt-cells - should provide a value of 1.
+		    #interrupt-mask - should provide a value of 0xffffffff.
+		    interrupt-map - Must create mapping for the number of interrupts
+				    that are defined in above interrupts property.
+				    For SDHC device node, it must define 3 mappings for
+				    hc_irq, pwr_irq and status_irq in the format
+				    mentioned in below example node of sdhc_2.
+
 	- qcom,bus-width - defines the bus I/O width that controller supports.
 			   Units - number of bits. The valid bus-width values are
 			   1, 4 and 8.
@@ -109,8 +127,17 @@
 		compatible = "qcom,sdhci-msm";
                 reg = <0xf9824900 0x11c>, <0xf9824000 0x800>;
                 reg-names = "hc_mem", "core_mem";
-                interrupts = <0 123 0>, <0 138 0>;
-                interrupt-names = "hc_irq", "pwr_irq";
+
+		#address-cells = <0>;
+		interrupt-parent = <&sdhc_2>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 125 0
+				1 &intc 0 221 0
+				2 &msmgpio 62 0x3>;
+                interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+		cd-gpios = <&msmgpio 62 0x1>;
 
 		vdd-supply = <&pm8941_l21>;
 		vdd-io-supply = <&pm8941_l13>;
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt
new file mode 100644
index 0000000..10c1bbf
--- /dev/null
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt
@@ -0,0 +1,44 @@
+Qualcomm QPNP Coincell - coincell battery charger devices
+
+Required properties:
+- compatible:      Must be "qcom,qpnp-coincell".
+- reg:             Specifies the SPMI address and size for this coincell device.
+
+Required structure:
+- A qcom,qpnp-coincell node must be a child of an SPMI node that has specified
+	the spmi-slave-container property.
+
+Optional properties:
+- qcom,rset-ohms:	Specifies the resistance of the current limiting
+			resistor in ohms.  Four values are supported:
+			800, 1200, 1700, and 2100.
+- qcom,vset-millivolts:	Specifies the coincell charging voltage in millivolts.
+			Four values are supported: 2500, 3000, 3100, and 3200.
+- qcom,charge-enable:	Specifies if coincell charging should be enabled or not.
+			0 = disable charging, 1 = enabled charging
+
+If any of the optional properties are not specified, then the hardware default
+values for the unspecified properties will be used instead.
+
+Example:
+	qcom,spmi@fc4c0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+
+		qcom,pm8941@1 {
+			spmi-slave-container;
+			reg = <0x1>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			qcom,coincell@2800 {
+				compatible = "qcom,qpnp-coincell";
+				reg = <0x2800 0x100>;
+				qcom,rset-ohms = <800>;
+				qcom,vset-millivolts = <3100>;
+				qcom,charge-enable = <1>;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 4590227..2832693 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -26,16 +26,17 @@
 - 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-vbatdet-mv:			Battery charging resume voltage in mV.
 - qcom,chg-ibatmax-ma:			Maximum battery charge current in mA
-- qcom,chg-ibatterm-ma:			Current at which charging is terminated.
 - qcom,chg-ibatsafe-ma:			Safety battery current setting
 - qcom,chg-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
+					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
 					by default. This can then be overriden
 					writing the the module parameter
@@ -44,6 +45,16 @@
 					battery temperature of 250 decidegree
 					Celsius, state of charge to be 50%
 					and disable charging.
+- qcom,chg-warm-bat-degc:		Warm battery temperature in degC.
+- qcom,chg-cool-bat-degc:		Cool battery temperature in degC.
+					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.
 
 Sub node required structure:
 - A qcom,chg node must be a child of an SPMI node that has specified
@@ -132,11 +143,17 @@
 		qcom,chg-vddmax-mv = <4200>;
 		qcom,chg-vddsafe-mv = <4200>;
 		qcom,chg-vinmin-mv = <4200>;
-		qcom,chg-vbatdet-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,chg-chgr@1000 {
 			reg = <0x1000 0x100>;
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index ffb0c6a..1885e8a 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -5,11 +5,14 @@
 - regs : offset and length of the register set in the memory map
 - interrupts: IRQ lines used by this controller
 - interrupt-names : Required interrupt resource entries are:
-            HSIC EHCI expects "core_irq" and optionally "async_irq".
+	"core_irq" : Interrupt for HSIC core
 - <supply-name>-supply: handle to the regulator device tree node
   Required "supply-name" is "HSIC_VDDCX" and optionally - "HSIC_GDSC".
 
 Optional properties :
+- interrupt-names : Optional interrupt resource entries are:
+	"async_irq" : Interrupt from HSIC for asynchronous events in HSIC LPM.
+	"wakeup" : Wakeup interrupt from HSIC during suspend (or XO shutdown).
 - hsic,<gpio-name>-gpio : handle to the GPIO node, see "gpios property"
   in Documentation/devicetree/bindings/gpio/gpio.txt.
   Optional "gpio-name" can be "strobe" and "data".
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 6cf59ee..df88caa 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -114,6 +114,7 @@
 - qcom,usb2-enable-hsphy2: If present, select second PHY for USB operation.
 - qcom,pool-64-bit-align: If present then the pool's memory will be aligned
   to 64 bits
+- qcom,enable_hbm: if present host bus manager is enabled.
 
 Example MSM HSUSB EHCI controller device node :
 	ehci: qcom,ehci-host@f9a55000 {
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
new file mode 100644
index 0000000..f09a78a
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -0,0 +1,159 @@
+/* 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_nt35590_720p_video {
+		compatible = "qcom,mdss-dsi-panel";
+		label = "nt35590 720p video mode dsi panel";
+		status = "disable";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+		qcom,rst-gpio = <&msmgpio 25 0>;
+		qcom,mdss-pan-res = <720 1280>;
+		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
+		qcom,mdss-pan-porch-values = <164 8 140 1 1 6>;
+		qcom,mdss-pan-underflow-clr = <0xff>;
+		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+		qcom,mdss-pan-bl-levels = <1 255>;
+		qcom,mdss-pan-dsi-mode = <0>;
+		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
+		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+		qcom,mdss-pan-dsi-traffic-mode = <2>;
+		qcom,mdss-pan-dsi-dst-format = <3>;
+		qcom,mdss-pan-dsi-vc = <0>;
+		qcom,mdss-pan-dsi-rgb-swap = <0>;
+		qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
+		qcom,mdss-pan-dsi-dlane-swap = <0>;
+		qcom,mdss-pan-dsi-t-clk = <0x2c 0x20>;
+		qcom,mdss-pan-dsi-stream = <0>;
+		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
+		qcom,mdss-pan-dsi-dma-tr = <0x04>;
+		qcom,mdss-pan-frame-rate = <60>;
+		qcom,panel-phy-regulatorSettings = [07 09 03 00  /* Regualotor settings */
+						    20 00 01];
+		qcom,panel-phy-timingSettings = [7d 25 1d 00 37 33
+						    22 27 1e 03 04 00];
+		qcom,panel-phy-strengthCtrl = [ff 06];
+		qcom,panel-phy-bistCtrl = [00 00 b1 ff           /* BIST Ctrl settings */
+					   00 00];
+		qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
+					     00 00 00 00 05 00 00 01 97 /* lane1 config */
+					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
+					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
+					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
+		qcom,panel-on-cmds = [29 01 00 00 00 02 FF EE
+					29 01 00 00 00 02 26 08
+					29 01 00 00 00 02 26 00
+					29 01 00 00 10 02 FF 00
+					29 01 00 00 00 02 BA 03
+					29 01 00 00 00 02 C2 03
+					29 01 00 00 00 02 FF 01
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 00 4A
+					29 01 00 00 00 02 01 33
+					29 01 00 00 00 02 02 53
+					29 01 00 00 00 02 03 55
+					29 01 00 00 00 02 04 55
+					29 01 00 00 00 02 05 33
+					29 01 00 00 00 02 06 22
+					29 01 00 00 00 02 08 56
+					29 01 00 00 00 02 09 8F
+					29 01 00 00 00 02 36 73
+					29 01 00 00 00 02 0B 9F
+					29 01 00 00 00 02 0C 9F
+					29 01 00 00 00 02 0D 2F
+					29 01 00 00 00 02 0E 24
+					29 01 00 00 00 02 11 83
+					29 01 00 00 00 02 12 03
+					29 01 00 00 00 02 71 2C
+					29 01 00 00 00 02 6F 03
+					29 01 00 00 00 02 0F 0A
+					29 01 00 00 00 02 FF 05
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 01 00
+					29 01 00 00 00 02 02 8B
+					29 01 00 00 00 02 03 82
+					29 01 00 00 00 02 04 82
+					29 01 00 00 00 02 05 30
+					29 01 00 00 00 02 06 33
+					29 01 00 00 00 02 07 01
+					29 01 00 00 00 02 08 00
+					29 01 00 00 00 02 09 46
+					29 01 00 00 00 02 0A 46
+					29 01 00 00 00 02 0D 0B
+					29 01 00 00 00 02 0E 1D
+					29 01 00 00 00 02 0F 08
+					29 01 00 00 00 02 10 53
+					29 01 00 00 00 02 11 00
+					29 01 00 00 00 02 12 00
+					29 01 00 00 00 02 14 01
+					29 01 00 00 00 02 15 00
+					29 01 00 00 00 02 16 05
+					29 01 00 00 00 02 17 00
+					29 01 00 00 00 02 19 7F
+					29 01 00 00 00 02 1A FF
+					29 01 00 00 00 02 1B 0F
+					29 01 00 00 00 02 1C 00
+					29 01 00 00 00 02 1D 00
+					29 01 00 00 00 02 1E 00
+					29 01 00 00 00 02 1F 07
+					29 01 00 00 00 02 20 00
+					29 01 00 00 00 02 21 06
+					29 01 00 00 00 02 22 55
+					29 01 00 00 00 02 23 4D
+					29 01 00 00 00 02 2D 02
+					29 01 00 00 00 02 28 01
+					29 01 00 00 00 02 2F 02
+					29 01 00 00 00 02 83 01
+					29 01 00 00 00 02 9E 58
+					29 01 00 00 00 02 9F 6A
+					29 01 00 00 00 02 A0 01
+					29 01 00 00 00 02 A2 10
+					29 01 00 00 00 02 BB 0A
+					29 01 00 00 00 02 BC 0A
+					29 01 00 00 00 02 32 08
+					29 01 00 00 00 02 33 B8
+					29 01 00 00 00 02 36 01
+					29 01 00 00 00 02 37 00
+					29 01 00 00 00 02 43 00
+					29 01 00 00 00 02 4B 21
+					29 01 00 00 00 02 4C 03
+					29 01 00 00 00 02 50 21
+					29 01 00 00 00 02 51 03
+					29 01 00 00 00 02 58 21
+					29 01 00 00 00 02 59 03
+					29 01 00 00 00 02 5D 21
+					29 01 00 00 00 02 5E 03
+					29 01 00 00 00 02 6C 00
+					29 01 00 00 00 02 6D 00
+					29 01 00 00 00 02 FF 01
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 FF 02
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 FF 04
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 FF 00
+					29 01 00 00 64 02 11 00
+					29 01 00 00 00 02 FF EE
+					29 01 00 00 00 02 12 50
+					29 01 00 00 00 02 13 02
+					29 01 00 00 00 02 6A 60
+					29 01 00 00 00 02 FF 00
+					29 01 00 00 78 02 29 00];
+
+		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+		qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+					05 01 00 00 78 02 10 00];
+		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+	};
+};
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 94db3ea..2f58185 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,4 +15,18 @@
 	#size-cells = <0>;
 	interrupt-controller;
 	#interrupt-cells = <3>;
+
+	qcom,pm8110@0 {
+		spmi-slave-container;
+		reg = <0x0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+
+	qcom,pm8110@1 {
+		spmi-slave-container;
+		reg = <0x1>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
new file mode 100644
index 0000000..ded9494
--- /dev/null
+++ b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
@@ -0,0 +1,492 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&rpm_bus {
+	rpm-regulator-smpa1 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s1 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa3 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s3 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s4 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s4";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa5 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s5 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s5";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l1 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l2 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l2";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l3 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l4 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l4";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l5 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l5";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <6>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l6 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l6";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <7>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l7 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l7";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <8>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l8 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l8";
+			qcom,set = <1>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <9>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l9 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l9";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <10>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l10 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l10";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <12>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l12 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l12";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <14>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l14 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l14";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <15>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l15 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l15";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <16>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l16 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l16";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <17>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l17 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l17";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <18>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l18 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l18";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa19 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <19>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l19 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l19";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa20 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <20>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l20 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l20";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa21 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <21>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l21 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l21";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa22 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <22>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l22 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l22";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa23 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <23>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l23 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l23";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa24 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <24>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l24 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l24";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa26 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <26>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l26 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l26";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa27 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <27>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l27 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l27";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa28 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <28>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l28 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l28";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-vsa1 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "vsa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <2>;
+		status = "disabled";
+
+		regulator-lvs1 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_lvs1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 28ca985..d456303 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -85,6 +85,11 @@
 			qcom,sample-rate = <4>;
 		};
 
+		pm8941_coincell: qcom,coincell@2800 {
+			compatible = "qcom,qpnp-coincell";
+			reg = <0x2800 0x100>;
+		};
+
 		pm8941_bms: qcom,bms {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-bms";
@@ -161,11 +166,16 @@
 			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,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 = <350>;
 
 			qcom,chg-chgr@1000 {
 				status = "disabled";
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 5cb68e5..ec4b464b 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -12,6 +12,7 @@
 
 /dts-v1/;
 /include/ "msm8226.dtsi"
+/include/ "dsi-panel-nt35590-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 CDP";
@@ -22,6 +23,10 @@
 		status = "ok";
 	};
 
+	qcom,mdss_dsi_nt35590_720p_video {
+		status = "ok";
+	};
+
 	i2c@f9927000 { /* BLSP1 QUP5 */
 		synaptics@20 {
 			compatible = "synaptics,rmi4";
@@ -69,6 +74,19 @@
 			debounce-interval = <15>;
 		};
 	};
+
+	spi@f9923000 {
+		ethernet-switch@3 {
+			compatible = "micrel,ks8851";
+			reg = <3>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <0 115 0>;
+			spi-max-frequency = <4800000>;
+			rst-gpio = <&msmgpio 114 0>;
+			vdd-io-supply = <&pm8226_lvs1>;
+			vdd-phy-supply = <&pm8226_lvs1>;
+		};
+	};
 };
 
 &sdcc1 {
diff --git a/arch/arm/boot/dts/msm8226-iommu.dtsi b/arch/arm/boot/dts/msm8226-iommu.dtsi
index bddafc9..460068b 100644
--- a/arch/arm/boot/dts/msm8226-iommu.dtsi
+++ b/arch/arm/boot/dts/msm8226-iommu.dtsi
@@ -14,6 +14,7 @@
 
 &jpeg_iommu {
 	status = "ok";
+	qcom,iommu-enable-halt;
 
 	qcom,iommu-bfb-regs =  <0x204c
 				0x2050
@@ -50,6 +51,7 @@
 
 &mdp_iommu {
 	status = "ok";
+	qcom,iommu-enable-halt;
 
 	qcom,iommu-bfb-regs =  <0x204c
 				0x2050
@@ -92,6 +94,7 @@
 
 &venus_iommu {
 	status = "ok";
+	qcom,iommu-enable-halt;
 
 	qcom,iommu-bfb-regs =  <0x204c
 				0x2050
@@ -154,6 +157,7 @@
 
 &kgsl_iommu {
 	status = "ok";
+	qcom,iommu-enable-halt;
 
 	qcom,iommu-bfb-regs =  <0x204c
 				0x2050
@@ -184,6 +188,7 @@
 
 &vfe_iommu {
 	status = "ok";
+	qcom,iommu-enable-halt;
 
 	qcom,iommu-bfb-regs =  <0x204c
 				0x2050
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 1691743..30a89ef 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -53,6 +53,17 @@
 		};
 	};
 
+	mdss_dsi0: qcom,mdss_dsi@fd922800 {
+		compatible = "qcom,mdss-dsi-ctrl";
+		label = "MDSS DSI CTRL->0";
+		cell-index = <0>;
+		reg = <0xfd922800 0x600>;
+		vdd-supply = <&pm8226_l15>;
+		vdd_io-supply = <&pm8226_l8>;
+		vreg-supply = <&pm8226_l4>;
+		qcom,mdss-fb-map = <&mdss_fb0>;
+	};
+
 	qcom,mdss_wb_panel {
 		compatible = "qcom,mdss_wb";
 		qcom,mdss_pan_res = <1280 720>;
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 07441d8..57fb4b5 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -12,6 +12,7 @@
 
 /dts-v1/;
 /include/ "msm8226.dtsi"
+/include/ "dsi-panel-nt35590-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 MTP";
@@ -22,6 +23,10 @@
 		status = "ok";
 	};
 
+	qcom,mdss_dsi_nt35590_720p_video {
+		status = "ok";
+	};
+
 	i2c@f9927000 { /* BLSP1 QUP5 */
 		synaptics@20 {
 			compatible = "synaptics,rmi4";
@@ -69,6 +74,19 @@
 			debounce-interval = <15>;
 		};
 	};
+
+	spi@f9923000 {
+		ethernet-switch@3 {
+			compatible = "micrel,ks8851";
+			reg = <3>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <0 115 0>;
+			spi-max-frequency = <4800000>;
+			rst-gpio = <&msmgpio 114 0>;
+			vdd-io-supply = <&pm8226_lvs1>;
+			vdd-phy-supply = <&pm8226_lvs1>;
+		};
+	};
 };
 
 &sdcc1 {
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index cdb2680..09b2d0b 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -12,6 +12,7 @@
 
 /dts-v1/;
 /include/ "msm8226.dtsi"
+/include/ "dsi-panel-nt35590-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 QRD";
@@ -22,6 +23,10 @@
 		status = "ok";
 	};
 
+	qcom,mdss_dsi_nt35590_720p_video {
+		status = "ok";
+	};
+
 	i2c@f9927000 { /* BLSP1 QUP5 */
 		synaptics@20 {
 			compatible = "synaptics,rmi4";
@@ -69,6 +74,19 @@
 			debounce-interval = <15>;
 		};
 	};
+
+	spi@f9923000 {
+		ethernet-switch@3 {
+			compatible = "micrel,ks8851";
+			reg = <3>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <0 115 0>;
+			spi-max-frequency = <4800000>;
+			rst-gpio = <&msmgpio 114 0>;
+			vdd-io-supply = <&pm8226_lvs1>;
+			vdd-phy-supply = <&pm8226_lvs1>;
+		};
+	};
 };
 
 &sdcc1 {
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 8168826..c39d987 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -10,300 +10,374 @@
  * GNU General Public License for more details.
  */
 
-/* Stub Regulators */
-
-/ {
-	pm8226_s1_corner: regulator-s1-corner {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "8226_s1_corner";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <1>;
-		regulator-max-microvolt = <7>;
-		qcom,consumer-supplies = "vdd_dig", "";
-	};
-};
-
 /* QPNP controlled regulators: */
 
 &spmi_bus {
-
 	qcom,pm8226@1 {
-
-		pm8226_s1: regulator@1400 {
-			status = "okay";
-			regulator-name = "8226_s1";
-			qcom,enable-time = <500>;
-			qcom,system-load = <100000>;
-			regulator-always-on;
-			regulator-min-microvolt = <1150000>;
-			regulator-max-microvolt = <1150000>;
-		};
-
 		pm8226_s2: regulator@1700 {
 			status = "okay";
 			regulator-name = "8226_s2";
 			qcom,enable-time = <500>;
 			qcom,system-load = <100000>;
-			regulator-always-on;
 			regulator-min-microvolt = <1050000>;
 			regulator-max-microvolt = <1150000>;
-		};
-
-		pm8226_s3: regulator@1a00 {
-			status = "okay";
-			regulator-name = "8226_s3";
-			qcom,enable-time = <500>;
-			qcom,system-load = <100000>;
 			regulator-always-on;
-			regulator-min-microvolt = <1300000>;
+		};
+	};
+};
+
+/* RPM controlled regulators: */
+
+&rpm_bus {
+	rpm-regulator-smpa1 {
+		status = "okay";
+		pm8226_s1: regulator-s1 {
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1275000>;
+			status = "okay";
+		};
+		pm8226_s1_corner: regulator-s1-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s1_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+			qcom,consumer-supplies = "vdd_dig", "";
+		};
+		pm8226_s1_corner_ao: regulator-s1-corner-ao {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s1_corner_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+		};
+	};
+
+	rpm-regulator-smpa3 {
+		status = "okay";
+		pm8226_s3: regulator-s3 {
+			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1300000>;
-		};
-
-		pm8226_s4: regulator@1d00 {
+			qcom,init-voltage = <1200000>;
 			status = "okay";
-			regulator-name = "8226_s4";
-			qcom,enable-time = <500>;
-			qcom,system-load = <100000>;
-			regulator-always-on;
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		status = "okay";
+		pm8226_s4: regulator-s4 {
 			regulator-min-microvolt = <2100000>;
 			regulator-max-microvolt = <2100000>;
-		};
-
-		pm8226_s5: regulator@2000 {
+			qcom,init-voltage = <2100000>;
 			status = "okay";
-			regulator-name = "8226_s5";
-			qcom,enable-time = <500>;
+		};
+	};
+
+	rpm-regulator-smpa5 {
+		status = "okay";
+		pm8226_s5: regulator-s5 {
 			regulator-min-microvolt = <1150000>;
 			regulator-max-microvolt = <1150000>;
-		};
-
-		pm8226_l1: regulator@4000 {
+			qcom,init-voltage = <1150000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		status = "okay";
+		pm8226_l1: regulator-l1 {
 			regulator-name = "8226_l1";
-			parent-supply = <&pm8226_s3>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1225000>;
 			regulator-max-microvolt = <1225000>;
-		};
-
-		pm8226_l2: regulator@4100 {
+			qcom,init-voltage = <1225000>;
 			status = "okay";
-			regulator-name = "8226_l2";
-			parent-supply = <&pm8226_s3>;
-			regulator-always-on;
-			qcom,enable-time = <200>;
-			qcom,system-load = <10000>;
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		status = "okay";
+		pm8226_l2: regulator-l2 {
 			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1200000>;
-		};
-
-		pm8226_l3: regulator@4200 {
+			qcom,init-voltage = <1200000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		status = "okay";
+		pm8226_l3: regulator-l3 {
 			regulator-name = "8226_l3";
-			parent-supply = <&pm8226_s3>;
-			qcom,system-load = <10000>;
-			regulator-always-on;
-			qcom,enable-time = <200>;
-			regulator-min-microvolt = <1150000>;
-			regulator-max-microvolt = <1150000>;
-		};
-
-		pm8226_l4: regulator@4300 {
+			regulator-min-microvolt = <750000>;
+			regulator-max-microvolt = <1275000>;
 			status = "okay";
+		};
+		pm8226_l3_ao: regulator-3-ao {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l3_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <750000>;
+			regulator-max-microvolt = <1275000>;
+			status = "okay";
+		};
+		pm8226_l3_so: regulator-l3-so {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l3_so";
+			qcom,set = <2>;
+			regulator-min-microvolt = <750000>;
+			regulator-max-microvolt = <1275000>;
+			qcom,init-voltage = <750000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		status = "okay";
+		pm8226_l4: regulator-l4 {
 			regulator-name = "8226_l4";
-			parent-supply = <&pm8226_s3>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1200000>;
-		};
-
-		pm8226_l5: regulator@4400 {
+			qcom,init-voltage = <1200000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		status = "okay";
+		pm8226_l5: regulator-l5 {
 			regulator-name = "8226_l5";
-			parent-supply = <&pm8226_s3>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1200000>;
-		};
-
-		pm8226_l6: regulator@4500 {
+			qcom,init-voltage = <1200000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		status = "okay";
+		pm8226_l6: regulator-l6 {
 			regulator-name = "8226_l6";
-			parent-supply = <&pm8226_s4>;
-			qcom,system-load = <10000>;
-			regulator-always-on;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
-		};
-
-		pm8226_l7: regulator@4600 {
+			qcom,init-voltage = <1800000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		status = "okay";
+		pm8226_l7: regulator-l7 {
 			regulator-name = "8226_l7";
-			parent-supply = <&pm8226_s4>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1850000>;
 			regulator-max-microvolt = <1850000>;
-		};
-
-		pm8226_l8: regulator@4700 {
+			qcom,init-voltage = <1850000>;
 			status = "okay";
-			regulator-name = "8226_l8";
-			parent-supply = <&pm8226_s4>;
-			qcom,enable-time = <200>;
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		status = "okay";
+		pm8226_l8: regulator-l8 {
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
 			qcom,consumer-supplies = "vdd_sr2_pll", "";
 		};
+	};
 
-		pm8226_l9: regulator@4800 {
-			status = "okay";
+	rpm-regulator-ldoa9 {
+		status = "okay";
+		pm8226_l9: regulator-l9 {
 			regulator-name = "8226_l9";
-			parent-supply = <&pm8226_s4>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2050000>;
 			regulator-max-microvolt = <2050000>;
-		};
-
-		pm8226_l10: regulator@4900 {
+			qcom,init-voltage = <2050000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		status = "okay";
+		pm8226_l10: regulator-l10 {
 			regulator-name = "8226_l10";
-			parent-supply = <&pm8226_s4>;
-			qcom,enable-time = <200>;
-			qcom,system-load = <5000>;
-			regulator-always-on;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
-		};
-
-		pm8226_l12: regulator@4b00 {
+			qcom,init-voltage = <1800000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		status = "okay";
+		pm8226_l12: regulator-l12 {
 			regulator-name = "8226_l12";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
-		};
-
-		pm8226_l14: regulator@4d00 {
+			qcom,init-voltage = <1800000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		status = "okay";
+		pm8226_l14: regulator-l14 {
 			regulator-name = "8226_l14";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2750000>;
 			regulator-max-microvolt = <2750000>;
-		};
-
-		pm8226_l15: regulator@4e00 {
+			qcom,init-voltage = <2750000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		status = "okay";
+		pm8226_l15: regulator-l15 {
 			regulator-name = "8226_l15";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2800000>;
 			regulator-max-microvolt = <2800000>;
-		};
-
-		pm8226_l16: regulator@4f00 {
+			qcom,init-voltage = <2800000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		status = "okay";
+		pm8226_l16: regulator-l16 {
 			regulator-name = "8226_l16";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <3000000>;
 			regulator-max-microvolt = <3300000>;
-		};
-
-		pm8226_l17: regulator@5000 {
+			qcom,init-voltage = <3300000>;
 			status = "okay";
-			regulator-name = "8226_l17";
-			qcom,enable-time = <200>;
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		status = "okay";
+		pm8226_l17: regulator-l17 {
 			regulator-min-microvolt = <2950000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_l18: regulator@5100 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		status = "okay";
+		pm8226_l18: regulator-l18 {
 			regulator-name = "8226_l18";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2950000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_l19: regulator@5200 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa19 {
+		status = "okay";
+		pm8226_l19: regulator-l19 {
 			regulator-name = "8226_l19";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2850000>;
 			regulator-max-microvolt = <2850000>;
-		};
-
-		pm8226_l20: regulator@5300 {
+			qcom,init-voltage = <2850000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa20 {
+		status = "okay";
+		pm8226_l20: regulator-l20 {
 			regulator-name = "8226_l20";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <3075000>;
 			regulator-max-microvolt = <3075000>;
-		};
-
-		pm8226_l21: regulator@5400 {
+			qcom,init-voltage = <3075000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa21 {
+		status = "okay";
+		pm8226_l21: regulator-l21 {
 			regulator-name = "8226_l21";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_l22: regulator@5500 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa22 {
+		status = "okay";
+		pm8226_l22: regulator-l22 {
 			regulator-name = "8226_l22";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_l23: regulator@5600 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa23 {
+		status = "okay";
+		pm8226_l23: regulator-l23 {
 			regulator-name = "8226_l23";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_l24: regulator@5700 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa24 {
+		status = "okay";
+		pm8226_l24: regulator-l24 {
 			regulator-name = "8226_l24";
-			parent-supply = <&pm8226_s3>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1300000>;
 			regulator-max-microvolt = <1300000>;
-		};
-
-		pm8226_l26: regulator@5900 {
+			qcom,init-voltage = <1300000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa26 {
+		status = "okay";
+		pm8226_l26: regulator-l26 {
 			regulator-name = "8226_l26";
-			parent-supply = <&pm8226_s3>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1225000>;
 			regulator-max-microvolt = <1225000>;
-		};
-
-		pm8226_l27: regulator@5a00 {
+			qcom,init-voltage = <1225000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa27 {
+		status = "okay";
+		pm8226_l27: regulator-l27 {
 			regulator-name = "8226_l27";
-			parent-supply = <&pm8226_s4>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2050000>;
 			regulator-max-microvolt = <2050000>;
-		};
-
-		pm8226_l28: regulator@5b00 {
+			qcom,init-voltage = <2050000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa28 {
+		status = "okay";
+		pm8226_l28: regulator-l28 {
 			regulator-name = "8226_l28";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_lvs1: regulator@8000 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
-			regulator-name = "8226_lvs1";
-			parent-supply = <&pm8226_l6>;
-			qcom,enable-time = <200>;
+		};
+	};
+
+	rpm-regulator-vsa1 {
+		status = "okay";
+		pm8226_lvs1: regulator-lvs1 {
+			status = "okay";
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 2ceaaaa..223675d 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -504,7 +504,7 @@
 		reg = <0xfdd00000 0x2000>,
 		      <0xfdd02000 0x2000>,
 		      <0xfe039000 0x400>,
-		      <0xfec00000 0x180000>;
+		      <0xfec00000 0x20000>;
 		reg-names = "ocmem_ctrl_physical", "dm_ctrl_physical", "br_ctrl_physical", "ocmem_physical";
 		interrupts = <0 76 0 0 77 0>;
 		interrupt-names = "ocmem_irq", "dm_irq";
@@ -513,12 +513,12 @@
 		qcom,resource-type = <0x706d636f>;
 		#address-cells = <1>;
 		#size-cells = <1>;
-		ranges = <0x0 0xfec00000 0x180000>;
+		ranges = <0x0 0xfec00000 0x20000>;
 
 		partition@0 {
-			reg = <0x0 0x100000>;
+			reg = <0x0 0x20000>;
 			qcom,ocmem-part-name = "graphics";
-			qcom,ocmem-part-min = <0x80000>;
+			qcom,ocmem-part-min = <0x20000>;
 		};
 	};
 
@@ -617,7 +617,7 @@
 		gpios = <&msmgpio 3 0>, /* CLK  */
 			<&msmgpio 1 0>, /* MISO */
 			<&msmgpio 0 0>; /* MOSI */
-		cs-gpios = <&msmgpio 2 0>;
+		cs-gpios = <&msmgpio 22 0>;
 
 		qcom,infinite-mode = <0>;
 		qcom,use-bam;
@@ -637,6 +637,17 @@
 		qcom,memory-reservation-type = "EBI1";
 		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
 	};
+
+	qcom,msm-rng@f9bff000 {
+                compatible = "qcom,msm-rng";
+                reg = <0xf9bff000 0x200>;
+                qcom,msm-rng-iface-clk;
+	};
+
+	qcom,tz-log@fc5b82c {
+		compatible = "qcom,tz-log";
+		reg = <0x0fc5b82c 0x1000>;
+	};
 };
 
 &gdsc_venus {
@@ -663,6 +674,7 @@
 	status = "ok";
 };
 
+/include/ "msm-pm8226-rpm-regulator.dtsi"
 /include/ "msm-pm8226.dtsi"
 /include/ "msm8226-regulator.dtsi"
 
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 2dff4c7..fe0ebf9 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -437,6 +437,19 @@
 		vdd_cx-supply = <&pm8110_s1_corner>;
 		qcom,firmware-name = "adsp";
 	};
+
+	tsens: tsens@fc4a8000 {
+		compatible = "qcom,msm-tsens";
+		reg = <0xfc4a8000 0x2000>,
+		      <0xfc4b8000 0x1000>;
+		reg-names = "tsens_physical", "tsens_eeprom_physical";
+		interrupts = <0 184 0>;
+		qcom,sensors = <2>;
+		qcom,slope = <2901 2846>;
+		qcom,calib-mode = "fuse_map2";
+		qcom,calibration-less-mode;
+	};
+
 };
 
 &gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
index fb2917c..24438f0 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
@@ -22,7 +22,7 @@
 
 	qcom,camera@6e {
 		compatible = "qcom,s5k3l1yx";
-		reg = <0x6e 0x0>;
+		reg = <0x6e>;
 		qcom,slave-id = <0x6e 0x0 0x3121>;
 		qcom,csiphy-sd-index = <0>;
 		qcom,csid-sd-index = <0>;
@@ -63,7 +63,7 @@
 
 	qcom,camera@6c {
 		compatible = "qcom,ov2720";
-		reg = <0x6c 0x0>;
+		reg = <0x6c>;
 		qcom,slave-id = <0x6c 0x300A 0x2720>;
 		qcom,csiphy-sd-index = <2>;
 		qcom,csid-sd-index = <0>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
index 4fe4220..c9d1abc 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -15,7 +15,7 @@
 
 	actuator0: qcom,actuator@18 {
 		cell-index = <0>;
-		reg = <0x18 0x0>;
+		reg = <0x18>;
 		compatible = "qcom,actuator";
 		qcom,cci-master = <0>;
 	};
@@ -99,7 +99,7 @@
 
 	qcom,camera@90 {
 		compatible = "qcom,mt9m114";
-		reg = <0x90 0x0>;
+		reg = <0x90>;
 		qcom,slave-id = <0x90 0x0 0x2481>;
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <0>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
index b313795..f9b89e1 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
@@ -16,14 +16,14 @@
 
 	actuator0: qcom,actuator@18 {
 		cell-index = <0>;
-		reg = <0x18 0x0>;
+		reg = <0x18>;
 		compatible = "qcom,actuator";
 		qcom,cci-master = <0>;
 	};
 
 	qcom,camera@6e {
 		compatible = "qcom,s5k3l1yx";
-		reg = <0x6e 0x0>;
+		reg = <0x6e>;
 		qcom,slave-id = <0x6e 0x0 0x3121>;
 		qcom,csiphy-sd-index = <0>;
 		qcom,csid-sd-index = <0>;
@@ -60,7 +60,7 @@
 
 	qcom,camera@6c {
 		compatible = "qcom,ov2720";
-		reg = <0x6c 0x0>;
+		reg = <0x6c>;
 		qcom,slave-id = <0x6c 0x300A 0x2720>;
 		qcom,csiphy-sd-index = <2>;
 		qcom,csid-sd-index = <0>;
@@ -95,7 +95,7 @@
 
 	qcom,camera@90 {
 		compatible = "qcom,mt9m114";
-		reg = <0x90 0x0>;
+		reg = <0x90>;
 		qcom,slave-id = <0x90 0x0 0x2481>;
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <0>;
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index ebb3912..95cafdb 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -179,8 +179,7 @@
 		compatible = "qcom,cci";
 		reg = <0xfda0C000 0x1000>;
                 #address-cells = <1>;
-                #size-cells = <1>;
-                ranges;
+		#size-cells = <0>;
 		reg-names = "cci";
 		interrupts = <0 50 0>;
 		interrupt-names = "cci";
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index ad26061..2b1cbb5 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -314,6 +314,17 @@
 };
 
 &sdhc_2 {
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 221 0
+			2 &msmgpio 62 0x3>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&msmgpio 62 0x1>;
+
 	vdd-supply = <&pm8941_l21>;
 	vdd-io-supply = <&pm8941_l13>;
 
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index dbb8958..d22c746 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -311,6 +311,17 @@
 };
 
 &sdhc_2 {
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 221 0
+			2 &msmgpio 62 0x3>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&msmgpio 62 0x1>;
+
 	vdd-supply = <&pm8941_l21>;
 	vdd-io-supply = <&pm8941_l13>;
 
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 4dd92b98..985b307 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -351,11 +351,18 @@
 		hub_int-supply = <&pm8941_l10>;
 		hub_vbus-supply = <&ext_5v>;
 
-		hsic@f9a00000 {
+		hsic_host: hsic@f9a00000 {
 			compatible = "qcom,hsic-host";
 			reg = <0xf9a00000 0x400>;
-			interrupts = <0 136 0>, <0 148 0>;
-			interrupt-names = "core_irq", "async_irq";
+			#address-cells = <0>;
+	                interrupt-parent = <&hsic_host>;
+			interrupts = <0 1 2>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0xffffffff>;
+			interrupt-map = <0 &intc 0 136 0
+		                1 &intc 0 148 0
+		                2 &msmgpio 144 0x8>;
+			interrupt-names = "core_irq", "async_irq", "wakeup";
 			HSIC_VDDCX-supply = <&pm8841_s2>;
 			HSIC_GDSC-supply = <&gdsc_usb_hsic>;
 			hsic,strobe-gpio = <&msmgpio 144 0x00>;
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index d3d53dd..380ec20 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -282,6 +282,17 @@
 };
 
 &sdhc_2 {
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 221 0
+			2 &msmgpio 62 0x3>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&msmgpio 62 0x1>;
+
 	vdd-supply = <&pm8941_l21>;
 	vdd-io-supply = <&pm8941_l13>;
 
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index fda8752..91e0c29 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -340,7 +340,8 @@
 		qcom,ipc-bit-offset = <1>;
 
 		qcom,gic-parent = <&intc>;
-		qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
+		qcom,gic-map = <47 165>, /* usb30_hs_phy_irq */
+			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
@@ -413,7 +414,8 @@
 			<37  86>,
 			<38  92>,
 			<39  93>,
-			<40  95>;
+			<40  95>,
+			<41  144>;
 	};
 
 	qcom,pm-8x60@fe805664 {
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index f0eed3f..fadf5da 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -337,7 +337,8 @@
 		qcom,ipc-bit-offset = <1>;
 
 		qcom,gic-parent = <&intc>;
-		qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
+		qcom,gic-map = <47 165>, /* usb30_hs_phy_irq */
+			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
@@ -410,7 +411,8 @@
 			<37  86>,
 			<38  92>,
 			<39  93>,
-			<40  95>;
+			<40  95>,
+			<41  144>;
 	};
 
 	qcom,pm-8x60@fe805664 {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 99886c7..3ebdbb6 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -84,9 +84,10 @@
 		clock-frequency = <19200000>;
 	};
 
-	qcom,mpm-counter@fc4a3000 {
-		compatible = "qcom,mpm-counter";
+	qcom,mpm2-sleep-counter@fc4a3000 {
+		compatible = "qcom,mpm2-sleep-counter";
 		reg = <0xfc4a3000 0x1000>;
+		clock-frequency = <32768>;
 	};
 
 	msm_vidc: qcom,vidc@fdc00000 {
@@ -1382,6 +1383,17 @@
 		reg = <0xfa00000 0x200000>;
 		status = "disable";
 	};
+
+	cpu-pmu {
+		compatible = "qcom,krait-pmu";
+		qcom,irq-is-percpu;
+		interrupts = <1 7 0xf00>;
+	};
+
+	l2-pmu {
+		compatible = "qcom,l2-pmu";
+		interrupts = <0 1 0>;
+	};
 };
 
 &gdsc_venus {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index e1501ac..78786f6 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -52,6 +52,12 @@
 		qcom,direct-connect-irqs = <8>;
 	};
 
+	qcom,mpm2-sleep-counter@fc4a3000 {
+		compatible = "qcom,mpm2-sleep-counter";
+		reg = <0xfc4a3000 0x1000>;
+		clock-frequency = <32768>;
+	};
+
 	timer: msm-qtimer@f9021000 {
 		compatible = "arm,armv7-timer";
 		reg = <0xF9021000 0x1000>;
@@ -731,6 +737,17 @@
 		status = "disable";
 	};
 
+	cpu-pmu {
+                compatible = "arm,cortex-a5-pmu";
+                qcom,irq-is-percpu;
+                interrupts = <1 7 0x00>;
+        };
+
+        l2-pmu {
+                compatible = "qcom,l2-pmu";
+                interrupts = <0 1 0>;
+        };
+
 };
 
 /include/ "msm-pm8019-rpm-regulator.dtsi"
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 9e38eca..b163a5d 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -58,8 +58,6 @@
 CONFIG_MSM_PIL_PRONTO=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
 CONFIG_MSM_PIL_VENUS=y
-CONFIG_WCNSS_CORE=y
-CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_MSM_DLOAD_MODE=y
@@ -125,6 +123,7 @@
 CONFIG_DUMMY=y
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
+CONFIG_KS8851=y
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
@@ -141,6 +140,7 @@
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
@@ -159,7 +159,6 @@
 CONFIG_HWMON=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_QPNP_CHARGER=y
-# CONFIG_HWMON is not set
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_SENSORS_QPNP_ADC_CURRENT=y
 CONFIG_REGULATOR=y
@@ -250,7 +249,6 @@
 CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_OCMEM=y
 CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
 CONFIG_MSM_OCMEM_DEBUG=y
@@ -268,3 +266,8 @@
 CONFIG_CORESIGHT_STM=y
 CONFIG_CORESIGHT_EVENT=m
 CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+CONFIG_PM_AUTOSLEEP=y
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_TZ_LOG=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 89f9d4a..a8ea31d 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -531,3 +531,7 @@
 CONFIG_CRC_CCITT=y
 CONFIG_SYNC=y
 CONFIG_SW_SYNC=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+CONFIG_PM_AUTOSLEEP=y
+# CONFIG_PM_WAKELOCKS_GC is not set
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 5b9c590..9f10bc4 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -549,3 +549,7 @@
 CONFIG_CRC_CCITT=y
 CONFIG_SYNC=y
 CONFIG_SW_SYNC=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+CONFIG_PM_AUTOSLEEP=y
+# CONFIG_PM_WAKELOCKS_GC is not set
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index c74262c..ea10007 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -291,6 +291,7 @@
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
+CONFIG_QPNP_REVID=y
 CONFIG_SLIMBUS_MSM_NGD=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
@@ -422,6 +423,7 @@
 CONFIG_QPNP_PWM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
+CONFIG_QPNP_COINCELL=y
 CONFIG_MSM_IOMMU=y
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
@@ -468,3 +470,7 @@
 CONFIG_CRYPTO_DEV_QCEDEV=y
 CONFIG_CRC_CCITT=y
 CONFIG_MSM_EVENT_TIMER=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+CONFIG_PM_AUTOSLEEP=y
+# CONFIG_PM_WAKELOCKS_GC is not set
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 48ea1a4..077c7a6 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -296,6 +296,7 @@
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
+CONFIG_QPNP_REVID=y
 CONFIG_SLIMBUS_MSM_NGD=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
@@ -430,6 +431,7 @@
 CONFIG_QPNP_PWM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
+CONFIG_QPNP_COINCELL=y
 CONFIG_MSM_IOMMU=y
 CONFIG_MSM_IOMMU_PMON=y
 CONFIG_MOBICORE_SUPPORT=m
@@ -493,3 +495,7 @@
 CONFIG_CRYPTO_DEV_QCEDEV=y
 CONFIG_CRC_CCITT=y
 CONFIG_MSM_EVENT_TIMER=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+CONFIG_PM_AUTOSLEEP=y
+# CONFIG_PM_WAKELOCKS_GC is not set
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index 1fe528a..f525eee 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -323,3 +323,7 @@
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_MSM_RTB=y
 CONFIG_MSM_MEMORY_DUMP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+CONFIG_PM_AUTOSLEEP=y
+# CONFIG_PM_WAKELOCKS_GC is not set
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index aa18209..f3a7b5c 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -324,3 +324,7 @@
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_MSM_RTB=y
 CONFIG_MSM_MEMORY_DUMP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+CONFIG_PM_AUTOSLEEP=y
+# CONFIG_PM_WAKELOCKS_GC is not set
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index d1a3e61..e1fc42f 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -52,6 +52,10 @@
 	void (*disable_irq)(int irq);
 };
 
+extern int multicore_request_irq(int irq, irq_handler_t *handle_irq);
+extern void multicore_free_irq(int irq);
+extern struct arm_pmu_platdata multicore_data;
+
 #ifdef CONFIG_CPU_HAS_PMU
 
 /**
@@ -151,9 +155,6 @@
 			    struct hw_perf_event *hwc,
 			    int idx);
 
-extern void enable_irq_callback(void *);
-extern void disable_irq_callback(void *);
-
 #endif /* CONFIG_HW_PERF_EVENTS */
 
 #endif /* __ARM_PMU_H__ */
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 5311d74..cef66ec 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -21,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
 #include <linux/irq.h>
+#include <linux/of.h>
 
 #include <asm/cputype.h>
 #include <asm/irq.h>
@@ -51,6 +52,8 @@
 /* Set at runtime when we know what CPU type we are. */
 static struct arm_pmu *cpu_pmu;
 
+static int per_cpu_irq;
+
 enum arm_perf_pmu_ids
 armpmu_get_pmu_id(void)
 {
@@ -381,6 +384,58 @@
 	return plat->handle_irq(irq, dev, armpmu->handle_irq);
 }
 
+static DEFINE_PER_CPU(u32, pmu_irq_cookie);
+
+void enable_irq_callback(void *info)
+{
+	int irq = *(unsigned int *)info;
+	enable_percpu_irq(irq, IRQ_TYPE_EDGE_RISING);
+}
+
+void disable_irq_callback(void *info)
+{
+	int irq = *(unsigned int *)info;
+	disable_percpu_irq(irq);
+}
+
+int
+multicore_request_irq(int irq, irq_handler_t *handle_irq)
+{
+	int err = 0;
+	int cpu;
+
+	err = request_percpu_irq(irq, *handle_irq, "l1-armpmu",
+			&pmu_irq_cookie);
+
+	if (!err) {
+		for_each_cpu(cpu, cpu_online_mask) {
+			smp_call_function_single(cpu,
+					enable_irq_callback, &irq, 1);
+		}
+	}
+
+	return err;
+}
+
+void
+multicore_free_irq(int irq)
+{
+	int cpu;
+
+	if (irq >= 0) {
+		for_each_cpu(cpu, cpu_online_mask) {
+			smp_call_function_single(cpu,
+					disable_irq_callback, &irq, 1);
+		}
+		free_percpu_irq(irq, &pmu_irq_cookie);
+	}
+}
+
+struct arm_pmu_platdata multicore_data = {
+	.request_pmu_irq = multicore_request_irq,
+	.free_pmu_irq = multicore_free_irq,
+};
+
 int
 armpmu_generic_request_irq(int irq, irq_handler_t *handle_irq)
 {
@@ -689,11 +744,12 @@
 	{.compatible = "arm,cortex-a8-pmu"},
 	{.compatible = "arm,arm1136-pmu"},
 	{.compatible = "arm,arm1176-pmu"},
+	{.compatible = "qcom,krait-pmu"},
 	{},
 };
 
 static struct platform_device_id armpmu_plat_device_ids[] = {
-	{.name = "cpu-arm-pmu"},
+	{.name = "cpu-pmu"},
 	{},
 };
 
@@ -703,12 +759,16 @@
 		return -ENODEV;
 
 	cpu_pmu->plat_device = pdev;
+
+	if (per_cpu_irq == 1)
+		cpu_pmu->plat_device->dev.platform_data = &multicore_data;
+
 	return 0;
 }
 
 static struct platform_driver armpmu_driver = {
 	.driver		= {
-		.name	= "cpu-arm-pmu",
+		.name	= "cpu-pmu",
 		.of_match_table = armpmu_of_device_ids,
 	},
 	.probe		= armpmu_device_probe,
@@ -756,18 +816,6 @@
 	return 0;
 }
 
-void enable_irq_callback(void *info)
-{
-	int irq = *(unsigned int *)info;
-	enable_percpu_irq(irq, IRQ_TYPE_EDGE_RISING);
-}
-
-void disable_irq_callback(void *info)
-{
-	int irq = *(unsigned int *)info;
-	disable_percpu_irq(irq);
-}
-
 /*
  * PMU hardware loses all context when a CPU goes offline.
  * When a CPU is hotplugged back in, since some hardware registers are
@@ -881,6 +929,24 @@
 	.notifier_call = perf_cpu_pm_notifier,
 };
 
+#ifdef CONFIG_OF
+static inline int get_dt_irq_prop(void)
+{
+	struct device_node *np = NULL;
+	int err = -1;
+
+	np = of_find_matching_node(NULL, armpmu_of_device_ids);
+	if (np)
+		err = of_property_read_bool(np, "qcom,irq-is-percpu");
+	else
+		pr_err("Perf: can't find DT node.\n");
+
+	return err;
+}
+#else
+static inline int get_dt_irq_prop(void) {return 0; }
+#endif
+
 /*
  * CPU PMU identification and registration.
  */
@@ -956,6 +1022,8 @@
 		register_cpu_notifier(&pmu_cpu_notifier);
 		armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW);
 		cpu_pm_register_notifier(&perf_cpu_pm_notifier_block);
+		per_cpu_irq = get_dt_irq_prop();
+
 	} else {
 		pr_info("no hardware support available\n");
 	}
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index f39046c..ce557b1 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -390,16 +390,17 @@
 	select MSM_GPIOMUX
 	select MSM_NATIVE_RESTART
 	select MSM_RESTART_V2
-	select MEMORY_HOLE_CARVEOUT
-	select DONT_MAP_HOLE_AFTER_MEMBANK
-	select QMI_ENCDEC
 	select MSM_QDSP6_APRV2
 	select MSM_QDSP6V2_CODECS
 	select MSM_AUDIO_QDSP6V2 if SND_SOC
+	select QMI_ENCDEC
 	select MSM_RPM_SMD
 	select MSM_SPM_V2
 	select MSM_L2_SPM
 	select MSM_PM8X60 if PM
+	select MEMORY_HOLE_CARVEOUT
+	select DONT_MAP_HOLE_AFTER_MEMBANK0
+	select MSM_BUS_SCALING
 	select CPU_FREQ_MSM
 	select CPU_FREQ
 	select CPU_FREQ_GOV_USERSPACE
@@ -407,6 +408,8 @@
 	select MSM_PIL
 	select MSM_RUN_QUEUE_STATS
 	select ARM_HAS_SG_CHAIN
+	select REGULATOR
+	select MSM_RPM_REGULATOR_SMD
 
 config ARCH_MSM8226
 	bool "MSM8226"
@@ -433,6 +436,12 @@
 	select MEMORY_HOLE_CARVEOUT
 	select DONT_MAP_HOLE_AFTER_MEMBANK0
 	select MSM_BUS_SCALING
+	select CPU_FREQ_MSM
+	select CPU_FREQ
+	select CPU_FREQ_GOV_USERSPACE
+	select CPU_FREQ_GOV_ONDEMAND
+	select MSM_PIL
+	select MSM_RUN_QUEUE_STATS
 	select ARM_HAS_SG_CHAIN
 	select REGULATOR
 	select MSM_RPM_REGULATOR_SMD
@@ -2850,4 +2859,12 @@
 	depends on SERIAL_MSM_HS
 	help
 		Select if BLSP based UART Core v.14 or higher is present.
+
+config MSM_BOOT_STATS
+	bool "Use MSM boot stats reporting"
+	help
+	 Use this to report msm boot stats such as bootloader throughput,
+	 display init, total boot time.
+	 This figures are reported in mpm sleep clock cycles and have a
+	 resolution of 31 bits as 1 bit is used as an overflow check.
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index cb5e712..fb7e4e3 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -29,15 +29,17 @@
 obj-$(CONFIG_DEBUG_FS) += acpuclock-krait-debug.o
 endif
 obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7627.o acpuclock-8625q.o clock-pll.o
-obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
 obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o
-obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o perf_event_msm_krait_l2.o
+ifndef CONFIG_OF
+obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o
+endif
+obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o perf_event_msm_krait_l2.o
 obj-$(CONFIG_ARCH_MSM_KRAIT) += krait-scm.o
 ifdef CONFIG_HW_PERF_EVENTS
-obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o perf_event_msm_pl310.o
-obj-$(CONFIG_ARCH_MSM9625) += pmu.o perf_event_msm_pl310.o
-obj-$(CONFIG_ARCH_MSM8625) += pmu.o perf_event_msm_pl310.o
-obj-$(CONFIG_ARCH_MSM9615) += pmu.o perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM7X27A) += perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM9625) += perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM8625) += perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM9615) += perf_event_msm_pl310.o
 obj-$(CONFIG_DEBUG_FS) += perf_debug.o
 endif
 
@@ -193,6 +195,7 @@
 obj-$(CONFIG_ARCH_MSM8X60) += clock-rpm.o
 obj-$(CONFIG_ARCH_MSM8X60) += saw-regulator.o
 obj-$(CONFIG_ARCH_MSM8X60) += footswitch-8x60.o
+obj-$(CONFIG_MSM_BOOT_STATS) += boot_stats.o
 
 ifdef CONFIG_MSM_RPM_REGULATOR
 obj-y += rpm-regulator.o
@@ -300,7 +303,7 @@
 obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o acpuclock-8930ab.o
 obj-$(CONFIG_ARCH_MPQ8092) += board-8092.o board-8092-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o
-obj-$(CONFIG_ARCH_MSM8226) += clock-local2.o clock-pll.o clock-8226.o clock-rpm.o clock-voter.o clock-mdss-8974.o
+obj-$(CONFIG_ARCH_MSM8226) += clock-local2.o clock-pll.o clock-8226.o clock-rpm.o clock-voter.o clock-mdss-8226.o
 obj-$(CONFIG_ARCH_MSM8226) += acpuclock-8226.o acpuclock-cortex.o
 obj-$(CONFIG_ARCH_MSM8610) += board-8610.o board-8610-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8610) += clock-local2.o clock-pll.o clock-8610.o clock-rpm.o clock-voter.o
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index efd0045..83c14a8 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -308,6 +308,168 @@
 	{ 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(3),   810000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   820000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   830000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   840000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   850000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   860000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  875000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  885000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  895000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  910000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  920000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  930000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  945000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  975000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  990000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1005000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1020000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1030000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19), 1045000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1060000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 3200000 },
+	{ 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(3),   795000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   805000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   815000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   835000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   845000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  855000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  865000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  875000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  900000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  910000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  925000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  940000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  955000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  970000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  980000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  995000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1005000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19), 1020000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1035000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 3200000 },
+	{ 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(3),   780000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   790000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   800000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   810000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   820000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   830000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  840000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  850000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  885000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  910000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  925000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  935000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  960000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  970000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  985000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  995000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1010000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 3200000 },
+	{ 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(3),   775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   780000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   790000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   800000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   810000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   820000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  830000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  840000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  850000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  870000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  880000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  895000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  910000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  920000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  940000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  950000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  960000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  975000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  985000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 3200000 },
+	{ 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(3),   760000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   770000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   780000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   790000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   800000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   810000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  820000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  830000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  840000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  850000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  860000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  870000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  880000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  890000, 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),  920000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  930000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  940000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  955000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  965000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  975000, 3200000 },
+	{ 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(3),   750000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   760000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   770000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   780000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   790000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   800000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  810000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  820000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  830000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  850000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  860000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  870000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  875000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  885000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  905000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  915000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  920000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  930000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  940000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
+	{ 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(3),   800000, 3200000 },
@@ -339,6 +501,192 @@
 	{ 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(3),   800000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   800000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   800000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   800000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   810000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   820000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  830000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  840000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  850000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  885000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  895000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  910000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  920000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  945000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  960000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  975000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  990000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1005000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
+	{ 1, { 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 },
+	{ 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(3),   775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   775000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   785000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   795000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   805000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  815000, 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),  845000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  855000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  865000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  875000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  890000, 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),  955000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  970000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  980000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  995000, 3200000 },
+	{ 1, { 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 },
+	{ 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(3),   775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   775000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   775000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   780000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   790000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  800000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  810000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  820000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  840000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  850000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  860000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  875000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  885000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  910000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  925000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  935000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  950000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  960000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  970000, 3200000 },
+	{ 1, { 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 },
+	{ 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(3),   775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   775000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   775000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   775000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   780000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  790000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  800000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  810000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  830000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  840000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  850000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  860000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  870000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  895000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  910000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  920000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  930000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  940000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
+	{ 1, { 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 },
+	{ 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(3),   750000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   750000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   750000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   750000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   760000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   770000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  780000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  790000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  800000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  820000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  830000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  840000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  850000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  860000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  880000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  890000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  900000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  910000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  920000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  930000, 3200000 },
+	{ 1, { 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 },
+	{ 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(3),   750000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   750000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   750000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   750000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   750000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   760000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  770000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  780000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  790000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  800000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  810000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  820000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  830000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  840000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  850000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  860000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  870000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  875000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  885000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  895000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  905000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  915000, 3200000 },
+	{ 1, { 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 },
+	{ 0, { 0 } }
+};
+
 static struct pvs_table pvs_v1[NUM_SPEED_BINS][NUM_PVS] __initdata = {
 	/* 8974v1 1.7GHz Parts */
 	[0][0] = { acpu_freq_tbl_v1_pvs0, sizeof(acpu_freq_tbl_v1_pvs0) },
@@ -351,23 +699,23 @@
 static struct pvs_table pvs_v2[NUM_SPEED_BINS][NUM_PVS] __initdata = {
 	/* 8974v2 2.0GHz Parts */
 	[0][0] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][1] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][2] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][3] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][4] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][5] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][6] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][7] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
+	[0][1] = { acpu_freq_tbl_2g_pvs1, sizeof(acpu_freq_tbl_2g_pvs1) },
+	[0][2] = { acpu_freq_tbl_2g_pvs2, sizeof(acpu_freq_tbl_2g_pvs2) },
+	[0][3] = { acpu_freq_tbl_2g_pvs3, sizeof(acpu_freq_tbl_2g_pvs3) },
+	[0][4] = { acpu_freq_tbl_2g_pvs4, sizeof(acpu_freq_tbl_2g_pvs4) },
+	[0][5] = { acpu_freq_tbl_2g_pvs5, sizeof(acpu_freq_tbl_2g_pvs5) },
+	[0][6] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
+	[0][7] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
 
 	/* 8974v2 2.3GHz Parts */
 	[1][0] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][1] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][2] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][3] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][4] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][5] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][6] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][7] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
+	[1][1] = { acpu_freq_tbl_2p3g_pvs1, sizeof(acpu_freq_tbl_2p3g_pvs1) },
+	[1][2] = { acpu_freq_tbl_2p3g_pvs2, sizeof(acpu_freq_tbl_2p3g_pvs2) },
+	[1][3] = { acpu_freq_tbl_2p3g_pvs3, sizeof(acpu_freq_tbl_2p3g_pvs3) },
+	[1][4] = { acpu_freq_tbl_2p3g_pvs4, sizeof(acpu_freq_tbl_2p3g_pvs4) },
+	[1][5] = { acpu_freq_tbl_2p3g_pvs5, sizeof(acpu_freq_tbl_2p3g_pvs5) },
+	[1][6] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
+	[1][7] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
 };
 
 static struct msm_bus_scale_pdata bus_scale_data __initdata = {
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 5db52dd..41263f8 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -114,6 +114,29 @@
 	},
 };
 
+static struct gpiomux_setting lcd_rst_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_LOW,
+};
+
+static struct gpiomux_setting lcd_rst_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config msm_lcd_configs[] __initdata = {
+	{
+		.gpio = 25,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &lcd_rst_act_cfg,
+			[GPIOMUX_SUSPENDED] = &lcd_rst_sus_cfg,
+		},
+	}
+};
+
 static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
 	{
 		.gpio      = 0,		/* BLSP1 QUP1 SPI_DATA_MOSI */
@@ -225,4 +248,6 @@
 	msm_gpiomux_install(&sd_card_det, 1);
 	msm_gpiomux_install(msm_synaptics_configs,
 			ARRAY_SIZE(msm_synaptics_configs));
+	msm_gpiomux_install_nowrite(msm_lcd_configs,
+			ARRAY_SIZE(msm_lcd_configs));
 }
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index b4f202d..2723e20 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -36,6 +36,7 @@
 #ifdef CONFIG_ION_MSM
 #include <mach/ion.h>
 #endif
+#include <linux/regulator/qpnp-regulator.h>
 #include <mach/msm_memtypes.h>
 #include <mach/socinfo.h>
 #include <mach/board.h>
@@ -96,6 +97,7 @@
 	msm_rpm_driver_init();
 	msm_lpmrs_module_init();
 	msm_spm_device_init();
+	qpnp_regulator_init();
 	msm_thermal_device_init();
 
 	if (machine_is_msm8610_rumi())
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 5240f38..d8a9c3e 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -644,7 +644,7 @@
 	{
 		.gpio = 25, /* WEBCAM2_RESET_N */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
 			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
@@ -665,36 +665,36 @@
 	{
 		.gpio = 28, /* WEBCAM1_STANDBY */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
 			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 	{
 		.gpio = 89, /* CAM1_STANDBY_N */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 	{
 		.gpio = 90, /* CAM1_RST_N */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 	{
 		.gpio = 91, /* CAM2_STANDBY_N */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 	{
 		.gpio = 92, /* CAM2_RST_N */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 };
diff --git a/arch/arm/mach-msm/boot_stats.c b/arch/arm/mach-msm/boot_stats.c
new file mode 100644
index 0000000..afb4374
--- /dev/null
+++ b/arch/arm/mach-msm/boot_stats.c
@@ -0,0 +1,100 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/smp.h>
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/sched.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <mach/msm_iomap.h>
+
+#include "boot_stats.h"
+
+#define MSM_BOOT_STATS_IMEM_START	(MSM_IMEM_BASE+0x6b0)
+
+static void __iomem *mpm_counter_base;
+static uint32_t mpm_counter_freq;
+static struct boot_stats *boot_stats =
+				(void __iomem *)(MSM_BOOT_STATS_IMEM_START);
+
+static const struct of_device_id mpm_counter_of_match[]	= {
+	{ .compatible	= "qcom,mpm2-sleep-counter",	},
+	{},
+};
+
+static int mpm_parse_dt(void)
+{
+	struct device_node *np;
+	u32 freq;
+
+	np = of_find_matching_node(NULL, mpm_counter_of_match);
+	if (!np) {
+		pr_err("mpm_counter: can't find DT node\n");
+		return -ENODEV;
+	}
+
+	if (!of_property_read_u32(np, "clock-frequency", &freq))
+		mpm_counter_freq = freq;
+	else
+		return -ENODEV;
+
+	if (of_get_address(np, 0, NULL, NULL)) {
+		mpm_counter_base = of_iomap(np, 0);
+		if (!mpm_counter_base) {
+			pr_err("mpm_counter: cant map counter base\n");
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static void print_boot_stats(void)
+{
+	pr_info("KPI: Bootloader start count = %u\n",
+			boot_stats->bootloader_start);
+	pr_info("KPI: Bootloader end count = %u\n",
+			boot_stats->bootloader_end);
+	pr_info("KPI: Bootloader display count = %u\n",
+			boot_stats->bootloader_display);
+	pr_info("KPI: Bootloader load kernel count = %u\n",
+			boot_stats->bootloader_load_kernel);
+	pr_info("KPI: Kernel MPM timestamp = %u\n",
+			__raw_readl(mpm_counter_base));
+	pr_info("KPI: Kernel MPM Clock frequency = %u\n",
+			mpm_counter_freq);
+}
+
+int boot_stats_init(void)
+{
+	int ret;
+
+	if (!boot_stats)
+		return -ENODEV;
+
+	ret = mpm_parse_dt();
+	if (ret < 0)
+		return -ENODEV;
+
+	print_boot_stats();
+
+	return 0;
+}
+
diff --git a/arch/arm/mach-msm/boot_stats.h b/arch/arm/mach-msm/boot_stats.h
new file mode 100644
index 0000000..93e36a2
--- /dev/null
+++ b/arch/arm/mach-msm/boot_stats.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+struct boot_stats {
+	uint32_t bootloader_start;
+	uint32_t bootloader_end;
+	uint32_t bootloader_display;
+	uint32_t bootloader_load_kernel;
+};
+
+#ifdef CONFIG_MSM_BOOT_STATS
+int boot_stats_init(void);
+#else
+static inline int boot_stats_init(void) { return 0; }
+#endif
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 5b8ee92..813b210 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3342,7 +3342,7 @@
 	"fdc84000.qcom,iommu"),
 	CLK_LOOKUP("iface_clk", venus0_ahb_clk.c, "fdc84000.qcom,iommu"),
 	CLK_LOOKUP("core_clk", venus0_axi_clk.c, "fdc84000.qcom,iommu"),
-
+	CLK_LOOKUP("iface_clk", gcc_prng_ahb_clk.c, "f9bff000.qcom,msm-rng"),
 	CLK_LOOKUP("cam_gp0_clk", camss_gp0_clk.c, ""),
 	CLK_LOOKUP("cam_gp1_clk", camss_gp1_clk.c, ""),
 	CLK_LOOKUP("iface_clk", camss_micro_ahb_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-mdss-8226.c b/arch/arm/mach-msm/clock-mdss-8226.c
new file mode 100644
index 0000000..e7eca7b
--- /dev/null
+++ b/arch/arm/mach-msm/clock-mdss-8226.c
@@ -0,0 +1,346 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/iopoll.h>
+#include <linux/clk.h>
+
+#include <asm/processor.h>
+#include <mach/msm_iomap.h>
+#include <mach/clk-provider.h>
+
+#include "clock-mdss-8226.h"
+
+#define REG_R(addr)		readl_relaxed(addr)
+#define REG_W(data, addr)	writel_relaxed(data, addr)
+
+#define GDSC_PHYS		0xFD8C2304
+#define GDSC_SIZE		0x4
+
+#define DSI_PHY_PHYS		0xFD922800
+#define DSI_PHY_SIZE		0x00000800
+
+static unsigned char *mdss_dsi_base;
+static unsigned char *gdsc_base;
+static int pll_byte_clk_rate;
+static int pll_pclk_rate;
+static int pll_initialized;
+static struct clk *mdss_dsi_ahb_clk;
+static unsigned long dsi_pll_rate;
+
+void __init mdss_clk_ctrl_pre_init(struct clk *ahb_clk)
+{
+	BUG_ON(ahb_clk == NULL);
+
+	gdsc_base = ioremap(GDSC_PHYS, GDSC_SIZE);
+	if (!gdsc_base)
+		pr_err("%s: unable to remap gdsc base", __func__);
+
+	mdss_dsi_base = ioremap(DSI_PHY_PHYS, DSI_PHY_SIZE);
+	if (!mdss_dsi_base)
+		pr_err("%s: unable to remap dsi base", __func__);
+
+	mdss_dsi_ahb_clk = ahb_clk;
+}
+
+#define PLL_POLL_MAX_READS 10
+#define PLL_POLL_TIMEOUT_US 50
+
+static int mdss_gdsc_enabled(void)
+{
+	if (!gdsc_base)
+		return 0;
+
+	return !!(readl_relaxed(gdsc_base) & BIT(31));
+}
+
+static int mdss_dsi_check_pll_lock(void)
+{
+	u32 status;
+
+	clk_prepare_enable(mdss_dsi_ahb_clk);
+	/* poll for PLL ready status */
+	if (readl_poll_timeout_noirq((mdss_dsi_base + 0x02c0),
+				status,
+				((status & BIT(0)) == 1),
+				PLL_POLL_MAX_READS, PLL_POLL_TIMEOUT_US)) {
+		pr_err("%s: DSI PLL status=%x failed to Lock\n",
+				__func__, status);
+		pll_initialized = 0;
+	} else {
+		pll_initialized = 1;
+	}
+	clk_disable_unprepare(mdss_dsi_ahb_clk);
+
+	return pll_initialized;
+}
+
+static long mdss_dsi_pll_byte_round_rate(struct clk *c, unsigned long rate)
+{
+	if (pll_initialized) {
+		return pll_byte_clk_rate;
+	} else {
+		pr_err("%s: DSI PLL not configured\n", __func__);
+		return -EINVAL;
+	}
+}
+
+static long mdss_dsi_pll_pixel_round_rate(struct clk *c, unsigned long rate)
+{
+	if (pll_initialized) {
+		return pll_pclk_rate;
+	} else {
+		pr_err("%s: Configure Byte clk first\n", __func__);
+		return -EINVAL;
+	}
+}
+
+static int mdss_dsi_pll_pixel_set_rate(struct clk *c, unsigned long rate)
+{
+	if (pll_initialized) {
+		pll_pclk_rate = (rate * 3) / 2;
+		pr_debug("%s: pll_pclk_rate=%d\n", __func__, pll_pclk_rate);
+		return 0;
+	} else {
+		pr_err("%s: Configure Byte clk first\n", __func__);
+		return -EINVAL;
+	}
+}
+
+static int __mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
+{
+	pr_debug("%s: rate=%ld\n", __func__, rate);
+
+	if (pll_initialized)
+		return 0;
+
+	REG_W(0x70, mdss_dsi_base + 0x0230); /* LPFC1 CFG */
+	REG_W(0x08, mdss_dsi_base + 0x022c); /* LPFR CFG */
+	REG_W(0x02, mdss_dsi_base + 0x0210); /* VREG CFG */
+	REG_W(0x00, mdss_dsi_base + 0x0204); /* postDiv1 */
+	REG_W(0x01, mdss_dsi_base + 0x0200); /* REFCLK CFG */
+	REG_W(0x03, mdss_dsi_base + 0x0224); /* postDiv2 */
+	REG_W(0x00, mdss_dsi_base + 0x0238); /* SDM CFG0 */
+	REG_W(0x0b, mdss_dsi_base + 0x023c); /* SDM CFG1 */
+	REG_W(0x00, mdss_dsi_base + 0x0240); /* SDM CFG2 */
+	REG_W(0x6c, mdss_dsi_base + 0x0244); /* SDM CFG3 */
+	REG_W(0x02, mdss_dsi_base + 0x0208); /* ChgPump */
+	REG_W(0x31, mdss_dsi_base + 0x020c); /* VCOLPF CFG */
+	REG_W(0x15, mdss_dsi_base + 0x0234); /* LPFC2 CFG */
+
+	REG_W(0x30, mdss_dsi_base + 0x0284); /* CAL CFG6 */
+	REG_W(0x00, mdss_dsi_base + 0x0288); /* CAL CFG7 */
+	REG_W(0x60, mdss_dsi_base + 0x028c); /* CAL CFG8 */
+	REG_W(0x00, mdss_dsi_base + 0x0290); /* CAL CFG9 */
+	REG_W(0xdd, mdss_dsi_base + 0x0294); /* CAL CFG10 */
+	REG_W(0x01, mdss_dsi_base + 0x0298); /* CAL CFG11 */
+
+	REG_W(0x03, mdss_dsi_base + 0x0228); /* postDiv3 */
+	REG_W(0x2b, mdss_dsi_base + 0x0278); /* Cal CFG3 */
+	REG_W(0x66, mdss_dsi_base + 0x027c); /* Cal CFG4 */
+	REG_W(0x05, mdss_dsi_base + 0x0264); /* LKDET CFG2 */
+	REG_W(0x00, mdss_dsi_base + 0x0248); /* SDM CFG4 */
+	REG_W(0x00, mdss_dsi_base + 0x0214); /* PWRGEN CFG */
+	REG_W(0x0a, mdss_dsi_base + 0x026c); /* CAL CFG0 */
+	REG_W(0x20, mdss_dsi_base + 0x029c); /* EFUSE CFG */
+
+	dsi_pll_rate = rate;
+	pll_byte_clk_rate = rate;
+
+	pr_debug("%s: PLL initialized. bcl=%d\n", __func__, pll_byte_clk_rate);
+	pll_initialized = 1;
+
+	return 0;
+}
+
+static int mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret;
+
+	clk_prepare_enable(mdss_dsi_ahb_clk);
+	ret = __mdss_dsi_pll_byte_set_rate(c, rate);
+	clk_disable_unprepare(mdss_dsi_ahb_clk);
+
+	return ret;
+}
+
+static void mdss_dsi_uniphy_pll_lock_detect_setting(void)
+{
+	REG_W(0x04, mdss_dsi_base + 0x0264); /* LKDetect CFG2 */
+	udelay(100);
+	REG_W(0x05, mdss_dsi_base + 0x0264); /* LKDetect CFG2 */
+	udelay(500);
+}
+
+static void mdss_dsi_uniphy_pll_sw_reset(void)
+{
+	REG_W(0x01, mdss_dsi_base + 0x0268); /* PLL TEST CFG */
+	udelay(1);
+	REG_W(0x00, mdss_dsi_base + 0x0268); /* PLL TEST CFG */
+	udelay(1);
+}
+
+static int __mdss_dsi_pll_enable(struct clk *c)
+{
+	u32 status;
+	u32 max_reads, timeout_us;
+	int i;
+
+	if (!pll_initialized) {
+		if (dsi_pll_rate)
+			__mdss_dsi_pll_byte_set_rate(c, dsi_pll_rate);
+		else
+			pr_err("%s: Calling clk_en before set_rate\n",
+				__func__);
+	}
+
+	mdss_dsi_uniphy_pll_sw_reset();
+	/* PLL power up */
+	/* Add HW recommended delay between
+	   register writes for the update to propagate */
+	REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
+	udelay(20);
+	REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
+	udelay(100);
+	REG_W(0x0d, mdss_dsi_base + 0x0220); /* GLB CFG */
+	udelay(20);
+	REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
+	udelay(200);
+
+	for (i = 0; i < 3; i++) {
+		mdss_dsi_uniphy_pll_lock_detect_setting();
+		/* poll for PLL ready status */
+		max_reads = 5;
+		timeout_us = 100;
+		if (readl_poll_timeout_noirq((mdss_dsi_base + 0x02c0),
+				   status,
+				   ((status & 0x01) == 1),
+					     max_reads, timeout_us)) {
+			pr_debug("%s: DSI PLL status=%x failed to Lock\n",
+			       __func__, status);
+			pr_debug("%s:Trying to power UP PLL again\n",
+			       __func__);
+		} else
+			break;
+
+		mdss_dsi_uniphy_pll_sw_reset();
+		udelay(1000);
+		/* Add HW recommended delay between
+		   register writes for the update to propagate */
+		REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
+		udelay(20);
+		REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
+		udelay(100);
+		REG_W(0x0d, mdss_dsi_base + 0x0220); /* GLB CFG */
+		udelay(20);
+		REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
+		udelay(200);
+	}
+
+	if ((status & 0x01) != 1) {
+		pr_err("%s: DSI PLL status=%x failed to Lock\n",
+		       __func__, status);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: **** PLL Lock success\n", __func__);
+
+	return 0;
+}
+
+static void __mdss_dsi_pll_disable(void)
+{
+	writel_relaxed(0x00, mdss_dsi_base + 0x0220); /* GLB CFG */
+	pr_debug("%s: **** disable pll Initialize\n", __func__);
+	pll_initialized = 0;
+}
+
+static DEFINE_SPINLOCK(dsipll_lock);
+static int dsipll_refcount;
+
+static void mdss_dsi_pll_disable(struct clk *c)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dsipll_lock, flags);
+	if (WARN(dsipll_refcount == 0, "DSI PLL clock is unbalanced"))
+		goto out;
+	if (dsipll_refcount == 1)
+		__mdss_dsi_pll_disable();
+	dsipll_refcount--;
+out:
+	spin_unlock_irqrestore(&dsipll_lock, flags);
+}
+
+static int mdss_dsi_pll_enable(struct clk *c)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&dsipll_lock, flags);
+	if (dsipll_refcount == 0) {
+		ret = __mdss_dsi_pll_enable(c);
+		if (ret < 0)
+			goto out;
+	}
+	dsipll_refcount++;
+out:
+	spin_unlock_irqrestore(&dsipll_lock, flags);
+	return ret;
+}
+
+/* todo: Adjust these values appropriately */
+static enum handoff mdss_dsi_pll_byte_handoff(struct clk *c)
+{
+	if (mdss_gdsc_enabled() && mdss_dsi_check_pll_lock()) {
+		c->rate = 59000000;
+		dsi_pll_rate = 59000000;
+		pll_byte_clk_rate = 59000000;
+		pll_pclk_rate = 117000000;
+		dsipll_refcount++;
+		return HANDOFF_ENABLED_CLK;
+	}
+
+	return HANDOFF_DISABLED_CLK;
+}
+
+/* todo: Adjust these values appropriately */
+static enum handoff mdss_dsi_pll_pixel_handoff(struct clk *c)
+{
+	if (mdss_gdsc_enabled() && mdss_dsi_check_pll_lock()) {
+		c->rate = 117000000;
+		dsipll_refcount++;
+		return HANDOFF_ENABLED_CLK;
+	}
+
+	return HANDOFF_DISABLED_CLK;
+}
+
+struct clk_ops clk_ops_dsi_pixel_pll = {
+	.enable = mdss_dsi_pll_enable,
+	.disable = mdss_dsi_pll_disable,
+	.set_rate = mdss_dsi_pll_pixel_set_rate,
+	.round_rate = mdss_dsi_pll_pixel_round_rate,
+	.handoff = mdss_dsi_pll_pixel_handoff,
+};
+
+struct clk_ops clk_ops_dsi_byte_pll = {
+	.enable = mdss_dsi_pll_enable,
+	.disable = mdss_dsi_pll_disable,
+	.set_rate = mdss_dsi_pll_byte_set_rate,
+	.round_rate = mdss_dsi_pll_byte_round_rate,
+	.handoff = mdss_dsi_pll_byte_handoff,
+};
diff --git a/arch/arm/mach-msm/clock-mdss-8226.h b/arch/arm/mach-msm/clock-mdss-8226.h
new file mode 100644
index 0000000..dcf4f92
--- /dev/null
+++ b/arch/arm/mach-msm/clock-mdss-8226.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8226
+#define __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8226
+
+extern struct clk_ops clk_ops_dsi_byte_pll;
+extern struct clk_ops clk_ops_dsi_pixel_pll;
+
+void mdss_clk_ctrl_pre_init(struct clk *ahb_clk);
+void mdss_clk_ctrl_post_init(void);
+
+#endif /* __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8226 */
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index 91e96b7..8e7f1fa 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -192,11 +192,12 @@
 
 static int mdss_dsi_pll_pixel_set_rate(struct clk *c, unsigned long rate)
 {
-	if (pll_initialized)
+	if (pll_initialized) {
+		pll_pclk_rate = (rate * 3) / 2;
+		pr_debug("%s: pll_pclk_rate=%d\n", __func__, pll_pclk_rate);
 		return 0;
-	else {
-		pr_err("%s: Configure Byte clk first\n",
-				__func__);
+	} else {
+		pr_err("%s: Configure Byte clk first\n", __func__);
 		return -EINVAL;
 	}
 }
@@ -256,11 +257,9 @@
 	REG_W(0x20, mdss_dsi_base + 0x029c); /* EFUSE CFG */
 
 	dsi_pll_rate = rate;
+	pll_byte_clk_rate = rate;
 
-	pll_byte_clk_rate = 53000000;
-	pll_pclk_rate = 105000000;
-
-	pr_debug("%s: **** PLL initialized success\n", __func__);
+	pr_debug("%s: PLL initialized. bcl=%d\n", __func__, pll_byte_clk_rate);
 	pll_initialized = 1;
 
 	return 0;
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index d3574c8..8c53ea5 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -69,7 +69,6 @@
 #endif
 
 #ifndef __ASSEMBLY__
-void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment);
 void *allocate_contiguous_ebi(unsigned long, unsigned long, int);
 unsigned long allocate_contiguous_ebi_nomap(unsigned long, unsigned long);
 void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long);
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index f3bd34a..5f11806 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -107,34 +107,6 @@
 	outer_inv_range(pstart, pstart + length);
 }
 
-void * __init alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
-{
-	void *unused_addr = NULL;
-	unsigned long addr, tmp_size, unused_size;
-
-	/* Allocate maximum size needed, see where it ends up.
-	 * Then free it -- in this path there are no other allocators
-	 * so we can depend on getting the same address back
-	 * when we allocate a smaller piece that is aligned
-	 * at the end (if necessary) and the piece we really want,
-	 * then free the unused first piece.
-	 */
-
-	tmp_size = size + alignment - PAGE_SIZE;
-	addr = (unsigned long)alloc_bootmem(tmp_size);
-	free_bootmem(__pa(addr), tmp_size);
-
-	unused_size = alignment - (addr % alignment);
-	if (unused_size)
-		unused_addr = alloc_bootmem(unused_size);
-
-	addr = (unsigned long)alloc_bootmem(size);
-	if (unused_size)
-		free_bootmem(__pa(unused_addr), unused_size);
-
-	return (void *)addr;
-}
-
 char *memtype_name[] = {
 	"SMI_KERNEL",
 	"SMI",
diff --git a/arch/arm/mach-msm/msm_mpmctr.c b/arch/arm/mach-msm/msm_mpmctr.c
index 4ab82ab..cc0c1c3 100644
--- a/arch/arm/mach-msm/msm_mpmctr.c
+++ b/arch/arm/mach-msm/msm_mpmctr.c
@@ -54,7 +54,7 @@
 }
 
 static struct of_device_id msm_mpmctr_of_match[] = {
-	{.compatible = "qcom,mpm-counter"},
+	{.compatible = "qcom,mpm2-sleep-counter"},
 	{}
 };
 
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 0579145..7f2f528 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -27,6 +27,7 @@
 	"2  Perf: Toggle PMU IRQ when CPU's are hotplugged\n"
 	"3  Perf: Correct irq for CPU hotplug detection\n"
 	"4  Perf: Check perf activity on correct CPU\n"
+	"5  Perf: Add DT support for L1 and L2 PMU\n"
 ;
 
 static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
index 34b9426..ad34457 100644
--- a/arch/arm/mach-msm/perf_event_msm_krait_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.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
@@ -564,6 +564,14 @@
 	.pmu.attr_groups		= msm_l2_pmu_attr_grps,
 };
 
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id l2pmu_of_device_ids[] = {
+	{.compatible = "qcom,l2-pmu"},
+	{},
+};
+
 static int __devinit krait_l2_pmu_device_probe(struct platform_device *pdev)
 {
 	krait_l2_pmu.plat_device = pdev;
@@ -576,7 +584,8 @@
 
 static struct platform_driver krait_l2_pmu_driver = {
 	.driver		= {
-		.name	= "l2-arm-pmu",
+		.name	= "l2-pmu",
+		.of_match_table = l2pmu_of_device_ids,
 	},
 	.probe		= krait_l2_pmu_device_probe,
 };
diff --git a/arch/arm/mach-msm/perf_event_msm_l2.c b/arch/arm/mach-msm/perf_event_msm_l2.c
index f78487a..efd5e21 100644
--- a/arch/arm/mach-msm/perf_event_msm_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_l2.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
@@ -917,7 +917,7 @@
 
 static struct platform_driver scorpion_l2_pmu_driver = {
 	.driver		= {
-		.name	= "l2-arm-pmu",
+		.name	= "l2-pmu",
 	},
 	.probe		= scorpion_l2_pmu_device_probe,
 };
diff --git a/arch/arm/mach-msm/perf_event_msm_pl310.c b/arch/arm/mach-msm/perf_event_msm_pl310.c
index e2a580f..a0d96bf 100644
--- a/arch/arm/mach-msm/perf_event_msm_pl310.c
+++ b/arch/arm/mach-msm/perf_event_msm_pl310.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 ARM Limited
- * 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
@@ -415,9 +415,18 @@
 	return 0;
 }
 
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id l2pmu_of_device_ids[] = {
+	{.compatible = "qcom,l2-pmu"},
+	{},
+};
+
 static struct platform_driver l2x0pmu_driver = {
 	.driver		= {
-		.name	= "l2-arm-pmu",
+		.name	= "l2-pmu",
+		.of_match_table = l2pmu_of_device_ids,
 	},
 	.probe		= l2x0pmu_device_probe,
 };
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 7027d1a..8f6c242 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -653,7 +653,7 @@
 	int64_t time = 0;
 
 	if (msm_pm_use_sync_timer)
-		return ktime_to_ns(ktime_get());
+		return sched_clock();
 
 	time = msm_timer_get_sclk_time(period);
 	if (!time)
@@ -665,7 +665,7 @@
 static int64_t msm_pm_timer_exit_suspend(int64_t time, int64_t period)
 {
 	if (msm_pm_use_sync_timer)
-		return ktime_to_ns(ktime_get()) - time;
+		return sched_clock() - time;
 
 	if (time != 0) {
 		int64_t end_time = msm_timer_get_sclk_time(NULL);
diff --git a/arch/arm/mach-msm/pmu.c b/arch/arm/mach-msm/pmu.c
index febeb19..57378c7 100644
--- a/arch/arm/mach-msm/pmu.c
+++ b/arch/arm/mach-msm/pmu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,62 +15,6 @@
 #include <mach/irqs.h>
 #include <mach/socinfo.h>
 
-/*
- * If a GIC is present, then all IRQ's < 32 are PPI's and can only be
- * requested and free'd using the percpu IRQ API.
- * If a VIC is present, then only the traditional request, free API works.
- *
- * All MPCore's have GIC's. The Cortex A5 however may or may not be MPcore, but
- * it still has a GIC. Except, the 7x27a, which is an A5 and yet has a VIC.
- * So if the chip is A5 but does not have a GIC, default to the traditional
- * IRQ {request, free}_irq API.
- */
-
-#if defined(CONFIG_ARCH_MSM_KRAITMP) || defined(CONFIG_ARCH_MSM_SCORPIONMP) \
-	|| defined(CONFIG_ARCH_MSM8625) || \
-	(defined(CONFIG_ARCH_MSM_CORTEX_A5) && !defined(CONFIG_MSM_VIC))
-
-static DEFINE_PER_CPU(u32, pmu_irq_cookie);
-
-static int
-multicore_request_irq(int irq, irq_handler_t *handle_irq)
-{
-	int err = 0;
-	int cpu;
-
-	err = request_percpu_irq(irq, *handle_irq, "l1-armpmu",
-			&pmu_irq_cookie);
-
-	if (!err) {
-		for_each_cpu(cpu, cpu_online_mask) {
-			smp_call_function_single(cpu,
-					enable_irq_callback, &irq, 1);
-		}
-	}
-
-	return err;
-}
-
-static void
-multicore_free_irq(int irq)
-{
-	int cpu;
-
-	if (irq >= 0) {
-		for_each_cpu(cpu, cpu_online_mask) {
-			smp_call_function_single(cpu,
-					disable_irq_callback, &irq, 1);
-		}
-		free_percpu_irq(irq, &pmu_irq_cookie);
-	}
-}
-
-static struct arm_pmu_platdata multicore_data = {
-	.request_pmu_irq = multicore_request_irq,
-	.free_pmu_irq = multicore_free_irq,
-};
-#endif
-
 static struct resource cpu_pmu_resource[] = {
 	{
 		.start = INT_ARMQC_PERFMON,
@@ -89,7 +33,7 @@
 };
 
 static struct platform_device l2_pmu_device = {
-	.name		= "l2-arm-pmu",
+	.name		= "l2-pmu",
 	.id		= ARM_PMU_DEVICE_L2CC,
 	.resource	= l2_pmu_resource,
 	.num_resources	= ARRAY_SIZE(l2_pmu_resource),
@@ -98,7 +42,7 @@
 #endif
 
 static struct platform_device cpu_pmu_device = {
-	.name		= "cpu-arm-pmu",
+	.name		= "cpu-pmu",
 	.id		= ARM_PMU_DEVICE_CPU,
 	.resource	= cpu_pmu_resource,
 	.num_resources	= ARRAY_SIZE(cpu_pmu_resource),
@@ -120,7 +64,7 @@
 };
 
 static struct platform_device msm8625_cpu_pmu_device = {
-	.name		= "cpu-arm-pmu",
+	.name		= "cpu-pmu",
 	.id		= ARM_PMU_DEVICE_CPU,
 	.resource	= msm8625_cpu_pmu_resource,
 	.num_resources	= ARRAY_SIZE(msm8625_cpu_pmu_resource),
@@ -135,7 +79,7 @@
 };
 
 static struct platform_device msm8625_l2_pmu_device = {
-	.name		= "l2-arm-pmu",
+	.name		= "l2-pmu",
 	.id		= ARM_PMU_DEVICE_L2CC,
 	.resource	= msm8625_l2_pmu_resource,
 	.num_resources	= ARRAY_SIZE(msm8625_l2_pmu_resource),
@@ -156,7 +100,6 @@
 	 * handlers to call the percpu API.
 	 * Defaults to unicore API {request,free}_irq().
 	 * See arch/arm/kernel/perf_event.c
-	 * See Comment above on the A5 and MSM_VIC.
 	 */
 #if defined(CONFIG_ARCH_MSM_KRAITMP) || defined(CONFIG_ARCH_MSM_SCORPIONMP) \
 	|| (defined(CONFIG_ARCH_MSM_CORTEX_A5) && !defined(CONFIG_MSM_VIC))
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 3da1c63..efbd8c6 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -29,6 +29,7 @@
 #include <mach/socinfo.h>
 
 #include "smd_private.h"
+#include "boot_stats.h"
 
 #define BUILD_ID_LENGTH 32
 
@@ -1139,6 +1140,7 @@
 	if (socinfo->v1.id < ARRAY_SIZE(cpu_of_id))
 		cur_cpu = cpu_of_id[socinfo->v1.id];
 
+	boot_stats_init();
 	socinfo_print();
 
 	return 0;
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h
index 0c6db93..2136f58 100644
--- a/arch/powerpc/include/asm/time.h
+++ b/arch/powerpc/include/asm/time.h
@@ -206,7 +206,5 @@
 
 DECLARE_PER_CPU(u64, decrementers_next_tb);
 
-extern void decrementer_check_overflow(void);
-
 #endif /* __KERNEL__ */
 #endif /* __POWERPC_TIME_H */
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index f8df241..2c42cd7 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -769,15 +769,6 @@
 	       clock->name, clock->mult, clock->shift);
 }
 
-void decrementer_check_overflow(void)
-{
-	u64 now = get_tb_or_rtc();
-	struct decrementer_clock *decrementer = &__get_cpu_var(decrementers);
-
-	if (now >= decrementer->next_tb)
-		set_dec(1);
-}
-
 static int decrementer_set_next_event(unsigned long evt,
 				      struct clock_event_device *dev)
 {
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index f34b238..276359e 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -20,8 +20,6 @@
 
 #include "entry.h"
 
-#include "entry.h"
-
 #ifdef CONFIG_SPARC64
 
 #include <linux/jump_label.h>
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index f493e52..146bb62 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -749,7 +749,7 @@
  */
 
 const int amd_erratum_400[] =
-	AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0x0f, 0x4, 0x2, 0xff, 0xf),
+	AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
 			    AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
 EXPORT_SYMBOL_GPL(amd_erratum_400);
 
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 13e40b9..48be2ad 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -417,6 +417,27 @@
 }
 
 static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL);
+
+#ifdef CONFIG_PM_AUTOSLEEP
+static ssize_t wakeup_prevent_sleep_time_show(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	s64 msec = 0;
+	bool enabled = false;
+
+	spin_lock_irq(&dev->power.lock);
+	if (dev->power.wakeup) {
+		msec = ktime_to_ms(dev->power.wakeup->prevent_sleep_time);
+		enabled = true;
+	}
+	spin_unlock_irq(&dev->power.lock);
+	return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_prevent_sleep_time_ms, 0444,
+		   wakeup_prevent_sleep_time_show, NULL);
+#endif /* CONFIG_PM_AUTOSLEEP */
 #endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_PM_ADVANCED_DEBUG
@@ -511,6 +532,9 @@
 	&dev_attr_wakeup_total_time_ms.attr,
 	&dev_attr_wakeup_max_time_ms.attr,
 	&dev_attr_wakeup_last_time_ms.attr,
+#ifdef CONFIG_PM_AUTOSLEEP
+	&dev_attr_wakeup_prevent_sleep_time_ms.attr,
+#endif
 #endif
 	NULL,
 };
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 1132799..cbb463b 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -133,6 +133,7 @@
 	spin_lock_init(&ws->lock);
 	setup_timer(&ws->timer, pm_wakeup_timer_fn, (unsigned long)ws);
 	ws->active = false;
+	ws->last_time = ktime_get();
 
 	spin_lock_irq(&events_lock);
 	list_add_rcu(&ws->entry, &wakeup_sources);
@@ -380,6 +381,8 @@
 	ws->active = true;
 	ws->active_count++;
 	ws->last_time = ktime_get();
+	if (ws->autosleep_enabled)
+		ws->start_prevent_time = ws->last_time;
 
 	/* Increment the counter of events in progress. */
 	cec = atomic_inc_return(&combined_event_count);
@@ -449,6 +452,17 @@
 }
 EXPORT_SYMBOL_GPL(pm_stay_awake);
 
+#ifdef CONFIG_PM_AUTOSLEEP
+static void update_prevent_sleep_time(struct wakeup_source *ws, ktime_t now)
+{
+	ktime_t delta = ktime_sub(now, ws->start_prevent_time);
+	ws->prevent_sleep_time = ktime_add(ws->prevent_sleep_time, delta);
+}
+#else
+static inline void update_prevent_sleep_time(struct wakeup_source *ws,
+					     ktime_t now) {}
+#endif
+
 /**
  * wakup_source_deactivate - Mark given wakeup source as inactive.
  * @ws: Wakeup source to handle.
@@ -490,6 +504,9 @@
 	del_timer(&ws->timer);
 	ws->timer_expires = 0;
 
+	if (ws->autosleep_enabled)
+		update_prevent_sleep_time(ws, now);
+
 	/*
 	 * Increment the counter of registered wakeup events and decrement the
 	 * couter of wakeup events in progress simultaneously.
@@ -660,29 +677,33 @@
 /**
  * pm_get_wakeup_count - Read the number of registered wakeup events.
  * @count: Address to store the value at.
+ * @block: Whether or not to block.
  *
- * Store the number of registered wakeup events at the address in @count.  Block
- * if the current number of wakeup events being processed is nonzero.
+ * Store the number of registered wakeup events at the address in @count.  If
+ * @block is set, block until the current number of wakeup events being
+ * processed is zero.
  *
- * Return 'false' if the wait for the number of wakeup events being processed to
- * drop down to zero has been interrupted by a signal (and the current number
- * of wakeup events being processed is still nonzero).  Otherwise return 'true'.
+ * Return 'false' if the current number of wakeup events being processed is
+ * nonzero.  Otherwise return 'true'.
  */
-bool pm_get_wakeup_count(unsigned int *count)
+bool pm_get_wakeup_count(unsigned int *count, bool block)
 {
 	unsigned int cnt, inpr;
-	DEFINE_WAIT(wait);
 
-	for (;;) {
-		prepare_to_wait(&wakeup_count_wait_queue, &wait,
-				TASK_INTERRUPTIBLE);
-		split_counters(&cnt, &inpr);
-		if (inpr == 0 || signal_pending(current))
-			break;
+	if (block) {
+		DEFINE_WAIT(wait);
 
-		schedule();
+		for (;;) {
+			prepare_to_wait(&wakeup_count_wait_queue, &wait,
+					TASK_INTERRUPTIBLE);
+			split_counters(&cnt, &inpr);
+			if (inpr == 0 || signal_pending(current))
+				break;
+
+			schedule();
+		}
+		finish_wait(&wakeup_count_wait_queue, &wait);
 	}
-	finish_wait(&wakeup_count_wait_queue, &wait);
 
 	split_counters(&cnt, &inpr);
 	*count = cnt;
@@ -714,6 +735,34 @@
 	return events_check_enabled;
 }
 
+#ifdef CONFIG_PM_AUTOSLEEP
+/**
+ * pm_wakep_autosleep_enabled - Modify autosleep_enabled for all wakeup sources.
+ * @enabled: Whether to set or to clear the autosleep_enabled flags.
+ */
+void pm_wakep_autosleep_enabled(bool set)
+{
+	struct wakeup_source *ws;
+	ktime_t now = ktime_get();
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
+		spin_lock_irq(&ws->lock);
+		if (ws->autosleep_enabled != set) {
+			ws->autosleep_enabled = set;
+			if (ws->active) {
+				if (set)
+					ws->start_prevent_time = now;
+				else
+					update_prevent_sleep_time(ws, now);
+			}
+		}
+		spin_unlock_irq(&ws->lock);
+	}
+	rcu_read_unlock();
+}
+#endif /* CONFIG_PM_AUTOSLEEP */
+
 static struct dentry *wakeup_sources_stats_dentry;
 
 /**
@@ -729,28 +778,37 @@
 	ktime_t max_time;
 	unsigned long active_count;
 	ktime_t active_time;
+	ktime_t prevent_sleep_time;
 	int ret;
 
 	spin_lock_irqsave(&ws->lock, flags);
 
 	total_time = ws->total_time;
 	max_time = ws->max_time;
+	prevent_sleep_time = ws->prevent_sleep_time;
 	active_count = ws->active_count;
 	if (ws->active) {
-		active_time = ktime_sub(ktime_get(), ws->last_time);
+		ktime_t now = ktime_get();
+
+		active_time = ktime_sub(now, ws->last_time);
 		total_time = ktime_add(total_time, active_time);
 		if (active_time.tv64 > max_time.tv64)
 			max_time = active_time;
+
+		if (ws->autosleep_enabled)
+			prevent_sleep_time = ktime_add(prevent_sleep_time,
+				ktime_sub(now, ws->start_prevent_time));
 	} else {
 		active_time = ktime_set(0, 0);
 	}
 
 	ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t"
-			"%lld\t\t%lld\t\t%lld\t\t%lld\n",
+			"%lld\t\t%lld\t\t%lld\t\t%lld\t\t%lld\n",
 			ws->name, active_count, ws->event_count,
 			ws->wakeup_count, ws->expire_count,
 			ktime_to_ms(active_time), ktime_to_ms(total_time),
-			ktime_to_ms(max_time), ktime_to_ms(ws->last_time));
+			ktime_to_ms(max_time), ktime_to_ms(ws->last_time),
+			ktime_to_ms(prevent_sleep_time));
 
 	spin_unlock_irqrestore(&ws->lock, flags);
 
@@ -767,7 +825,7 @@
 
 	seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
 		"expire_count\tactive_since\ttotal_time\tmax_time\t"
-		"last_change\n");
+		"last_change\tprevent_suspend_time\n");
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index e4b6b6b..ea2f2d2 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -703,8 +703,7 @@
 		break;
 
 	case HCI_ACLDATA_PKT:
-		if (!data->bulk_tx_ep || (hdev->conn_hash.acl_num < 1 &&
-						hdev->conn_hash.le_num < 1))
+		if (!data->bulk_tx_ep)
 			return -ENODEV;
 
 		urb = usb_alloc_urb(0, GFP_ATOMIC);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index be71347..3d5614b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -787,6 +787,8 @@
 
 			spin_lock_irqsave(&cpufreq_driver_lock, flags);
 			cpumask_copy(managed_policy->cpus, policy->cpus);
+			cpumask_and(managed_policy->cpus,
+					managed_policy->cpus, cpu_online_mask);
 			per_cpu(cpufreq_cpu_data, cpu) = managed_policy;
 			spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
diff --git a/drivers/crypto/msm/qce.c b/drivers/crypto/msm/qce.c
index 7f8460b..5c1cc5a 100644
--- a/drivers/crypto/msm/qce.c
+++ b/drivers/crypto/msm/qce.c
@@ -505,19 +505,6 @@
 	return nents;
 }
 
-static int dma_map_pmem_sg(struct buf_info *pmem, unsigned entries,
-						struct scatterlist *sg)
-{
-	int i = 0;
-	for (i = 0; i < entries; i++) {
-
-		sg->dma_address = (dma_addr_t)pmem->offset;
-		sg++;
-		pmem++;
-	}
-	return 0;
-}
-
 static int _probe_ce_engine(struct qce_device *pce_dev)
 {
 	unsigned int val;
@@ -1084,52 +1071,6 @@
 	return 0;
 };
 
-static int _ablk_cipher_use_pmem_complete(struct qce_device *pce_dev)
-{
-	struct ablkcipher_request *areq;
-	uint32_t iv_out[4];
-	unsigned char iv[4 * sizeof(uint32_t)];
-	uint32_t status;
-
-	areq = (struct ablkcipher_request *) pce_dev->areq;
-
-	/* check ce error status */
-	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
-	if (status & (1 << CRYPTO_SW_ERR)) {
-		pce_dev->err++;
-		dev_err(pce_dev->pdev,
-			"Qualcomm Crypto Error at 0x%x, status%x\n",
-			pce_dev->phy_iobase, status);
-		_init_ce_engine(pce_dev);
-		clk_disable(pce_dev->ce_clk);
-		pce_dev->qce_cb(areq, NULL, NULL, -ENXIO);
-		return 0;
-	};
-
-	/* get iv out */
-	if (pce_dev->mode == QCE_MODE_ECB) {
-		clk_disable(pce_dev->ce_clk);
-		pce_dev->qce_cb(areq, NULL, NULL, pce_dev->chan_ce_in_status |
-					pce_dev->chan_ce_out_status);
-	} else {
-		iv_out[0] = readl_relaxed(pce_dev->iobase +
-							CRYPTO_CNTR0_IV0_REG);
-		iv_out[1] = readl_relaxed(pce_dev->iobase +
-							CRYPTO_CNTR1_IV1_REG);
-		iv_out[2] = readl_relaxed(pce_dev->iobase +
-							CRYPTO_CNTR2_IV2_REG);
-		iv_out[3] = readl_relaxed(pce_dev->iobase +
-							CRYPTO_CNTR3_IV3_REG);
-
-		_net_words_to_byte_stream(iv_out, iv, sizeof(iv));
-		clk_disable(pce_dev->ce_clk);
-		pce_dev->qce_cb(areq, NULL, iv, pce_dev->chan_ce_in_status |
-					pce_dev->chan_ce_out_status);
-	}
-
-	return 0;
-};
-
 static int qce_split_and_insert_dm_desc(struct dmov_desc *pdesc,
 			unsigned int plen, unsigned int paddr, int *index)
 {
@@ -1555,53 +1496,6 @@
 };
 
 
-static void _ablk_cipher_ce_in_call_back_pmem(struct msm_dmov_cmd *cmd_ptr,
-		unsigned int result, struct msm_dmov_errdata *err)
-{
-	struct qce_device *pce_dev;
-
-	pce_dev = (struct qce_device *) cmd_ptr->user;
-	if (result != ADM_STATUS_OK) {
-		dev_err(pce_dev->pdev, "Qualcomm ADM status error %x\n",
-						result);
-		pce_dev->chan_ce_in_status = -1;
-	} else
-		pce_dev->chan_ce_in_status = 0;
-
-	pce_dev->chan_ce_in_state = QCE_CHAN_STATE_COMP;
-	if (pce_dev->chan_ce_out_state == QCE_CHAN_STATE_COMP) {
-		pce_dev->chan_ce_in_state = QCE_CHAN_STATE_IDLE;
-		pce_dev->chan_ce_out_state = QCE_CHAN_STATE_IDLE;
-
-		/* done */
-		_ablk_cipher_use_pmem_complete(pce_dev);
-	}
-};
-
-static void _ablk_cipher_ce_out_call_back_pmem(struct msm_dmov_cmd *cmd_ptr,
-		unsigned int result, struct msm_dmov_errdata *err)
-{
-	struct qce_device *pce_dev;
-
-	pce_dev = (struct qce_device *) cmd_ptr->user;
-	if (result != ADM_STATUS_OK) {
-		dev_err(pce_dev->pdev, "Qualcomm ADM status error %x\n",
-						result);
-		pce_dev->chan_ce_out_status = -1;
-	} else {
-		pce_dev->chan_ce_out_status = 0;
-	};
-
-	pce_dev->chan_ce_out_state = QCE_CHAN_STATE_COMP;
-	if (pce_dev->chan_ce_in_state == QCE_CHAN_STATE_COMP) {
-		pce_dev->chan_ce_in_state = QCE_CHAN_STATE_IDLE;
-		pce_dev->chan_ce_out_state = QCE_CHAN_STATE_IDLE;
-
-		/* done */
-		_ablk_cipher_use_pmem_complete(pce_dev);
-	}
-};
-
 static int _setup_cmd_template(struct qce_device *pce_dev)
 {
 	dmov_sg *pcmd;
@@ -2183,14 +2077,9 @@
 	/* cipher input       */
 	pce_dev->src_nents = count_sg(areq->src, areq->nbytes);
 
-	if (c_req->use_pmem != 1)
-		qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 								DMA_TO_DEVICE);
-	else
-		dma_map_pmem_sg(&c_req->pmem->src[0], pce_dev->src_nents,
-								areq->src);
-
 	if (_chain_sg_buffer_in(pce_dev, areq->src, areq->nbytes) < 0) {
 		rc = -ENOMEM;
 		goto bad;
@@ -2199,12 +2088,8 @@
 	/* cipher output      */
 	if (areq->src != areq->dst) {
 		pce_dev->dst_nents = count_sg(areq->dst, areq->nbytes);
-		if (c_req->use_pmem != 1)
-			qce_dma_map_sg(pce_dev->pdev, areq->dst,
+		qce_dma_map_sg(pce_dev->pdev, areq->dst,
 					pce_dev->dst_nents, DMA_FROM_DEVICE);
-		else
-			dma_map_pmem_sg(&c_req->pmem->dst[0],
-					pce_dev->dst_nents, areq->dst);
 	};
 	if (_chain_sg_buffer_out(pce_dev, areq->dst, areq->nbytes) < 0) {
 		rc = -ENOMEM;
@@ -2241,34 +2126,25 @@
 	/* setup for callback, and issue command to adm */
 	pce_dev->areq = areq;
 	pce_dev->qce_cb = c_req->qce_cb;
-	if (c_req->use_pmem == 1) {
-		pce_dev->chan_ce_in_cmd->complete_func =
-					_ablk_cipher_ce_in_call_back_pmem;
-		pce_dev->chan_ce_out_cmd->complete_func =
-					_ablk_cipher_ce_out_call_back_pmem;
-	} else {
-		pce_dev->chan_ce_in_cmd->complete_func =
+	pce_dev->chan_ce_in_cmd->complete_func =
 					_ablk_cipher_ce_in_call_back;
-		pce_dev->chan_ce_out_cmd->complete_func =
+	pce_dev->chan_ce_out_cmd->complete_func =
 					_ablk_cipher_ce_out_call_back;
-	}
 	rc = _qce_start_dma(pce_dev, true, true);
 
 	if (rc == 0)
 		return 0;
 bad:
-	if (c_req->use_pmem != 1) {
-		if (pce_dev->dst_nents) {
-			qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
-				pce_dev->dst_nents, DMA_FROM_DEVICE);
-		}
-		if (pce_dev->src_nents) {
-			qce_dma_unmap_sg(pce_dev->pdev, areq->src,
-					pce_dev->src_nents,
-					(areq->src == areq->dst) ?
-						DMA_BIDIRECTIONAL :
-						DMA_TO_DEVICE);
-		}
+	if (pce_dev->dst_nents) {
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
+			pce_dev->dst_nents, DMA_FROM_DEVICE);
+	}
+	if (pce_dev->src_nents) {
+		qce_dma_unmap_sg(pce_dev->pdev, areq->src,
+				pce_dev->src_nents,
+				(areq->src == areq->dst) ?
+					DMA_BIDIRECTIONAL :
+					DMA_TO_DEVICE);
 	}
 	return rc;
 }
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 41ab8dc..2440404 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -12,7 +12,7 @@
  * GNU General Public License for more details.
  */
 #include <linux/mman.h>
-#include <linux/android_pmem.h>
+
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
@@ -454,14 +454,12 @@
 
 	/* start the command on the podev->active_command */
 	qcedev_areq = podev->active_command;
-
 	qcedev_areq->cipher_req.cookie = qcedev_areq->handle;
-	creq.use_pmem = qcedev_areq->cipher_op_req.use_pmem;
-	if (qcedev_areq->cipher_op_req.use_pmem == QCEDEV_USE_PMEM)
-		creq.pmem = &qcedev_areq->cipher_op_req.pmem;
-	else
-		creq.pmem = NULL;
-
+	if (qcedev_areq->cipher_op_req.use_pmem == QCEDEV_USE_PMEM) {
+		pr_err("%s: Use of PMEM is not supported\n", __func__);
+		goto unsupported;
+	}
+	creq.pmem = NULL;
 	switch (qcedev_areq->cipher_op_req.alg) {
 	case QCEDEV_ALG_DES:
 		creq.alg = CIPHER_ALG_DES;
@@ -1274,224 +1272,6 @@
 		return qcedev_hmac_final(areq, handle);
 }
 
-#ifdef CONFIG_ANDROID_PMEM
-static int qcedev_pmem_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
-						struct qcedev_handle *handle)
-{
-	int i = 0;
-	int err = 0;
-	struct scatterlist *sg_src = NULL;
-	struct scatterlist *sg_dst = NULL;
-	struct scatterlist *sg_ndex = NULL;
-	struct file *file_src = NULL;
-	struct file *file_dst = NULL;
-	unsigned long paddr;
-	unsigned long kvaddr;
-	unsigned long len;
-
-	sg_src = kmalloc((sizeof(struct scatterlist) *
-				areq->cipher_op_req.entries),	GFP_KERNEL);
-	if (sg_src == NULL) {
-		pr_err("%s: Can't Allocate memory:sg_src 0x%x\n",
-			__func__, (uint32_t)sg_src);
-		return -ENOMEM;
-
-	}
-	memset(sg_src, 0, (sizeof(struct scatterlist) *
-				areq->cipher_op_req.entries));
-	sg_ndex = sg_src;
-	areq->cipher_req.creq.src = sg_src;
-
-	/* address src */
-	get_pmem_file(areq->cipher_op_req.pmem.fd_src, &paddr,
-					&kvaddr, &len, &file_src);
-
-	for (i = 0; i < areq->cipher_op_req.entries; i++) {
-		sg_set_buf(sg_ndex,
-		((uint8_t *)(areq->cipher_op_req.pmem.src[i].offset) + kvaddr),
-		areq->cipher_op_req.pmem.src[i].len);
-		sg_ndex++;
-	}
-	sg_mark_end(--sg_ndex);
-
-	for (i = 0; i < areq->cipher_op_req.entries; i++)
-		areq->cipher_op_req.pmem.src[i].offset += (uint32_t)paddr;
-
-	/* address dst */
-	/* If not place encryption/decryption */
-	if (areq->cipher_op_req.in_place_op != 1) {
-		sg_dst = kmalloc((sizeof(struct scatterlist) *
-				areq->cipher_op_req.entries), GFP_KERNEL);
-		if (sg_dst == NULL) {
-			pr_err("%s: Can't Allocate memory: sg_dst 0x%x\n",
-			__func__, (uint32_t)sg_dst);
-			return -ENOMEM;
-		}
-		memset(sg_dst, 0, (sizeof(struct scatterlist) *
-					areq->cipher_op_req.entries));
-		areq->cipher_req.creq.dst = sg_dst;
-		sg_ndex = sg_dst;
-
-		get_pmem_file(areq->cipher_op_req.pmem.fd_dst, &paddr,
-					&kvaddr, &len, &file_dst);
-		for (i = 0; i < areq->cipher_op_req.entries; i++)
-			sg_set_buf(sg_ndex++,
-			((uint8_t *)(areq->cipher_op_req.pmem.dst[i].offset)
-			+ kvaddr), areq->cipher_op_req.pmem.dst[i].len);
-		sg_mark_end(--sg_ndex);
-
-		for (i = 0; i < areq->cipher_op_req.entries; i++)
-			areq->cipher_op_req.pmem.dst[i].offset +=
-							(uint32_t)paddr;
-	} else {
-		areq->cipher_req.creq.dst = sg_src;
-		for (i = 0; i < areq->cipher_op_req.entries; i++) {
-			areq->cipher_op_req.pmem.dst[i].offset =
-				areq->cipher_op_req.pmem.src[i].offset;
-			areq->cipher_op_req.pmem.dst[i].len =
-				areq->cipher_op_req.pmem.src[i].len;
-		}
-	}
-
-	areq->cipher_req.creq.nbytes = areq->cipher_op_req.data_len;
-	areq->cipher_req.creq.info = areq->cipher_op_req.iv;
-
-	err = submit_req(areq, handle);
-
-	kfree(sg_src);
-	kfree(sg_dst);
-
-	if (file_dst)
-		put_pmem_file(file_dst);
-	if (file_src)
-		put_pmem_file(file_src);
-
-	return err;
-};
-
-
-static int qcedev_pmem_ablk_cipher(struct qcedev_async_req *qcedev_areq,
-						struct qcedev_handle *handle)
-{
-	int err = 0;
-	int i = 0;
-	int j = 0;
-	int k = 0;
-	int num_entries = 0;
-	uint32_t total = 0;
-	struct qcedev_cipher_op_req *saved_req;
-	struct qcedev_cipher_op_req *creq = &qcedev_areq->cipher_op_req;
-
-	saved_req = kmalloc(sizeof(struct qcedev_cipher_op_req), GFP_KERNEL);
-	if (saved_req == NULL) {
-		pr_err(KERN_ERR "%s:Can't Allocate mem:saved_req 0x%x\n",
-		__func__, (uint32_t)saved_req);
-		return -ENOMEM;
-	}
-	memcpy(saved_req, creq, sizeof(struct qcedev_cipher_op_req));
-
-	if (qcedev_areq->cipher_op_req.data_len > QCE_MAX_OPER_DATA) {
-
-		struct qcedev_cipher_op_req req;
-
-		/* save the original req structure */
-		memcpy(&req, creq, sizeof(struct qcedev_cipher_op_req));
-
-		i = 0;
-		/* Address 32 KB  at a time */
-		while ((i < req.entries) && (err == 0)) {
-			if (creq->pmem.src[i].len > QCE_MAX_OPER_DATA) {
-				creq->pmem.src[0].len =	QCE_MAX_OPER_DATA;
-				if (i > 0) {
-					creq->pmem.src[0].offset =
-						creq->pmem.src[i].offset;
-				}
-
-				creq->data_len = QCE_MAX_OPER_DATA;
-				creq->entries = 1;
-
-				err =
-				qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq,
-								handle);
-
-				creq->pmem.src[i].len =	req.pmem.src[i].len -
-							QCE_MAX_OPER_DATA;
-				creq->pmem.src[i].offset =
-						req.pmem.src[i].offset +
-						QCE_MAX_OPER_DATA;
-				req.pmem.src[i].offset =
-						creq->pmem.src[i].offset;
-				req.pmem.src[i].len = creq->pmem.src[i].len;
-			} else {
-				total = 0;
-				for (j = i; j < req.entries; j++) {
-					num_entries++;
-					if ((total + creq->pmem.src[j].len)
-							>= QCE_MAX_OPER_DATA) {
-						creq->pmem.src[j].len =
-						QCE_MAX_OPER_DATA - total;
-						total = QCE_MAX_OPER_DATA;
-						break;
-					}
-					total += creq->pmem.src[j].len;
-				}
-
-				creq->data_len = total;
-				if (i > 0)
-					for (k = 0; k < num_entries; k++) {
-						creq->pmem.src[k].len =
-						creq->pmem.src[i+k].len;
-						creq->pmem.src[k].offset =
-						creq->pmem.src[i+k].offset;
-					}
-				creq->entries =  num_entries;
-
-				i = j;
-				err =
-				qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq,
-								handle);
-				num_entries = 0;
-
-					creq->pmem.src[i].offset =
-						req.pmem.src[i].offset +
-						creq->pmem.src[i].len;
-					creq->pmem.src[i].len =
-						req.pmem.src[i].len -
-						creq->pmem.src[i].len;
-					req.pmem.src[i].offset =
-						creq->pmem.src[i].offset;
-					req.pmem.src[i].len =
-						creq->pmem.src[i].len;
-
-				if (creq->pmem.src[i].len == 0)
-					i++;
-			}
-
-		} /* end of while ((i < req.entries) && (err == 0)) */
-
-	} else
-		err = qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq, handle);
-
-	/* Restore the original req structure */
-	for (i = 0; i < saved_req->entries; i++) {
-		creq->pmem.src[i].len = saved_req->pmem.src[i].len;
-		creq->pmem.src[i].offset = saved_req->pmem.src[i].offset;
-	}
-	creq->entries = saved_req->entries;
-	creq->data_len = saved_req->data_len;
-	kfree(saved_req);
-
-	return err;
-
-}
-#else
-static int qcedev_pmem_ablk_cipher(struct qcedev_async_req *qcedev_areq,
-						struct qcedev_handle *handle)
-{
-	return -EPERM;
-}
-#endif/*CONFIG_ANDROID_PMEM*/
-
 static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
 				int *di, struct qcedev_handle *handle,
 				uint8_t *k_align_src)
@@ -1753,6 +1533,10 @@
 static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
 						struct qcedev_control *podev)
 {
+	if (req->use_pmem) {
+		pr_err("%s: Use of PMEM is not supported\n", __func__);
+		goto error;
+	}
 	if ((req->entries == 0) || (req->data_len == 0))
 		goto error;
 	if ((req->alg >= QCEDEV_ALG_LAST) ||
@@ -1792,15 +1576,6 @@
 	if (req->byteoffset) {
 		if (req->mode != QCEDEV_AES_MODE_CTR)
 			goto error;
-		else { /* if using CTR mode make sure not using Pmem */
-			if (req->use_pmem)
-				goto error;
-		}
-	}
-	/* if using PMEM with non-zero byteoffset, ensure it is in_place_op */
-	if (req->use_pmem) {
-		if (!req->in_place_op)
-			goto error;
 	}
 	/* Ensure zer ivlen for ECB  mode  */
 	if (req->ivlen != 0) {
@@ -1890,10 +1665,7 @@
 				podev))
 			return -EINVAL;
 
-		if (qcedev_areq.cipher_op_req.use_pmem)
-			err = qcedev_pmem_ablk_cipher(&qcedev_areq, handle);
-		else
-			err = qcedev_vbuf_ablk_cipher(&qcedev_areq, handle);
+		err = qcedev_vbuf_ablk_cipher(&qcedev_areq, handle);
 		if (err)
 			return err;
 		if (__copy_to_user((void __user *)arg,
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index b114875..9d24d65 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3737,10 +3737,6 @@
 # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE		(1 << 12)
 # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE		(1 << 11)
 
-#define GEN6_UCGCTL2				0x9404
-# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE		(1 << 12)
-# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE		(1 << 11)
-
 #define GEN6_RPNSWREQ				0xA008
 #define   GEN6_TURBO_DISABLE			(1<<31)
 #define   GEN6_FREQUENCY(x)			((x)<<25)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 48dae40..f7eb5d8 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -439,9 +439,6 @@
 	struct radeon_i2c_chan *ddc_bus;
 	/* some systems have an hdmi and vga port with a shared ddc line */
 	bool shared_ddc;
-	/* for some Radeon chip families we apply an additional EDID header
-	   check as part of the DDC probe */
-	bool requires_extended_probe;
 	bool use_digital;
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
@@ -529,8 +526,7 @@
 				u8 val);
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
-			bool requires_extended_probe);
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index b1a45bf..bf45a63 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -251,23 +251,19 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-	result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc,
-				     GSL_PT_PAGE_RV);
+	result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc);
 	if (result)
 		goto error;
 
-	result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc,
-				     GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc);
 	if (result)
 		goto unmap_buffer_desc;
 
-	result = kgsl_mmu_map_global(pagetable, &device->memstore,
-				     GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	result = kgsl_mmu_map_global(pagetable, &device->memstore);
 	if (result)
 		goto unmap_memptrs_desc;
 
-	result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory,
-				     GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory);
 	if (result)
 		goto unmap_memstore_desc;
 
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 5cdf911..69b34fa 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -485,6 +485,7 @@
 	 */
 	rb->sizedwords = KGSL_RB_SIZE >> 2;
 
+	rb->buffer_desc.flags = KGSL_MEMFLAGS_GPUREADONLY;
 	/* allocate memory for ringbuffer */
 	status = kgsl_allocate_contiguous(&rb->buffer_desc,
 		(rb->sizedwords << 2));
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 130474a..6e1ecd1 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1871,10 +1871,7 @@
 	else if (entry->memdesc.size >= SZ_64K)
 		kgsl_memdesc_set_align(&entry->memdesc, ilog2(SZ_64));
 
-	result = kgsl_mmu_map(private->pagetable,
-			      &entry->memdesc,
-			      GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
-
+	result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
 	if (result)
 		goto error_put_file_ptr;
 
@@ -2065,8 +2062,7 @@
 	if (result)
 		return result;
 
-	result = kgsl_mmu_map(private->pagetable, &entry->memdesc,
-				kgsl_memdesc_protflags(&entry->memdesc));
+	result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
 	if (result)
 		goto err;
 
@@ -2104,8 +2100,7 @@
 		goto err;
 
 	if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
-		result = kgsl_mmu_map(private->pagetable, &entry->memdesc,
-				kgsl_memdesc_protflags(&entry->memdesc));
+		result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
 		if (result)
 			goto err;
 	}
@@ -2719,8 +2714,7 @@
 	if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
 		entry->memdesc.gpuaddr = vma->vm_start;
 
-		ret = kgsl_mmu_map(private->pagetable, &entry->memdesc,
-				   kgsl_memdesc_protflags(&entry->memdesc));
+		ret = kgsl_mmu_map(private->pagetable, &entry->memdesc);
 		if (ret) {
 			kgsl_mem_entry_put(entry);
 			return ret;
@@ -2753,6 +2747,29 @@
 	}
 
 	vma->vm_ops = &kgsl_gpumem_vm_ops;
+
+	if (cache == KGSL_CACHEMODE_WRITEBACK
+		|| cache == KGSL_CACHEMODE_WRITETHROUGH) {
+		struct scatterlist *s;
+		int i;
+		int sglen = entry->memdesc.sglen;
+		unsigned long addr = vma->vm_start;
+
+		/* don't map in the guard page, it should always fault */
+		if (kgsl_memdesc_has_guard_page(&entry->memdesc))
+			sglen--;
+
+		for_each_sg(entry->memdesc.sg, s, sglen, i) {
+			int j;
+			for (j = 0; j < (sg_dma_len(s) >> PAGE_SHIFT); j++) {
+				struct page *page = sg_page(s);
+				page = nth_page(page, j);
+				vm_insert_page(vma, addr, page);
+				addr += PAGE_SIZE;
+			}
+		}
+	}
+
 	vma->vm_file = file;
 
 	entry->memdesc.useraddr = vma->vm_start;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 3eb8831..70a704b 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -149,6 +149,8 @@
 #define KGSL_MEMDESC_GUARD_PAGE BIT(0)
 /* Set if the memdesc is mapped into all pagetables */
 #define KGSL_MEMDESC_GLOBAL BIT(1)
+/* The memdesc is frozen during a snapshot */
+#define KGSL_MEMDESC_FROZEN BIT(2)
 
 /* shared memory allocation */
 struct kgsl_memdesc {
@@ -175,15 +177,10 @@
 #define KGSL_MEM_ENTRY_ION    4
 #define KGSL_MEM_ENTRY_MAX    5
 
-/* List of flags */
-
-#define KGSL_MEM_ENTRY_FROZEN (1 << 0)
-
 struct kgsl_mem_entry {
 	struct kref refcount;
 	struct kgsl_memdesc memdesc;
 	int memtype;
-	int flags;
 	void *priv_data;
 	struct rb_node node;
 	unsigned int id;
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index c24e03b..11d6ffa 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -210,8 +210,7 @@
 				return result;
 			}
 
-			result = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
-					GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+			result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
 			if (result) {
 				DRM_ERROR(
 				"kgsl_mmu_map failed.  result = %d\n", result);
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index df8e1d0..93b7e5d 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -43,6 +43,8 @@
 	{ 0x820, 0, 0 },			/* RESUME */
 	{ 0x03C, 0, 0 },			/* TLBLKCR */
 	{ 0x818, 0, 0 },			/* V2PUR */
+	{ 0x2C, 0, 0 },                         /* FSYNR0 */
+	{ 0x2C, 0, 0 },                         /* FSYNR0 */
 };
 
 static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = {
@@ -51,7 +53,11 @@
 	{ 0x28, 0x00FFFFFF, 14 },		/* TTBR1 */
 	{ 0x58, 0, 0 },				/* FSR */
 	{ 0x618, 0, 0 },			/* TLBIALL */
-	{ 0x008, 0, 0 }				/* RESUME */
+	{ 0x008, 0, 0 },			/* RESUME */
+	{ 0, 0, 0 },				/* TLBLKCR */
+	{ 0, 0, 0 },				/* V2PUR */
+	{ 0x68, 0, 0 },				/* FSYNR0 */
+	{ 0x6C, 0, 0 }				/* FSYNR1 */
 };
 
 struct remote_iommu_petersons_spinlock kgsl_iommu_sync_lock_vars;
@@ -118,6 +124,7 @@
 	unsigned int gpuaddr;
 	unsigned int size;
 	unsigned int flags;
+	unsigned int priv;
 	pid_t pid;
 };
 
@@ -146,7 +153,8 @@
 		if (entry->memdesc.gpuaddr > ret->gpuaddr) {
 			ret->gpuaddr = entry->memdesc.gpuaddr;
 			ret->size = entry->memdesc.size;
-			ret->flags = entry->flags;
+			ret->flags = entry->memdesc.flags;
+			ret->priv = entry->memdesc.priv;
 			ret->pid = priv->pid;
 		}
 
@@ -179,7 +187,8 @@
 		if (entry->memdesc.gpuaddr < ret->gpuaddr) {
 			ret->gpuaddr = entry->memdesc.gpuaddr;
 			ret->size = entry->memdesc.size;
-			ret->flags = entry->flags;
+			ret->flags = entry->memdesc.flags;
+			ret->priv = entry->memdesc.priv;
 			ret->pid = priv->pid;
 		}
 
@@ -224,9 +233,10 @@
 	kgsl_get_memory_usage(name, sizeof(name) - 1, entry->flags);
 
 	KGSL_LOG_DUMP(device,
-		"[%8.8X - %8.8X] (pid = %d) (%s)\n",
+		"[%8.8X - %8.8X] %s (pid = %d) (%s)\n",
 		entry->gpuaddr,
 		entry->gpuaddr + entry->size,
+		entry->priv & KGSL_MEMDESC_GUARD_PAGE ? "(+guard)" : "",
 		entry->pid, name);
 }
 
@@ -275,6 +285,8 @@
 	unsigned int pid;
 
 	struct _mem_entry prev, next;
+	unsigned int fsynr0, fsynr1;
+	int write;
 
 	ret = get_iommu_unit(dev, &mmu, &iommu_unit);
 	if (ret)
@@ -292,12 +304,25 @@
 
 	fsr = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
 		iommu_dev->ctx_id, FSR);
+	fsynr0 = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
+		iommu_dev->ctx_id, FSYNR0);
+	fsynr1 = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
+		iommu_dev->ctx_id, FSYNR1);
+
+	if (msm_soc_version_supports_iommu_v0())
+		write = ((fsynr1 & (KGSL_IOMMU_FSYNR1_AWRITE_MASK <<
+			KGSL_IOMMU_FSYNR1_AWRITE_SHIFT)) ? 1 : 0);
+	else
+		write = ((fsynr0 & (KGSL_IOMMU_V1_FSYNR0_WNR_MASK <<
+			KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT)) ? 1 : 0);
 
 	pid = kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase);
 	KGSL_MEM_CRIT(iommu_dev->kgsldev,
 		"GPU PAGE FAULT: addr = %lX pid = %d\n", addr, pid);
-	KGSL_MEM_CRIT(iommu_dev->kgsldev, "context = %d FSR = %X\n",
-		iommu_dev->ctx_id, fsr);
+	KGSL_MEM_CRIT(iommu_dev->kgsldev,
+		"context = %d FSR = %X FSYNR0 = %X FSYNR1 = %X(%s fault)\n",
+		iommu_dev->ctx_id, fsr, fsynr0, fsynr1,
+		write ? "write" : "read");
 
 	_check_if_freed(iommu_dev, addr, pid);
 
@@ -321,7 +346,8 @@
 	iommu_dev->fault = 1;
 
 	trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
-			kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase), 0);
+			kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase),
+			write ? "write" : "read");
 
 	/*
 	 * We do not want the h/w to resume fetching data from an iommu unit
@@ -1118,16 +1144,14 @@
 
 	for (i = 0; i < iommu->unit_count; i++) {
 		status = kgsl_mmu_map_global(pt,
-				&(iommu->iommu_units[i].reg_map),
-				GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+				&(iommu->iommu_units[i].reg_map));
 		if (status)
 			goto err;
 	}
 
 	/* Map Lock variables to GPU pagetable */
 	if (iommu->sync_lock_initialized) {
-		status = kgsl_mmu_map_global(pt, &iommu->sync_lock_desc,
-				GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+		status = kgsl_mmu_map_global(pt, &iommu->sync_lock_desc);
 		if (status)
 			goto err;
 	}
@@ -1499,25 +1523,39 @@
 	unsigned int iommu_virt_addr;
 	struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
 	int size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
-	unsigned int iommu_flags = IOMMU_READ;
 
 	BUG_ON(NULL == iommu_pt);
 
-	if (protflags & GSL_PT_PAGE_WV)
-		iommu_flags |= IOMMU_WRITE;
+	/* if there's a guard page, we'll map it read only below */
+	if ((protflags & IOMMU_WRITE) && kgsl_memdesc_has_guard_page(memdesc))
+			size -= PAGE_SIZE;
 
 	iommu_virt_addr = memdesc->gpuaddr;
 
 	ret = iommu_map_range(iommu_pt->domain, iommu_virt_addr, memdesc->sg,
-				size, iommu_flags);
+				size, protflags);
 	if (ret) {
-		KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %d) "
-				"failed with err: %d\n", iommu_pt->domain,
-				iommu_virt_addr, memdesc->sg, size,
-				iommu_flags, ret);
+		KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %x) err: %d\n",
+			iommu_pt->domain, iommu_virt_addr, memdesc->sg, size,
+			protflags, ret);
 		return ret;
 	}
+	if ((protflags & IOMMU_WRITE) && kgsl_memdesc_has_guard_page(memdesc)) {
+		struct scatterlist *sg = &memdesc->sg[memdesc->sglen - 1];
 
+		ret = iommu_map(iommu_pt->domain, iommu_virt_addr + size,
+				kgsl_get_sg_pa(sg), PAGE_SIZE,
+				protflags & ~IOMMU_WRITE);
+		if (ret) {
+			KGSL_CORE_ERR("iommu_map(%p, %x, %x, %x) err: %d\n",
+				iommu_pt->domain, iommu_virt_addr + size,
+				kgsl_get_sg_pa(sg), protflags & ~IOMMU_WRITE,
+				ret);
+			/* cleanup the partial mapping */
+			iommu_unmap_range(iommu_pt->domain, iommu_virt_addr,
+					  size);
+		}
+	}
 	return ret;
 }
 
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index bf40113..c09bc4b 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -19,7 +19,7 @@
 #define KGSL_IOMMU_CTX_OFFSET_V1	0x8000
 #define KGSL_IOMMU_CTX_SHIFT		12
 
-/* TLBLKCR feilds */
+/* TLBLKCR fields */
 #define KGSL_IOMMU_TLBLKCR_LKE_MASK		0x00000001
 #define KGSL_IOMMU_TLBLKCR_LKE_SHIFT		0
 #define KGSL_IOMMU_TLBLKCR_TLBIALLCFG_MASK	0x00000001
@@ -33,12 +33,19 @@
 #define KGSL_IOMMU_TLBLKCR_VICTIM_MASK		0x000000FF
 #define KGSL_IOMMU_TLBLKCR_VICTIM_SHIFT		16
 
-/* V2PXX feilds */
+/* V2PXX fields */
 #define KGSL_IOMMU_V2PXX_INDEX_MASK		0x000000FF
 #define KGSL_IOMMU_V2PXX_INDEX_SHIFT		0
 #define KGSL_IOMMU_V2PXX_VA_MASK		0x000FFFFF
 #define KGSL_IOMMU_V2PXX_VA_SHIFT		12
 
+/* FSYNR1 V0 fields */
+#define KGSL_IOMMU_FSYNR1_AWRITE_MASK		0x00000001
+#define KGSL_IOMMU_FSYNR1_AWRITE_SHIFT		8
+/* FSYNR0 V1 fields */
+#define KGSL_IOMMU_V1_FSYNR0_WNR_MASK		0x00000001
+#define KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT		4
+
 enum kgsl_iommu_reg_map {
 	KGSL_IOMMU_GLOBAL_BASE = 0,
 	KGSL_IOMMU_CTX_TTBR0,
@@ -48,6 +55,8 @@
 	KGSL_IOMMU_CTX_RESUME,
 	KGSL_IOMMU_CTX_TLBLKCR,
 	KGSL_IOMMU_CTX_V2PUR,
+	KGSL_IOMMU_CTX_FSYNR0,
+	KGSL_IOMMU_CTX_FSYNR1,
 	KGSL_IOMMU_REG_MAX
 };
 
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index f71cf8c..83cf83d 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -580,13 +580,13 @@
 
 int
 kgsl_mmu_map(struct kgsl_pagetable *pagetable,
-				struct kgsl_memdesc *memdesc,
-				unsigned int protflags)
+				struct kgsl_memdesc *memdesc)
 {
 	int ret;
 	struct gen_pool *pool = NULL;
 	int size;
 	int page_align = ilog2(PAGE_SIZE);
+	unsigned int protflags = kgsl_memdesc_protflags(memdesc);
 
 	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
 		if (memdesc->sglen == 1) {
@@ -738,7 +738,7 @@
 EXPORT_SYMBOL(kgsl_mmu_unmap);
 
 int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
-			struct kgsl_memdesc *memdesc, unsigned int protflags)
+			struct kgsl_memdesc *memdesc)
 {
 	int result = -EINVAL;
 	unsigned int gpuaddr = 0;
@@ -750,11 +750,10 @@
 	/* Not all global mappings are needed for all MMU types */
 	if (!memdesc->size)
 		return 0;
-
 	gpuaddr = memdesc->gpuaddr;
 	memdesc->priv |= KGSL_MEMDESC_GLOBAL;
 
-	result = kgsl_mmu_map(pagetable, memdesc, protflags);
+	result = kgsl_mmu_map(pagetable, memdesc);
 	if (result)
 		goto error;
 
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 2b33baf..0458a13 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -201,10 +201,9 @@
 int kgsl_mmu_start(struct kgsl_device *device);
 int kgsl_mmu_close(struct kgsl_device *device);
 int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
-		 struct kgsl_memdesc *memdesc,
-		 unsigned int protflags);
+		 struct kgsl_memdesc *memdesc);
 int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
-			struct kgsl_memdesc *memdesc, unsigned int protflags);
+			struct kgsl_memdesc *memdesc);
 int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
 		    struct kgsl_memdesc *memdesc);
 unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 27b9151..279490f 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
 #include "kgsl_mmu.h"
 #include <linux/slab.h>
 #include <linux/kmemleak.h>
+#include <linux/iommu.h>
 
 #include "kgsl_log.h"
 
@@ -195,15 +196,24 @@
 /*
  * kgsl_memdesc_protflags - get mmu protection flags
  * @memdesc - the memdesc
- * Returns a mask of GSL_PT_PAGE* values based on the
- * memdesc flags.
+ * Returns a mask of GSL_PT_PAGE* or IOMMU* values based
+ * on the memdesc flags.
  */
 static inline unsigned int
 kgsl_memdesc_protflags(const struct kgsl_memdesc *memdesc)
 {
-	unsigned int protflags = GSL_PT_PAGE_RV;
-	if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
-		protflags |= GSL_PT_PAGE_WV;
+	unsigned int protflags = 0;
+	enum kgsl_mmutype mmutype = kgsl_mmu_get_mmutype();
+
+	if (mmutype == KGSL_MMU_TYPE_GPU) {
+		protflags = GSL_PT_PAGE_RV;
+		if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
+			protflags |= GSL_PT_PAGE_WV;
+	} else if (mmutype == KGSL_MMU_TYPE_IOMMU) {
+		protflags = IOMMU_READ;
+		if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
+			protflags |= IOMMU_WRITE;
+	}
 	return protflags;
 }
 
@@ -248,8 +258,7 @@
 	ret = kgsl_sharedmem_page_alloc(memdesc, pagetable, size);
 	if (ret)
 		return ret;
-	ret = kgsl_mmu_map(pagetable, memdesc,
-			   kgsl_memdesc_protflags(memdesc));
+	ret = kgsl_mmu_map(pagetable, memdesc);
 	if (ret)
 		kgsl_sharedmem_free(memdesc);
 	return ret;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 0935f64..c4647a1 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -283,7 +283,7 @@
 {
 	list_del(&obj->node);
 
-	obj->entry->flags &= ~KGSL_MEM_ENTRY_FROZEN;
+	obj->entry->memdesc.priv &= ~KGSL_MEMDESC_FROZEN;
 	kgsl_mem_entry_put(obj->entry);
 
 	kfree(obj);
@@ -416,10 +416,10 @@
 	 * 0 so it doesn't get counted twice
 	 */
 
-	if (entry->flags & KGSL_MEM_ENTRY_FROZEN)
+	if (entry->memdesc.priv & KGSL_MEMDESC_FROZEN)
 		return 0;
 
-	entry->flags |= KGSL_MEM_ENTRY_FROZEN;
+	entry->memdesc.priv |= KGSL_MEMDESC_FROZEN;
 
 	return entry->memdesc.size;
 }
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index e578b0e..f0410d6 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -244,20 +244,17 @@
 	int result = 0;
 	struct z180_device *z180_dev = Z180_DEVICE(device);
 
-	result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory,
-				     GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory);
 
 	if (result)
 		goto error;
 
-	result = kgsl_mmu_map_global(pagetable, &device->memstore,
-				     GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	result = kgsl_mmu_map_global(pagetable, &device->memstore);
 	if (result)
 		goto error_unmap_dummy;
 
 	result = kgsl_mmu_map_global(pagetable,
-				     &z180_dev->ringbuffer.cmdbufdesc,
-				     GSL_PT_PAGE_RV);
+				     &z180_dev->ringbuffer.cmdbufdesc);
 	if (result)
 		goto error_unmap_memstore;
 	/*
@@ -498,6 +495,7 @@
 	struct z180_device *z180_dev = Z180_DEVICE(device);
 	memset(&z180_dev->ringbuffer, 0, sizeof(struct z180_ringbuffer));
 	z180_dev->ringbuffer.prevctx = Z180_INVALID_CONTEXT;
+	z180_dev->ringbuffer.cmdbufdesc.flags = KGSL_MEMFLAGS_GPUREADONLY;
 	return kgsl_allocate_contiguous(&z180_dev->ringbuffer.cmdbufdesc,
 		Z180_RB_SIZE);
 }
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index fda9e0a..3a78489 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1363,7 +1363,7 @@
 	int is_eth;
 	int is_vlan = 0;
 	int is_grh;
-	u16 vlan = 0;
+	u16 vlan;
 
 	send_size = 0;
 	for (i = 0; i < wr->num_sge; ++i)
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
index 0eb0a23..8c484e7 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
@@ -293,8 +293,12 @@
 	pgmn_dev->jpeg_clk, ARRAY_SIZE(jpeg_8x_clk_info), 0);
 
 fail_clk:
-	regulator_put(pgmn_dev->jpeg_fs);
-	regulator_disable(pgmn_dev->jpeg_fs);
+	rc = regulator_disable(pgmn_dev->jpeg_fs);
+	if (!rc)
+		regulator_put(pgmn_dev->jpeg_fs);
+	else
+		JPEG_PR_ERR("%s:%d] regulator disable failed %d",
+			__func__, __LINE__, rc);
 	pgmn_dev->jpeg_fs = NULL;
 
 fail_fs:
@@ -330,8 +334,12 @@
 	JPEG_DBG("%s:%d] clock disbale done", __func__, __LINE__);
 
 	if (pgmn_dev->jpeg_fs) {
-		regulator_put(pgmn_dev->jpeg_fs);
-		regulator_disable(pgmn_dev->jpeg_fs);
+		result = regulator_disable(pgmn_dev->jpeg_fs);
+		if (!result)
+			regulator_put(pgmn_dev->jpeg_fs);
+		else
+			JPEG_PR_ERR("%s:%d] regulator disable failed %d",
+				__func__, __LINE__, result);
 		pgmn_dev->jpeg_fs = NULL;
 	}
 	iounmap(pgmn_dev->jpeg_vbif);
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 8c30b6c..1b7ecf0 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -164,6 +164,11 @@
 	}
 
 	qinfo =	(struct vidc_iface_q_info *) info;
+	if (!qinfo || !qinfo->q_array.align_virtual_addr) {
+		dprintk(VIDC_WARN, "Queues have already been freed\n");
+		return -EINVAL;
+	}
+
 	venus_hfi_sim_modify_cmd_packet(packet);
 
 	queue = (struct hfi_queue_header *) qinfo->q_hdr;
@@ -282,6 +287,10 @@
 	}
 
 	qinfo =	(struct vidc_iface_q_info *) info;
+	if (!qinfo || !qinfo->q_array.align_virtual_addr) {
+		dprintk(VIDC_WARN, "Queues have already been freed\n");
+		return -EINVAL;
+	}
 	queue = (struct hfi_queue_header *) qinfo->q_hdr;
 
 	if (!queue) {
@@ -634,6 +643,8 @@
 	int num_entries = sizeof(venus_qdss_entries)/(2 * sizeof(u32));
 	int domain, partition;
 
+	mutex_lock(&device->write_lock);
+	mutex_lock(&device->read_lock);
 	if (device->qdss.mem_data) {
 		qdss = (struct hfi_mem_map_table *)
 			device->qdss.align_virtual_addr;
@@ -674,6 +685,8 @@
 
 	msm_smem_delete_client(device->hal_client);
 	device->hal_client = NULL;
+	mutex_unlock(&device->read_lock);
+	mutex_unlock(&device->write_lock);
 }
 static int venus_hfi_get_qdss_iommu_virtual_addr(struct hfi_mem_map *mem_map,
 						int domain, int partition)
@@ -937,7 +950,6 @@
 	}
 
 	dev->intr_status = 0;
-	enable_irq(dev->hal_data->irq);
 	INIT_LIST_HEAD(&dev->sess_head);
 	mutex_init(&dev->read_lock);
 	mutex_init(&dev->write_lock);
@@ -966,6 +978,7 @@
 		rc = -EEXIST;
 		goto err_core_init;
 	}
+	enable_irq(dev->hal_data->irq);
 	venus_hfi_write_register(dev->hal_data->register_base_addr,
 		VIDC_CTRL_INIT, 0x1, 0);
 	rc = venus_hfi_core_start_cpu(dev);
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 1f3dc2f..153552d 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -2696,6 +2696,9 @@
 {
 	struct iris_device *radio = video_get_drvdata(video_devdata(file));
 	int retval = 0;
+	int cf0;
+	struct hci_fm_def_data_rd_req rd;
+	int lsb, msb;
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_VOLUME:
@@ -2858,6 +2861,113 @@
 	case V4L2_CID_PRIVATE_VALID_CHANNEL:
 		ctrl->value = radio->is_station_valid;
 		break;
+	case V4L2_CID_PRIVATE_AF_RMSSI_TH:
+		rd.mode = FM_RDS_CNFG_MODE;
+		rd.length = FM_RDS_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Get AF Jump Threshold failed %x", retval);
+			return retval;
+		}
+		lsb = radio->default_data.data[AF_RMSSI_TH_LSB_OFFSET];
+		msb = radio->default_data.data[AF_RMSSI_TH_MSB_OFFSET];
+		ctrl->value = ((msb << 8) | lsb);
+		break;
+	case V4L2_CID_PRIVATE_AF_RMSSI_SAMPLES:
+		rd.mode = FM_RDS_CNFG_MODE;
+		rd.length = FM_RDS_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Get AF jump rmssi samples failed %x", retval);
+			return retval;
+		}
+		ctrl->value = radio->default_data.data[AF_RMSSI_SAMPLES_OFFSET];
+		break;
+	case V4L2_CID_PRIVATE_GOOD_CH_RMSSI_TH:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("get good channel rmssi th failed %x", retval);
+			return retval;
+		}
+		ctrl->value = radio->default_data.data[GD_CH_RMSSI_TH_OFFSET];
+		if (ctrl->value > MAX_GD_CH_RMSSI_TH)
+			ctrl->value -= 256;
+		break;
+	case V4L2_CID_PRIVATE_SRCHALGOTYPE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("get search algo type failed %x", retval);
+			return retval;
+		}
+		ctrl->value = radio->default_data.data[SRCH_ALGO_TYPE_OFFSET];
+		break;
+	case V4L2_CID_PRIVATE_SINRFIRSTSTAGE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x", retval);
+			return retval;
+		}
+		ctrl->value = radio->default_data.data[SINRFIRSTSTAGE_OFFSET];
+		if (ctrl->value > MAX_SINR_FIRSTSTAGE)
+			ctrl->value -= 256;
+		break;
+	case V4L2_CID_PRIVATE_RMSSIFIRSTSTAGE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x", retval);
+			return retval;
+		}
+		ctrl->value = radio->default_data.data[RMSSIFIRSTSTAGE_OFFSET];
+		if (ctrl->value > MAX_RMSSI_FIRSTSTAGE)
+			ctrl->value -= 256;
+		break;
+	case V4L2_CID_PRIVATE_CF0TH12:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x", retval);
+			return retval;
+		}
+		ctrl->value = radio->default_data.data[CF0TH12_BYTE1_OFFSET];
+		cf0 = radio->default_data.data[CF0TH12_BYTE2_OFFSET];
+		ctrl->value |= (cf0 << 8);
+		cf0 = radio->default_data.data[CF0TH12_BYTE3_OFFSET];
+		ctrl->value |= (cf0 << 16);
+		cf0 = radio->default_data.data[CF0TH12_BYTE4_OFFSET];
+		if (cf0 > 127)
+			cf0 -= 256;
+		ctrl->value |= (cf0 << 24);
+		break;
 	default:
 		retval = -EINVAL;
 	}
@@ -3022,8 +3132,8 @@
 	unsigned long arg = 0;
 	struct hci_fm_tx_ps tx_ps = {0};
 	struct hci_fm_tx_rt tx_rt = {0};
-	struct hci_fm_def_data_rd_req rd_txgain;
-	struct hci_fm_def_data_wr_req wr_txgain;
+	struct hci_fm_def_data_rd_req rd;
+	struct hci_fm_def_data_wr_req wrd;
 	char sinr_th, sinr;
 	__u8 intf_det_low_th, intf_det_high_th, intf_det_out;
 
@@ -3325,25 +3435,25 @@
 			ctrl->value = FM_TX_PWR_LVL_MAX;
 		if (ctrl->value < FM_TX_PWR_LVL_0)
 			ctrl->value = FM_TX_PWR_LVL_0;
-		rd_txgain.mode = FM_TX_PHY_CFG_MODE;
-		rd_txgain.length = FM_TX_PHY_CFG_LEN;
-		rd_txgain.param_len = 0x00;
-		rd_txgain.param = 0x00;
+		rd.mode = FM_TX_PHY_CFG_MODE;
+		rd.length = FM_TX_PHY_CFG_LEN;
+		rd.param_len = 0x00;
+		rd.param = 0x00;
 
-		retval = hci_def_data_read(&rd_txgain, radio->fm_hdev);
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("Default data read failed for PHY_CFG %d\n",
 			retval);
 			break;
 		}
-		memset(&wr_txgain, 0, sizeof(wr_txgain));
-		wr_txgain.mode = FM_TX_PHY_CFG_MODE;
-		wr_txgain.length = FM_TX_PHY_CFG_LEN;
-		memcpy(&wr_txgain.data, &radio->default_data.data,
+		memset(&wrd, 0, sizeof(wrd));
+		wrd.mode = FM_TX_PHY_CFG_MODE;
+		wrd.length = FM_TX_PHY_CFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
 					radio->default_data.ret_data_len);
-		wr_txgain.data[FM_TX_PWR_GAIN_OFFSET] =
+		wrd.data[FM_TX_PWR_GAIN_OFFSET] =
 				(ctrl->value) * FM_TX_PWR_LVL_STEP_SIZE;
-		retval = hci_def_data_write(&wr_txgain, radio->fm_hdev);
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
 		if (retval < 0)
 			FMDERR("Default write failed for PHY_TXGAIN %d\n",
 			retval);
@@ -3536,6 +3646,150 @@
 		else
 			radio->is_station_valid = INVALID_CHANNEL;
 		break;
+	case V4L2_CID_PRIVATE_AF_RMSSI_TH:
+		rd.mode = FM_RDS_CNFG_MODE;
+		rd.length = FM_RDS_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x", retval);
+			return retval;
+		}
+		wrd.mode = FM_RDS_CNFG_MODE;
+		wrd.length = FM_RDS_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[AF_RMSSI_TH_LSB_OFFSET] = ((ctrl->value) & 255);
+		wrd.data[AF_RMSSI_TH_MSB_OFFSET] = ((ctrl->value) >> 8);
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set AF jump RMSSI threshold failed\n");
+		break;
+	case V4L2_CID_PRIVATE_AF_RMSSI_SAMPLES:
+		rd.mode = FM_RDS_CNFG_MODE;
+		rd.length = FM_RDS_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x", retval);
+			return retval;
+		}
+		wrd.mode = FM_RDS_CNFG_MODE;
+		wrd.length = FM_RDS_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[AF_RMSSI_SAMPLES_OFFSET] = ctrl->value;
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set AF jump RMSSI Samples failed\n");
+		break;
+	case V4L2_CID_PRIVATE_GOOD_CH_RMSSI_TH:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x", retval);
+			return retval;
+		}
+		wrd.mode = FM_RX_CONFG_MODE;
+		wrd.length = FM_RX_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[GD_CH_RMSSI_TH_OFFSET] = ctrl->value;
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set good channel RMSSI th failed\n");
+		break;
+	case V4L2_CID_PRIVATE_SRCHALGOTYPE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x", retval);
+			return retval;
+		}
+		wrd.mode = FM_RX_CONFG_MODE;
+		wrd.length = FM_RX_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[SRCH_ALGO_TYPE_OFFSET] = ctrl->value;
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set Search Algo Type failed\n");
+		break;
+	case V4L2_CID_PRIVATE_SINRFIRSTSTAGE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x", retval);
+			return retval;
+		}
+		wrd.mode = FM_RX_CONFG_MODE;
+		wrd.length = FM_RX_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[SINRFIRSTSTAGE_OFFSET] = ctrl->value;
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set SINR First Stage failed\n");
+		break;
+	case V4L2_CID_PRIVATE_RMSSIFIRSTSTAGE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x", retval);
+			return retval;
+		}
+		wrd.mode = FM_RX_CONFG_MODE;
+		wrd.length = FM_RX_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[RMSSIFIRSTSTAGE_OFFSET] = ctrl->value;
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set RMSSI First Stage failed\n");
+		break;
+	case V4L2_CID_PRIVATE_CF0TH12:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x", retval);
+			return retval;
+		}
+		wrd.mode = FM_RX_CONFG_MODE;
+		wrd.length = FM_RX_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[CF0TH12_BYTE1_OFFSET] = (ctrl->value & 255);
+		wrd.data[CF0TH12_BYTE2_OFFSET] = ((ctrl->value >> 8) & 255);
+		wrd.data[CF0TH12_BYTE3_OFFSET] = ((ctrl->value >> 16) & 255);
+		wrd.data[CF0TH12_BYTE4_OFFSET] = ((ctrl->value >> 24) & 255);
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set CF0 Threshold failed\n");
+		break;
 	default:
 		retval = -EINVAL;
 	}
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 8a99968..f3a979b 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -41,7 +41,7 @@
 	struct rc_dev *rcdev;
 	struct pm_qos_request pm_qos_req;
 	struct timer_list gpio_ir_timer;
-	unsigned int gpio_nr;
+	int gpio_nr;
 	bool active_low;
 	int can_sleep;
 	bool can_wakeup;
@@ -52,7 +52,7 @@
 static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id)
 {
 	struct gpio_rc_dev *gpio_dev = dev_id;
-	unsigned int gval;
+	int gval;
 	int rc = 0;
 	enum raw_event_type type = IR_SPACE;
 
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index b2ef948..ff2cddd 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -68,15 +68,6 @@
 			goto done;
 		}
 
-		/* Prevent excessive memory consumption, as well as integer
-		 * overflows.
-		 */
-		if (xmap->menu_count == 0 ||
-		    xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) {
-			ret = -EINVAL;
-			goto done;
-		}
-
 		size = xmap->menu_count * sizeof(*map->menu_info);
 		map->menu_info = kmalloc(size, GFP_KERNEL);
 		if (map->menu_info == NULL) {
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 834e0e2..b075435 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -34,6 +34,7 @@
 #include <linux/delay.h>
 #include <linux/capability.h>
 #include <linux/compat.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/mmc/ioctl.h>
 #include <linux/mmc/card.h>
@@ -2497,6 +2498,7 @@
 #endif
 
 	if (req && !mq->mqrq_prev->req) {
+		mmc_rpm_hold(host, &card->dev);
 		/* claim host only for the first request */
 		mmc_claim_host(card->host);
 		if (card->ext_csd.bkops_en)
@@ -2558,6 +2560,7 @@
 			mmc_start_bkops(card, false);
 		/* release host only when there are no more requests */
 		mmc_release_host(card->host);
+		mmc_rpm_release(host, &card->dev);
 	}
 	return ret;
 }
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 58efd5e..96e3dc0 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -2695,6 +2695,7 @@
 	pr_info("%s: Starting tests of card %s...\n",
 		mmc_hostname(test->card->host), mmc_card_id(test->card));
 
+	mmc_rpm_hold(test->card->host, &test->card->dev);
 	mmc_claim_host(test->card->host);
 
 	for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) {
@@ -2778,6 +2779,7 @@
 	}
 
 	mmc_release_host(test->card->host);
+	mmc_rpm_release(test->card->host, &test->card->dev);
 
 	pr_info("%s: Tests completed.\n",
 		mmc_hostname(test->card->host));
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 169ccf1..0e024dd 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -57,7 +57,6 @@
 {
 	struct mmc_queue *mq = d;
 	struct request_queue *q = mq->queue;
-	struct request *req;
 	struct mmc_card *card = mq->card;
 
 	current->flags |= PF_MEMALLOC;
@@ -65,7 +64,7 @@
 	down(&mq->thread_sem);
 	do {
 		struct mmc_queue_req *tmp;
-		req = NULL;	/* Must be set to NULL at each iteration */
+		struct request *req = NULL;
 
 		spin_lock_irq(q->queue_lock);
 		set_current_state(TASK_INTERRUPTIBLE);
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 2f27407..7b9e133 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -26,6 +26,7 @@
 #include "bus.h"
 
 #define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
+#define RUNTIME_SUSPEND_DELAY_MS 10000
 
 static ssize_t mmc_type_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
@@ -144,9 +145,6 @@
 		ret = drv->resume(card);
 	return ret;
 }
-#else
-#define mmc_bus_suspend NULL
-#define mmc_bus_resume NULL
 #endif
 
 #ifdef CONFIG_PM_RUNTIME
@@ -155,19 +153,38 @@
 {
 	struct mmc_card *card = mmc_dev_to_card(dev);
 
-	return mmc_power_save_host(card->host);
+	if (mmc_use_core_runtime_pm(card->host))
+		return 0;
+	else
+		return mmc_power_save_host(card->host);
 }
 
 static int mmc_runtime_resume(struct device *dev)
 {
 	struct mmc_card *card = mmc_dev_to_card(dev);
 
-	return mmc_power_restore_host(card->host);
+	if (mmc_use_core_runtime_pm(card->host))
+		return 0;
+	else
+		return mmc_power_restore_host(card->host);
 }
 
 static int mmc_runtime_idle(struct device *dev)
 {
-	return pm_runtime_suspend(dev);
+	struct mmc_card *card = mmc_dev_to_card(dev);
+	struct mmc_host *host = card->host;
+	int ret = 0;
+
+	if (mmc_use_core_runtime_pm(card->host)) {
+		ret = pm_schedule_suspend(dev, card->idle_timeout);
+		if (ret) {
+			pr_err("%s: %s: pm_schedule_suspend failed: err: %d\n",
+			       mmc_hostname(host), __func__, ret);
+			return ret;
+		}
+	}
+
+	return ret;
 }
 
 #endif /* !CONFIG_PM_RUNTIME */
@@ -178,6 +195,42 @@
 	SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume)
 };
 
+static ssize_t show_rpm_delay(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct mmc_card *card = mmc_dev_to_card(dev);
+
+	if (!card) {
+		pr_err("%s: %s: card is NULL\n", dev_name(dev), __func__);
+		return -EINVAL;
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", card->idle_timeout);
+}
+
+static ssize_t store_rpm_delay(struct device *dev, struct device_attribute
+			       *attr, const char *buf, size_t count)
+{
+	struct mmc_card *card = mmc_dev_to_card(dev);
+	unsigned int delay;
+
+	if (!card) {
+		pr_err("%s: %s: card is NULL\n", dev_name(dev), __func__);
+		return -EINVAL;
+	}
+
+	if (!kstrtou32(buf, 0, &delay)) {
+		if (delay < 2000) {
+			pr_err("%s: %s: less than 2 sec delay is unsupported\n",
+			       mmc_hostname(card->host), __func__);
+			return -EINVAL;
+		}
+		card->idle_timeout = delay;
+	}
+
+	return count;
+}
+
 static struct bus_type mmc_bus_type = {
 	.name		= "mmc",
 	.dev_attrs	= mmc_dev_attrs,
@@ -330,10 +383,34 @@
 #endif
 	mmc_init_context_info(card->host);
 
+	if (mmc_use_core_runtime_pm(card->host)) {
+		ret = pm_runtime_set_active(&card->dev);
+		if (ret)
+			pr_err("%s: %s: failed setting runtime active: ret: %d\n",
+			       mmc_hostname(card->host), __func__, ret);
+		else
+			pm_runtime_enable(&card->dev);
+	}
+
 	ret = device_add(&card->dev);
 	if (ret)
 		return ret;
 
+	if (mmc_use_core_runtime_pm(card->host)) {
+		card->rpm_attrib.show = show_rpm_delay;
+		card->rpm_attrib.store = store_rpm_delay;
+		sysfs_attr_init(&card->rpm_attrib.attr);
+		card->rpm_attrib.attr.name = "runtime_pm_timeout";
+		card->rpm_attrib.attr.mode = S_IRUGO | S_IWUSR;
+
+		ret = device_create_file(&card->dev, &card->rpm_attrib);
+		if (ret)
+			pr_err("%s: %s: creating runtime pm sysfs entry: failed: %d\n",
+			       mmc_hostname(card->host), __func__, ret);
+		/* Default timeout is 10 seconds */
+		card->idle_timeout = RUNTIME_SUSPEND_DELAY_MS;
+	}
+
 	mmc_card_set_present(card);
 
 	return 0;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index a3c3967..07702b4 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -409,9 +409,12 @@
 		return;
 	}
 
+	mmc_rpm_hold(card->host, &card->dev);
 	/* In case of delayed bkops we might be in race with suspend. */
-	if (!mmc_try_claim_host(card->host))
+	if (!mmc_try_claim_host(card->host)) {
+		mmc_rpm_release(card->host, &card->dev);
 		return;
+	}
 
 	/*
 	 * Since the cancel_delayed_work can be changed while we are waiting
@@ -486,6 +489,7 @@
 
 out:
 	mmc_release_host(card->host);
+	mmc_rpm_release(card->host, &card->dev);
 }
 EXPORT_SYMBOL(mmc_start_bkops);
 
@@ -515,6 +519,7 @@
 	 * the host from getting into suspend
 	 */
 	do {
+		mmc_rpm_hold(card->host, &card->dev);
 		mmc_claim_host(card->host);
 
 		if (!mmc_card_doing_bkops(card))
@@ -541,6 +546,7 @@
 		}
 
 		mmc_release_host(card->host);
+		mmc_rpm_release(card->host, &card->dev);
 
 		/*
 		 * Sleep before checking the card status again to allow the
@@ -559,6 +565,7 @@
 	return;
 out:
 	mmc_release_host(card->host);
+	mmc_rpm_release(card->host, &card->dev);
 }
 
 /**
@@ -2786,8 +2793,9 @@
 	if (!host->card || !host->bus_ops ||
 			!host->bus_ops->change_bus_speed ||
 			!host->clk_scaling.enable || !host->ios.clock)
-		goto out;
+		return;
 
+	mmc_rpm_hold(host, &host->card->dev);
 	if (!mmc_try_claim_host(host)) {
 		/* retry after a timer tick */
 		queue_delayed_work(system_nrt_wq, &host->clk_scaling.work, 1);
@@ -2797,6 +2805,7 @@
 	mmc_clk_scaling(host, true);
 	mmc_release_host(host);
 out:
+	mmc_rpm_release(host, &host->card->dev);
 	return;
 }
 
@@ -3020,16 +3029,8 @@
 	/* Order's important: probe SDIO, then SD, then MMC */
 	if (!mmc_attach_sdio(host))
 		return 0;
-
-	if (!host->ios.vdd)
-		mmc_power_up(host);
-
 	if (!mmc_attach_sd(host))
 		return 0;
-
-	if (!host->ios.vdd)
-		mmc_power_up(host);
-
 	if (!mmc_attach_mmc(host))
 		return 0;
 
@@ -3147,11 +3148,12 @@
 	if (host->ops->get_cd && host->ops->get_cd(host) == 0)
 		goto out;
 
+	mmc_rpm_hold(host, &host->class_dev);
 	mmc_claim_host(host);
 	if (!mmc_rescan_try_freq(host, host->f_min))
 		extend_wakelock = true;
 	mmc_release_host(host);
-
+	mmc_rpm_release(host, &host->class_dev);
  out:
 	if (extend_wakelock)
 		wake_lock_timeout(&host->detect_wake_lock, HZ / 2);
@@ -3374,9 +3376,6 @@
 	if (mmc_bus_needs_resume(host))
 		return 0;
 
-	cancel_delayed_work(&host->detect);
-	mmc_flush_scheduled_work();
-
 	mmc_bus_get(host);
 	if (host->bus_ops && !host->bus_dead) {
 		/*
@@ -3413,7 +3412,6 @@
 				 * It will be redetected on resume.  (Calling
 				 * bus_ops->remove() with a claimed host can
 				 * deadlock.)
-				 * It will be redetected on resume.
 				 */
 				if (host->bus_ops->remove)
 					host->bus_ops->remove(host);
@@ -3588,6 +3586,37 @@
 EXPORT_SYMBOL(mmc_set_embedded_sdio_data);
 #endif
 
+void mmc_rpm_hold(struct mmc_host *host, struct device *dev)
+{
+	int ret = 0;
+
+	if (!mmc_use_core_runtime_pm(host))
+		return;
+
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		pr_err("%s: %s: %s: error resuming device: %d\n",
+		       dev_name(dev), mmc_hostname(host), __func__, ret);
+		if (pm_runtime_suspended(dev))
+			BUG_ON(1);
+	}
+}
+EXPORT_SYMBOL(mmc_rpm_hold);
+
+void mmc_rpm_release(struct mmc_host *host, struct device *dev)
+{
+	int ret = 0;
+
+	if (!mmc_use_core_runtime_pm(host))
+		return;
+
+	ret = pm_runtime_put_sync(dev);
+	if (ret < 0 && ret != -EBUSY)
+		pr_err("%s: %s: %s: put sync ret: %d\n",
+		       dev_name(dev), mmc_hostname(host), __func__, ret);
+}
+EXPORT_SYMBOL(mmc_rpm_release);
+
 /**
  * mmc_init_context_info() - init synchronization context
  * @host: mmc host
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 0cfddc4..0d7d98b 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -21,6 +21,7 @@
 #include <linux/leds.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
@@ -37,9 +38,73 @@
 	kfree(host);
 }
 
+static int mmc_host_runtime_suspend(struct device *dev)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+	int ret = 0;
+
+	ret = mmc_suspend_host(host);
+	if (ret < 0)
+		pr_err("%s: %s: suspend host failed: %d\n", mmc_hostname(host),
+		       __func__, ret);
+
+	return ret;
+}
+
+static int mmc_host_runtime_resume(struct device *dev)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+	int ret = 0;
+
+	ret = mmc_resume_host(host);
+	if (ret < 0) {
+		pr_err("%s: %s: resume host: failed: ret: %d\n",
+		       mmc_hostname(host), __func__, ret);
+		if (pm_runtime_suspended(dev))
+			BUG_ON(1);
+	}
+
+	return ret;
+}
+
+static int mmc_host_suspend(struct device *dev)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+	int ret = 0;
+
+	if (!pm_runtime_suspended(dev)) {
+		ret = mmc_suspend_host(host);
+		if (ret < 0)
+			pr_err("%s: %s: failed: ret: %d\n", mmc_hostname(host),
+			       __func__, ret);
+	}
+	return ret;
+}
+
+static int mmc_host_resume(struct device *dev)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+	int ret = 0;
+
+	if (!pm_runtime_suspended(dev)) {
+		ret = mmc_resume_host(host);
+		if (ret < 0)
+			pr_err("%s: %s: failed: ret: %d\n", mmc_hostname(host),
+			       __func__, ret);
+	}
+	return ret;
+}
+
+static const struct dev_pm_ops mmc_host_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(mmc_host_suspend, mmc_host_resume)
+	SET_RUNTIME_PM_OPS(mmc_host_runtime_suspend, mmc_host_runtime_resume,
+			   pm_generic_runtime_idle)
+};
+
 static struct class mmc_host_class = {
 	.name		= "mmc_host",
 	.dev_release	= mmc_host_classdev_release,
+	.pm		= &mmc_host_pm_ops,
 };
 
 int mmc_register_host_class(void)
@@ -60,8 +125,7 @@
 		struct device_attribute *attr, char *buf)
 {
 	struct mmc_host *host = cls_dev_to_mmc_host(dev);
-	return snprintf(buf, PAGE_SIZE, "%lu\n",
-			host->clkgate_delay);
+	return snprintf(buf, PAGE_SIZE, "%lu\n", host->clkgate_delay);
 }
 
 static ssize_t clkgate_delay_store(struct device *dev,
@@ -76,9 +140,6 @@
 	spin_lock_irqsave(&host->clk_lock, flags);
 	host->clkgate_delay = value;
 	spin_unlock_irqrestore(&host->clk_lock, flags);
-
-	pr_info("%s: clock gate delay set to %lu ms\n",
-			mmc_hostname(host), value);
 	return count;
 }
 
@@ -533,7 +594,7 @@
 static ssize_t
 show_perf(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct mmc_host *host = dev_get_drvdata(dev);
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
 	int64_t rtime_drv, wtime_drv;
 	unsigned long rbytes_drv, wbytes_drv;
 
@@ -559,8 +620,8 @@
 set_perf(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
 	int64_t value;
-	struct mmc_host *host = dev_get_drvdata(dev);
 
 	sscanf(buf, "%lld", &value);
 	spin_lock(&host->lock);
@@ -605,6 +666,14 @@
 	WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
 		!host->ops->enable_sdio_irq);
 
+	if (mmc_use_core_runtime_pm(host)) {
+		err = pm_runtime_set_active(&host->class_dev);
+		if (err)
+			pr_err("%s: %s: failed setting runtime active: err: %d\n",
+			       mmc_hostname(host), __func__, err);
+		else
+			pm_runtime_enable(&host->class_dev);
+	}
 	err = device_add(&host->class_dev);
 	if (err)
 		return err;
@@ -625,7 +694,7 @@
 		pr_err("%s: failed to create clk scale sysfs group with err %d\n",
 				__func__, err);
 
-	err = sysfs_create_group(&host->parent->kobj, &dev_attr_grp);
+	err = sysfs_create_group(&host->class_dev.kobj, &dev_attr_grp);
 	if (err)
 		pr_err("%s: failed to create sysfs group with err %d\n",
 							 __func__, err);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 0e6956f..8a866cf 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -17,6 +17,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/mmc.h>
+#include <linux/pm_runtime.h>
 
 #include "core.h"
 #include "bus.h"
@@ -293,7 +294,7 @@
 
 	card->ext_csd.rev = ext_csd[EXT_CSD_REV];
 	if (card->ext_csd.rev > 7) {
-		printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n",
+		pr_err("%s: unrecognised EXT_CSD revision %d\n",
 			mmc_hostname(card->host), card->ext_csd.rev);
 		err = -EINVAL;
 		goto out;
@@ -1495,6 +1496,7 @@
 	BUG_ON(!host);
 	BUG_ON(!host->card);
 
+	mmc_rpm_hold(host, &host->card->dev);
 	mmc_claim_host(host);
 
 	/*
@@ -1504,6 +1506,13 @@
 
 	mmc_release_host(host);
 
+	/*
+	 * if detect fails, the device would be removed anyway;
+	 * the rpm framework would mark the device state suspended.
+	 */
+	if (!err)
+		mmc_rpm_release(host, &host->card->dev);
+
 	if (err) {
 		mmc_remove(host);
 
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 318d590..dc129f7 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -18,6 +18,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sd.h>
+#include <linux/pm_runtime.h>
 
 #include "core.h"
 #include "bus.h"
@@ -944,9 +945,9 @@
 		int ro = -1;
 
 		if (host->ops->get_ro) {
-			mmc_host_clk_hold(host);
+			mmc_host_clk_hold(card->host);
 			ro = host->ops->get_ro(host);
-			mmc_host_clk_release(host);
+			mmc_host_clk_release(card->host);
 		}
 
 		if (ro < 0) {
@@ -1067,9 +1068,9 @@
 		 * value registers for UHS-I cards.
 		 */
 		if (host->ops->enable_preset_value) {
-			mmc_host_clk_hold(host);
+			mmc_host_clk_hold(card->host);
 			host->ops->enable_preset_value(host, true);
-			mmc_host_clk_release(host);
+			mmc_host_clk_release(card->host);
 		}
 	} else {
 		/*
@@ -1145,7 +1146,8 @@
 
 	BUG_ON(!host);
 	BUG_ON(!host->card);
-       
+
+	mmc_rpm_hold(host, &host->card->dev);
 	mmc_claim_host(host);
 
 	/*
@@ -1170,6 +1172,13 @@
 #endif
 	mmc_release_host(host);
 
+	/*
+	 * if detect fails, the device would be removed anyway;
+	 * the rpm framework would mark the device state suspended.
+	 */
+	if (!err)
+		mmc_rpm_release(host, &host->card->dev);
+
 	if (err) {
 		mmc_sd_remove(host);
 
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 1c4697d..56d4499 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1389,8 +1389,6 @@
 			dto -= 13;
 		else
 			dto = 0;
-		/* Use the maximum timeout value allowed in the standard of 14
-		   or 0xE */
 		if (dto > 14)
 			dto = 14;
 	}
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 27e6c79..7bae401 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -32,6 +32,9 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/mmc/mmc.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/mmc/cd-gpio.h>
 #include <mach/gpio.h>
 #include <mach/msm_bus.h>
 
@@ -200,6 +203,7 @@
 	bool nonremovable;
 	struct sdhci_msm_pin_data *pin_data;
 	u32 cpu_dma_latency_us;
+	int status_gpio; /* card detection GPIO that is configured as IRQ */
 	struct sdhci_msm_bus_voting_data *voting_data;
 };
 
@@ -216,6 +220,7 @@
 struct sdhci_msm_host {
 	struct platform_device	*pdev;
 	void __iomem *core_mem;    /* MSM SDCC mapped address */
+	int	pwr_irq;	/* power irq */
 	struct clk	 *clk;     /* main SD/MMC bus clock */
 	struct clk	 *pclk;    /* SDHC peripheral bus clock */
 	struct clk	 *bus_clk; /* SDHC bus voter clock */
@@ -1075,6 +1080,8 @@
 		goto out;
 	}
 
+	pdata->status_gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, 0);
+
 	of_property_read_u32(np, "qcom,bus-width", &bus_width);
 	if (bus_width == 8)
 		pdata->mmc_bus_width = MMC_CAP_8_BIT_DATA;
@@ -1864,7 +1871,7 @@
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_msm_host *msm_host;
 	struct resource *core_memres = NULL;
-	int ret = 0, pwr_irq = 0, dead = 0;
+	int ret = 0, dead = 0;
 	u32 vdd_max_current;
 	u32 host_version;
 
@@ -1987,18 +1994,18 @@
 	}
 
 	/* Setup PWRCTL irq */
-	pwr_irq = platform_get_irq_byname(pdev, "pwr_irq");
-	if (pwr_irq < 0) {
+	msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq");
+	if (msm_host->pwr_irq < 0) {
 		dev_err(&pdev->dev, "Failed to get pwr_irq by name (%d)\n",
-				pwr_irq);
+				msm_host->pwr_irq);
 		goto vreg_deinit;
 	}
-	ret = devm_request_threaded_irq(&pdev->dev, pwr_irq, NULL,
+	ret = devm_request_threaded_irq(&pdev->dev, msm_host->pwr_irq, NULL,
 					sdhci_msm_pwr_irq, IRQF_ONESHOT,
 					dev_name(&pdev->dev), host);
 	if (ret) {
 		dev_err(&pdev->dev, "Request threaded irq(%d) failed (%d)\n",
-				pwr_irq, ret);
+				msm_host->pwr_irq, ret);
 		goto vreg_deinit;
 	}
 
@@ -2029,6 +2036,7 @@
 
 	msm_host->mmc->caps |= MMC_CAP_HW_RESET;
 	msm_host->mmc->caps2 |= msm_host->pdata->caps2;
+	msm_host->mmc->caps2 |= MMC_CAP2_CORE_RUNTIME_PM;
 	msm_host->mmc->caps2 |= MMC_CAP2_PACKED_WR;
 	msm_host->mmc->caps2 |= MMC_CAP2_PACKED_WR_CONTROL;
 	msm_host->mmc->caps2 |= (MMC_CAP2_BOOTPART_NOACC |
@@ -2051,10 +2059,20 @@
 		INIT_DELAYED_WORK(&msm_host->msm_bus_vote.vote_work,
 				  sdhci_msm_bus_work);
 
+	if (gpio_is_valid(msm_host->pdata->status_gpio)) {
+		ret = mmc_cd_gpio_request(msm_host->mmc,
+				msm_host->pdata->status_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to request card detection IRQ %d\n",
+					__func__, ret);
+			goto bus_unregister;
+		}
+	}
+
 	ret = sdhci_add_host(host);
 	if (ret) {
 		dev_err(&pdev->dev, "Add host failed (%d)\n", ret);
-		goto bus_unregister;
+		goto free_cd_gpio;
 	}
 
 	 /* Set core clk rate, optionally override from dts */
@@ -2076,12 +2094,22 @@
 	if (ret)
 		goto remove_host;
 
+	ret = pm_runtime_set_active(&pdev->dev);
+	if (ret)
+		pr_err("%s: %s: pm_runtime_set_active failed: err: %d\n",
+		       mmc_hostname(host->mmc), __func__, ret);
+	else
+		pm_runtime_enable(&pdev->dev);
+
 	/* Successful initialization */
 	goto out;
 
 remove_host:
 	dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
 	sdhci_remove_host(host, dead);
+free_cd_gpio:
+	if (gpio_is_valid(msm_host->pdata->status_gpio))
+		mmc_cd_gpio_free(msm_host->mmc);
 bus_unregister:
 	sdhci_msm_bus_unregister(msm_host);
 vreg_deinit:
@@ -2114,7 +2142,12 @@
 	pr_debug("%s: %s\n", dev_name(&pdev->dev), __func__);
 	device_remove_file(&pdev->dev, &msm_host->msm_bus_vote.max_bus_bw);
 	sdhci_remove_host(host, dead);
+	pm_runtime_disable(&pdev->dev);
 	sdhci_pltfm_free(pdev);
+
+	if (gpio_is_valid(msm_host->pdata->status_gpio))
+		mmc_cd_gpio_free(msm_host->mmc);
+
 	sdhci_msm_vreg_init(&pdev->dev, msm_host->pdata, false);
 
 	if (pdata->pin_data)
@@ -2127,6 +2160,92 @@
 	return 0;
 }
 
+static int sdhci_msm_runtime_suspend(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+
+	disable_irq(host->irq);
+	disable_irq(msm_host->pwr_irq);
+
+	return 0;
+}
+
+static int sdhci_msm_runtime_resume(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+
+	enable_irq(msm_host->pwr_irq);
+	enable_irq(host->irq);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int sdhci_msm_suspend(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	int ret = 0;
+
+	if (gpio_is_valid(msm_host->pdata->status_gpio))
+		mmc_cd_gpio_free(msm_host->mmc);
+
+	if (pm_runtime_suspended(dev)) {
+		pr_debug("%s: %s: already runtime suspended\n",
+		mmc_hostname(host->mmc), __func__);
+		goto out;
+	}
+
+	return sdhci_msm_runtime_suspend(dev);
+out:
+	return ret;
+}
+
+static int sdhci_msm_resume(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	int ret = 0;
+
+	if (gpio_is_valid(msm_host->pdata->status_gpio)) {
+		ret = mmc_cd_gpio_request(msm_host->mmc,
+				msm_host->pdata->status_gpio);
+		if (ret)
+			pr_err("%s: %s: Failed to request card detection IRQ %d\n",
+					mmc_hostname(host->mmc), __func__, ret);
+	}
+
+	if (pm_runtime_suspended(dev)) {
+		pr_debug("%s: %s: runtime suspended, defer system resume\n",
+		mmc_hostname(host->mmc), __func__);
+		goto out;
+	}
+
+	return sdhci_msm_runtime_resume(dev);
+out:
+	return ret;
+}
+#endif
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops sdhci_msm_pmops = {
+	SET_SYSTEM_SLEEP_PM_OPS(sdhci_msm_suspend, sdhci_msm_resume)
+	SET_RUNTIME_PM_OPS(sdhci_msm_runtime_suspend, sdhci_msm_runtime_resume,
+			   NULL)
+};
+
+#define SDHCI_MSM_PMOPS (&sdhci_msm_pmops)
+
+#else
+#define SDHCI_PM_OPS NULL
+#endif
 static const struct of_device_id sdhci_msm_dt_match[] = {
 	{.compatible = "qcom,sdhci-msm"},
 };
@@ -2139,6 +2258,7 @@
 		.name	= "sdhci_msm",
 		.owner	= THIS_MODULE,
 		.of_match_table = sdhci_msm_dt_match,
+		.pm = SDHCI_MSM_PMOPS,
 	},
 };
 
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index e7a3741..69ef0be 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -23,9 +23,8 @@
 #include <linux/scatterlist.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
-#include <linux/mmc/sdhci-pci-data.h>
-#include <linux/sfi.h>
 #include <linux/pm_runtime.h>
+#include <linux/mmc/sdhci-pci-data.h>
 
 #include "sdhci.h"
 
@@ -368,8 +367,6 @@
 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
 	}
 
-	slot->host->mmc->caps2 = MMC_CAP2_BOOTPART_NOACC;
-
 	return 0;
 }
 
@@ -1452,8 +1449,6 @@
 	int i;
 	struct sdhci_pci_chip *chip;
 
-	sdhci_pci_runtime_pm_forbid(&pdev->dev);
-
 	chip = pci_get_drvdata(pdev);
 
 	if (chip) {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 97c1013..0a89ea2 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -453,6 +453,44 @@
 	dataddr[0] = cpu_to_le32(addr);
 }
 
+static int sdhci_pre_dma_transfer(struct sdhci_host *host,
+				  struct mmc_data *data,
+				  struct sdhci_next *next)
+{
+	int sg_count;
+
+	if (!next && data->host_cookie &&
+	    data->host_cookie != host->next_data.cookie) {
+		printk(KERN_WARNING "[%s] invalid cookie: data->host_cookie %d"
+		       " host->next_data.cookie %d\n",
+		       __func__, data->host_cookie, host->next_data.cookie);
+		data->host_cookie = 0;
+	}
+
+	/* Check if next job is already prepared */
+	if (next ||
+	    (!next && data->host_cookie != host->next_data.cookie)) {
+		sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg,
+				      data->sg_len,
+				      (data->flags & MMC_DATA_WRITE) ?
+				      DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	} else {
+		sg_count = host->next_data.sg_count;
+		host->next_data.sg_count = 0;
+	}
+
+	if (sg_count == 0)
+		return -EINVAL;
+
+	if (next) {
+		next->sg_count = sg_count;
+		data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie;
+	} else
+		host->sg_count = sg_count;
+
+	return sg_count;
+}
+
 static int sdhci_adma_table_pre(struct sdhci_host *host,
 	struct mmc_data *data)
 {
@@ -491,9 +529,8 @@
 		goto fail;
 	BUG_ON(host->align_addr & 0x3);
 
-	host->sg_count = dma_map_sg(mmc_dev(host->mmc),
-		data->sg, data->sg_len, direction);
-	if (host->sg_count == 0)
+	host->sg_count = sdhci_pre_dma_transfer(host, data, NULL);
+	if (host->sg_count < 0)
 		goto unmap_align;
 
 	desc = host->adma_desc;
@@ -638,8 +675,9 @@
 		}
 	}
 
-	dma_unmap_sg(mmc_dev(host->mmc), data->sg,
-		data->sg_len, direction);
+	if (!data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     direction);
 }
 
 static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
@@ -819,11 +857,7 @@
 		} else {
 			int sg_cnt;
 
-			sg_cnt = dma_map_sg(mmc_dev(host->mmc),
-					data->sg, data->sg_len,
-					(data->flags & MMC_DATA_READ) ?
-						DMA_FROM_DEVICE :
-						DMA_TO_DEVICE);
+			sg_cnt = sdhci_pre_dma_transfer(host, data, NULL);
 			if (sg_cnt == 0) {
 				/*
 				 * This only happens when someone fed
@@ -927,9 +961,11 @@
 		if (host->flags & SDHCI_USE_ADMA)
 			sdhci_adma_table_post(host, data);
 		else {
-			dma_unmap_sg(mmc_dev(host->mmc), data->sg,
-				data->sg_len, (data->flags & MMC_DATA_READ) ?
-					DMA_FROM_DEVICE : DMA_TO_DEVICE);
+			if (!data->host_cookie)
+				dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+					     data->sg_len,
+					     (data->flags & MMC_DATA_READ) ?
+					     DMA_FROM_DEVICE : DMA_TO_DEVICE);
 		}
 	}
 
@@ -1304,6 +1340,35 @@
 	return 0;
 }
 
+static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+			  bool is_first_req)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+
+	if (mrq->data->host_cookie) {
+		mrq->data->host_cookie = 0;
+		return;
+	}
+
+	if (host->flags & SDHCI_REQ_USE_DMA)
+		if (sdhci_pre_dma_transfer(host, mrq->data, &host->next_data) < 0)
+			mrq->data->host_cookie = 0;
+}
+
+static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
+			   int err)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+
+	if (host->flags & SDHCI_REQ_USE_DMA) {
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     (data->flags & MMC_DATA_WRITE) ?
+			     DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		data->host_cookie = 0;
+	}
+}
+
 static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct sdhci_host *host;
@@ -2016,6 +2081,8 @@
 }
 
 static const struct mmc_host_ops sdhci_ops = {
+	.pre_req	= sdhci_pre_req,
+	.post_req	= sdhci_post_req,
 	.request	= sdhci_request,
 	.set_ios	= sdhci_set_ios,
 	.get_ro		= sdhci_get_ro,
@@ -2598,13 +2665,20 @@
 
 static int sdhci_runtime_pm_get(struct sdhci_host *host)
 {
-	return pm_runtime_get_sync(host->mmc->parent);
+	if (!mmc_use_core_runtime_pm(host->mmc))
+		return pm_runtime_get_sync(host->mmc->parent);
+	else
+		return 0;
 }
 
 static int sdhci_runtime_pm_put(struct sdhci_host *host)
 {
-	pm_runtime_mark_last_busy(host->mmc->parent);
-	return pm_runtime_put_autosuspend(host->mmc->parent);
+	if (!mmc_use_core_runtime_pm(host->mmc)) {
+		pm_runtime_mark_last_busy(host->mmc->parent);
+		return pm_runtime_put_autosuspend(host->mmc->parent);
+	} else {
+		return 0;
+	}
 }
 
 int sdhci_runtime_suspend_host(struct sdhci_host *host)
@@ -2805,6 +2879,8 @@
 		}
 	}
 
+	host->next_data.cookie = 1;
+
 	/*
 	 * If we use DMA, then it's up to the caller to set the DMA
 	 * mask, but PIO does not need the hw shim so we set a new
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 4f96a69..fa84e37 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -538,17 +538,6 @@
 	ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
 			 AR_WA_ASPM_TIMER_BASED_DISABLE);
 
-	/*
-	 * Read back AR_WA into a permanent copy and set bits 14 and 17.
-	 * We need to do this to avoid RMW of this register. We cannot
-	 * read the reg when chip is asleep.
-	 */
-	ah->WARegVal = REG_READ(ah, AR_WA);
-	ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
-			 AR_WA_ASPM_TIMER_BASED_DISABLE);
-
-	ath9k_hw_read_revisions(ah);
-
 	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
 		ath_err(common, "Couldn't reset chip\n");
 		return -EIO;
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 740f09b..cb00645 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -621,10 +621,8 @@
 static void ath9k_init_txpower_limits(struct ath_softc *sc)
 {
 	struct ath_hw *ah = sc->sc_ah;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath9k_channel *curchan = ah->curchan;
 
-	ah->txchainmask = common->tx_chainmask;
 	if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
 		ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
 	if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 5e66310..77dc327 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -148,31 +148,6 @@
 	}
 }
 
-static void ath_pci_aspm_init(struct ath_common *common)
-{
-	struct ath_softc *sc = (struct ath_softc *) common->priv;
-	struct ath_hw *ah = sc->sc_ah;
-	struct pci_dev *pdev = to_pci_dev(sc->dev);
-	struct pci_dev *parent;
-	int pos;
-	u8 aspm;
-
-	if (!pci_is_pcie(pdev))
-		return;
-
-	parent = pdev->bus->self;
-	if (WARN_ON(!parent))
-		return;
-
-	pos = pci_pcie_cap(parent);
-	pci_read_config_byte(parent, pos +  PCI_EXP_LNKCTL, &aspm);
-	if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
-		ah->aspm_enabled = true;
-		/* Initialize PCIe PM and SERDES registers. */
-		ath9k_hw_configpcipowersave(ah, 0, 0);
-	}
-}
-
 static const struct ath_bus_ops ath_pci_bus_ops = {
 	.ath_bus_type = ATH_PCI,
 	.read_cachesize = ath_pci_read_cachesize,
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 0cd9f47..e4d6dc2 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2527,13 +2527,6 @@
 		b43_print_fw_helptext(dev->wl, 1);
 		err = -EOPNOTSUPP;
 		goto error;
-	} else if (fwrev >= 598) {
-		b43err(dev->wl, "YOUR FIRMWARE IS TOO NEW. Support for "
-		       "firmware 598 and up requires kernel 3.2 or newer. You "
-		       "have to install older firmware or upgrade kernel.\n");
-		b43_print_fw_helptext(dev->wl, 1);
-		err = -EOPNOTSUPP;
-		goto error;
 	}
 	dev->fw.rev = fwrev;
 	dev->fw.patch = fwpatch;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 826dd3e..2e1a317 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -551,9 +551,6 @@
 
 	mutex_lock(&priv->mutex);
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		goto out;
-
 	if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
 		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
 		goto out;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
index 4763426..506b9a0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
@@ -104,7 +104,7 @@
 			tx_agc[RF90_PATH_A] = 0x10101010;
 			tx_agc[RF90_PATH_B] = 0x10101010;
 		} else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
-			   TXHIGHPWRLEVEL_LEVEL2) {
+			   TXHIGHPWRLEVEL_LEVEL1) {
 			tx_agc[RF90_PATH_A] = 0x00000000;
 			tx_agc[RF90_PATH_B] = 0x00000000;
 		} else{
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 46b4651..88e8d43 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -91,6 +91,16 @@
 	  in the kernel log along with the PMIC option status. The PMIC
 	  type is mapped to a Qualcomm chip part number and logged as well.
 
+config QPNP_COINCELL
+	tristate "Qualcomm QPNP coincell charger support"
+	depends on SPMI && OF_SPMI
+	help
+	  This driver supports the QPNP coincell peripheral found inside of
+	  Qualcomm QPNP PMIC devices.  The coincell charger provides a means to
+	  charge a coincell battery or backup capacitor which is used to
+	  maintain PMIC register state when the main battery is removed from the
+	  mobile device.
+
 config IPA
 	tristate "IPA support"
 	depends on SPS
diff --git a/drivers/platform/msm/Makefile b/drivers/platform/msm/Makefile
index 6b9c5ad..efb78e5 100644
--- a/drivers/platform/msm/Makefile
+++ b/drivers/platform/msm/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_QPNP_POWER_ON) += qpnp-power-on.o
 obj-$(CONFIG_QPNP_VIBRATOR) += qpnp-vibrator.o
 obj-$(CONFIG_QPNP_CLKDIV) += qpnp-clkdiv.o
+obj-$(CONFIG_QPNP_COINCELL) += qpnp-coincell.o
 obj-$(CONFIG_MSM_AVTIMER) += avtimer.o
 obj-$(CONFIG_SSM) += ssm.o
 obj-$(CONFIG_QPNP_REVID) += qpnp-revid.o
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index 1142094..42a0016 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -1919,22 +1919,26 @@
 	ipa_ctx->aggregation_byte_limit = 1;
 	ipa_ctx->aggregation_time_limit = 0;
 
-	/* Initialize IPA RM (resource manager) */
-	result = ipa_rm_initialize();
-	if (result) {
-		IPAERR(":cdev_add err=%d\n", -result);
-		result = -ENODEV;
-		goto fail_ipa_rm_init;
+	if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_PCIE) {
+		/* Initialize IPA RM (resource manager) */
+		result = ipa_rm_initialize();
+		if (result) {
+			IPAERR(":cdev_add err=%d\n", -result);
+			result = -ENODEV;
+			goto fail_ipa_rm_init;
+		}
 	}
 
-	a2_mux_init();
+	if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_NORMAL) {
+		a2_mux_init();
 
-	/* Initialize the tethering bridge driver */
-	result = teth_bridge_driver_init();
-	if (result) {
-		IPAERR(":teth_bridge_driver_init() failed\n");
-		result = -ENODEV;
-		goto fail_cdev_add;
+		/* Initialize the tethering bridge driver */
+		result = teth_bridge_driver_init();
+		if (result) {
+			IPAERR(":teth_bridge_driver_init() failed\n");
+			result = -ENODEV;
+			goto fail_cdev_add;
+		}
 	}
 
 	/* gate IPA clocks */
diff --git a/drivers/platform/msm/ipa/teth_bridge.c b/drivers/platform/msm/ipa/teth_bridge.c
index 76e2eee..29253cd 100644
--- a/drivers/platform/msm/ipa/teth_bridge.c
+++ b/drivers/platform/msm/ipa/teth_bridge.c
@@ -69,6 +69,11 @@
 	bool device_mac_addr_known;
 };
 
+struct stats {
+	u64 a2_to_usb_num_sw_tx_packets;
+	u64 usb_to_a2_num_sw_tx_packets;
+};
+
 struct teth_bridge_ctx {
 	struct class *class;
 	dev_t dev_num;
@@ -90,6 +95,7 @@
 	struct work_struct comp_hw_bridge_work;
 	bool comp_hw_bridge_in_progress;
 	struct teth_aggr_capabilities *aggr_caps;
+	struct stats stats;
 };
 
 static struct teth_bridge_ctx *teth_ctx;
@@ -806,6 +812,7 @@
 				&teth_ctx->mac_addresses.device_mac_addr_known);
 
 		/* Send the packet to A2, using a2_service driver API */
+		teth_ctx->stats.usb_to_a2_num_sw_tx_packets++;
 		res = a2_mux_write(A2_MUX_TETHERED_0, skb);
 		if (res) {
 			TETH_ERR("Packet send failure, dropping packet !\n");
@@ -843,6 +850,7 @@
 				mac_addresses.host_pc_mac_addr_known);
 
 		/* Send the packet to USB */
+		teth_ctx->stats.a2_to_usb_num_sw_tx_packets++;
 		res = ipa_tx_dp(IPA_CLIENT_USB_CONS, skb, NULL);
 		if (res) {
 			TETH_ERR("Packet send failure, dropping packet !\n");
@@ -1216,6 +1224,8 @@
 static struct dentry *dfile_link_protocol;
 static struct dentry *dfile_get_aggr_params;
 static struct dentry *dfile_set_aggr_protocol;
+static struct dentry *dfile_stats;
+static struct dentry *dfile_is_hw_bridge_complete;
 
 static ssize_t teth_debugfs_read_link_protocol(struct file *file,
 					       char __user *ubuf,
@@ -1351,6 +1361,43 @@
 	return count;
 }
 
+static ssize_t teth_debugfs_stats(struct file *file,
+				  char __user *ubuf,
+				  size_t count,
+				  loff_t *ppos)
+{
+	int nbytes = 0;
+
+	nbytes += scnprintf(&dbg_buff[nbytes],
+			    TETH_MAX_MSG_LEN - nbytes,
+			   "USB to A2 SW Tx packets: %lld\n",
+			    teth_ctx->stats.usb_to_a2_num_sw_tx_packets);
+	nbytes += scnprintf(&dbg_buff[nbytes],
+			    TETH_MAX_MSG_LEN - nbytes,
+			   "A2 to USB SW Tx packets: %lld\n",
+			    teth_ctx->stats.a2_to_usb_num_sw_tx_packets);
+	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
+static ssize_t teth_debugfs_hw_bridge_status(struct file *file,
+					     char __user *ubuf,
+					     size_t count,
+					     loff_t *ppos)
+{
+	int nbytes = 0;
+
+	if (teth_ctx->is_hw_bridge_complete)
+		nbytes += scnprintf(&dbg_buff[nbytes],
+				    TETH_MAX_MSG_LEN - nbytes,
+				   "HW bridge is in use.\n");
+	else
+		nbytes += scnprintf(&dbg_buff[nbytes],
+				    TETH_MAX_MSG_LEN - nbytes,
+				   "SW bridge is in use. HW bridge not complete yet.\n");
+
+	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
 const struct file_operations teth_link_protocol_ops = {
 	.read = teth_debugfs_read_link_protocol,
 	.write = teth_debugfs_write_link_protocol,
@@ -1364,6 +1411,14 @@
 	.write = teth_debugfs_set_aggr_protocol,
 };
 
+const struct file_operations teth_stats_ops = {
+	.read = teth_debugfs_stats,
+};
+
+const struct file_operations teth_hw_bridge_status_ops = {
+	.read = teth_debugfs_hw_bridge_status,
+};
+
 void teth_debugfs_init(void)
 {
 	const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH;
@@ -1400,6 +1455,23 @@
 		goto fail;
 	}
 
+	dfile_stats =
+		debugfs_create_file("stats", read_only_mode, dent,
+				    0, &teth_stats_ops);
+	if (!dfile_stats || IS_ERR(dfile_stats)) {
+		IPAERR("fail to create file stats\n");
+		goto fail;
+	}
+
+	dfile_is_hw_bridge_complete =
+		debugfs_create_file("is_hw_bridge_complete", read_only_mode,
+				    dent, 0, &teth_hw_bridge_status_ops);
+	if (!dfile_is_hw_bridge_complete ||
+	    IS_ERR(dfile_is_hw_bridge_complete)) {
+		IPAERR("fail to create file is_hw_bridge_complete\n");
+		goto fail;
+	}
+
 	return;
 fail:
 	debugfs_remove_recursive(dent);
diff --git a/drivers/platform/msm/qpnp-coincell.c b/drivers/platform/msm/qpnp-coincell.c
new file mode 100644
index 0000000..e08fd7d
--- /dev/null
+++ b/drivers/platform/msm/qpnp-coincell.c
@@ -0,0 +1,266 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#define QPNP_COINCELL_DRIVER_NAME "qcom,qpnp-coincell"
+
+struct qpnp_coincell {
+	struct spmi_device	*spmi_dev;
+	u16			base_addr;
+};
+
+#define QPNP_COINCELL_REG_TYPE		0x04
+#define QPNP_COINCELL_REG_SUBTYPE	0x05
+#define QPNP_COINCELL_REG_RSET		0x44
+#define QPNP_COINCELL_REG_VSET		0x45
+#define QPNP_COINCELL_REG_ENABLE	0x46
+
+#define QPNP_COINCELL_TYPE		0x02
+#define QPNP_COINCELL_SUBTYPE		0x20
+#define QPNP_COINCELL_ENABLE		0x80
+#define QPNP_COINCELL_DISABLE		0x00
+
+static const int qpnp_rset_map[] = {2100, 1700, 1200, 800};
+static const int qpnp_vset_map[] = {2500, 3200, 3100, 3000};
+
+static int qpnp_coincell_set_resistance(struct qpnp_coincell *chip, int rset)
+{
+	int i, rc;
+	u8 reg;
+
+	for (i = 0; i < ARRAY_SIZE(qpnp_rset_map); i++)
+		if (rset == qpnp_rset_map[i])
+			break;
+
+	if (i >= ARRAY_SIZE(qpnp_rset_map)) {
+		pr_err("invalid rset=%d value\n", rset);
+		return -EINVAL;
+	}
+
+	reg = i;
+	rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+		chip->base_addr + QPNP_COINCELL_REG_RSET, &reg, 1);
+	if (rc)
+		dev_err(&chip->spmi_dev->dev, "%s: could not write to RSET register, rc=%d\n",
+			__func__, rc);
+
+	return rc;
+}
+
+static int qpnp_coincell_set_voltage(struct qpnp_coincell *chip, int vset)
+{
+	int i, rc;
+	u8 reg;
+
+	for (i = 0; i < ARRAY_SIZE(qpnp_vset_map); i++)
+		if (vset == qpnp_vset_map[i])
+			break;
+
+	if (i >= ARRAY_SIZE(qpnp_vset_map)) {
+		pr_err("invalid vset=%d value\n", vset);
+		return -EINVAL;
+	}
+
+	reg = i;
+	rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+		chip->base_addr + QPNP_COINCELL_REG_VSET, &reg, 1);
+	if (rc)
+		dev_err(&chip->spmi_dev->dev, "%s: could not write to VSET register, rc=%d\n",
+			__func__, rc);
+
+	return rc;
+}
+
+static int qpnp_coincell_set_charge(struct qpnp_coincell *chip, bool enabled)
+{
+	int rc;
+	u8 reg;
+
+	reg = enabled ? QPNP_COINCELL_ENABLE : QPNP_COINCELL_DISABLE;
+	rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+		chip->base_addr + QPNP_COINCELL_REG_ENABLE, &reg, 1);
+	if (rc)
+		dev_err(&chip->spmi_dev->dev, "%s: could not write to ENABLE register, rc=%d\n",
+			__func__, rc);
+
+	return rc;
+}
+
+static void qpnp_coincell_charger_show_state(struct qpnp_coincell *chip)
+{
+	int rc, rset, vset, temp;
+	bool enabled;
+	u8 reg[QPNP_COINCELL_REG_ENABLE - QPNP_COINCELL_REG_RSET + 1];
+
+	rc = spmi_ext_register_readl(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+		chip->base_addr + QPNP_COINCELL_REG_RSET, reg, ARRAY_SIZE(reg));
+	if (rc) {
+		dev_err(&chip->spmi_dev->dev, "%s: could not read RSET register, rc=%d\n",
+			__func__, rc);
+		return;
+	}
+
+	temp = reg[QPNP_COINCELL_REG_RSET - QPNP_COINCELL_REG_RSET];
+	if (temp >= ARRAY_SIZE(qpnp_rset_map)) {
+		dev_err(&chip->spmi_dev->dev, "unknown RSET=0x%02X register value\n",
+			temp);
+		return;
+	}
+	rset = qpnp_rset_map[temp];
+
+	temp = reg[QPNP_COINCELL_REG_VSET - QPNP_COINCELL_REG_RSET];
+	if (temp >= ARRAY_SIZE(qpnp_vset_map)) {
+		dev_err(&chip->spmi_dev->dev, "unknown VSET=0x%02X register value\n",
+			temp);
+		return;
+	}
+	vset = qpnp_vset_map[temp];
+
+	temp = reg[QPNP_COINCELL_REG_ENABLE - QPNP_COINCELL_REG_RSET];
+	enabled = temp & QPNP_COINCELL_ENABLE;
+
+	pr_info("enabled=%c, voltage=%d mV, resistance=%d ohm\n",
+		(enabled ? 'Y' : 'N'), vset, rset);
+}
+
+static int qpnp_coincell_check_type(struct qpnp_coincell *chip)
+{
+	int rc;
+	u8 type[2];
+
+	rc = spmi_ext_register_readl(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+		chip->base_addr + QPNP_COINCELL_REG_TYPE, type, 2);
+	if (rc) {
+		dev_err(&chip->spmi_dev->dev, "%s: could not read type register, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	if (type[0] != QPNP_COINCELL_TYPE || type[1] != QPNP_COINCELL_SUBTYPE) {
+		dev_err(&chip->spmi_dev->dev, "%s: invalid type=0x%02X or subtype=0x%02X register value\n",
+			__func__, type[0], type[1]);
+		return -ENODEV;
+	}
+
+	return rc;
+}
+
+static int qpnp_coincell_probe(struct spmi_device *spmi)
+{
+	struct device_node *node = spmi->dev.of_node;
+	struct qpnp_coincell *chip;
+	struct resource *res;
+	u32 temp;
+	int rc = 0;
+
+	if (!node) {
+		dev_err(&spmi->dev, "%s: device node missing\n", __func__);
+		return -ENODEV;
+	}
+
+	chip = devm_kzalloc(&spmi->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip) {
+		dev_err(&spmi->dev, "%s: cannot allocate qpnp_coincell\n",
+			__func__);
+		return -ENOMEM;
+	}
+	chip->spmi_dev = spmi;
+
+	res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&spmi->dev, "%s: node is missing base address\n",
+			__func__);
+		return -EINVAL;
+	}
+	chip->base_addr = res->start;
+
+	rc = qpnp_coincell_check_type(chip);
+	if (rc)
+		return rc;
+
+	rc = of_property_read_u32(node, "qcom,rset-ohms", &temp);
+	if (!rc) {
+		rc = qpnp_coincell_set_resistance(chip, temp);
+		if (rc)
+			return rc;
+	}
+
+	rc = of_property_read_u32(node, "qcom,vset-millivolts", &temp);
+	if (!rc) {
+		rc = qpnp_coincell_set_voltage(chip, temp);
+		if (rc)
+			return rc;
+	}
+
+	rc = of_property_read_u32(node, "qcom,charge-enable", &temp);
+	if (!rc) {
+		rc = qpnp_coincell_set_charge(chip, temp);
+		if (rc)
+			return rc;
+	}
+
+	qpnp_coincell_charger_show_state(chip);
+
+	return 0;
+}
+
+static int __devexit qpnp_coincell_remove(struct spmi_device *spmi)
+{
+	return 0;
+}
+
+static struct of_device_id qpnp_coincell_match_table[] = {
+	{ .compatible = QPNP_COINCELL_DRIVER_NAME, },
+	{}
+};
+
+static const struct spmi_device_id qpnp_coincell_id[] = {
+	{ QPNP_COINCELL_DRIVER_NAME, 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(spmi, qpnp_coincell_id);
+
+static struct spmi_driver qpnp_coincell_driver = {
+	.driver	= {
+		.name		= QPNP_COINCELL_DRIVER_NAME,
+		.of_match_table	= qpnp_coincell_match_table,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= qpnp_coincell_probe,
+	.remove		= __devexit_p(qpnp_coincell_remove),
+	.id_table	= qpnp_coincell_id,
+};
+
+static int __init qpnp_coincell_init(void)
+{
+	return spmi_driver_register(&qpnp_coincell_driver);
+}
+
+static void __exit qpnp_coincell_exit(void)
+{
+	spmi_driver_unregister(&qpnp_coincell_driver);
+}
+
+MODULE_DESCRIPTION("QPNP PMIC coincell charger driver");
+MODULE_LICENSE("GPL v2");
+
+module_init(qpnp_coincell_init);
+module_exit(qpnp_coincell_exit);
diff --git a/drivers/platform/msm/ssm.c b/drivers/platform/msm/ssm.c
index c57bb91..3afb954 100644
--- a/drivers/platform/msm/ssm.c
+++ b/drivers/platform/msm/ssm.c
@@ -66,7 +66,7 @@
 	struct device *dev;
 	smd_channel_t *ch;
 	ion_phys_addr_t buff_phys;
-	ion_virt_addr_t buff_virt;
+	void *buff_virt;
 	dev_t ssm_device_no;
 	struct work_struct ipc_work;
 	struct mutex mutex;
@@ -401,7 +401,7 @@
 	const struct elf32_phdr *phdr;
 	struct ion_handle *ion_handle;
 	ion_phys_addr_t buff_phys;
-	ion_virt_addr_t buff_virt;
+	void *buff_virt;
 
 	/* Check if TZ app already loaded */
 	app_req.cmd_id = APP_LOOKUP_COMMAND;
@@ -509,8 +509,7 @@
 		goto ion_free;
 	}
 
-	buff_virt =
-		(ion_virt_addr_t)ion_map_kernel(ssm_drv->ssm_ion_client,
+	buff_virt = ion_map_kernel(ssm_drv->ssm_ion_client,
 				ion_handle);
 	if (IS_ERR_OR_NULL((void *)buff_virt)) {
 		rc = PTR_ERR((void *)buff_virt);
@@ -605,8 +604,7 @@
 		goto ion_free;
 	}
 
-	ssm->buff_virt =
-		(ion_virt_addr_t)ion_map_kernel(ssm->ssm_ion_client,
+	ssm->buff_virt = ion_map_kernel(ssm->ssm_ion_client,
 				ssm->ssm_ion_handle);
 	if (IS_ERR_OR_NULL((void *)ssm->buff_virt)) {
 		rc = PTR_ERR((void *)ssm->buff_virt);
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index bc2e2ae..0d161b7 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -432,6 +432,7 @@
 	tristate "QPNP Charger driver"
 	depends on SPMI
 	depends on OF_SPMI
+	depends on THERMAL_QPNP_ADC_TM
 	help
 	  Say Y here to enable the switch mode battery charger
 	  and boost device which supports USB detection and charging. The driver
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 7833afa..3d9e4b7 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -171,17 +171,27 @@
  * @boost_base:			boost peripheral base address
  * @misc_base:			misc peripheral base address
  * @freq_base:			freq peripheral base address
+ * @bat_is_cool:		indicates that battery is cool
+ * @bat_is_warm:		indicates that battery is warm
  * @chg_done:			indicates that charging is completed
  * @usb_present:		present status of usb
  * @dc_present:			present status of dc
+ * @batt_present:		present status of battery
  * @use_default_batt_values:	flag to report default battery properties
  * @max_voltage_mv:		the max volts the batt should be charged up to
  * @min_voltage_mv:		min battery voltage before turning the FET on
- * @resume_voltage_mv:		voltage at which the battery resumes charging
+ * @max_bat_chg_current:	maximum battery charge current in mA
+ * @warm_bat_chg_ma:	warm battery maximum charge current in mA
+ * @cool_bat_chg_ma:	cool battery maximum charge current in mA
+ * @warm_bat_mv:		warm temperature battery target voltage
+ * @cool_bat_mv:		cool temperature battery target voltage
+ * @resume_delta_mv:		voltage delta at which battery resumes charging
  * @term_current:		the charging based term current
  * @safe_current:		battery safety current setting
  * @maxinput_usb_ma:		Maximum Input current USB
  * @maxinput_dc_ma:		Maximum Input current DC
+ * @warm_bat_degc		Warm battery temperature in degree Celsius
+ * @cool_bat_degc		Cool battery temperature in degree Celsius
  * @revision:			PMIC revision
  * @thermal_levels		amount of thermal mitigation levels
  * @thermal_mitigation		thermal mitigation level values
@@ -208,20 +218,32 @@
 	unsigned int			usbin_valid_irq;
 	unsigned int			dcin_valid_irq;
 	unsigned int			chg_done_irq;
+	unsigned int			chg_fastchg_irq;
+	unsigned int			chg_trklchg_irq;
 	unsigned int			chg_failed_irq;
+	unsigned int			batt_pres_irq;
+	bool				bat_is_cool;
+	bool				bat_is_warm;
 	bool				chg_done;
 	bool				usb_present;
 	bool				dc_present;
+	bool				batt_present;
 	bool				charging_disabled;
 	bool				use_default_batt_values;
 	unsigned int			max_bat_chg_current;
+	unsigned int			warm_bat_chg_ma;
+	unsigned int			cool_bat_chg_ma;
 	unsigned int			safe_voltage_mv;
 	unsigned int			max_voltage_mv;
 	unsigned int			min_voltage_mv;
-	unsigned int			resume_voltage_mv;
+	unsigned int			warm_bat_mv;
+	unsigned int			cool_bat_mv;
+	unsigned int			resume_delta_mv;
 	unsigned int			term_current;
 	unsigned int			maxinput_usb_ma;
 	unsigned int			maxinput_dc_ma;
+	unsigned int			warm_bat_degc;
+	unsigned int			cool_bat_degc;
 	unsigned int			safe_current;
 	unsigned int			revision;
 	unsigned int			thermal_levels;
@@ -232,6 +254,7 @@
 	struct power_supply		*bms_psy;
 	struct power_supply		batt_psy;
 	uint32_t			flags;
+	struct qpnp_adc_tm_btm_param	adc_param;
 };
 
 static struct of_device_id qpnp_charger_match_table[] = {
@@ -323,6 +346,23 @@
 	return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
 }
 
+static int
+qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
+{
+	u8 batt_pres_rt_sts;
+	int rc;
+
+	rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
+				 INT_RT_STS(chip->bat_if_base), 1);
+	if (rc) {
+		pr_err("spmi read failed: addr=%03X, rc=%d\n",
+				INT_RT_STS(chip->bat_if_base), rc);
+		return rc;
+	}
+
+	return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
+}
+
 #define USB_VALID_BIT	BIT(7)
 static int
 qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
@@ -493,6 +533,23 @@
 }
 
 static irqreturn_t
+qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+	int batt_present;
+
+	batt_present = qpnp_chg_is_batt_present(chip);
+	pr_debug("batt-pres triggered: %d\n", batt_present);
+
+	if (chip->batt_present ^ batt_present) {
+		chip->batt_present = batt_present;
+		power_supply_changed(&chip->batt_psy);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
 qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
 {
 	struct qpnp_chg_chip *chip = _chip;
@@ -527,12 +584,47 @@
 }
 
 static irqreturn_t
-qpnp_chg_chgr_chg_done_irq_handler(int irq, void *_chip)
+qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
 {
 	struct qpnp_chg_chip *chip = _chip;
 
+	pr_debug("TRKL IRQ triggered\n");
+
+	chip->chg_done = false;
+	power_supply_changed(&chip->batt_psy);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+
+	pr_debug("FAST_CHG IRQ triggered\n");
+
+	chip->chg_done = false;
+	power_supply_changed(&chip->batt_psy);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+qpnp_chg_chgr_chg_done_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+	u8 chgr_sts;
+	int rc;
+
 	pr_debug("CHG_DONE IRQ triggered\n");
+
+	rc = qpnp_chg_read(chip, &chgr_sts,
+				INT_RT_STS(chip->chgr_base), 1);
+	if (rc)
+		pr_err("failed to read interrupt sts %d\n", rc);
+
 	chip->chg_done = true;
+	power_supply_changed(&chip->batt_psy);
 
 	return IRQ_HANDLED;
 }
@@ -597,8 +689,8 @@
 	return rc;
 }
 
-static
-int switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
+static int
+switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
 {
 	int rc;
 
@@ -625,8 +717,8 @@
 	return 0;
 }
 
-static
-int switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
+static int
+switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
 {
 	int rc;
 
@@ -791,19 +883,16 @@
 	int rc;
 	u8 chgr_sts;
 
+	if (chip->chg_done)
+		return POWER_SUPPLY_STATUS_FULL;
+
 	rc = qpnp_chg_read(chip, &chgr_sts,
 				INT_RT_STS(chip->chgr_base), 1);
 	if (rc) {
 		pr_err("failed to read interrupt sts %d\n", rc);
-		return POWER_SUPPLY_STATUS_DISCHARGING;
+		return POWER_SUPPLY_CHARGE_TYPE_NONE;
 	}
 
-	pr_debug("chgr sts 0x%x\n", chgr_sts);
-	if (chgr_sts & CHG_DONE_IRQ || chip->chg_done)
-		return POWER_SUPPLY_STATUS_FULL;
-	else
-		chip->chg_done = false;
-
 	if (chgr_sts & TRKL_CHG_ON_IRQ)
 		return POWER_SUPPLY_STATUS_CHARGING;
 	if (chgr_sts & FAST_CHG_ON_IRQ)
@@ -1147,8 +1236,33 @@
 	temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
 
 	pr_debug("voltage=%d setting %02x\n", voltage, temp);
-	return qpnp_chg_write(chip, &temp,
-		chip->chgr_base + CHGR_VDD_MAX, 1);
+	return qpnp_chg_write(chip, &temp, chip->chgr_base + CHGR_VDD_MAX, 1);
+}
+
+/* JEITA compliance logic */
+static void
+qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
+{
+	if (chip->bat_is_cool)
+		qpnp_chg_vddmax_set(chip, chip->cool_bat_mv);
+	else if (chip->bat_is_warm)
+		qpnp_chg_vddmax_set(chip, chip->warm_bat_mv);
+	else
+		qpnp_chg_vddmax_set(chip, chip->max_voltage_mv);
+}
+
+static void
+qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
+{
+	if (chip->bat_is_cool)
+		qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
+			- chip->resume_delta_mv);
+	else if (chip->bat_is_warm)
+		qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
+			- chip->resume_delta_mv);
+	else
+		qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
+			- chip->resume_delta_mv);
 }
 
 static void
@@ -1156,6 +1270,12 @@
 {
 	unsigned int chg_current = chip->max_bat_chg_current;
 
+	if (chip->bat_is_cool)
+		chg_current = min(chg_current, chip->cool_bat_chg_ma);
+
+	if (chip->bat_is_warm)
+		chg_current = min(chg_current, chip->warm_bat_chg_ma);
+
 	if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
 		chg_current = min(chg_current,
 			chip->thermal_mitigation[chip->therm_lvl_sel]);
@@ -1181,6 +1301,58 @@
 	}
 }
 
+#define TEMP_HYSTERISIS_DEGC 2
+static void
+qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
+{
+	struct qpnp_chg_chip *chip = ctx;
+	bool bat_warm = 0, bat_cool = 0;
+
+	if (state >= ADC_TM_STATE_NUM) {
+		pr_err("invalid notification %d\n", state);
+		return;
+	}
+
+	pr_debug("state = %s\n", state == ADC_TM_HIGH_STATE ? "high" : "low");
+
+	if (state == ADC_TM_HIGH_STATE) {
+		if (!chip->bat_is_warm) {
+			bat_warm = true;
+			bat_cool = false;
+			chip->adc_param.low_temp =
+				chip->warm_bat_degc - TEMP_HYSTERISIS_DEGC;
+		} else if (chip->bat_is_cool) {
+			bat_warm = false;
+			bat_cool = false;
+			chip->adc_param.high_temp = chip->warm_bat_degc;
+		}
+	} else {
+		if (!chip->bat_is_cool) {
+			bat_cool = true;
+			bat_warm = false;
+			chip->adc_param.high_temp =
+				chip->cool_bat_degc + TEMP_HYSTERISIS_DEGC;
+		} else if (chip->bat_is_warm) {
+			bat_cool = false;
+			bat_warm = false;
+			chip->adc_param.low_temp = chip->cool_bat_degc;
+		}
+	}
+
+	if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
+		/* set appropriate voltages and currents */
+		qpnp_chg_set_appropriate_vddmax(chip);
+		qpnp_chg_set_appropriate_battery_current(chip);
+		qpnp_chg_set_appropriate_vbatdet(chip);
+
+		chip->bat_is_cool = bat_cool;
+		chip->bat_is_warm = bat_warm;
+	}
+
+	/* re-arm ADC interrupt */
+	qpnp_adc_tm_btm_configure(&chip->adc_param);
+}
+
 static int
 qpnp_batt_power_set_property(struct power_supply *psy,
 				  enum power_supply_property psp,
@@ -1231,20 +1403,37 @@
 			return -ENXIO;
 		}
 
+		chip->chg_fastchg_irq = spmi_get_irq_byname(chip->spmi,
+						spmi_resource, "fast-chg-on");
+		if (chip->chg_fastchg_irq < 0) {
+			pr_err("Unable to get fast-chg-on irq\n");
+			return -ENXIO;
+		}
+
+		chip->chg_trklchg_irq = spmi_get_irq_byname(chip->spmi,
+						spmi_resource, "trkl-chg-on");
+		if (chip->chg_trklchg_irq < 0) {
+			pr_err("Unable to get trkl-chg-on irq\n");
+			return -ENXIO;
+		}
+
 		chip->chg_failed_irq = spmi_get_irq_byname(chip->spmi,
 						spmi_resource, "chg-failed");
 		if (chip->chg_failed_irq < 0) {
 			pr_err("Unable to get chg_failed irq\n");
 			return -ENXIO;
 		}
+
 		rc |= devm_request_irq(chip->dev, chip->chg_done_irq,
 				qpnp_chg_chgr_chg_done_irq_handler,
-				IRQF_TRIGGER_RISING, "chg_done", chip);
+				IRQF_TRIGGER_RISING,
+				"chg_done", chip);
 		if (rc < 0) {
 			pr_err("Can't request %d chg_done for chg: %d\n",
 						chip->chg_done_irq, rc);
 			return -ENXIO;
 		}
+
 		rc |= devm_request_irq(chip->dev, chip->chg_failed_irq,
 				qpnp_chg_chgr_chg_failed_irq_handler,
 				IRQF_TRIGGER_RISING, "chg_failed", chip);
@@ -1254,6 +1443,26 @@
 			return -ENXIO;
 		}
 
+		rc |= devm_request_irq(chip->dev, chip->chg_fastchg_irq,
+				qpnp_chg_chgr_chg_fastchg_irq_handler,
+				IRQF_TRIGGER_RISING,
+				"fast-chg-on", chip);
+		if (rc < 0) {
+			pr_err("Can't request %d fast-chg-on for chg: %d\n",
+						chip->chg_fastchg_irq, rc);
+			return -ENXIO;
+		}
+
+		rc |= devm_request_irq(chip->dev, chip->chg_trklchg_irq,
+				qpnp_chg_chgr_chg_trklchg_irq_handler,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				"fast-chg-on", chip);
+		if (rc < 0) {
+			pr_err("Can't request %d trkl-chg-on for chg: %d\n",
+						chip->chg_trklchg_irq, rc);
+			return -ENXIO;
+		}
+
 		rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
 		if (rc) {
 			pr_debug("failed setting  min_voltage rc=%d\n", rc);
@@ -1269,7 +1478,8 @@
 			pr_debug("failed setting safe_voltage rc=%d\n", rc);
 			return rc;
 		}
-		rc = qpnp_chg_vbatdet_set(chip, chip->resume_voltage_mv);
+		rc = qpnp_chg_vbatdet_set(chip,
+				chip->max_voltage_mv - chip->resume_delta_mv);
 		if (rc) {
 			pr_debug("failed setting resume_voltage rc=%d\n", rc);
 			return rc;
@@ -1279,10 +1489,12 @@
 			pr_debug("failed setting ibatmax rc=%d\n", rc);
 			return rc;
 		}
-		rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
-		if (rc) {
-			pr_debug("failed setting ibatterm rc=%d\n", rc);
-			return rc;
+		if (chip->term_current) {
+			rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
+			if (rc) {
+				pr_debug("failed setting ibatterm rc=%d\n", rc);
+				return rc;
+			}
 		}
 		rc = qpnp_chg_ibatsafe_set(chip, chip->safe_current);
 		if (rc) {
@@ -1293,11 +1505,14 @@
 		rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
 			0xFF, 0xA0, 1);
 
-		/* HACK: use analog EOC */
+		/* HACK: use digital EOC */
 		rc = qpnp_chg_masked_write(chip, chip->chgr_base +
 			CHGR_IBAT_TERM_CHGR,
-			0x80, 0x80, 1);
+			0x88, 0x80, 1);
 
+		enable_irq_wake(chip->chg_fastchg_irq);
+		enable_irq_wake(chip->chg_trklchg_irq);
+		enable_irq_wake(chip->chg_failed_irq);
 		enable_irq_wake(chip->chg_done_irq);
 		break;
 	case SMBB_BUCK_SUBTYPE:
@@ -1313,6 +1528,23 @@
 		break;
 	case SMBB_BAT_IF_SUBTYPE:
 	case SMBBP_BAT_IF_SUBTYPE:
+		chip->batt_pres_irq = spmi_get_irq_byname(chip->spmi,
+						spmi_resource, "batt-pres");
+		if (chip->batt_pres_irq < 0) {
+			pr_err("Unable to get batt-pres irq\n");
+			return -ENXIO;
+		}
+		rc = devm_request_irq(chip->dev, chip->batt_pres_irq,
+				qpnp_chg_bat_if_batt_pres_irq_handler,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				"bat_if_batt_pres", chip);
+		if (rc < 0) {
+			pr_err("Can't request %d batt-pres irq for chg: %d\n",
+						chip->batt_pres_irq, rc);
+			return -ENXIO;
+		}
+
+		enable_irq_wake(chip->batt_pres_irq);
 		break;
 	case SMBB_USB_CHGPTH_SUBTYPE:
 	case SMBBP_USB_CHGPTH_SUBTYPE:
@@ -1427,7 +1659,7 @@
 	/* Get the vddmax property */
 	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddmax-mv",
 						&chip->max_voltage_mv);
-	if (rc && rc != -EINVAL) {
+	if (rc) {
 		pr_err("Error reading vddmax property %d\n", rc);
 		goto fail_chg_enable;
 	}
@@ -1435,7 +1667,7 @@
 	/* Get the vinmin property */
 	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vinmin-mv",
 						&chip->min_voltage_mv);
-	if (rc && rc != -EINVAL) {
+	if (rc) {
 		pr_err("Error reading vddmax property %d\n", rc);
 		goto fail_chg_enable;
 	}
@@ -1443,17 +1675,17 @@
 	/* Get the vddmax property */
 	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddsafe-mv",
 						&chip->safe_voltage_mv);
-	if (rc && rc != -EINVAL) {
+	if (rc) {
 		pr_err("Error reading vddsave property %d\n", rc);
 		goto fail_chg_enable;
 	}
 
-	/* Get the ibatsafe property */
+	/* Get the vbatdet-delta property */
 	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-vbatdet-mv",
-				&chip->resume_voltage_mv);
-	if (rc) {
-		pr_err("Error reading vbatdet property %d\n", rc);
+				"qcom,chg-vbatdet-delta-mv",
+				&chip->resume_delta_mv);
+	if (rc && rc != -EINVAL) {
+		pr_err("Error reading vbatdet-delta property %d\n", rc);
 		goto fail_chg_enable;
 	}
 
@@ -1478,17 +1710,8 @@
 	/* Get the ibatmax property */
 	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-ibatmax-ma",
 						&chip->max_bat_chg_current);
-	if (rc && rc != -EINVAL) {
-		pr_err("Error reading ibatmax property %d\n", rc);
-		goto fail_chg_enable;
-	}
-
-	/* Get the ibatsafe property */
-	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-vbatdet-mv",
-				&chip->resume_voltage_mv);
 	if (rc) {
-		pr_err("Error reading vbatdet property %d\n", rc);
+		pr_err("Error reading ibatmax property %d\n", rc);
 		goto fail_chg_enable;
 	}
 
@@ -1514,6 +1737,67 @@
 	chip->charging_disabled = of_property_read_bool(spmi->dev.of_node,
 					"qcom,chg-charging-disabled");
 
+	/* Get the warm-bat-degc property */
+	rc = of_property_read_u32(spmi->dev.of_node,
+				"qcom,chg-warm-bat-degc",
+				&chip->warm_bat_degc);
+	if (rc && rc != -EINVAL) {
+		pr_err("Error reading warm-bat-degc property %d\n", rc);
+		goto fail_chg_enable;
+	}
+
+	/* Get the cool-bat-degc property */
+	rc = of_property_read_u32(spmi->dev.of_node,
+				"qcom,chg-cool-bat-degc",
+				&chip->cool_bat_degc);
+	if (rc && rc != -EINVAL) {
+		pr_err("Error reading cool-bat-degc property %d\n", rc);
+		goto fail_chg_enable;
+	}
+
+	if (chip->cool_bat_degc && chip->warm_bat_degc) {
+		rc = qpnp_adc_tm_is_ready();
+		if (rc) {
+			pr_err("tm not ready %d\n", rc);
+			goto fail_chg_enable;
+		}
+
+		/* Get the ibatmax-warm property */
+		rc = of_property_read_u32(spmi->dev.of_node,
+					"qcom,chg-ibatmax-warm-ma",
+					&chip->warm_bat_chg_ma);
+		if (rc) {
+			pr_err("Error reading ibatmax-warm-ma %d\n", rc);
+			goto fail_chg_enable;
+		}
+
+		/* Get the ibatmax-cool property */
+		rc = of_property_read_u32(spmi->dev.of_node,
+					"qcom,chg-ibatmax-cool-ma",
+					&chip->cool_bat_chg_ma);
+		if (rc) {
+			pr_err("Error reading ibatmax-cool-ma %d\n", rc);
+			goto fail_chg_enable;
+		}
+		/* Get the cool-bat-mv property */
+		rc = of_property_read_u32(spmi->dev.of_node,
+					"qcom,chg-cool-bat-mv",
+					&chip->cool_bat_mv);
+		if (rc) {
+			pr_err("Error reading cool-bat-mv property %d\n", rc);
+			goto fail_chg_enable;
+		}
+
+		/* Get the warm-bat-mv property */
+		rc = of_property_read_u32(spmi->dev.of_node,
+					"qcom,chg-warm-bat-mv",
+					&chip->warm_bat_mv);
+		if (rc) {
+			pr_err("Error reading warm-bat-mv property %d\n", rc);
+			goto fail_chg_enable;
+		}
+	}
+
 	/* 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");
@@ -1701,6 +1985,22 @@
 		}
 	}
 
+	if (chip->cool_bat_degc && chip->warm_bat_degc) {
+		chip->adc_param.low_temp = chip->cool_bat_degc;
+		chip->adc_param.high_temp = chip->warm_bat_degc;
+		chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
+		chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
+		chip->adc_param.btm_ctx = chip;
+		chip->adc_param.threshold_notification =
+						qpnp_chg_adc_notification;
+
+		rc = qpnp_adc_tm_btm_configure(&chip->adc_param);
+		if (rc) {
+			pr_err("request ADC error %d\n", rc);
+			goto fail_chg_enable;
+		}
+	}
+
 	qpnp_chg_charge_en(chip, !chip->charging_disabled);
 	qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
 
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c
index aea91ef..8097e69 100644
--- a/drivers/rtc/rtc-pm8xxx.c
+++ b/drivers/rtc/rtc-pm8xxx.c
@@ -15,31 +15,37 @@
 #include <linux/rtc.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
-#include<linux/spinlock.h>
+#include <linux/spinlock.h>
 
 #include <linux/mfd/pm8xxx/core.h>
 #include <linux/mfd/pm8xxx/rtc.h>
 
 
 /* RTC Register offsets from RTC CTRL REG */
-#define PM8XXX_ALARM_CTRL_OFFSET 0x01
-#define PM8XXX_RTC_WRITE_OFFSET 0x02
-#define PM8XXX_RTC_READ_OFFSET 0x06
-#define PM8XXX_ALARM_RW_OFFSET 0x0A
+#define PM8XXX_ALARM_CTRL_OFFSET	0x01
+#define PM8XXX_RTC_WRITE_OFFSET		0x02
+#define PM8XXX_RTC_READ_OFFSET		0x06
+#define PM8XXX_ALARM_RW_OFFSET		0x0A
 
 /* RTC_CTRL register bit fields */
-#define PM8xxx_RTC_ENABLE	BIT(7)
-#define PM8xxx_RTC_ALARM_ENABLE	BIT(1)
-#define PM8xxx_RTC_ABORT_ENABLE BIT(0)
+#define PM8xxx_RTC_ENABLE		BIT(7)
+#define PM8xxx_RTC_ALARM_ENABLE		BIT(1)
+#define PM8xxx_RTC_ALARM_CLEAR		BIT(0)
+#define PM8xxx_RTC_ABORT_ENABLE		BIT(0)
 
-#define PM8xxx_RTC_ALARM_CLEAR  BIT(0)
-
-#define NUM_8_BIT_RTC_REGS	0x4
+#define NUM_8_BIT_RTC_REGS		0x4
 
 /**
- * struct pm8xxx_rtc - rtc driver internal structure
- * @rtc: rtc device for this driver
- * @rtc_alarm_irq: rtc alarm irq number
+ * struct pm8xxx_rtc -  rtc driver internal structure
+ * @rtc:		rtc device for this driver.
+ * @rtc_alarm_irq:	rtc alarm irq number.
+ * @rtc_base:		address of rtc control register.
+ * @rtc_read_base:	base address of read registers.
+ * @rtc_write_base:	base address of write registers.
+ * @alarm_rw_base:	base address of alarm registers.
+ * @ctrl_reg:		rtc control register.
+ * @rtc_dev:		device structure.
+ * @ctrl_reg_lock:	spinlock protecting access to ctrl_reg.
  */
 struct pm8xxx_rtc {
 	struct rtc_device *rtc;
@@ -57,9 +63,8 @@
  * The RTC registers need to be read/written one byte at a time. This is a
  * hardware limitation.
  */
-
 static int pm8xxx_read_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val,
-			int base, int count)
+		int base, int count)
 {
 	int i, rc;
 	struct device *parent = rtc_dd->rtc_dev->parent;
@@ -67,7 +72,7 @@
 	for (i = 0; i < count; i++) {
 		rc = pm8xxx_readb(parent, base + i, &rtc_val[i]);
 		if (rc < 0) {
-			dev_err(rtc_dd->rtc_dev, "PM8xxx read failed\n");
+			dev_err(rtc_dd->rtc_dev, "PMIC read failed\n");
 			return rc;
 		}
 	}
@@ -76,7 +81,7 @@
 }
 
 static int pm8xxx_write_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val,
-			int base, int count)
+		int base, int count)
 {
 	int i, rc;
 	struct device *parent = rtc_dd->rtc_dev->parent;
@@ -84,7 +89,7 @@
 	for (i = 0; i < count; i++) {
 		rc = pm8xxx_writeb(parent, base + i, rtc_val[i]);
 		if (rc < 0) {
-			dev_err(rtc_dd->rtc_dev, "PM8xxx write failed\n");
+			dev_err(rtc_dd->rtc_dev, "PMIC write failed\n");
 			return rc;
 		}
 	}
@@ -92,7 +97,6 @@
 	return 0;
 }
 
-
 /*
  * Steps to write the RTC registers.
  * 1. Disable alarm if enabled.
@@ -100,20 +104,19 @@
  * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0].
  * 4. Enable alarm if disabled in step 1.
  */
-static int
-pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
+static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-	int rc;
+	int rc, i;
 	unsigned long secs, irq_flags;
-	u8 value[4], reg = 0, alarm_enabled = 0, ctrl_reg;
+	u8 value[NUM_8_BIT_RTC_REGS], reg = 0, alarm_enabled = 0, ctrl_reg;
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
 
 	rtc_tm_to_time(tm, &secs);
 
-	value[0] = secs & 0xFF;
-	value[1] = (secs >> 8) & 0xFF;
-	value[2] = (secs >> 16) & 0xFF;
-	value[3] = (secs >> 24) & 0xFF;
+	for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
+		value[i] = secs & 0xFF;
+		secs >>= 8;
+	}
 
 	dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
 
@@ -124,20 +127,21 @@
 		alarm_enabled = 1;
 		ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE;
 		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
-									1);
+				1);
 		if (rc < 0) {
-			dev_err(dev, "PM8xxx write failed\n");
+			dev_err(dev, "Write to RTC control register "
+								"failed\n");
 			goto rtc_rw_fail;
 		}
+		rtc_dd->ctrl_reg = ctrl_reg;
 	} else
 		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
 
-	/* Write Byte[1], Byte[2], Byte[3], Byte[0] */
 	/* Write 0 to Byte[0] */
 	reg = 0;
 	rc = pm8xxx_write_wrapper(rtc_dd, &reg, rtc_dd->rtc_write_base, 1);
 	if (rc < 0) {
-		dev_err(dev, "PM8xxx write failed\n");
+		dev_err(dev, "Write to RTC write data register failed\n");
 		goto rtc_rw_fail;
 	}
 
@@ -145,14 +149,14 @@
 	rc = pm8xxx_write_wrapper(rtc_dd, value + 1,
 					rtc_dd->rtc_write_base + 1, 3);
 	if (rc < 0) {
-		dev_err(dev, "Write to RTC registers failed\n");
+		dev_err(dev, "Write to RTC write data register failed\n");
 		goto rtc_rw_fail;
 	}
 
 	/* Write Byte[0] */
 	rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->rtc_write_base, 1);
 	if (rc < 0) {
-		dev_err(dev, "Write to RTC register failed\n");
+		dev_err(dev, "Write to RTC write data register failed\n");
 		goto rtc_rw_fail;
 	}
 
@@ -161,13 +165,13 @@
 		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
 									1);
 		if (rc < 0) {
-			dev_err(dev, "PM8xxx write failed\n");
+			dev_err(dev, "Write to RTC control register "
+								"failed\n");
 			goto rtc_rw_fail;
 		}
+		rtc_dd->ctrl_reg = ctrl_reg;
 	}
 
-	rtc_dd->ctrl_reg = ctrl_reg;
-
 rtc_rw_fail:
 	if (alarm_enabled)
 		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
@@ -175,18 +179,17 @@
 	return rc;
 }
 
-static int
-pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	int rc;
-	u8 value[4], reg;
+	u8 value[NUM_8_BIT_RTC_REGS], reg;
 	unsigned long secs;
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
 
 	rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->rtc_read_base,
 							NUM_8_BIT_RTC_REGS);
 	if (rc < 0) {
-		dev_err(dev, "RTC time read failed\n");
+		dev_err(dev, "RTC read data register failed\n");
 		return rc;
 	}
 
@@ -196,7 +199,7 @@
 	 */
 	rc = pm8xxx_read_wrapper(rtc_dd, &reg, rtc_dd->rtc_read_base, 1);
 	if (rc < 0) {
-		dev_err(dev, "PM8xxx read failed\n");
+		dev_err(dev, "RTC read data register failed\n");
 		return rc;
 	}
 
@@ -204,96 +207,76 @@
 		rc = pm8xxx_read_wrapper(rtc_dd, value,
 				rtc_dd->rtc_read_base, NUM_8_BIT_RTC_REGS);
 		if (rc < 0) {
-			dev_err(dev, "RTC time read failed\n");
+			dev_err(dev, "RTC read data register failed\n");
 			return rc;
 		}
 	}
 
-	secs = value[0] | (value[1] << 8) | (value[2] << 16) \
-						| (value[3] << 24);
+	secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
 
 	rtc_time_to_tm(secs, tm);
 
 	rc = rtc_valid_tm(tm);
 	if (rc < 0) {
-		dev_err(dev, "Invalid time read from PM8xxx\n");
+		dev_err(dev, "Invalid time read from RTC\n");
 		return rc;
 	}
 
 	dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n",
-			secs, tm->tm_hour, tm->tm_min, tm->tm_sec,
-			tm->tm_mday, tm->tm_mon, tm->tm_year);
+				secs, tm->tm_hour, tm->tm_min, tm->tm_sec,
+				tm->tm_mday, tm->tm_mon, tm->tm_year);
 
 	return 0;
 }
 
-static int
-pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-	int rc;
-	u8 value[4], ctrl_reg;
-	unsigned long secs, secs_rtc, irq_flags;
+	int rc, i;
+	u8 value[NUM_8_BIT_RTC_REGS], ctrl_reg;
+	unsigned long secs, irq_flags;
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
-	struct rtc_time rtc_tm;
 
 	rtc_tm_to_time(&alarm->time, &secs);
 
-	/*
-	 * Read the current RTC time and verify if the alarm time is in the
-	 * past. If yes, return invalid.
-	 */
-	rc = pm8xxx_rtc_read_time(dev, &rtc_tm);
-	if (rc < 0) {
-		dev_err(dev, "Unamble to read RTC time\n");
-		return -EINVAL;
+	for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
+		value[i] = secs & 0xFF;
+		secs >>= 8;
 	}
 
-	rtc_tm_to_time(&rtc_tm, &secs_rtc);
-	if (secs < secs_rtc) {
-		dev_err(dev, "Trying to set alarm in the past\n");
-		return -EINVAL;
-	}
-
-	value[0] = secs & 0xFF;
-	value[1] = (secs >> 8) & 0xFF;
-	value[2] = (secs >> 16) & 0xFF;
-	value[3] = (secs >> 24) & 0xFF;
-
 	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
 
 	rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base,
 							NUM_8_BIT_RTC_REGS);
 	if (rc < 0) {
-		dev_err(dev, "Write to RTC ALARM registers failed\n");
+		dev_err(dev, "Write to RTC ALARM register failed\n");
 		goto rtc_rw_fail;
 	}
 
 	ctrl_reg = rtc_dd->ctrl_reg;
-	ctrl_reg = (alarm->enabled) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
+	ctrl_reg = alarm->enabled ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
 					(ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE);
 
 	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
 	if (rc < 0) {
-		dev_err(dev, "PM8xxx write failed\n");
+		dev_err(dev, "Write to RTC control register failed\n");
 		goto rtc_rw_fail;
 	}
 
 	rtc_dd->ctrl_reg = ctrl_reg;
 
 	dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
-			alarm->time.tm_hour, alarm->time.tm_min,
-			alarm->time.tm_sec, alarm->time.tm_mday,
-			alarm->time.tm_mon, alarm->time.tm_year);
+				alarm->time.tm_hour, alarm->time.tm_min,
+				alarm->time.tm_sec, alarm->time.tm_mday,
+				alarm->time.tm_mon, alarm->time.tm_year);
 rtc_rw_fail:
 	spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
 	return rc;
 }
 
-static int
-pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
 	int rc;
-	u8 value[4];
+	u8 value[NUM_8_BIT_RTC_REGS];
 	unsigned long secs;
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
 
@@ -304,28 +287,25 @@
 		return rc;
 	}
 
-	secs = value[0] | (value[1] << 8) | (value[2] << 16) | \
-						 (value[3] << 24);
+	secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
 
 	rtc_time_to_tm(secs, &alarm->time);
 
 	rc = rtc_valid_tm(&alarm->time);
 	if (rc < 0) {
-		dev_err(dev, "Invalid time read from PM8xxx\n");
+		dev_err(dev, "Invalid alarm time read from RTC\n");
 		return rc;
 	}
 
 	dev_dbg(dev, "Alarm set for - h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
-		alarm->time.tm_hour, alarm->time.tm_min,
+				alarm->time.tm_hour, alarm->time.tm_min,
 				alarm->time.tm_sec, alarm->time.tm_mday,
 				alarm->time.tm_mon, alarm->time.tm_year);
 
 	return 0;
 }
 
-
-static int
-pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
 {
 	int rc;
 	unsigned long irq_flags;
@@ -334,12 +314,12 @@
 
 	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
 	ctrl_reg = rtc_dd->ctrl_reg;
-	ctrl_reg = (enabled) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
+	ctrl_reg = (enable) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
 				(ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE);
 
 	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
 	if (rc < 0) {
-		dev_err(dev, "PM8xxx write failed\n");
+		dev_err(dev, "Write to RTC control register failed\n");
 		goto rtc_rw_fail;
 	}
 
@@ -375,7 +355,8 @@
 	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
 	if (rc < 0) {
 		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
-		dev_err(rtc_dd->rtc_dev, "PM8xxx write failed!\n");
+		dev_err(rtc_dd->rtc_dev, "Write to RTC control register "
+								"failed\n");
 		goto rtc_alarm_handled;
 	}
 
@@ -386,7 +367,8 @@
 	rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base +
 						PM8XXX_ALARM_CTRL_OFFSET, 1);
 	if (rc < 0) {
-		dev_err(rtc_dd->rtc_dev, "PM8xxx write failed!\n");
+		dev_err(rtc_dd->rtc_dev, "RTC Alarm control register read "
+								"failed\n");
 		goto rtc_alarm_handled;
 	}
 
@@ -394,7 +376,8 @@
 	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base +
 						PM8XXX_ALARM_CTRL_OFFSET, 1);
 	if (rc < 0)
-		dev_err(rtc_dd->rtc_dev, "PM8xxx write failed!\n");
+		dev_err(rtc_dd->rtc_dev, "Write to RTC Alarm control register"
+								" failed\n");
 
 rtc_alarm_handled:
 	return IRQ_HANDLED;
@@ -408,7 +391,7 @@
 	struct pm8xxx_rtc *rtc_dd;
 	struct resource *rtc_resource;
 	const struct pm8xxx_rtc_platform_data *pdata =
-		pdev->dev.platform_data;
+						dev_get_platdata(&pdev->dev);
 
 	if (pdata != NULL)
 		rtc_write_enable = pdata->rtc_write_enable;
@@ -419,7 +402,7 @@
 		return -ENOMEM;
 	}
 
-	/* Initialise spinlock to protect RTC cntrol register */
+	/* Initialise spinlock to protect RTC control register */
 	spin_lock_init(&rtc_dd->ctrl_reg_lock);
 
 	rtc_dd->rtc_alarm_irq = platform_get_irq(pdev, 0);
@@ -444,12 +427,12 @@
 	rtc_dd->rtc_read_base = rtc_dd->rtc_base + PM8XXX_RTC_READ_OFFSET;
 	rtc_dd->alarm_rw_base = rtc_dd->rtc_base + PM8XXX_ALARM_RW_OFFSET;
 
-	rtc_dd->rtc_dev = &(pdev->dev);
+	rtc_dd->rtc_dev = &pdev->dev;
 
 	/* Check if the RTC is on, else turn it on */
 	rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
 	if (rc < 0) {
-		dev_err(&pdev->dev, "PM8xxx read failed!\n");
+		dev_err(&pdev->dev, "RTC control register read failed!\n");
 		goto fail_rtc_enable;
 	}
 
@@ -458,7 +441,8 @@
 		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
 									1);
 		if (rc < 0) {
-			dev_err(&pdev->dev, "PM8xxx write failed!\n");
+			dev_err(&pdev->dev, "Write to RTC control register "
+								"failed\n");
 			goto fail_rtc_enable;
 		}
 	}
@@ -510,7 +494,20 @@
 	return rc;
 }
 
-#ifdef CONFIG_PM
+static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev)
+{
+	struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev);
+
+	device_init_wakeup(&pdev->dev, 0);
+	free_irq(rtc_dd->rtc_alarm_irq, rtc_dd);
+	rtc_device_unregister(rtc_dd->rtc);
+	platform_set_drvdata(pdev, NULL);
+	kfree(rtc_dd);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
 static int pm8xxx_rtc_resume(struct device *dev)
 {
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
@@ -530,24 +527,9 @@
 
 	return 0;
 }
-
-static const struct dev_pm_ops pm8xxx_rtc_pm_ops = {
-	.suspend = pm8xxx_rtc_suspend,
-	.resume = pm8xxx_rtc_resume,
-};
 #endif
-static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev)
-{
-	struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev);
 
-	device_init_wakeup(&pdev->dev, 0);
-	free_irq(rtc_dd->rtc_alarm_irq, rtc_dd);
-	rtc_device_unregister(rtc_dd->rtc);
-	platform_set_drvdata(pdev, NULL);
-	kfree(rtc_dd);
-
-	return 0;
-}
+static SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resume);
 
 static void pm8xxx_rtc_shutdown(struct platform_device *pdev)
 {
@@ -572,7 +554,7 @@
 		reg &= ~PM8xxx_RTC_ALARM_ENABLE;
 		rc = pm8xxx_write_wrapper(rtc_dd, &reg, rtc_dd->rtc_base, 1);
 		if (rc < 0) {
-			dev_err(rtc_dd->rtc_dev, "PM8xxx write failed\n");
+			dev_err(rtc_dd->rtc_dev, "Disabling alarm failed\n");
 			goto fail_alarm_disable;
 		}
 
@@ -580,7 +562,7 @@
 		rc = pm8xxx_write_wrapper(rtc_dd, value,
 				rtc_dd->alarm_rw_base, NUM_8_BIT_RTC_REGS);
 		if (rc < 0)
-			dev_err(rtc_dd->rtc_dev, "PM8xxx write failed\n");
+			dev_err(rtc_dd->rtc_dev, "Clearing alarm failed\n");
 
 fail_alarm_disable:
 		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
@@ -594,23 +576,11 @@
 	.driver	= {
 		.name	= PM8XXX_RTC_DEV_NAME,
 		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
 		.pm	= &pm8xxx_rtc_pm_ops,
-#endif
 	},
 };
 
-static int __init pm8xxx_rtc_init(void)
-{
-	return platform_driver_register(&pm8xxx_rtc_driver);
-}
-module_init(pm8xxx_rtc_init);
-
-static void __exit pm8xxx_rtc_exit(void)
-{
-	platform_driver_unregister(&pm8xxx_rtc_driver);
-}
-module_exit(pm8xxx_rtc_exit);
+module_platform_driver(pm8xxx_rtc_driver);
 
 MODULE_ALIAS("platform:rtc-pm8xxx");
 MODULE_DESCRIPTION("PMIC8xxx RTC driver");
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
index ef9c77d..fab3586 100644
--- a/drivers/scsi/isci/phy.c
+++ b/drivers/scsi/isci/phy.c
@@ -293,18 +293,6 @@
 
 	writel(sp_timeouts, &llr->sas_phy_timeouts);
 
-	sp_timeouts = readl(&iphy->link_layer_registers->sas_phy_timeouts);
-
-	/* Clear the default 0x36 (54us) RATE_CHANGE timeout value. */
-	sp_timeouts &= ~SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0xFF);
-
-	/* Set RATE_CHANGE timeout value to 0x3B (59us).  This ensures SCU can
-	 * lock with 3Gb drive when SCU max rate is set to 1.5Gb.
-	 */
-	sp_timeouts |= SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0x3B);
-
-	writel(sp_timeouts, &iphy->link_layer_registers->sas_phy_timeouts);
-
 	if (is_a2(ihost->pdev)) {
 		/* Program the max ARB time for the PHY to 700us so we
 		 * inter-operate with the PMC expander which shuts down
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 1756897..706fba7 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -2,51 +2,61 @@
 # Kernel configuration file for the UFS Host Controller
 #
 # This code is based on drivers/scsi/ufs/Kconfig
-# Copyright (C) 2011  Samsung Samsung India Software Operations
+# Copyright (C) 2011-2013 Samsung India Software Operations
 #
-# Santosh Yaraganavi <santosh.sy@samsung.com>
-# Vinayak Holikatti <h.vinayak@samsung.com>
-
+# 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.
-
-# NO WARRANTY
-# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
-# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
-# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
-# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
-# solely responsible for determining the appropriateness of using and
-# distributing the Program and assumes all risks associated with its
-# exercise of rights under this Agreement, including but not limited to
-# the risks and costs of program errors, damage to or loss of data,
-# programs or equipment, and unavailability or interruption of operations.
-
-# DISCLAIMER OF LIABILITY
-# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
-# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
-# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
-# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
-# USA.
+#
+# 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.
 
 config SCSI_UFSHCD
-	tristate "Universal Flash Storage host controller driver"
-	depends on PCI && SCSI
+	tristate "Universal Flash Storage Controller Driver Core"
+	depends on SCSI
 	---help---
-	This is a generic driver which supports PCIe UFS Host controllers.
+	This selects the support for UFS devices in Linux, say Y and make
+	  sure that you know the name of your UFS host adapter (the card
+	  inside your computer that "speaks" the UFS protocol, also
+	  called UFS Host Controller), because you will be asked for it.
+	  The module will be called ufshcd.
+
+	  To compile this driver as a module, choose M here and read
+	  <file:Documentation/scsi/ufs.txt>.
+	  However, do not compile this as a module if your root file system
+	  (the one containing the directory /) is located on a UFS device.
+
+config SCSI_UFSHCD_PCI
+	tristate "PCI bus based UFS Controller support"
+	depends on SCSI_UFSHCD && PCI
+	---help---
+	This selects the PCI UFS Host Controller Interface. Select this if
+	you have UFS Host Controller with PCI Interface.
+
+	  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"
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 489058d..bbcc202 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,3 +1,4 @@
 # UFSHCD makefile
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFS_TEST) += ufs_test.o
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index b207529..139bc06 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -2,45 +2,35 @@
  * Universal Flash Storage Host controller driver
  *
  * This code is based on drivers/scsi/ufs/ufs.h
- * Copyright (C) 2011-2012 Samsung India Software Operations
+ * Copyright (C) 2011-2013 Samsung India Software Operations
  *
- * Santosh Yaraganavi <santosh.sy@samsung.com>
- * Vinayak Holikatti <h.vinayak@samsung.com>
+ * 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.
  *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
+ * 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.
  */
 
 #ifndef _UFS_H
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
new file mode 100644
index 0000000..5cb1d75
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -0,0 +1,211 @@
+/*
+ * Universal Flash Storage Host controller PCI glue driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd-pci.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/pci.h>
+
+#ifdef CONFIG_PM
+/**
+ * ufshcd_pci_suspend - suspend power management function
+ * @pdev: pointer to PCI device handle
+ * @state: power state
+ *
+ * Returns -ENOSYS
+ */
+static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	/*
+	 * TODO:
+	 * 1. Call ufshcd_suspend
+	 * 2. Do bus specific power management
+	 */
+
+	return -ENOSYS;
+}
+
+/**
+ * ufshcd_pci_resume - resume power management function
+ * @pdev: pointer to PCI device handle
+ *
+ * Returns -ENOSYS
+ */
+static int ufshcd_pci_resume(struct pci_dev *pdev)
+{
+	/*
+	 * TODO:
+	 * 1. Call ufshcd_resume.
+	 * 2. Do bus specific wake up
+	 */
+
+	return -ENOSYS;
+}
+#endif /* CONFIG_PM */
+
+/**
+ * ufshcd_pci_shutdown - main function to put the controller in reset state
+ * @pdev: pointer to PCI device handle
+ */
+static void ufshcd_pci_shutdown(struct pci_dev *pdev)
+{
+	ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
+}
+
+/**
+ * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
+ *		data structure memory
+ * @pdev - pointer to PCI handle
+ */
+static void ufshcd_pci_remove(struct pci_dev *pdev)
+{
+	struct ufs_hba *hba = pci_get_drvdata(pdev);
+
+	disable_irq(pdev->irq);
+	free_irq(pdev->irq, hba);
+	ufshcd_remove(hba);
+	pci_release_regions(pdev);
+	pci_set_drvdata(pdev, NULL);
+	pci_clear_master(pdev);
+	pci_disable_device(pdev);
+}
+
+/**
+ * ufshcd_set_dma_mask - Set dma mask based on the controller
+ *			 addressing capability
+ * @pdev: PCI device structure
+ *
+ * Returns 0 for success, non-zero for failure
+ */
+static int ufshcd_set_dma_mask(struct pci_dev *pdev)
+{
+	int err;
+
+	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
+		&& !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
+		return 0;
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (!err)
+		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	return err;
+}
+
+/**
+ * ufshcd_pci_probe - probe routine of the driver
+ * @pdev: pointer to PCI device handle
+ * @id: PCI device id
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int
+ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct ufs_hba *hba;
+	void __iomem *mmio_base;
+	int err;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "pci_enable_device failed\n");
+		goto out_error;
+	}
+
+	pci_set_master(pdev);
+
+
+	err = pci_request_regions(pdev, UFSHCD);
+	if (err < 0) {
+		dev_err(&pdev->dev, "request regions failed\n");
+		goto out_disable;
+	}
+
+	mmio_base = pci_ioremap_bar(pdev, 0);
+	if (!mmio_base) {
+		dev_err(&pdev->dev, "memory map failed\n");
+		err = -ENOMEM;
+		goto out_release_regions;
+	}
+
+	err = ufshcd_set_dma_mask(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "set dma mask failed\n");
+		goto out_iounmap;
+	}
+
+	err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq);
+	if (err) {
+		dev_err(&pdev->dev, "Initialization failed\n");
+		goto out_iounmap;
+	}
+
+	pci_set_drvdata(pdev, hba);
+
+	return 0;
+
+out_iounmap:
+	iounmap(mmio_base);
+out_release_regions:
+	pci_release_regions(pdev);
+out_disable:
+	pci_clear_master(pdev);
+	pci_disable_device(pdev);
+out_error:
+	return err;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
+	{ PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ }	/* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
+
+static struct pci_driver ufshcd_pci_driver = {
+	.name = UFSHCD,
+	.id_table = ufshcd_pci_tbl,
+	.probe = ufshcd_pci_probe,
+	.remove = ufshcd_pci_remove,
+	.shutdown = ufshcd_pci_shutdown,
+#ifdef CONFIG_PM
+	.suspend = ufshcd_pci_suspend,
+	.resume = ufshcd_pci_resume,
+#endif
+};
+
+module_pci_driver(ufshcd_pci_driver);
+
+MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
+MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
+MODULE_DESCRIPTION("UFS host controller PCI 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 58f4ba6..60fd40c 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1,77 +1,39 @@
 /*
- * Universal Flash Storage Host controller driver
+ * Universal Flash Storage Host controller driver Core
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
- * Copyright (C) 2011-2012 Samsung India Software Operations
+ * Copyright (C) 2011-2013 Samsung India Software Operations
  *
- * Santosh Yaraganavi <santosh.sy@samsung.com>
- * Vinayak Holikatti <h.vinayak@samsung.com>
+ * 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.
  *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
+ * 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 <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/bitops.h>
-
-#include <asm/irq.h>
-#include <asm/byteorder.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_eh.h>
-
-#include "ufs.h"
-#include "ufshci.h"
-
-#define UFSHCD "ufshcd"
-#define UFSHCD_DRIVER_VERSION "0.1"
+#include "ufshcd.h"
 
 enum {
 	UFSHCD_MAX_CHANNEL	= 0,
@@ -102,121 +64,6 @@
 };
 
 /**
- * struct uic_command - UIC command structure
- * @command: UIC command
- * @argument1: UIC command argument 1
- * @argument2: UIC command argument 2
- * @argument3: UIC command argument 3
- * @cmd_active: Indicate if UIC command is outstanding
- * @result: UIC command result
- */
-struct uic_command {
-	u32 command;
-	u32 argument1;
-	u32 argument2;
-	u32 argument3;
-	int cmd_active;
-	int result;
-};
-
-/**
- * struct ufs_hba - per adapter private structure
- * @mmio_base: UFSHCI base register address
- * @ucdl_base_addr: UFS Command Descriptor base address
- * @utrdl_base_addr: UTP Transfer Request Descriptor base address
- * @utmrdl_base_addr: UTP Task Management Descriptor base address
- * @ucdl_dma_addr: UFS Command Descriptor DMA address
- * @utrdl_dma_addr: UTRDL DMA address
- * @utmrdl_dma_addr: UTMRDL DMA address
- * @host: Scsi_Host instance of the driver
- * @pdev: PCI device handle
- * @lrb: local reference block
- * @outstanding_tasks: Bits representing outstanding task requests
- * @outstanding_reqs: Bits representing outstanding transfer requests
- * @capabilities: UFS Controller Capabilities
- * @nutrs: Transfer Request Queue depth supported by controller
- * @nutmrs: Task Management Queue depth supported by controller
- * @active_uic_cmd: handle of active UIC command
- * @ufshcd_tm_wait_queue: wait queue for task management
- * @tm_condition: condition variable for task management
- * @ufshcd_state: UFSHCD states
- * @int_enable_mask: Interrupt Mask Bits
- * @uic_workq: Work queue for UIC completion handling
- * @feh_workq: Work queue for fatal controller error handling
- * @errors: HBA errors
- */
-struct ufs_hba {
-	void __iomem *mmio_base;
-
-	/* Virtual memory reference */
-	struct utp_transfer_cmd_desc *ucdl_base_addr;
-	struct utp_transfer_req_desc *utrdl_base_addr;
-	struct utp_task_req_desc *utmrdl_base_addr;
-
-	/* DMA memory reference */
-	dma_addr_t ucdl_dma_addr;
-	dma_addr_t utrdl_dma_addr;
-	dma_addr_t utmrdl_dma_addr;
-
-	struct Scsi_Host *host;
-	struct pci_dev *pdev;
-
-	struct ufshcd_lrb *lrb;
-
-	unsigned long outstanding_tasks;
-	unsigned long outstanding_reqs;
-
-	u32 capabilities;
-	int nutrs;
-	int nutmrs;
-	u32 ufs_version;
-
-	struct uic_command active_uic_cmd;
-	wait_queue_head_t ufshcd_tm_wait_queue;
-	unsigned long tm_condition;
-
-	u32 ufshcd_state;
-	u32 int_enable_mask;
-
-	/* Work Queues */
-	struct work_struct uic_workq;
-	struct work_struct feh_workq;
-
-	/* HBA Errors */
-	u32 errors;
-};
-
-/**
- * struct ufshcd_lrb - local reference block
- * @utr_descriptor_ptr: UTRD address of the command
- * @ucd_cmd_ptr: UCD address of the command
- * @ucd_rsp_ptr: Response UPIU address for this command
- * @ucd_prdt_ptr: PRDT address of the command
- * @cmd: pointer to SCSI command
- * @sense_buffer: pointer to sense buffer address of the SCSI command
- * @sense_bufflen: Length of the sense buffer
- * @scsi_status: SCSI status of the command
- * @command_type: SCSI, UFS, Query.
- * @task_tag: Task tag of the command
- * @lun: LUN of the command
- */
-struct ufshcd_lrb {
-	struct utp_transfer_req_desc *utr_descriptor_ptr;
-	struct utp_upiu_cmd *ucd_cmd_ptr;
-	struct utp_upiu_rsp *ucd_rsp_ptr;
-	struct ufshcd_sg_entry *ucd_prdt_ptr;
-
-	struct scsi_cmnd *cmd;
-	u8 *sense_buffer;
-	unsigned int sense_bufflen;
-	int scsi_status;
-
-	int command_type;
-	int task_tag;
-	unsigned int lun;
-};
-
-/**
  * ufshcd_get_ufs_version - Get the UFS version supported by the HBA
  * @hba - Pointer to adapter instance
  *
@@ -335,21 +182,21 @@
 
 	if (hba->utmrdl_base_addr) {
 		utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
-		dma_free_coherent(&hba->pdev->dev, utmrdl_size,
+		dma_free_coherent(hba->dev, utmrdl_size,
 				  hba->utmrdl_base_addr, hba->utmrdl_dma_addr);
 	}
 
 	if (hba->utrdl_base_addr) {
 		utrdl_size =
 		(sizeof(struct utp_transfer_req_desc) * hba->nutrs);
-		dma_free_coherent(&hba->pdev->dev, utrdl_size,
+		dma_free_coherent(hba->dev, utrdl_size,
 				  hba->utrdl_base_addr, hba->utrdl_dma_addr);
 	}
 
 	if (hba->ucdl_base_addr) {
 		ucdl_size =
 		(sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
-		dma_free_coherent(&hba->pdev->dev, ucdl_size,
+		dma_free_coherent(hba->dev, ucdl_size,
 				  hba->ucdl_base_addr, hba->ucdl_dma_addr);
 	}
 }
@@ -429,15 +276,6 @@
 }
 
 /**
- * ufshcd_hba_stop - Send controller to reset state
- * @hba: per adapter instance
- */
-static inline void ufshcd_hba_stop(struct ufs_hba *hba)
-{
-	writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
-}
-
-/**
  * ufshcd_hba_start - Start controller initialization sequence
  * @hba: per adapter instance
  */
@@ -724,7 +562,7 @@
 
 	/* Allocate memory for UTP command descriptors */
 	ucdl_size = (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
-	hba->ucdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
+	hba->ucdl_base_addr = dma_alloc_coherent(hba->dev,
 						 ucdl_size,
 						 &hba->ucdl_dma_addr,
 						 GFP_KERNEL);
@@ -737,7 +575,7 @@
 	 */
 	if (!hba->ucdl_base_addr ||
 	    WARN_ON(hba->ucdl_dma_addr & (PAGE_SIZE - 1))) {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"Command Descriptor Memory allocation failed\n");
 		goto out;
 	}
@@ -747,13 +585,13 @@
 	 * UFSHCI requires 1024 byte alignment of UTRD
 	 */
 	utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
-	hba->utrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
+	hba->utrdl_base_addr = dma_alloc_coherent(hba->dev,
 						  utrdl_size,
 						  &hba->utrdl_dma_addr,
 						  GFP_KERNEL);
 	if (!hba->utrdl_base_addr ||
 	    WARN_ON(hba->utrdl_dma_addr & (PAGE_SIZE - 1))) {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"Transfer Descriptor Memory allocation failed\n");
 		goto out;
 	}
@@ -763,13 +601,13 @@
 	 * UFSHCI requires 1024 byte alignment of UTMRD
 	 */
 	utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
-	hba->utmrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
+	hba->utmrdl_base_addr = dma_alloc_coherent(hba->dev,
 						   utmrdl_size,
 						   &hba->utmrdl_dma_addr,
 						   GFP_KERNEL);
 	if (!hba->utmrdl_base_addr ||
 	    WARN_ON(hba->utmrdl_dma_addr & (PAGE_SIZE - 1))) {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 		"Task Management Descriptor Memory allocation failed\n");
 		goto out;
 	}
@@ -777,7 +615,7 @@
 	/* Allocate memory for local reference block */
 	hba->lrb = kcalloc(hba->nutrs, sizeof(struct ufshcd_lrb), GFP_KERNEL);
 	if (!hba->lrb) {
-		dev_err(&hba->pdev->dev, "LRB Memory allocation failed\n");
+		dev_err(hba->dev, "LRB Memory allocation failed\n");
 		goto out;
 	}
 	return 0;
@@ -867,7 +705,7 @@
 	/* check if controller is ready to accept UIC commands */
 	if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
 	    UIC_COMMAND_READY) == 0x0) {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"Controller not ready"
 			" to accept UIC commands\n");
 		return -EIO;
@@ -912,7 +750,7 @@
 	/* check if device present */
 	reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
 	if (!ufshcd_is_device_present(reg)) {
-		dev_err(&hba->pdev->dev, "cc: Device not present\n");
+		dev_err(hba->dev, "cc: Device not present\n");
 		err = -ENXIO;
 		goto out;
 	}
@@ -924,7 +762,7 @@
 	if (!(ufshcd_get_lists_status(reg))) {
 		ufshcd_enable_run_stop_reg(hba);
 	} else {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"Host controller not ready to process requests");
 		err = -EIO;
 		goto out;
@@ -1005,7 +843,7 @@
 		if (retry) {
 			retry--;
 		} else {
-			dev_err(&hba->pdev->dev,
+			dev_err(hba->dev,
 				"Controller enable failed\n");
 			return -EIO;
 		}
@@ -1084,7 +922,7 @@
 
 	/* start the initialization process */
 	if (ufshcd_initialize_hba(hba)) {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"Reset: Controller initialization failed\n");
 		return FAILED;
 	}
@@ -1167,7 +1005,7 @@
 			task_result = SUCCESS;
 	} else {
 		task_result = FAILED;
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"trc: Invalid ocs = %x\n", ocs_value);
 	}
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -1281,7 +1119,7 @@
 		/* check if the returned transfer response is valid */
 		result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr);
 		if (result) {
-			dev_err(&hba->pdev->dev,
+			dev_err(hba->dev,
 				"Invalid response = %x\n", result);
 			break;
 		}
@@ -1310,7 +1148,7 @@
 	case OCS_FATAL_ERROR:
 	default:
 		result |= DID_ERROR << 16;
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 		"OCS error from controller = %x\n", ocs);
 		break;
 	} /* end of switch */
@@ -1374,7 +1212,7 @@
 	    !(ufshcd_get_uic_cmd_result(hba))) {
 
 		if (ufshcd_make_hba_operational(hba))
-			dev_err(&hba->pdev->dev,
+			dev_err(hba->dev,
 				"cc: hba not operational state\n");
 		return;
 	}
@@ -1509,7 +1347,7 @@
 	free_slot = ufshcd_get_tm_free_slot(hba);
 	if (free_slot >= hba->nutmrs) {
 		spin_unlock_irqrestore(host->host_lock, flags);
-		dev_err(&hba->pdev->dev, "Task management queue full\n");
+		dev_err(hba->dev, "Task management queue full\n");
 		err = FAILED;
 		goto out;
 	}
@@ -1552,7 +1390,7 @@
 					 &hba->tm_condition) != 0),
 					 60 * HZ);
 	if (!err) {
-		dev_err(&hba->pdev->dev,
+		dev_err(hba->dev,
 			"Task management command timed-out\n");
 		err = FAILED;
 		goto out;
@@ -1688,23 +1526,13 @@
 };
 
 /**
- * ufshcd_shutdown - main function to put the controller in reset state
- * @pdev: pointer to PCI device handle
- */
-static void ufshcd_shutdown(struct pci_dev *pdev)
-{
-	ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
-}
-
-#ifdef CONFIG_PM
-/**
  * ufshcd_suspend - suspend power management function
- * @pdev: pointer to PCI device handle
+ * @hba: per adapter instance
  * @state: power state
  *
  * Returns -ENOSYS
  */
-static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
+int ufshcd_suspend(struct ufs_hba *hba, pm_message_t state)
 {
 	/*
 	 * TODO:
@@ -1717,14 +1545,15 @@
 
 	return -ENOSYS;
 }
+EXPORT_SYMBOL_GPL(ufshcd_suspend);
 
 /**
  * ufshcd_resume - resume power management function
- * @pdev: pointer to PCI device handle
+ * @hba: per adapter instance
  *
  * Returns -ENOSYS
  */
-static int ufshcd_resume(struct pci_dev *pdev)
+int ufshcd_resume(struct ufs_hba *hba)
 {
 	/*
 	 * TODO:
@@ -1737,7 +1566,7 @@
 
 	return -ENOSYS;
 }
-#endif /* CONFIG_PM */
+EXPORT_SYMBOL_GPL(ufshcd_resume);
 
 /**
  * ufshcd_hba_free - free allocated memory for
@@ -1748,108 +1577,67 @@
 {
 	iounmap(hba->mmio_base);
 	ufshcd_free_hba_memory(hba);
-	pci_release_regions(hba->pdev);
 }
 
 /**
- * ufshcd_remove - de-allocate PCI/SCSI host and host memory space
+ * ufshcd_remove - de-allocate SCSI host and host memory space
  *		data structure memory
- * @pdev - pointer to PCI handle
+ * @hba - per adapter instance
  */
-static void ufshcd_remove(struct pci_dev *pdev)
+void ufshcd_remove(struct ufs_hba *hba)
 {
-	struct ufs_hba *hba = pci_get_drvdata(pdev);
-
 	/* disable interrupts */
 	ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
-	free_irq(pdev->irq, hba);
 
 	ufshcd_hba_stop(hba);
 	ufshcd_hba_free(hba);
 
 	scsi_remove_host(hba->host);
 	scsi_host_put(hba->host);
-	pci_set_drvdata(pdev, NULL);
-	pci_clear_master(pdev);
-	pci_disable_device(pdev);
 }
+EXPORT_SYMBOL_GPL(ufshcd_remove);
 
 /**
- * ufshcd_set_dma_mask - Set dma mask based on the controller
- *			 addressing capability
- * @pdev: PCI device structure
- *
- * Returns 0 for success, non-zero for failure
- */
-static int ufshcd_set_dma_mask(struct ufs_hba *hba)
-{
-	int err;
-	u64 dma_mask;
-
-	/*
-	 * If controller supports 64 bit addressing mode, then set the DMA
-	 * mask to 64-bit, else set the DMA mask to 32-bit
-	 */
-	if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT)
-		dma_mask = DMA_BIT_MASK(64);
-	else
-		dma_mask = DMA_BIT_MASK(32);
-
-	err = pci_set_dma_mask(hba->pdev, dma_mask);
-	if (err)
-		return err;
-
-	err = pci_set_consistent_dma_mask(hba->pdev, dma_mask);
-
-	return err;
-}
-
-/**
- * ufshcd_probe - probe routine of the driver
- * @pdev: pointer to PCI device handle
- * @id: PCI device id
- *
+ * ufshcd_init - Driver initialization routine
+ * @dev: pointer to device handle
+ * @hba_handle: driver private handle
+ * @mmio_base: base register address
+ * @irq: Interrupt line of device
  * Returns 0 on success, non-zero value on failure
  */
-static int __devinit
-ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
+		 void __iomem *mmio_base, unsigned int irq)
 {
 	struct Scsi_Host *host;
 	struct ufs_hba *hba;
 	int err;
 
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "pci_enable_device failed\n");
+	if (!dev) {
+		dev_err(dev,
+		"Invalid memory reference for dev is NULL\n");
+		err = -ENODEV;
 		goto out_error;
 	}
 
-	pci_set_master(pdev);
+	if (!mmio_base) {
+		dev_err(dev,
+		"Invalid memory reference for mmio_base is NULL\n");
+		err = -ENODEV;
+		goto out_error;
+	}
 
 	host = scsi_host_alloc(&ufshcd_driver_template,
 				sizeof(struct ufs_hba));
 	if (!host) {
-		dev_err(&pdev->dev, "scsi_host_alloc failed\n");
+		dev_err(dev, "scsi_host_alloc failed\n");
 		err = -ENOMEM;
-		goto out_disable;
+		goto out_error;
 	}
 	hba = shost_priv(host);
-
-	err = pci_request_regions(pdev, UFSHCD);
-	if (err < 0) {
-		dev_err(&pdev->dev, "request regions failed\n");
-		goto out_host_put;
-	}
-
-	hba->mmio_base = pci_ioremap_bar(pdev, 0);
-	if (!hba->mmio_base) {
-		dev_err(&pdev->dev, "memory map failed\n");
-		err = -ENOMEM;
-		goto out_release_regions;
-	}
-
 	hba->host = host;
-	hba->pdev = pdev;
+	hba->dev = dev;
+	hba->mmio_base = mmio_base;
+	hba->irq = irq;
 
 	/* Read capabilities registers */
 	ufshcd_hba_capabilities(hba);
@@ -1857,17 +1645,11 @@
 	/* Get UFS version supported by the controller */
 	hba->ufs_version = ufshcd_get_ufs_version(hba);
 
-	err = ufshcd_set_dma_mask(hba);
-	if (err) {
-		dev_err(&pdev->dev, "set dma mask failed\n");
-		goto out_iounmap;
-	}
-
 	/* Allocate memory for host memory space */
 	err = ufshcd_memory_alloc(hba);
 	if (err) {
-		dev_err(&pdev->dev, "Memory allocation failed\n");
-		goto out_iounmap;
+		dev_err(hba->dev, "Memory allocation failed\n");
+		goto out_disable;
 	}
 
 	/* Configure LRB */
@@ -1889,76 +1671,50 @@
 	INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
 
 	/* IRQ registration */
-	err = request_irq(pdev->irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
+	err = request_irq(irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
 	if (err) {
-		dev_err(&pdev->dev, "request irq failed\n");
+		dev_err(hba->dev, "request irq failed\n");
 		goto out_lrb_free;
 	}
 
 	/* Enable SCSI tag mapping */
 	err = scsi_init_shared_tag_map(host, host->can_queue);
 	if (err) {
-		dev_err(&pdev->dev, "init shared queue failed\n");
+		dev_err(hba->dev, "init shared queue failed\n");
 		goto out_free_irq;
 	}
 
-	pci_set_drvdata(pdev, hba);
-
-	err = scsi_add_host(host, &pdev->dev);
+	err = scsi_add_host(host, hba->dev);
 	if (err) {
-		dev_err(&pdev->dev, "scsi_add_host failed\n");
+		dev_err(hba->dev, "scsi_add_host failed\n");
 		goto out_free_irq;
 	}
 
 	/* Initialization routine */
 	err = ufshcd_initialize_hba(hba);
 	if (err) {
-		dev_err(&pdev->dev, "Initialization failed\n");
-		goto out_free_irq;
+		dev_err(hba->dev, "Initialization failed\n");
+		goto out_remove_scsi_host;
 	}
+	*hba_handle = hba;
 
 	return 0;
 
+out_remove_scsi_host:
+	scsi_remove_host(hba->host);
 out_free_irq:
-	free_irq(pdev->irq, hba);
+	free_irq(irq, hba);
 out_lrb_free:
 	ufshcd_free_hba_memory(hba);
-out_iounmap:
-	iounmap(hba->mmio_base);
-out_release_regions:
-	pci_release_regions(pdev);
-out_host_put:
-	scsi_host_put(host);
 out_disable:
-	pci_clear_master(pdev);
-	pci_disable_device(pdev);
+	scsi_host_put(host);
 out_error:
 	return err;
 }
+EXPORT_SYMBOL_GPL(ufshcd_init);
 
-static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
-	{ PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ }	/* terminate list */
-};
-
-MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
-
-static struct pci_driver ufshcd_pci_driver = {
-	.name = UFSHCD,
-	.id_table = ufshcd_pci_tbl,
-	.probe = ufshcd_probe,
-	.remove = __devexit_p(ufshcd_remove),
-	.shutdown = ufshcd_shutdown,
-#ifdef CONFIG_PM
-	.suspend = ufshcd_suspend,
-	.resume = ufshcd_resume,
-#endif
-};
-
-module_pci_driver(ufshcd_pci_driver);
-
-MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>, "
-	      "Vinayak Holikatti <h.vinayak@samsung.com>");
-MODULE_DESCRIPTION("Generic UFS host controller driver");
+MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
+MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
+MODULE_DESCRIPTION("Generic UFS host controller driver Core");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
new file mode 100644
index 0000000..6b99a42
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -0,0 +1,202 @@
+/*
+ * Universal Flash Storage Host controller driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd.h
+ * 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.
+ */
+
+#ifndef _UFSHCD_H
+#define _UFSHCD_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+
+#include <asm/irq.h>
+#include <asm/byteorder.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_eh.h>
+
+#include "ufs.h"
+#include "ufshci.h"
+
+#define UFSHCD "ufshcd"
+#define UFSHCD_DRIVER_VERSION "0.2"
+
+/**
+ * struct uic_command - UIC command structure
+ * @command: UIC command
+ * @argument1: UIC command argument 1
+ * @argument2: UIC command argument 2
+ * @argument3: UIC command argument 3
+ * @cmd_active: Indicate if UIC command is outstanding
+ * @result: UIC command result
+ */
+struct uic_command {
+	u32 command;
+	u32 argument1;
+	u32 argument2;
+	u32 argument3;
+	int cmd_active;
+	int result;
+};
+
+/**
+ * struct ufshcd_lrb - local reference block
+ * @utr_descriptor_ptr: UTRD address of the command
+ * @ucd_cmd_ptr: UCD address of the command
+ * @ucd_rsp_ptr: Response UPIU address for this command
+ * @ucd_prdt_ptr: PRDT address of the command
+ * @cmd: pointer to SCSI command
+ * @sense_buffer: pointer to sense buffer address of the SCSI command
+ * @sense_bufflen: Length of the sense buffer
+ * @scsi_status: SCSI status of the command
+ * @command_type: SCSI, UFS, Query.
+ * @task_tag: Task tag of the command
+ * @lun: LUN of the command
+ */
+struct ufshcd_lrb {
+	struct utp_transfer_req_desc *utr_descriptor_ptr;
+	struct utp_upiu_cmd *ucd_cmd_ptr;
+	struct utp_upiu_rsp *ucd_rsp_ptr;
+	struct ufshcd_sg_entry *ucd_prdt_ptr;
+
+	struct scsi_cmnd *cmd;
+	u8 *sense_buffer;
+	unsigned int sense_bufflen;
+	int scsi_status;
+
+	int command_type;
+	int task_tag;
+	unsigned int lun;
+};
+
+
+/**
+ * struct ufs_hba - per adapter private structure
+ * @mmio_base: UFSHCI base register address
+ * @ucdl_base_addr: UFS Command Descriptor base address
+ * @utrdl_base_addr: UTP Transfer Request Descriptor base address
+ * @utmrdl_base_addr: UTP Task Management Descriptor base address
+ * @ucdl_dma_addr: UFS Command Descriptor DMA address
+ * @utrdl_dma_addr: UTRDL DMA address
+ * @utmrdl_dma_addr: UTMRDL DMA address
+ * @host: Scsi_Host instance of the driver
+ * @dev: device handle
+ * @lrb: local reference block
+ * @outstanding_tasks: Bits representing outstanding task requests
+ * @outstanding_reqs: Bits representing outstanding transfer requests
+ * @capabilities: UFS Controller Capabilities
+ * @nutrs: Transfer Request Queue depth supported by controller
+ * @nutmrs: Task Management Queue depth supported by controller
+ * @ufs_version: UFS Version to which controller complies
+ * @irq: Irq number of the controller
+ * @active_uic_cmd: handle of active UIC command
+ * @ufshcd_tm_wait_queue: wait queue for task management
+ * @tm_condition: condition variable for task management
+ * @ufshcd_state: UFSHCD states
+ * @int_enable_mask: Interrupt Mask Bits
+ * @uic_workq: Work queue for UIC completion handling
+ * @feh_workq: Work queue for fatal controller error handling
+ * @errors: HBA errors
+ */
+struct ufs_hba {
+	void __iomem *mmio_base;
+
+	/* Virtual memory reference */
+	struct utp_transfer_cmd_desc *ucdl_base_addr;
+	struct utp_transfer_req_desc *utrdl_base_addr;
+	struct utp_task_req_desc *utmrdl_base_addr;
+
+	/* DMA memory reference */
+	dma_addr_t ucdl_dma_addr;
+	dma_addr_t utrdl_dma_addr;
+	dma_addr_t utmrdl_dma_addr;
+
+	struct Scsi_Host *host;
+	struct device *dev;
+
+	struct ufshcd_lrb *lrb;
+
+	unsigned long outstanding_tasks;
+	unsigned long outstanding_reqs;
+
+	u32 capabilities;
+	int nutrs;
+	int nutmrs;
+	u32 ufs_version;
+	unsigned int irq;
+
+	struct uic_command active_uic_cmd;
+	wait_queue_head_t ufshcd_tm_wait_queue;
+	unsigned long tm_condition;
+
+	u32 ufshcd_state;
+	u32 int_enable_mask;
+
+	/* Work Queues */
+	struct work_struct uic_workq;
+	struct work_struct feh_workq;
+
+	/* HBA Errors */
+	u32 errors;
+};
+
+int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * ,
+			unsigned int);
+void ufshcd_remove(struct ufs_hba *);
+
+/**
+ * ufshcd_hba_stop - Send controller to reset state
+ * @hba: per adapter instance
+ */
+static inline void ufshcd_hba_stop(struct ufs_hba *hba)
+{
+	writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
+}
+
+#endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 6e3510f..0c16484 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -2,45 +2,35 @@
  * Universal Flash Storage Host controller driver
  *
  * This code is based on drivers/scsi/ufs/ufshci.h
- * Copyright (C) 2011-2012 Samsung India Software Operations
+ * Copyright (C) 2011-2013 Samsung India Software Operations
  *
- * Santosh Yaraganavi <santosh.sy@samsung.com>
- * Vinayak Holikatti <h.vinayak@samsung.com>
+ * 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.
  *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
+ * 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.
  */
 
 #ifndef _UFSHCI_H
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 7f60128..b89f608 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.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
@@ -276,13 +276,12 @@
 		if (dd->input_block_size == 4 || dd->output_block_size == 4)
 			dd->use_dma = 0;
 
-		/* DM mode is currently unsupported for different block sizes */
-		if (dd->input_block_size != dd->output_block_size)
-			dd->use_dma = 0;
-
-		if (dd->use_dma)
-			dd->burst_size = max(dd->input_block_size,
-							DM_BURST_SIZE);
+		if (dd->use_dma) {
+			dd->input_burst_size = max(dd->input_block_size,
+						DM_BURST_SIZE);
+			dd->output_burst_size = max(dd->output_block_size,
+						DM_BURST_SIZE);
+		}
 	}
 
 	return;
@@ -646,7 +645,8 @@
 static void msm_spi_setup_dm_transfer(struct msm_spi *dd)
 {
 	dmov_box *box;
-	int bytes_to_send, num_rows, bytes_sent;
+	int bytes_to_send, bytes_sent;
+	int tx_num_rows, rx_num_rows;
 	u32 num_transfers;
 
 	atomic_set(&dd->rx_irq_called, 0);
@@ -678,64 +678,80 @@
 			      dd->max_trfr_len);
 
 	num_transfers = DIV_ROUND_UP(bytes_to_send, dd->bytes_per_word);
-	dd->unaligned_len = bytes_to_send % dd->burst_size;
-	num_rows = bytes_to_send / dd->burst_size;
+	dd->tx_unaligned_len = bytes_to_send % dd->output_burst_size;
+	dd->rx_unaligned_len = bytes_to_send % dd->input_burst_size;
+	tx_num_rows = bytes_to_send / dd->output_burst_size;
+	rx_num_rows = bytes_to_send / dd->input_burst_size;
 
 	dd->mode = SPI_DMOV_MODE;
 
-	if (num_rows) {
+	if (tx_num_rows) {
 		/* src in 16 MSB, dst in 16 LSB */
 		box = &dd->tx_dmov_cmd->box;
 		box->src_row_addr = dd->cur_transfer->tx_dma + bytes_sent;
-		box->src_dst_len = (dd->burst_size << 16) | dd->burst_size;
-		box->num_rows = (num_rows << 16) | num_rows;
-		box->row_offset = (dd->burst_size << 16) | 0;
+		box->src_dst_len
+			= (dd->output_burst_size << 16) | dd->output_burst_size;
+		box->num_rows = (tx_num_rows << 16) | tx_num_rows;
+		box->row_offset = (dd->output_burst_size << 16) | 0;
 
+		dd->tx_dmov_cmd->cmd_ptr = CMD_PTR_LP |
+				   DMOV_CMD_ADDR(dd->tx_dmov_cmd_dma +
+				   offsetof(struct spi_dmov_cmd, box));
+	} else {
+		dd->tx_dmov_cmd->cmd_ptr = CMD_PTR_LP |
+				   DMOV_CMD_ADDR(dd->tx_dmov_cmd_dma +
+				   offsetof(struct spi_dmov_cmd, single_pad));
+	}
+
+	if (rx_num_rows) {
+		/* src in 16 MSB, dst in 16 LSB */
 		box = &dd->rx_dmov_cmd->box;
 		box->dst_row_addr = dd->cur_transfer->rx_dma + bytes_sent;
-		box->src_dst_len = (dd->burst_size << 16) | dd->burst_size;
-		box->num_rows = (num_rows << 16) | num_rows;
-		box->row_offset = (0 << 16) | dd->burst_size;
+		box->src_dst_len
+			= (dd->input_burst_size << 16) | dd->input_burst_size;
+		box->num_rows = (rx_num_rows << 16) | rx_num_rows;
+		box->row_offset = (0 << 16) | dd->input_burst_size;
 
-		dd->tx_dmov_cmd->cmd_ptr = CMD_PTR_LP |
-				   DMOV_CMD_ADDR(dd->tx_dmov_cmd_dma +
-				   offsetof(struct spi_dmov_cmd, box));
 		dd->rx_dmov_cmd->cmd_ptr = CMD_PTR_LP |
 				   DMOV_CMD_ADDR(dd->rx_dmov_cmd_dma +
 				   offsetof(struct spi_dmov_cmd, box));
 	} else {
-		dd->tx_dmov_cmd->cmd_ptr = CMD_PTR_LP |
-				   DMOV_CMD_ADDR(dd->tx_dmov_cmd_dma +
-				   offsetof(struct spi_dmov_cmd, single_pad));
 		dd->rx_dmov_cmd->cmd_ptr = CMD_PTR_LP |
 				   DMOV_CMD_ADDR(dd->rx_dmov_cmd_dma +
 				   offsetof(struct spi_dmov_cmd, single_pad));
 	}
 
-	if (!dd->unaligned_len) {
+	if (!dd->tx_unaligned_len) {
 		dd->tx_dmov_cmd->box.cmd |= CMD_LC;
-		dd->rx_dmov_cmd->box.cmd |= CMD_LC;
 	} else {
 		dmov_s *tx_cmd = &(dd->tx_dmov_cmd->single_pad);
-		dmov_s *rx_cmd = &(dd->rx_dmov_cmd->single_pad);
-		u32 offset = dd->cur_transfer->len - dd->unaligned_len;
+		u32 tx_offset = dd->cur_transfer->len - dd->tx_unaligned_len;
 
 		if ((dd->multi_xfr) && (dd->read_len <= 0))
-			offset = dd->cur_msg_len - dd->unaligned_len;
+			tx_offset = dd->cur_msg_len - dd->tx_unaligned_len;
 
 		dd->tx_dmov_cmd->box.cmd &= ~CMD_LC;
-		dd->rx_dmov_cmd->box.cmd &= ~CMD_LC;
 
-		memset(dd->tx_padding, 0, dd->burst_size);
-		memset(dd->rx_padding, 0, dd->burst_size);
+		memset(dd->tx_padding, 0, dd->output_burst_size);
 		if (dd->write_buf)
-			memcpy(dd->tx_padding, dd->write_buf + offset,
-			       dd->unaligned_len);
+			memcpy(dd->tx_padding, dd->write_buf + tx_offset,
+			       dd->tx_unaligned_len);
 
 		tx_cmd->src = dd->tx_padding_dma;
-		rx_cmd->dst = dd->rx_padding_dma;
-		tx_cmd->len = rx_cmd->len = dd->burst_size;
+		tx_cmd->len = dd->output_burst_size;
 	}
+
+	if (!dd->rx_unaligned_len) {
+		dd->rx_dmov_cmd->box.cmd |= CMD_LC;
+	} else {
+		dmov_s *rx_cmd = &(dd->rx_dmov_cmd->single_pad);
+		dd->rx_dmov_cmd->box.cmd &= ~CMD_LC;
+
+		memset(dd->rx_padding, 0, dd->input_burst_size);
+		rx_cmd->dst = dd->rx_padding_dma;
+		rx_cmd->len = dd->input_burst_size;
+	}
+
 	/* This also takes care of the padding dummy buf
 	   Since this is set to the correct length, the
 	   dummy bytes won't be actually sent */
@@ -893,7 +909,7 @@
 		if ((!dd->read_buf || op & SPI_OP_MAX_INPUT_DONE_FLAG) &&
 		    (!dd->write_buf || op & SPI_OP_MAX_OUTPUT_DONE_FLAG)) {
 			msm_spi_ack_transfer(dd);
-			if (dd->unaligned_len == 0) {
+			if (dd->rx_unaligned_len == 0) {
 				if (atomic_inc_return(&dd->rx_irq_called) == 1)
 					return IRQ_HANDLED;
 			}
@@ -1145,11 +1161,11 @@
 						 prev_xfr->len,
 						 DMA_TO_DEVICE);
 			}
-			if (dd->unaligned_len && dd->read_buf) {
-				offset = dd->cur_msg_len - dd->unaligned_len;
+			if (dd->rx_unaligned_len && dd->read_buf) {
+				offset = dd->cur_msg_len - dd->rx_unaligned_len;
 				dma_coherent_post_ops();
 				memcpy(dd->read_buf + offset, dd->rx_padding,
-				       dd->unaligned_len);
+				       dd->rx_unaligned_len);
 				memcpy(dd->cur_transfer->rx_buf,
 				       dd->read_buf + prev_xfr->len,
 				       dd->cur_transfer->len);
@@ -1171,11 +1187,11 @@
 
 unmap_end:
 	/* If we padded the transfer, we copy it from the padding buf */
-	if (dd->unaligned_len && dd->read_buf) {
-		offset = dd->cur_transfer->len - dd->unaligned_len;
+	if (dd->rx_unaligned_len && dd->read_buf) {
+		offset = dd->cur_transfer->len - dd->rx_unaligned_len;
 		dma_coherent_post_ops();
 		memcpy(dd->read_buf + offset, dd->rx_padding,
-		       dd->unaligned_len);
+		       dd->rx_unaligned_len);
 	}
 }
 
@@ -1960,7 +1976,8 @@
 			"use_dma ?    %s\n"
 			"rx block size = %d bytes\n"
 			"tx block size = %d bytes\n"
-			"burst size = %d bytes\n"
+			"input burst size = %d bytes\n"
+			"output burst size = %d bytes\n"
 			"DMA configuration:\n"
 			"tx_ch=%d, rx_ch=%d, tx_crci= %d, rx_crci=%d\n"
 			"--statistics--\n"
@@ -1975,7 +1992,8 @@
 			dd->use_dma ? "yes" : "no",
 			dd->input_block_size,
 			dd->output_block_size,
-			dd->burst_size,
+			dd->input_burst_size,
+			dd->output_burst_size,
 			dd->tx_dma_chan,
 			dd->rx_dma_chan,
 			dd->tx_dma_crci,
@@ -2104,12 +2122,15 @@
 	}
 }
 
-static inline u32 get_chunk_size(struct msm_spi *dd)
+static inline u32 get_chunk_size(struct msm_spi *dd, int input_burst_size,
+			int output_burst_size)
 {
 	u32 cache_line = dma_get_cache_alignment();
+	int burst_size = (input_burst_size > output_burst_size) ?
+		input_burst_size : output_burst_size;
 
 	return (roundup(sizeof(struct spi_dmov_cmd), DM_BYTE_ALIGN) +
-			  roundup(dd->burst_size, cache_line))*2;
+			  roundup(burst_size, cache_line))*2;
 }
 
 static void msm_spi_dmov_teardown(struct msm_spi *dd)
@@ -2125,8 +2146,10 @@
 		msleep(10);
 	}
 
-	dma_free_coherent(NULL, get_chunk_size(dd), dd->tx_dmov_cmd,
-			  dd->tx_dmov_cmd_dma);
+	dma_free_coherent(NULL,
+		get_chunk_size(dd, dd->input_burst_size, dd->output_burst_size),
+		dd->tx_dmov_cmd,
+		dd->tx_dmov_cmd_dma);
 	dd->tx_dmov_cmd = dd->rx_dmov_cmd = NULL;
 	dd->tx_padding = dd->rx_padding = NULL;
 }
@@ -2304,8 +2327,11 @@
 
 	/* We send NULL device, since it requires coherent_dma_mask id
 	   device definition, we're okay with using system pool */
-	dd->tx_dmov_cmd = dma_alloc_coherent(NULL, get_chunk_size(dd),
-					     &dd->tx_dmov_cmd_dma, GFP_KERNEL);
+	dd->tx_dmov_cmd
+		= dma_alloc_coherent(NULL,
+			get_chunk_size(dd, dd->input_burst_size,
+				dd->output_burst_size),
+			&dd->tx_dmov_cmd_dma, GFP_KERNEL);
 	if (dd->tx_dmov_cmd == NULL)
 		return -ENOMEM;
 
@@ -2319,9 +2345,9 @@
 	dd->tx_padding = (u8 *)ALIGN((size_t)&dd->rx_dmov_cmd[1], cache_line);
 	dd->tx_padding_dma = ALIGN(dd->rx_dmov_cmd_dma +
 			      sizeof(struct spi_dmov_cmd), cache_line);
-	dd->rx_padding = (u8 *)ALIGN((size_t)(dd->tx_padding + dd->burst_size),
-				     cache_line);
-	dd->rx_padding_dma = ALIGN(dd->tx_padding_dma + dd->burst_size,
+	dd->rx_padding = (u8 *)ALIGN((size_t)(dd->tx_padding +
+		dd->output_burst_size), cache_line);
+	dd->rx_padding_dma = ALIGN(dd->tx_padding_dma + dd->output_burst_size,
 				      cache_line);
 
 	/* Setup DM commands */
diff --git a/drivers/spi/spi_qsd.h b/drivers/spi/spi_qsd.h
index 7f5b726..b749cc0 100644
--- a/drivers/spi/spi_qsd.h
+++ b/drivers/spi/spi_qsd.h
@@ -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
@@ -318,7 +318,8 @@
 	struct msm_dmov_cmd      rx_hdr;
 	int                      input_block_size;
 	int                      output_block_size;
-	int                      burst_size;
+	int                      input_burst_size;
+	int                      output_burst_size;
 	atomic_t                 rx_irq_called;
 	atomic_t                 tx_irq_called;
 	/* Used to pad messages unaligned to block size */
@@ -326,7 +327,8 @@
 	dma_addr_t               tx_padding_dma;
 	u8                       *rx_padding;
 	dma_addr_t               rx_padding_dma;
-	u32                      unaligned_len;
+	u32                      tx_unaligned_len;
+	u32                      rx_unaligned_len;
 	/* DMA statistics */
 	int                      stat_dmov_tx_err;
 	int                      stat_dmov_rx_err;
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index 0348145..8760603 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -1719,7 +1719,7 @@
  */
 static int smux_handle_rx_power_cmd(struct smux_pkt_t *pkt)
 {
-	struct smux_pkt_t *ack_pkt = NULL;
+	struct smux_pkt_t *ack_pkt;
 	int power_down = 0;
 	unsigned long flags;
 
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index c982587..65e4989 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -218,6 +218,7 @@
 	u32 bus_perf_client;
 	/* BLSP UART required BUS Scaling data */
 	struct msm_bus_scale_pdata *bus_scale_table;
+	bool rx_discard_flush_issued;
 };
 
 #define MSM_UARTDM_BURST_SIZE 16   /* DM burst size (in bytes) */
@@ -229,6 +230,7 @@
 #define BAM_PIPE_MAX 11
 #define BUS_SCALING 1
 #define BUS_RESET 0
+#define RX_FLUSH_COMPLETE_TIMEOUT 300 /* In jiffies */
 
 static struct dentry *debug_base;
 static struct msm_hs_port q_uart_port[UARTDM_NR];
@@ -849,6 +851,7 @@
 {
 	unsigned int bps;
 	unsigned long data;
+	int ret;
 	unsigned int c_cflag = termios->c_cflag;
 	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 	struct msm_hs_rx *rx = &msm_uport->rx;
@@ -969,8 +972,17 @@
 			msm_hs_spsconnect_rx(uport);
 			msm_serial_hs_rx_tlet((unsigned long) &rx->tlet);
 		} else {
+			msm_uport->rx_discard_flush_issued = true;
 			/* do discard flush */
 			msm_dmov_flush(msm_uport->dma_rx_channel, 0);
+			pr_debug("%s(): wainting for flush completion.\n",
+								__func__);
+			ret = wait_event_timeout(msm_uport->rx.wait,
+				msm_uport->rx_discard_flush_issued == false,
+				RX_FLUSH_COMPLETE_TIMEOUT);
+			if (!ret)
+				pr_err("%s(): Discard flush pending.\n",
+								__func__);
 		}
 	}
 
@@ -1514,8 +1526,23 @@
 					struct msm_dmov_errdata *err)
 {
 	struct msm_hs_port *msm_uport;
+	struct uart_port *uport;
+	unsigned long flags;
 
 	msm_uport = container_of(cmd_ptr, struct msm_hs_port, rx.xfer);
+	uport = &(msm_uport->uport);
+
+	pr_debug("%s(): called result:%x\n", __func__, result);
+	if (!(result & DMOV_RSLT_ERROR)) {
+		if (result & DMOV_RSLT_FLUSH) {
+			if (msm_uport->rx_discard_flush_issued) {
+				spin_lock_irqsave(&uport->lock, flags);
+				msm_uport->rx_discard_flush_issued = false;
+				spin_unlock_irqrestore(&uport->lock, flags);
+				wake_up(&msm_uport->rx.wait);
+			}
+		}
+	}
 
 	tasklet_schedule(&msm_uport->rx.tlet);
 }
@@ -1661,6 +1688,7 @@
 {
 	unsigned long sr_status;
 	unsigned long flags;
+	int ret;
 	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 	struct circ_buf *tx_buf = &uport->state->xmit;
 
@@ -1716,10 +1744,23 @@
 	}
 
 	if (msm_uport->rx.flush != FLUSH_SHUTDOWN) {
-		if (msm_uport->rx.flush == FLUSH_NONE)
+		if (msm_uport->rx.flush == FLUSH_NONE) {
 			msm_hs_stop_rx_locked(uport);
+			msm_uport->rx_discard_flush_issued = true;
+		}
 
 		spin_unlock_irqrestore(&uport->lock, flags);
+		if (msm_uport->rx_discard_flush_issued) {
+			pr_debug("%s(): wainting for flush completion.\n",
+								__func__);
+			ret = wait_event_timeout(msm_uport->rx.wait,
+				msm_uport->rx_discard_flush_issued == false,
+				RX_FLUSH_COMPLETE_TIMEOUT);
+			if (!ret)
+				pr_err("%s(): Flush complete pending.\n",
+								__func__);
+		}
+
 		mutex_unlock(&msm_uport->clk_mutex);
 		return 0;  /* come back later to really clock off */
 	}
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 9dd9c40..87a0078 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -516,6 +516,82 @@
 /*-------------------------------------------------------------------------*/
 /* Supported functions initialization */
 
+/* ACM */
+static char acm_transports[32];	/*enabled ACM ports - "tty[,sdio]"*/
+static ssize_t acm_transports_store(
+		struct device *device, struct device_attribute *attr,
+		const char *buff, size_t size)
+{
+	strlcpy(acm_transports, buff, sizeof(acm_transports));
+
+	return size;
+}
+
+static DEVICE_ATTR(acm_transports, S_IWUSR, NULL, acm_transports_store);
+static struct device_attribute *acm_function_attributes[] = {
+		&dev_attr_acm_transports,
+		NULL
+};
+
+static void acm_function_cleanup(struct android_usb_function *f)
+{
+	gserial_cleanup();
+}
+
+static int
+acm_function_bind_config(struct android_usb_function *f,
+		struct usb_configuration *c)
+{
+	char *name;
+	char buf[32], *b;
+	int err = -1, i;
+	static int acm_initialized, ports;
+
+	if (acm_initialized)
+		goto bind_config;
+
+	acm_initialized = 1;
+	strlcpy(buf, acm_transports, sizeof(buf));
+	b = strim(buf);
+
+	while (b) {
+		name = strsep(&b, ",");
+
+		if (name) {
+			err = acm_init_port(ports, name);
+			if (err) {
+				pr_err("acm: Cannot open port '%s'", name);
+				goto out;
+			}
+			ports++;
+		}
+	}
+	err = acm_port_setup(c);
+	if (err) {
+		pr_err("acm: Cannot setup transports");
+		goto out;
+	}
+
+bind_config:
+	for (i = 0; i < ports; i++) {
+		err = acm_bind_config(c, i);
+		if (err) {
+			pr_err("acm: bind_config failed for port %d", i);
+			goto out;
+		}
+	}
+
+out:
+	return err;
+}
+
+static struct android_usb_function acm_function = {
+	.name		= "acm",
+	.cleanup	= acm_function_cleanup,
+	.bind_config	= acm_function_bind_config,
+	.attributes	= acm_function_attributes,
+};
+
 /* RMNET_SMD */
 static int rmnet_smd_function_bind_config(struct android_usb_function *f,
 					  struct usb_configuration *c)
@@ -996,78 +1072,6 @@
 	.attributes	= serial_function_attributes,
 };
 
-/* ACM */
-static char acm_transports[32];	/*enabled ACM ports - "tty[,sdio]"*/
-static ssize_t acm_transports_store(
-		struct device *device, struct device_attribute *attr,
-		const char *buff, size_t size)
-{
-	strlcpy(acm_transports, buff, sizeof(acm_transports));
-
-	return size;
-}
-
-static DEVICE_ATTR(acm_transports, S_IWUSR, NULL, acm_transports_store);
-static struct device_attribute *acm_function_attributes[] = {
-		&dev_attr_acm_transports, NULL };
-
-static void acm_function_cleanup(struct android_usb_function *f)
-{
-	gserial_cleanup();
-}
-
-static int acm_function_bind_config(struct android_usb_function *f,
-					struct usb_configuration *c)
-{
-	char *name;
-	char buf[32], *b;
-	int err = -1, i;
-	static int acm_initialized, ports;
-
-	if (acm_initialized)
-		goto bind_config;
-
-	acm_initialized = 1;
-	strlcpy(buf, acm_transports, sizeof(buf));
-	b = strim(buf);
-
-	while (b) {
-		name = strsep(&b, ",");
-
-		if (name) {
-			err = acm_init_port(ports, name);
-			if (err) {
-				pr_err("acm: Cannot open port '%s'", name);
-				goto out;
-			}
-			ports++;
-		}
-	}
-	err = acm_port_setup(c);
-	if (err) {
-		pr_err("acm: Cannot setup transports");
-		goto out;
-	}
-
-bind_config:
-	for (i = 0; i < ports; i++) {
-		err = acm_bind_config(c, i);
-		if (err) {
-			pr_err("acm: bind_config failed for port %d", i);
-			goto out;
-		}
-	}
-
-out:
-	return err;
-}
-static struct android_usb_function acm_function = {
-	.name		= "acm",
-	.cleanup	= acm_function_cleanup,
-	.bind_config	= acm_function_bind_config,
-	.attributes	= acm_function_attributes,
-};
-
 /* CCID */
 static int ccid_function_init(struct android_usb_function *f,
 					struct usb_composite_dev *cdev)
@@ -1093,7 +1097,8 @@
 	.bind_config	= ccid_function_bind_config,
 };
 
-static int mtp_function_init(struct android_usb_function *f,
+static int
+mtp_function_init(struct android_usb_function *f,
 		struct usb_composite_dev *cdev)
 {
 	return mtp_setup();
@@ -1104,13 +1109,16 @@
 	mtp_cleanup();
 }
 
-static int mtp_function_bind_config(struct android_usb_function *f,
+static int
+mtp_function_bind_config(struct android_usb_function *f,
 		struct usb_configuration *c)
 {
 	return mtp_bind_config(c, false);
 }
 
-static int ptp_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
+static int
+ptp_function_init(struct android_usb_function *f,
+		struct usb_composite_dev *cdev)
 {
 	/* nothing to do - initialization is handled by mtp_function_init */
 	return 0;
@@ -1121,7 +1129,9 @@
 	/* nothing to do - cleanup is handled by mtp_function_cleanup */
 }
 
-static int ptp_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
+static int
+ptp_function_bind_config(struct android_usb_function *f,
+		struct usb_configuration *c)
 {
 	return mtp_bind_config(c, true);
 }
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index c02c8e4..81fc1cc 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1391,9 +1391,6 @@
 		dev_err(dev, "[%s] EINVAL\n", __func__);
 		return 0;
 	}
-	dump = kmalloc(2048, GFP_KERNEL);
-	if (dump == NULL)
-		return -ENOMEM;
 
 	dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
 	if (!dump) {
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 4bc0da2..de4a233 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -176,13 +176,12 @@
 	_ep->comp_desc = comp_desc;
 	if (g->speed == USB_SPEED_SUPER) {
 		switch (usb_endpoint_type(_ep->desc)) {
-		case USB_ENDPOINT_XFER_BULK:
-		case USB_ENDPOINT_XFER_INT:
-			_ep->maxburst = comp_desc->bMaxBurst + 1;
-			break;
 		case USB_ENDPOINT_XFER_ISOC:
 			/* mult: bits 1:0 of bmAttributes */
 			_ep->mult = comp_desc->bmAttributes & 0x3;
+		case USB_ENDPOINT_XFER_BULK:
+		case USB_ENDPOINT_XFER_INT:
+			_ep->maxburst = comp_desc->bMaxBurst + 1;
 			break;
 		default:
 			if (comp_desc->bMaxBurst != 0)
@@ -693,7 +692,6 @@
 			CONFIG_USB_GADGET_VBUS_DRAW;
 done:
 	usb_gadget_vbus_draw(gadget, power);
-
 	if (result >= 0 && cdev->delayed_status)
 		result = USB_GADGET_DELAYED_STATUS;
 	return result;
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 0752188..de54714 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -18,7 +18,6 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <linux/usb/android_composite.h>
 #include <mach/usb_gadget_xport.h>
 
 #include "u_serial.h"
diff --git a/drivers/usb/gadget/f_ccid.c b/drivers/usb/gadget/f_ccid.c
index 4e28d34..6888935 100644
--- a/drivers/usb/gadget/f_ccid.c
+++ b/drivers/usb/gadget/f_ccid.c
@@ -16,7 +16,6 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <linux/usb/android_composite.h>
 #include <linux/fs.h>
 #include <linux/usb/ccid_desc.h>
 #include <linux/miscdevice.h>
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 245a972..bac8b68 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -3200,7 +3200,7 @@
 	if (unlikely(!fsg))
 		return -ENOMEM;
 
-	fsg->function.name        = "mass_storage";
+	fsg->function.name        = FSG_DRIVER_DESC;
 	fsg->function.strings     = fsg_strings_array;
 	fsg->function.bind        = fsg_bind;
 	fsg->function.unbind      = fsg_unbind;
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 0d8fa0f..af68827 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <linux/usb/android_composite.h>
 #include <linux/spinlock.h>
 
 #include <mach/usb_gadget_xport.h>
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index c71685d..502c33a 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -448,6 +448,8 @@
 		prev_len = req->length;
 		port->nbytes_from_tty += req->length;
 
+		port->write_started++;
+
 	}
 
 	if (do_tty_wake && port->port_tty)
@@ -1381,7 +1383,6 @@
 	/* export the driver ... */
 	status = tty_register_driver(gs_tty_driver);
 	if (status) {
-		put_tty_driver(gs_tty_driver);
 		pr_err("%s: cannot register, err %d\n",
 				__func__, status);
 		goto fail;
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index ea5484b..8c0894c 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -49,6 +49,7 @@
 #include <linux/spinlock.h>
 #include <linux/cpu.h>
 #include <mach/rpm-regulator.h>
+#include "hbm.c"
 
 #define MSM_USB_BASE (hcd->regs)
 #define USB_REG_START_OFFSET 0x90
@@ -105,6 +106,7 @@
 	int			reset_again;
 
 	struct pm_qos_request pm_qos_req_dma;
+	unsigned		enable_hbm:1;
 };
 
 struct msm_hsic_hcd *__mehci;
@@ -1367,6 +1369,18 @@
 		pm_runtime_set_autosuspend_delay(&dev->dev, 200);
 }
 
+static int ehci_msm_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+				gfp_t mem_flags)
+{
+	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+	struct usb_host_bam_type *usb_host_bam =
+			(struct usb_host_bam_type *)urb->priv_data;
+
+	if (usb_host_bam && mehci && mehci->enable_hbm)
+		return hbm_urb_enqueue(hcd, urb, mem_flags);
+	return ehci_urb_enqueue(hcd, urb, mem_flags);
+}
+
 static struct hc_driver msm_hsic_driver = {
 	.description		= hcd_name,
 	.product_desc		= "Qualcomm EHCI Host Controller using HSIC",
@@ -1387,7 +1401,7 @@
 	/*
 	 * managing i/o requests and associated device resources
 	 */
-	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_enqueue		= ehci_msm_urb_enqueue,
 	.urb_dequeue		= ehci_urb_dequeue,
 	.endpoint_disable	= ehci_endpoint_disable,
 	.endpoint_reset		= ehci_endpoint_reset,
@@ -1778,6 +1792,8 @@
 
 	pdata->pool_64_bit_align = of_property_read_bool(node,
 				"qcom,pool-64-bit-align");
+	pdata->enable_hbm = of_property_read_bool(node,
+				"qcom,enable-hbm");
 
 	return pdata;
 }
@@ -1789,6 +1805,7 @@
 	struct resource *res;
 	struct msm_hsic_hcd *mehci;
 	struct msm_hsic_host_platform_data *pdata;
+	unsigned long wakeup_irq_flags = 0;
 	int ret;
 
 	dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
@@ -1797,6 +1814,9 @@
 		dev_dbg(&pdev->dev, "device tree enabled\n");
 		pdev->dev.platform_data = msm_hsic_dt_to_pdata(pdev);
 		dev_set_name(&pdev->dev, ehci_msm_hsic_driver.driver.name);
+	} else {
+		/* explicitly pass wakeup_irq flag for !DT */
+		wakeup_irq_flags = IRQF_TRIGGER_HIGH;
 	}
 	if (!pdev->dev.platform_data)
 		dev_dbg(&pdev->dev, "No platform data given\n");
@@ -1857,6 +1877,7 @@
 
 	mehci->ehci.resume_sof_bug = 1;
 	mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
+	mehci->enable_hbm = pdata->enable_hbm;
 
 	if (pdata)
 		mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
@@ -1944,7 +1965,7 @@
 		 */
 		irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
 		ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
-				IRQF_TRIGGER_HIGH,
+				wakeup_irq_flags,
 				"msm_hsic_wakeup", mehci);
 		if (ret) {
 			dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
@@ -1963,7 +1984,8 @@
 		if (ret) {
 			dev_err(&pdev->dev, "request irq failed (ASYNC INT)\n");
 			mehci->async_irq = 0;
-		} else {
+		} else if (!mehci->wakeup_irq) {
+			/* Async IRQ is used only in absence of dedicated irq */
 			enable_irq_wake(mehci->async_irq);
 		}
 	}
@@ -2006,6 +2028,9 @@
 	if (pdev->dev.parent)
 		pm_runtime_put_sync(pdev->dev.parent);
 
+	if (mehci->enable_hbm)
+		hbm_init(hcd);
+
 	return 0;
 
 destroy_wq:
@@ -2035,6 +2060,9 @@
 
 	pm_runtime_set_suspended(&pdev->dev);
 
+	if (mehci->enable_hbm)
+		hbm_uninit();
+
 	/* Remove the HCD prior to releasing our resources. */
 	usb_remove_hcd(hcd);
 
@@ -2093,12 +2121,12 @@
 
 	dbg_log_event(NULL, "PM Suspend", 0);
 
-	if (device_may_wakeup(dev))
+	if (device_may_wakeup(dev) && !mehci->async_irq)
 		enable_irq_wake(hcd->irq);
 
 	ret = msm_hsic_suspend(mehci);
 
-	if (ret && device_may_wakeup(dev))
+	if (ret && device_may_wakeup(dev) && !mehci->async_irq)
 		disable_irq_wake(hcd->irq);
 
 	return ret;
@@ -2126,7 +2154,7 @@
 	dev_dbg(dev, "ehci-msm-hsic PM resume\n");
 	dbg_log_event(NULL, "PM Resume", 0);
 
-	if (device_may_wakeup(dev))
+	if (device_may_wakeup(dev) && !mehci->async_irq)
 		disable_irq_wake(hcd->irq);
 
 	/*
diff --git a/drivers/usb/host/hbm.c b/drivers/usb/host/hbm.c
index f516ad8..d48a631 100644
--- a/drivers/usb/host/hbm.c
+++ b/drivers/usb/host/hbm.c
@@ -194,12 +194,6 @@
 		pr_err("%s: hbm_ctx alloc failed\n", __func__);
 		return;
 	}
-	hbm_ctx->base = kzalloc(sizeof(u32), GFP_KERNEL);
-	if (!hbm_ctx->base) {
-		pr_err("%s: hbm_ctx base alloc failed\n", __func__);
-		kfree(hbm_ctx);
-		return;
-	}
 
 	hbm_ctx->base = hcd->regs;
 	hbm_ctx->hcd = hcd;
@@ -214,7 +208,7 @@
 
 void hbm_uninit(void)
 {
-	kfree(hbm_ctx->base);
+	hbm_config(false);
 	kfree(hbm_ctx);
 }
 
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 1c7d928..7760d28 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -151,8 +151,8 @@
 		rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
 				USB_PHY_1P8_VOL_MAX);
 		if (rc) {
-			dev_err(motg->phy.dev, "unable to set voltage level for"
-					"hsusb 1p8\n");
+			dev_err(motg->phy.dev, "unable to set voltage level "
+					"for hsusb 1p8\n");
 			goto put_1p8;
 		}
 
@@ -207,7 +207,7 @@
 		ret = regulator_set_optimum_mode(hsusb_1p8,
 				USB_PHY_1P8_HPM_LOAD);
 		if (ret < 0) {
-			pr_err("%s: Unable to set HPM of the regulator:"
+			pr_err("%s: Unable to set HPM of the regulator "
 				"HSUSB_1p8\n", __func__);
 			return ret;
 		}
@@ -223,7 +223,7 @@
 		ret = regulator_set_optimum_mode(hsusb_3p3,
 				USB_PHY_3P3_HPM_LOAD);
 		if (ret < 0) {
-			pr_err("%s: Unable to set HPM of the regulator:"
+			pr_err("%s: Unable to set HPM of the regulator "
 				"HSUSB_3p3\n", __func__);
 			regulator_set_optimum_mode(hsusb_1p8, 0);
 			regulator_disable(hsusb_1p8);
@@ -252,7 +252,7 @@
 
 		ret = regulator_set_optimum_mode(hsusb_1p8, 0);
 		if (ret < 0)
-			pr_err("%s: Unable to set LPM of the regulator:"
+			pr_err("%s: Unable to set LPM of the regulator "
 				"HSUSB_1p8\n", __func__);
 
 		ret = regulator_disable(hsusb_3p3);
@@ -263,7 +263,7 @@
 		}
 		ret = regulator_set_optimum_mode(hsusb_3p3, 0);
 		if (ret < 0)
-			pr_err("%s: Unable to set LPM of the regulator:"
+			pr_err("%s: Unable to set LPM of the regulator "
 				"HSUSB_3p3\n", __func__);
 
 		break;
@@ -1575,7 +1575,7 @@
 }
 
 static int msm_otg_set_peripheral(struct usb_otg *otg,
-			struct usb_gadget *gadget)
+					struct usb_gadget *gadget)
 {
 	struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy);
 
@@ -3017,10 +3017,10 @@
 
 	if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
 		if (otgsc & OTGSC_ID) {
-			pr_debug("Id set\n");
+			dev_dbg(otg->phy->dev, "ID set\n");
 			set_bit(ID, &motg->inputs);
 		} else {
-			pr_debug("Id clear\n");
+			dev_dbg(otg->phy->dev, "ID clear\n");
 			/*
 			 * Assert a_bus_req to supply power on
 			 * VBUS when Micro/Mini-A cable is connected
@@ -3049,10 +3049,10 @@
 			!test_bit(ID_A, &motg->inputs))
 			return IRQ_HANDLED;
 		if (otgsc & OTGSC_BSV) {
-			pr_debug("BSV set\n");
+			dev_dbg(otg->phy->dev, "BSV set\n");
 			set_bit(B_SESS_VLD, &motg->inputs);
 		} else {
-			pr_debug("BSV clear\n");
+			dev_dbg(otg->phy->dev, "BSV clear\n");
 			clear_bit(B_SESS_VLD, &motg->inputs);
 			clear_bit(A_BUS_SUSPEND, &motg->inputs);
 
@@ -3245,9 +3245,9 @@
 static int msm_otg_mode_show(struct seq_file *s, void *unused)
 {
 	struct msm_otg *motg = s->private;
-	struct usb_phy *phy = &motg->phy;
+	struct usb_otg *otg = motg->phy.otg;
 
-	switch (phy->state) {
+	switch (otg->phy->state) {
 	case OTG_STATE_A_HOST:
 		seq_printf(s, "host\n");
 		break;
@@ -4228,10 +4228,10 @@
 static int __devexit msm_otg_remove(struct platform_device *pdev)
 {
 	struct msm_otg *motg = platform_get_drvdata(pdev);
-	struct usb_otg *otg = motg->phy.otg;
+	struct usb_phy *phy = &motg->phy;
 	int cnt = 0;
 
-	if (otg->host || otg->gadget)
+	if (phy->otg->host || phy->otg->gadget)
 		return -EBUSY;
 
 	if (pdev->dev.of_node)
@@ -4264,8 +4264,8 @@
 	/*
 	 * Put PHY in low power mode.
 	 */
-	ulpi_read(otg->phy, 0x14);
-	ulpi_write(otg->phy, 0x08, 0x09);
+	ulpi_read(phy, 0x14);
+	ulpi_write(phy, 0x08, 0x09);
 
 	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
 	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
@@ -4275,7 +4275,7 @@
 		cnt++;
 	}
 	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
-		dev_err(otg->phy->dev, "Unable to suspend PHY\n");
+		dev_err(phy->dev, "Unable to suspend PHY\n");
 
 	clk_disable_unprepare(motg->pclk);
 	clk_disable_unprepare(motg->core_clk);
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index ed4c25d..1c59a68 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -10,6 +10,8 @@
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
+	select SYNC
+	select SW_SYNC
 	---help---
 	  Support for MSM Framebuffer.
 
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 99eea82..9c77445 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -659,7 +659,7 @@
 		return rc;
 	}
 
-	if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 103300000))
+	if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 250000000))
 		dsi_pclk_rate = 35000000;
 	mipi->dsi_pclk_rate = dsi_pclk_rate;
 
@@ -718,7 +718,8 @@
 			pr_err("request reset gpio failed, rc=%d\n",
 				rc);
 			gpio_free(ctrl_pdata->rst_gpio);
-			gpio_free(ctrl_pdata->disp_en_gpio);
+			if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+				gpio_free(ctrl_pdata->disp_en_gpio);
 			return -ENODEV;
 		}
 	}
@@ -782,7 +783,7 @@
 		devm_kfree(&pdev->dev, ctrl_pdata);
 		if (ctrl_pdata->rst_gpio)
 			gpio_free(ctrl_pdata->rst_gpio);
-		if (ctrl_pdata->disp_en_gpio)
+		if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
 			gpio_free(ctrl_pdata->disp_en_gpio);
 		return rc;
 	}
@@ -790,6 +791,11 @@
 	ctrl_pdata->on = panel_data->on;
 	ctrl_pdata->off = panel_data->off;
 
+	ctrl_pdata->pclk_rate = dsi_pclk_rate;
+	ctrl_pdata->byte_clk_rate = panel_data->panel_info.clk_rate / 8;
+	pr_debug("%s: pclk=%d, bclk=%d\n", __func__,
+			ctrl_pdata->pclk_rate, ctrl_pdata->byte_clk_rate);
+
 	pr_debug("%s: Panal data initialized\n", __func__);
 	return 0;
 }
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 06c2952..4b920a6 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -286,6 +286,8 @@
 	struct dsi_panel_cmds_list *on_cmds;
 	struct dsi_panel_cmds_list *off_cmds;
 	struct dsi_drv_cm_data shared_pdata;
+	u32 pclk_rate;
+	u32 byte_clk_rate;
 };
 
 int dsi_panel_device_register(struct platform_device *pdev,
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 4c30d18..8d38737 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -45,7 +45,6 @@
 	if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
 		pr_debug("%s:%d, reset line not configured\n",
 			   __func__, __LINE__);
-		return;
 	}
 
 	if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
@@ -59,18 +58,16 @@
 	if (enable) {
 		gpio_set_value((ctrl_pdata->rst_gpio), 1);
 		msleep(20);
-		wmb();
 		gpio_set_value((ctrl_pdata->rst_gpio), 0);
 		udelay(200);
-		wmb();
 		gpio_set_value((ctrl_pdata->rst_gpio), 1);
 		msleep(20);
-		wmb();
-		gpio_set_value((ctrl_pdata->disp_en_gpio), 1);
-		wmb();
+		if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+			gpio_set_value((ctrl_pdata->disp_en_gpio), 1);
 	} else {
 		gpio_set_value((ctrl_pdata->rst_gpio), 0);
-		gpio_set_value((ctrl_pdata->disp_en_gpio), 0);
+		if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+			gpio_set_value((ctrl_pdata->disp_en_gpio), 0);
 	}
 }
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 4f95aee..6c7a1195 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -1774,6 +1774,12 @@
 		return -ENODEV;
 	}
 
+	if (!hdmi_ctrl->audio_sdev.state) {
+		DEV_ERR("%s: failed. HDMI is not connected/ready for audio\n",
+			__func__);
+		return -EPERM;
+	}
+
 	return hdmi_edid_get_audio_blk(
 		hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], blk);
 } /* hdmi_tx_get_audio_edid_blk */
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 30dd471..ccddf44 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -1712,18 +1712,18 @@
 		struct input_dev *input = mhl_ctrl->input;
 
 		mhl_ctrl->rcp_key_code_tbl = vmalloc(
-			ARRAY_SIZE(support_rcp_key_code_tbl));
+			sizeof(support_rcp_key_code_tbl));
 		if (!mhl_ctrl->rcp_key_code_tbl) {
 			pr_err("%s: no alloc mem for rcp keycode tbl\n",
 			       __func__);
 			return -ENOMEM;
 		}
 
+		mhl_ctrl->rcp_key_code_tbl_len = sizeof(
+			support_rcp_key_code_tbl);
 		memcpy(mhl_ctrl->rcp_key_code_tbl,
 		       &support_rcp_key_code_tbl[0],
-		       ARRAY_SIZE(support_rcp_key_code_tbl));
-		mhl_ctrl->rcp_key_code_tbl_len = ARRAY_SIZE(
-			support_rcp_key_code_tbl);
+		       mhl_ctrl->rcp_key_code_tbl_len);
 
 		input->phys = "cbus/input0";
 		input->id.bustype = BUS_VIRTUAL;
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index 3b6fc38..2b07e43 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -173,6 +173,7 @@
 void mdss_dsi_clk_enable(struct mdss_panel_data *pdata)
 {
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+	u32 esc_clk_rate = 19200000;
 
 	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
 				panel_data);
@@ -186,17 +187,17 @@
 		return;
 	}
 
-	if (clk_set_rate(ctrl_pdata->esc_clk, 19200000) < 0)
-		pr_err("%s: dsi_esc_clk - clk_set_rate failed\n",
-					__func__);
+	pr_debug("%s: Setting clock rates: pclk=%d, byteclk=%d escclk=%d\n",
+			__func__, ctrl_pdata->pclk_rate,
+			ctrl_pdata->byte_clk_rate, esc_clk_rate);
+	if (clk_set_rate(ctrl_pdata->esc_clk, esc_clk_rate) < 0)
+		pr_err("%s: dsi_esc_clk - clk_set_rate failed\n", __func__);
 
-	if (clk_set_rate(ctrl_pdata->byte_clk, 53000000) < 0)
-		pr_err("%s: dsi_byte_clk - clk_set_rate failed\n",
-					__func__);
+	if (clk_set_rate(ctrl_pdata->byte_clk, ctrl_pdata->byte_clk_rate) < 0)
+		pr_err("%s: dsi_byte_clk - clk_set_rate failed\n", __func__);
 
-	if (clk_set_rate(ctrl_pdata->pixel_clk, 70000000) < 0)
-		pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n",
-					__func__);
+	if (clk_set_rate(ctrl_pdata->pixel_clk, ctrl_pdata->pclk_rate) < 0)
+		pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n", __func__);
 
 	clk_enable(ctrl_pdata->esc_clk);
 	clk_enable(ctrl_pdata->byte_clk);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index b96e093..e5f8a69 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -41,6 +41,9 @@
 #include <linux/android_pmem.h>
 #include <linux/leds.h>
 #include <linux/pm_runtime.h>
+#include <linux/sync.h>
+#include <linux/sw_sync.h>
+#include <linux/file.h>
 
 #define MSM_FB_C
 #include "msm_fb.h"
@@ -121,6 +124,9 @@
 #define MSM_FB_MAX_DBGFS 1024
 #define MAX_BACKLIGHT_BRIGHTNESS 255
 
+/* 200 ms for time out */
+#define WAIT_FENCE_TIMEOUT 200
+
 int msm_fb_debugfs_file_index;
 struct dentry *msm_fb_debugfs_root;
 struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS];
@@ -419,6 +425,16 @@
 
 	pdev_list[pdev_list_cnt++] = pdev;
 	msm_fb_create_sysfs(pdev);
+	if (mfd->timeline == NULL) {
+		mfd->timeline = sw_sync_timeline_create("mdp-timeline");
+		if (mfd->timeline == NULL) {
+			pr_err("%s: cannot create time line", __func__);
+			return -ENOMEM;
+		} else {
+			mfd->timeline_value = 0;
+		}
+	}
+
 	return 0;
 }
 
@@ -1677,6 +1693,7 @@
 	struct mdp_dirty_region dirty;
 	struct mdp_dirty_region *dirtyPtr = NULL;
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	int i, ret;
 
 	/*
 	 * If framebuffer is 2, io pen display is not allowed.
@@ -1748,11 +1765,25 @@
 	mutex_unlock(&msm_fb_notify_update_sem);
 
 	down(&msm_fb_pan_sem);
-
+	/* buf sync */
+	for (i = 0; i < mfd->acq_fen_cnt; i++) {
+		ret = sync_fence_wait(mfd->acq_fen[i], WAIT_FENCE_TIMEOUT);
+		sync_fence_put(mfd->acq_fen[i]);
+		if (ret < 0) {
+			pr_err("%s: sync_fence_wait failed! ret = %x\n",
+				__func__, ret);
+			break;
+		}
+	}
+	mfd->acq_fen_cnt = 0;
 	if (info->node == 0 && !(mfd->cont_splash_done)) { /* primary */
 		mdp_set_dma_pan_info(info, NULL, TRUE);
 		if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
 			pr_err("%s: can't turn on display!\n", __func__);
+			if (mfd->timeline) {
+				sw_sync_timeline_inc(mfd->timeline, 2);
+				mfd->timeline_value += 2;
+			}
 			return -EINVAL;
 		}
 	}
@@ -1760,6 +1791,12 @@
 	mdp_set_dma_pan_info(info, dirtyPtr,
 			     (var->activate & FB_ACTIVATE_VBL));
 	mdp_dma_pan_update(info);
+	if (mfd->timeline) {
+		sw_sync_timeline_inc(mfd->timeline, 1);
+		mfd->timeline_value++;
+	}
+	mfd->last_rel_fence = mfd->cur_rel_fence;
+	mfd->cur_rel_fence = 0;
 	up(&msm_fb_pan_sem);
 
 	if (unset_bl_level && !bl_updated)
@@ -3331,6 +3368,76 @@
 	return ret;
 }
 
+static int msmfb_handle_buf_sync_ioctl(struct msm_fb_data_type *mfd,
+						struct mdp_buf_sync *buf_sync)
+{
+	int i, fence_cnt = 0, ret;
+	int acq_fen_fd[MDP_MAX_FENCE_FD];
+	struct sync_fence *fence;
+
+	if ((buf_sync->acq_fen_fd_cnt == 0) ||
+		(buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
+		(mfd->timeline == NULL))
+		return -EINVAL;
+
+	ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd,
+			buf_sync->acq_fen_fd_cnt * sizeof(int));
+	if (ret) {
+		pr_err("%s:copy_from_user failed", __func__);
+		return ret;
+	}
+	for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
+		fence = sync_fence_fdget(acq_fen_fd[i]);
+		if (fence == NULL) {
+			pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
+				acq_fen_fd[i]);
+			ret = -EINVAL;
+			break;
+		}
+		mfd->acq_fen[i] = fence;
+	}
+	fence_cnt = i;
+	if (ret)
+		goto buf_sync_err_1;
+	mfd->cur_rel_sync_pt = sw_sync_pt_create(mfd->timeline,
+			mfd->timeline_value + 2);
+	if (mfd->cur_rel_sync_pt == NULL) {
+		pr_err("%s: cannot create sync point", __func__);
+		ret = -ENOMEM;
+		goto buf_sync_err_1;
+	}
+	/* create fence */
+	mfd->cur_rel_fence = sync_fence_create("mdp-fence",
+			mfd->cur_rel_sync_pt);
+	if (mfd->cur_rel_fence == NULL) {
+		sync_pt_free(mfd->cur_rel_sync_pt);
+		mfd->cur_rel_sync_pt = NULL;
+		pr_err("%s: cannot create fence", __func__);
+		ret = -ENOMEM;
+		goto buf_sync_err_1;
+	}
+	/* create fd */
+	mfd->cur_rel_fen_fd = get_unused_fd_flags(0);
+	sync_fence_install(mfd->cur_rel_fence, mfd->cur_rel_fen_fd);
+	ret = copy_to_user(buf_sync->rel_fen_fd,
+		&mfd->cur_rel_fen_fd, sizeof(int));
+	if (ret) {
+		pr_err("%s:copy_to_user failed", __func__);
+		goto buf_sync_err_2;
+	}
+	mfd->acq_fen_cnt = buf_sync->acq_fen_fd_cnt;
+	return ret;
+buf_sync_err_2:
+	sync_fence_put(mfd->cur_rel_fence);
+	put_unused_fd(mfd->cur_rel_fen_fd);
+	mfd->cur_rel_fence = NULL;
+	mfd->cur_rel_fen_fd = 0;
+buf_sync_err_1:
+	for (i = 0; i < fence_cnt; i++)
+		sync_fence_put(mfd->acq_fen[i]);
+	mfd->acq_fen_cnt = 0;
+	return ret;
+}
 static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
 			unsigned long arg)
 {
@@ -3349,6 +3456,7 @@
 	struct mdp_page_protection fb_page_protection;
 	struct msmfb_mdp_pp mdp_pp;
 	struct msmfb_metadata mdp_metadata;
+	struct mdp_buf_sync buf_sync;
 	int ret = 0;
 
 	switch (cmd) {
@@ -3636,6 +3744,16 @@
 		if (ret == 1)
 			ret = copy_to_user(argp, &mdp_pp, sizeof(mdp_pp));
 		break;
+	case MSMFB_BUFFER_SYNC:
+		ret = copy_from_user(&buf_sync, argp, sizeof(buf_sync));
+		if (ret)
+			return ret;
+
+		ret = msmfb_handle_buf_sync_ioctl(mfd, &buf_sync);
+
+		if (!ret)
+			ret = copy_to_user(argp, &buf_sync, sizeof(buf_sync));
+		break;
 
 	case MSMFB_METADATA_SET:
 		ret = copy_from_user(&mdp_metadata, argp, sizeof(mdp_metadata));
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 34cb1fc..7e1716a 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -197,6 +197,14 @@
 	void *cpu_pm_hdl;
 	u32 avtimer_phy;
 	int vsync_sysfs_created;
+	u32 acq_fen_cnt;
+	struct sync_fence *acq_fen[MDP_MAX_FENCE_FD];
+	int cur_rel_fen_fd;
+	struct sync_pt *cur_rel_sync_pt;
+	struct sync_fence *cur_rel_fence;
+	struct sync_fence *last_rel_fence;
+	struct sw_sync_timeline *timeline;
+	int timeline_value;
 };
 
 struct dentry *msm_fb_get_debugfs_root(void);
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index afc5130..1c69d8f 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -25,7 +25,7 @@
 #include <linux/uaccess.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
-#include <linux/android_pmem.h>
+
 #include <linux/clk.h>
 #include <linux/timer.h>
 #include <mach/msm_subsystem_map.h>
@@ -48,8 +48,6 @@
 static dev_t vid_dec_dev_num;
 static struct class *vid_dec_class;
 
-static unsigned int vidc_mmu_subsystem[] = {
-	MSM_SUBSYSTEM_VIDEO};
 static s32 vid_dec_get_empty_client_index(void)
 {
 	u32 i, found = false;
@@ -875,11 +873,8 @@
 {
 	struct vcd_property_hdr vcd_property_hdr;
 	struct vcd_property_meta_buffer *vcd_meta_buffer = NULL;
-	struct msm_mapped_buffer *mapped_buffer = NULL;
-	struct msm_mapped_buffer *mapped_buffer_iommu = NULL;
 	u32 vcd_status = VCD_ERR_FAIL;
-	u32 len = 0, flags = 0, len_iommu = 0, flags_iommu = 0, buf_size = 0;
-	struct file *file, *file_iommu;
+	u32 len = 0, len_iommu = 0, buf_size = 0;
 	int rc = 0;
 	unsigned long ionflag = 0, ionflag_iommu = 0;
 	unsigned long buffer_size = 0, buffer_size_iommu = 0;
@@ -903,54 +898,8 @@
 	vcd_meta_buffer->pmem_fd_iommu = meta_buffers->pmem_fd_iommu;
 
 	if (!vcd_get_ion_status()) {
-		if (get_pmem_file(vcd_meta_buffer->pmem_fd,
-				(unsigned long *) (&(vcd_meta_buffer->
-				physical_addr)),
-				(unsigned long *) (&vcd_meta_buffer->
-							kernel_virtual_addr),
-				(unsigned long *) (&len), &file)) {
-				ERR("%s(): get_pmem_file failed\n", __func__);
-				return false;
-			}
-		put_pmem_file(file);
-		flags = MSM_SUBSYSTEM_MAP_IOVA;
-		mapped_buffer = msm_subsystem_map_buffer(
-			(unsigned long)vcd_meta_buffer->physical_addr,
-				len, flags, vidc_mmu_subsystem,
-				sizeof(vidc_mmu_subsystem)/
-				sizeof(unsigned int));
-		if (IS_ERR(mapped_buffer)) {
-			pr_err("buffer map failed");
-			return false;
-		}
-		vcd_meta_buffer->client_data = (void *) mapped_buffer;
-		vcd_meta_buffer->dev_addr =
-			(u8 *)mapped_buffer->iova[0];
-
-		if (get_pmem_file(vcd_meta_buffer->pmem_fd_iommu,
-				(unsigned long *) (&(vcd_meta_buffer->
-				physical_addr_iommu)),
-				(unsigned long *) (&vcd_meta_buffer->
-				kernel_virt_addr_iommu),
-				(unsigned long *) (&len_iommu), &file_iommu)) {
-				ERR("%s(): get_pmem_file failed\n", __func__);
-				return false;
-			}
-		put_pmem_file(file_iommu);
-		flags_iommu = MSM_SUBSYSTEM_MAP_IOVA;
-		mapped_buffer_iommu = msm_subsystem_map_buffer(
-			(unsigned long)vcd_meta_buffer->physical_addr_iommu,
-				len_iommu, flags_iommu, vidc_mmu_subsystem,
-				sizeof(vidc_mmu_subsystem)/
-				sizeof(unsigned int));
-		if (IS_ERR(mapped_buffer_iommu)) {
-			pr_err("buffer map failed");
-			return false;
-		}
-		vcd_meta_buffer->client_data_iommu =
-					(void *) mapped_buffer_iommu;
-		vcd_meta_buffer->dev_addr_iommu =
-					(u8 *)mapped_buffer_iommu->iova[0];
+		pr_err("PMEM Not available\n");
+		return false;
 	} else {
 		client_ctx->meta_buffer_ion_handle = ion_import_dma_buf(
 					client_ctx->user_ion_client,
@@ -1132,10 +1081,8 @@
 {
 	struct vcd_property_hdr vcd_property_hdr;
 	struct vcd_property_h264_mv_buffer *vcd_h264_mv_buffer = NULL;
-	struct msm_mapped_buffer *mapped_buffer = NULL;
 	u32 vcd_status = VCD_ERR_FAIL;
-	u32 len = 0, flags = 0;
-	struct file *file;
+	u32 len = 0;
 	int rc = 0;
 	unsigned long ionflag = 0;
 	unsigned long buffer_size = 0;
@@ -1156,28 +1103,8 @@
 	vcd_h264_mv_buffer->offset = mv_data->offset;
 
 	if (!vcd_get_ion_status()) {
-		if (get_pmem_file(vcd_h264_mv_buffer->pmem_fd,
-			(unsigned long *) (&(vcd_h264_mv_buffer->
-			physical_addr)),
-			(unsigned long *) (&vcd_h264_mv_buffer->
-						kernel_virtual_addr),
-			(unsigned long *) (&len), &file)) {
-			ERR("%s(): get_pmem_file failed\n", __func__);
-			return false;
-		}
-		put_pmem_file(file);
-		flags = MSM_SUBSYSTEM_MAP_IOVA;
-		mapped_buffer = msm_subsystem_map_buffer(
-			(unsigned long)vcd_h264_mv_buffer->physical_addr, len,
-				flags, vidc_mmu_subsystem,
-				sizeof(vidc_mmu_subsystem)/
-				sizeof(unsigned int));
-		if (IS_ERR(mapped_buffer)) {
-			pr_err("buffer map failed");
-			return false;
-		}
-		vcd_h264_mv_buffer->client_data = (void *) mapped_buffer;
-		vcd_h264_mv_buffer->dev_addr = (u8 *)mapped_buffer->iova[0];
+		pr_err("PMEM not available\n");
+		return false;
 	} else {
 		client_ctx->h264_mv_ion_handle = ion_import_dma_buf(
 					client_ctx->user_ion_client,
@@ -1818,7 +1745,6 @@
 	u32 vcd_status;
 	unsigned long kernel_vaddr, phy_addr, len;
 	unsigned long ker_vaddr;
-	struct file *pmem_file;
 	u32 result = true;
 	void __user *arg = (void __user *)u_arg;
 	int rc = 0;
@@ -2133,12 +2059,8 @@
 		}
 
 		if (!vcd_get_ion_status()) {
-			if (get_pmem_file(seq_header.pmem_fd,
-				  &phy_addr, &kernel_vaddr, &len, &pmem_file)) {
-				ERR("%s(): get_pmem_file failed\n", __func__);
-				return false;
-			}
-			put_pmem_file(pmem_file);
+			pr_err("PMEM Not available\n");
+			return -EINVAL;
 		} else {
 			client_ctx->seq_hdr_ion_handle = ion_import_dma_buf(
 				client_ctx->user_ion_client,
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index aa17f84..823626a 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -25,7 +25,7 @@
 #include <linux/uaccess.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
-#include <linux/android_pmem.h>
+
 #include <linux/clk.h>
 #include <media/msm/vidc_type.h>
 #include <media/msm/vcd_api.h>
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index 14d8bfc..3dae4be1 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -25,7 +25,7 @@
 #include <linux/uaccess.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
-#include <linux/android_pmem.h>
+
 #include <linux/clk.h>
 #include <mach/msm_subsystem_map.h>
 #include <media/msm/vidc_type.h>
@@ -41,9 +41,6 @@
 #endif
 
 #define ERR(x...) printk(KERN_ERR x)
-static unsigned int vidc_mmu_subsystem[] = {
-	MSM_SUBSYSTEM_VIDEO};
-
 
 u32 vid_enc_set_get_base_cfg(struct video_client_ctx *client_ctx,
 		struct venc_basecfg *base_config, u32 set_flag)
@@ -1801,11 +1798,9 @@
 		struct venc_recon_addr *venc_recon)
 {
 	u32 vcd_status = VCD_ERR_FAIL;
-	u32 len, i, flags = 0;
-	struct file *file;
+	u32 len, i;
 	struct vcd_property_hdr vcd_property_hdr;
 	struct vcd_property_enc_recon_buffer *control = NULL;
-	struct msm_mapped_buffer *mapped_buffer = NULL;
 	int rc = -1;
 	unsigned long ionflag = 0;
 	unsigned long iova = 0;
@@ -1837,25 +1832,8 @@
 	control->user_virtual_addr = venc_recon->pbuffer;
 
 	if (!vcd_get_ion_status()) {
-		if (get_pmem_file(control->pmem_fd, (unsigned long *)
-			(&(control->physical_addr)), (unsigned long *)
-			(&control->kernel_virtual_addr),
-			(unsigned long *) (&len), &file)) {
-				ERR("%s(): get_pmem_file failed\n", __func__);
-				return false;
-			}
-			put_pmem_file(file);
-			flags = MSM_SUBSYSTEM_MAP_IOVA;
-			mapped_buffer = msm_subsystem_map_buffer(
-			(unsigned long)control->physical_addr, len,
-			flags, vidc_mmu_subsystem,
-			sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
-			if (IS_ERR(mapped_buffer)) {
-				pr_err("buffer map failed");
-				return false;
-			}
-			control->client_data = (void *) mapped_buffer;
-			control->dev_addr = (u8 *)mapped_buffer->iova[0];
+		pr_err("PMEM not available\n");
+		return false;
 	} else {
 		client_ctx->recon_buffer_ion_handle[i] = ion_import_dma_buf(
 				client_ctx->user_ion_client, control->pmem_fd);
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index 9007145..72a1d5f 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -24,7 +24,7 @@
 #include <linux/uaccess.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
-#include <linux/android_pmem.h>
+
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/debugfs.h>
@@ -49,7 +49,6 @@
 static struct vidc_dev *vidc_device_p;
 static dev_t vidc_dev_num;
 static struct class *vidc_class;
-static unsigned int vidc_mmu_subsystem[] = {MSM_SUBSYSTEM_VIDEO};
 
 static const struct file_operations vidc_fops = {
 	.owner = THIS_MODULE,
@@ -565,9 +564,8 @@
 	unsigned long len, phys_addr;
 	struct file *file = NULL;
 	u32 *num_of_buffers = NULL;
-	u32 i, flags;
+	u32 i;
 	struct buf_addr_table *buf_addr_table;
-	struct msm_mapped_buffer *mapped_buffer = NULL;
 	struct ion_handle *buff_ion_handle = NULL;
 	unsigned long ionflag = 0;
 	unsigned long iova = 0;
@@ -609,26 +607,8 @@
 		goto bail_out_add;
 	} else {
 		if (!vcd_get_ion_status()) {
-			if (get_pmem_file(pmem_fd, &phys_addr,
-					kernel_vaddr, &len, &file)) {
-				ERR("%s(): get_pmem_file failed\n", __func__);
-				goto bail_out_add;
-			}
-			put_pmem_file(file);
-			flags = (buffer == BUFFER_TYPE_INPUT)
-			? MSM_SUBSYSTEM_MAP_IOVA :
-			MSM_SUBSYSTEM_MAP_IOVA|MSM_SUBSYSTEM_ALIGN_IOVA_8K;
-			mapped_buffer = msm_subsystem_map_buffer(phys_addr,
-			length, flags, vidc_mmu_subsystem,
-			sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
-			if (IS_ERR(mapped_buffer)) {
-				pr_err("buffer map failed");
-				goto bail_out_add;
-			}
-			buf_addr_table[*num_of_buffers].client_data = (void *)
-				mapped_buffer;
-			buf_addr_table[*num_of_buffers].dev_addr =
-				mapped_buffer->iova[0];
+			pr_err("PMEM not available\n");
+			return false;
 		} else {
 			buff_ion_handle = ion_import_dma_buf(
 				client_ctx->user_ion_client, pmem_fd);
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index e52effd..1afb701 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1413,14 +1413,6 @@
 		goto out;
 	}
 
-	if (be32_to_cpu(sb->s_first) == 0 ||
-	    be32_to_cpu(sb->s_first) >= journal->j_maxlen) {
-		printk(KERN_WARNING
-			"JBD2: Invalid start block of journal: %u\n",
-			be32_to_cpu(sb->s_first));
-		goto out;
-	}
-
 	return 0;
 
 out:
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index e35df2d..74c00bc 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1721,18 +1721,6 @@
 								\
 	save = resp->p;
 
-static bool seqid_mutating_err(__be32 err)
-{
-	/* rfc 3530 section 8.1.5: */
-	return	err != nfserr_stale_clientid &&
-		err != nfserr_stale_stateid &&
-		err != nfserr_bad_stateid &&
-		err != nfserr_bad_seqid &&
-		err != nfserr_bad_xdr &&
-		err != nfserr_resource &&
-		err != nfserr_nofilehandle;
-}
-
 /*
  * Routine for encoding the result of a "seqid-mutating" NFSv4 operation.  This
  * is where sequence id's are incremented, and the replay cache is filled.
diff --git a/include/linux/ion.h b/include/linux/ion.h
index f159fe2..fb1c5f6 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -74,7 +74,6 @@
    be converted to phys_addr_t.  For the time being many kernel interfaces
    do not accept phys_addr_t's that would have to */
 #define ion_phys_addr_t unsigned long
-#define ion_virt_addr_t unsigned long
 
 /**
  * struct ion_platform_heap - defines a heap in the given platform
diff --git a/include/linux/mhl_defs.h b/include/linux/mhl_defs.h
index f9d1ce4..aa63e03 100644
--- a/include/linux/mhl_defs.h
+++ b/include/linux/mhl_defs.h
@@ -57,7 +57,7 @@
 /* bits 4..7 */
 #define	MHL_VER_MAJOR           (0x01 << 4)
 /* bits 0..3 */
-#define	MHL_VER_MINOR		0x01
+#define	MHL_VER_MINOR		0x02
 #define MHL_VERSION		(MHL_VER_MAJOR | MHL_VER_MINOR)
 
 /*Device Category*/
diff --git a/include/linux/mhl_devcap.h b/include/linux/mhl_devcap.h
index 40a87fe..37a0dc5 100644
--- a/include/linux/mhl_devcap.h
+++ b/include/linux/mhl_devcap.h
@@ -16,26 +16,23 @@
 #define SILICON_IMAGE_ADOPTER_ID 322
 #define TRANSCODER_DEVICE_ID 0x8334
 
-#define MHL_DEV_LD_AUDIO (0x01 << 2)
-#define MHL_DEV_LD_VIDEO (0x01 << 1)
-#define MHL_DEV_LD_MEDIA (0x01 << 3)
 #define MHL_DEV_LD_GUI (0x01 << 7)
-#define	MHL_LOGICAL_DEVICE_MAP		(MHL_DEV_LD_AUDIO |\
-	MHL_DEV_LD_VIDEO | MHL_DEV_LD_MEDIA | MHL_DEV_LD_GUI)
+#define	MHL_LOGICAL_DEVICE_MAP		MHL_DEV_LD_GUI
 
 #define DEVCAP_VAL_DEV_STATE       0
 #define DEVCAP_VAL_MHL_VERSION     MHL_VERSION
-#define DEVCAP_VAL_DEV_CAT         (MHL_DEV_CAT_SOURCE |\
-	MHL_DEV_CATEGORY_POW_BIT)
+#define DEVCAP_VAL_DEV_CAT         MHL_DEV_CAT_SOURCE
+
 #define DEVCAP_VAL_ADOPTER_ID_H    (uint8_t)(SILICON_IMAGE_ADOPTER_ID >>   8)
 #define DEVCAP_VAL_ADOPTER_ID_L    (uint8_t)(SILICON_IMAGE_ADOPTER_ID & 0xFF)
-#define DEVCAP_VAL_VID_LINK_MODE   MHL_DEV_VID_LINK_SUPPRGB444
+#define DEVCAP_VAL_VID_LINK_MODE   (MHL_DEV_VID_LINK_SUPPRGB444 |\
+						MHL_DEV_VID_LINK_SUPP_ISLANDS)
 #define DEVCAP_VAL_AUD_LINK_MODE   MHL_DEV_AUD_LINK_2CH
 #define DEVCAP_VAL_VIDEO_TYPE      0
 #define DEVCAP_VAL_LOG_DEV_MAP     MHL_LOGICAL_DEVICE_MAP
 #define DEVCAP_VAL_BANDWIDTH       0
 #define DEVCAP_VAL_FEATURE_FLAG    (MHL_FEATURE_RCP_SUPPORT |\
-	MHL_FEATURE_RAP_SUPPORT | MHL_FEATURE_SP_SUPPORT)
+			MHL_FEATURE_RAP_SUPPORT | MHL_FEATURE_SP_SUPPORT)
 #define DEVCAP_VAL_DEVICE_ID_H     (uint8_t)(TRANSCODER_DEVICE_ID >>   8)
 #define DEVCAP_VAL_DEVICE_ID_L     (uint8_t)(TRANSCODER_DEVICE_ID & 0xFF)
 #define DEVCAP_VAL_SCRATCHPAD_SIZE MHL_SCRATCHPAD_SIZE
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index e4aab43..9a4e61d 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -385,6 +385,9 @@
 	struct mmc_wr_pack_stats wr_pack_stats; /* packed commands stats*/
 
 	struct mmc_bkops_info	bkops_info;
+
+	struct device_attribute rpm_attrib;
+	unsigned int		idle_timeout;
 };
 
 /*
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 5f1e2d9..995f8a2 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -198,14 +198,13 @@
 extern void mmc_release_host(struct mmc_host *host);
 extern int mmc_try_claim_host(struct mmc_host *host);
 extern void mmc_set_ios(struct mmc_host *host);
-extern int mmc_detect_card_removed(struct mmc_host *host);
-extern int mmc_flush_cache(struct mmc_card *);
-
 extern int mmc_flush_cache(struct mmc_card *);
 
 extern int mmc_detect_card_removed(struct mmc_host *host);
 
 extern void mmc_blk_init_bkops_statistics(struct mmc_card *card);
+extern void mmc_rpm_hold(struct mmc_host *host, struct device *dev);
+extern void mmc_rpm_release(struct mmc_host *host, struct device *dev);
 
 /**
  *	mmc_claim_host - exclusively claim a host
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 2bfd9a2..05271ba 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -60,8 +60,6 @@
 #define MMC_TIMING_UHS_DDR50	5
 #define MMC_TIMING_MMC_HS200	6
 
-	unsigned char	ddr;			/* dual data rate used */
-
 #define MMC_SDR_MODE		0
 #define MMC_1_2V_DDR_MODE	1
 #define MMC_1_8V_DDR_MODE	2
@@ -283,6 +281,8 @@
 #define MMC_CAP2_INIT_BKOPS	    (1 << 16)	/* Need to set BKOPS_EN */
 #define MMC_CAP2_CLK_SCALE	(1 << 17)	/* Allow dynamic clk scaling */
 #define MMC_CAP2_STOP_REQUEST	(1 << 18)	/* Allow stop ongoing request */
+/* Use runtime PM framework provided by MMC core */
+#define MMC_CAP2_CORE_RUNTIME_PM (1 << 19)
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
 	int			clk_requests;	/* internal reference counter */
@@ -386,7 +386,6 @@
 	} perf;
 	bool perf_enable;
 #endif
-
 	struct mmc_ios saved_ios;
 	struct {
 		unsigned long	busy_time_us;
@@ -483,9 +482,6 @@
 int mmc_card_sleep(struct mmc_host *host);
 int mmc_card_can_sleep(struct mmc_host *host);
 
-int mmc_host_enable(struct mmc_host *host);
-int mmc_host_disable(struct mmc_host *host);
-int mmc_host_lazy_disable(struct mmc_host *host);
 int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *);
 
 /* Module parameter */
@@ -543,4 +539,10 @@
 	return host->ios.clock;
 }
 #endif
+
+static inline int mmc_use_core_runtime_pm(struct mmc_host *host)
+{
+	return host->caps2 & MMC_CAP2_CORE_RUNTIME_PM;
+}
+
 #endif /* LINUX_MMC_HOST_H */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 7f316a9..de145d6 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -348,7 +348,6 @@
 
 #define EXT_CSD_PART_CONFIG_ACC_MASK	(0x7)
 #define EXT_CSD_PART_CONFIG_ACC_BOOT0	(0x1)
-#define EXT_CSD_PART_CONFIG_ACC_BOOT1	(0x2)
 #define EXT_CSD_PART_CONFIG_ACC_RPMB	(0x3)
 #define EXT_CSD_PART_CONFIG_ACC_GP0	(0x4)
 
@@ -390,14 +389,6 @@
 #define EXT_CSD_POWER_OFF_SHORT		2
 #define EXT_CSD_POWER_OFF_LONG		3
 
-#define EXT_CSD_RST_N_EN_MASK	0x3
-#define EXT_CSD_RST_N_ENABLED	1	/* RST_n is enabled on card */
-
-#define EXT_CSD_NO_POWER_NOTIFICATION	0
-#define EXT_CSD_POWER_ON		1
-#define EXT_CSD_POWER_OFF_SHORT		2
-#define EXT_CSD_POWER_OFF_LONG		3
-
 #define EXT_CSD_PWR_CL_8BIT_MASK	0xF0	/* 8 bit PWR CLS */
 #define EXT_CSD_PWR_CL_4BIT_MASK	0x0F	/* 8 bit PWR CLS */
 #define EXT_CSD_PWR_CL_8BIT_SHIFT	4
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index bd24575..f26b903 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -18,6 +18,11 @@
 #include <linux/mmc/host.h>
 #include <linux/pm_qos.h>
 
+struct sdhci_next {
+	unsigned int sg_count;
+	s32 cookie;
+};
+
 struct sdhci_host {
 	/* Data set by hardware interface driver */
 	const char *hw_name;	/* Hardware bus name */
@@ -191,6 +196,8 @@
 	unsigned int cpu_dma_latency_us;
 	struct pm_qos_request pm_qos_req_dma;
 
+	struct sdhci_next next_data;
+
 	unsigned long private[0] ____cacheline_aligned;
 };
 #endif /* LINUX_MMC_SDHCI_H */
diff --git a/include/linux/msm_audio_acdb.h b/include/linux/msm_audio_acdb.h
index f0c4915..646c22e 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -53,6 +53,10 @@
 			(AUDIO_MAX_COMMON_IOCTL_NUM+23), unsigned)
 #define AUDIO_SET_ASM_CUSTOM_TOPOLOGY	_IOW(AUDIO_IOCTL_MAGIC, \
 			(AUDIO_MAX_COMMON_IOCTL_NUM+24), unsigned)
+#define AUDIO_SET_SPEAKER_PROT _IOW(AUDIO_IOCTL_MAGIC, 25, \
+		struct msm_spk_prot_cfg)
+#define AUDIO_GET_SPEAKER_PROT _IOR(AUDIO_IOCTL_MAGIC, 26, \
+		struct msm_spk_prot_status)
 
 #define	AUDIO_MAX_ACDB_IOCTL	(AUDIO_MAX_COMMON_IOCTL_NUM+30)
 
@@ -67,6 +71,19 @@
 	uint16_t	gain;
 };
 
+struct msm_spk_prot_cfg {
+	int r0;
+	int t0;
+	uint32_t mode; /*0 - Start spk prot
+	1 - Start calib
+	2 - Disable spk prot*/
+};
+
+struct msm_spk_prot_status {
+	int r0;
+	int status;
+};
+
 /* For Real-Time Audio Calibration */
 #define AUDIO_GET_RTAC_ADM_INFO		_IOR(AUDIO_IOCTL_MAGIC, \
 			(AUDIO_MAX_ACDB_IOCTL+1), unsigned)
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index ff22e12..a683ed4 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -163,7 +163,7 @@
 	enum ion_fixed_position fixed_position;
 	int iommu_map_all;
 	int iommu_2x_map_domain;
-	ion_virt_addr_t *virt_addr;
+	void *virt_addr;
 	int (*request_region)(void *);
 	int (*release_region)(void *);
 	void *(*setup_region)(void);
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
index 5285317..569781f 100644
--- a/include/linux/pm_wakeup.h
+++ b/include/linux/pm_wakeup.h
@@ -34,6 +34,7 @@
  * @total_time: Total time this wakeup source has been active.
  * @max_time: Maximum time this wakeup source has been continuously active.
  * @last_time: Monotonic clock when the wakeup source's was touched last time.
+ * @prevent_sleep_time: Total time this source has been preventing autosleep.
  * @event_count: Number of signaled wakeup events.
  * @active_count: Number of times the wakeup sorce was activated.
  * @relax_count: Number of times the wakeup sorce was deactivated.
@@ -51,12 +52,15 @@
 	ktime_t total_time;
 	ktime_t max_time;
 	ktime_t last_time;
+	ktime_t start_prevent_time;
+	ktime_t prevent_sleep_time;
 	unsigned long		event_count;
 	unsigned long		active_count;
 	unsigned long		relax_count;
 	unsigned long		expire_count;
 	unsigned long		wakeup_count;
 	bool			active:1;
+	bool			autosleep_enabled:1;
 };
 
 #ifdef CONFIG_PM_SLEEP
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index ac1c114..cd83059 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -356,8 +356,9 @@
 extern bool events_check_enabled;
 
 extern bool pm_wakeup_pending(void);
-extern bool pm_get_wakeup_count(unsigned int *count);
+extern bool pm_get_wakeup_count(unsigned int *count, bool block);
 extern bool pm_save_wakeup_count(unsigned int count);
+extern void pm_wakep_autosleep_enabled(bool set);
 
 static inline void lock_system_sleep(void)
 {
@@ -407,6 +408,17 @@
 
 #endif /* !CONFIG_PM_SLEEP */
 
+#ifdef CONFIG_PM_AUTOSLEEP
+
+/* kernel/power/autosleep.c */
+void queue_up_suspend_work(void);
+
+#else /* !CONFIG_PM_AUTOSLEEP */
+
+static inline void queue_up_suspend_work(void) {}
+
+#endif /* !CONFIG_PM_AUTOSLEEP */
+
 #ifdef CONFIG_ARCH_SAVE_PAGE_KEYS
 /*
  * The ARCH_SAVE_PAGE_KEYS functions can be used by an architecture
diff --git a/include/linux/usb/android_composite.h b/include/linux/usb/android_composite.h
deleted file mode 100644
index 438dfa4..0000000
--- a/include/linux/usb/android_composite.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Platform data for Android USB
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#ifndef	__LINUX_USB_ANDROID_H
-#define	__LINUX_USB_ANDROID_H
-
-#include <linux/usb/composite.h>
-#include <linux/if_ether.h>
-
-struct android_usb_function {
-	struct list_head	list;
-	char			*name;
-	int 			(*bind_config)(struct usb_configuration *c);
-};
-
-struct android_usb_product {
-	/* Default product ID. */
-	__u16 product_id;
-
-	/* List of function names associated with this product.
-	 * This is used to compute the USB product ID dynamically
-	 * based on which functions are enabled.
-	 */
-	int num_functions;
-	char **functions;
-};
-
-struct android_usb_platform_data {
-	/* USB device descriptor fields */
-	__u16 vendor_id;
-
-	/* Default product ID. */
-	__u16 product_id;
-
-	__u16 version;
-
-	char *product_name;
-	char *manufacturer_name;
-	char *serial_number;
-
-	/* List of available USB products.
-	 * This is used to compute the USB product ID dynamically
-	 * based on which functions are enabled.
-	 * if num_products is zero or no match can be found,
-	 * we use the default product ID
-	 */
-	int num_products;
-	struct android_usb_product *products;
-
-	/* List of all supported USB functions.
-	 * This list is used to define the order in which
-	 * the functions appear in the configuration's list of USB interfaces.
-	 * This is necessary to avoid depending upon the order in which
-	 * the individual function drivers are initialized.
-	 */
-	int num_functions;
-	char **functions;
-};
-
-/* Platform data for "usb_mass_storage" driver. */
-struct usb_mass_storage_platform_data {
-	/* Contains values for the SC_INQUIRY SCSI command. */
-	char *vendor;
-	char *product;
-	int release;
-
-	char can_stall;
-	/* number of LUNS */
-	int nluns;
-};
-
-/* Platform data for USB ethernet driver. */
-struct usb_ether_platform_data {
-	u8	ethaddr[ETH_ALEN];
-	u32	vendorID;
-	const char *vendorDescr;
-};
-
-extern void android_register_function(struct android_usb_function *f);
-
-extern int android_enable_function(struct usb_function *f, int enable);
-
-
-#endif	/* __LINUX_USB_ANDROID_H */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index c7c6b05..c5943c9 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -412,6 +412,7 @@
 	/*standalone latency is required when HSCI is active*/
 	u32 standalone_latency;
 	bool pool_64_bit_align;
+	bool enable_hbm;
 };
 
 struct msm_usb_host_platform_data {
diff --git a/include/linux/wakelock.h b/include/linux/wakelock.h
index 5b2d0f3..f4a698a 100644
--- a/include/linux/wakelock.h
+++ b/include/linux/wakelock.h
@@ -1,6 +1,6 @@
 /* include/linux/wakelock.h
  *
- * Copyright (C) 2007-2008 Google, Inc.
+ * Copyright (C) 2007-2012 Google, Inc.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -16,14 +16,12 @@
 #ifndef _LINUX_WAKELOCK_H
 #define _LINUX_WAKELOCK_H
 
-#include <linux/list.h>
 #include <linux/ktime.h>
+#include <linux/device.h>
 
 /* A wake_lock prevents the system from entering suspend or other low power
  * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock
- * prevents a full system suspend. If the type is WAKE_LOCK_IDLE, low power
- * states that cause large interrupt latencies or that disable a set of
- * interrupts will not entered from idle until the wake_locks are released.
+ * prevents a full system suspend.
  */
 
 enum {
@@ -32,59 +30,38 @@
 };
 
 struct wake_lock {
-#ifdef CONFIG_HAS_WAKELOCK
-	struct list_head    link;
-	int                 flags;
-	const char         *name;
-	unsigned long       expires;
-#ifdef CONFIG_WAKELOCK_STAT
-	struct {
-		int             count;
-		int             expire_count;
-		int             wakeup_count;
-		ktime_t         total_time;
-		ktime_t         prevent_suspend_time;
-		ktime_t         max_time;
-		ktime_t         last_time;
-	} stat;
-#endif
-#endif
+	struct wakeup_source ws;
 };
 
-#ifdef CONFIG_HAS_WAKELOCK
-
-void wake_lock_init(struct wake_lock *lock, int type, const char *name);
-void wake_lock_destroy(struct wake_lock *lock);
-void wake_lock(struct wake_lock *lock);
-void wake_lock_timeout(struct wake_lock *lock, long timeout);
-void wake_unlock(struct wake_lock *lock);
-
-/* wake_lock_active returns a non-zero value if the wake_lock is currently
- * locked. If the wake_lock has a timeout, it does not check the timeout
- * but if the timeout had aready been checked it will return 0.
- */
-int wake_lock_active(struct wake_lock *lock);
-
-/* has_wake_lock returns 0 if no wake locks of the specified type are active,
- * and non-zero if one or more wake locks are held. Specifically it returns
- * -1 if one or more wake locks with no timeout are active or the
- * number of jiffies until all active wake locks time out.
- */
-long has_wake_lock(int type);
-
-#else
-
 static inline void wake_lock_init(struct wake_lock *lock, int type,
-					const char *name) {}
-static inline void wake_lock_destroy(struct wake_lock *lock) {}
-static inline void wake_lock(struct wake_lock *lock) {}
-static inline void wake_lock_timeout(struct wake_lock *lock, long timeout) {}
-static inline void wake_unlock(struct wake_lock *lock) {}
+				  const char *name)
+{
+	wakeup_source_init(&lock->ws, name);
+}
 
-static inline int wake_lock_active(struct wake_lock *lock) { return 0; }
-static inline long has_wake_lock(int type) { return 0; }
+static inline void wake_lock_destroy(struct wake_lock *lock)
+{
+	wakeup_source_trash(&lock->ws);
+}
+
+static inline void wake_lock(struct wake_lock *lock)
+{
+	__pm_stay_awake(&lock->ws);
+}
+
+static inline void wake_lock_timeout(struct wake_lock *lock, long timeout)
+{
+	__pm_wakeup_event(&lock->ws, jiffies_to_msecs(timeout));
+}
+
+static inline void wake_unlock(struct wake_lock *lock)
+{
+	__pm_relax(&lock->ws);
+}
+
+static inline int wake_lock_active(struct wake_lock *lock)
+{
+	return lock->ws.active;
+}
 
 #endif
-
-#endif
-
diff --git a/include/media/gpio-ir-recv.h b/include/media/gpio-ir-recv.h
index 63f40f7..a81f0bb 100644
--- a/include/media/gpio-ir-recv.h
+++ b/include/media/gpio-ir-recv.h
@@ -14,7 +14,7 @@
 #define __GPIO_IR_RECV_H__
 
 struct gpio_ir_recv_platform_data {
-	unsigned int gpio_nr;
+	int gpio_nr;
 	bool active_low;
 	bool can_wakeup;
 	u32 swfi_latency;
diff --git a/include/media/msm/vidc_type.h b/include/media/msm/vidc_type.h
index 77bae5a..5463fc6 100644
--- a/include/media/msm/vidc_type.h
+++ b/include/media/msm/vidc_type.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -21,7 +21,7 @@
 #include <linux/list.h>
 #include <linux/time.h>
 #include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
 
 #define DDL_MSG_LOG 0
 #define DEBUG 0
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index e3c4567..84789f1 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -52,6 +52,27 @@
 #define FM_TX_PHY_CFG_MODE   0x3c
 #define FM_TX_PHY_CFG_LEN    0x10
 #define FM_TX_PWR_GAIN_OFFSET 14
+/**RDS CONFIG MODE**/
+#define FM_RDS_CNFG_MODE	0x0f
+#define FM_RDS_CNFG_LEN		0x10
+#define AF_RMSSI_TH_LSB_OFFSET	10
+#define AF_RMSSI_TH_MSB_OFFSET	11
+#define AF_RMSSI_SAMPLES_OFFSET	15
+/**RX CONFIG MODE**/
+#define FM_RX_CONFG_MODE	0x15
+#define FM_RX_CNFG_LEN		0x20
+#define GD_CH_RMSSI_TH_OFFSET	12
+#define MAX_GD_CH_RMSSI_TH	127
+#define SRCH_ALGO_TYPE_OFFSET  25
+#define SINRFIRSTSTAGE_OFFSET  26
+#define RMSSIFIRSTSTAGE_OFFSET 27
+#define CF0TH12_BYTE1_OFFSET   8
+#define CF0TH12_BYTE2_OFFSET   9
+#define CF0TH12_BYTE3_OFFSET   10
+#define CF0TH12_BYTE4_OFFSET   11
+#define MAX_SINR_FIRSTSTAGE	127
+#define MAX_RMSSI_FIRSTSTAGE	127
+
 /* HCI timeouts */
 #define RADIO_HCI_TIMEOUT	(10000)	/* 10 seconds */
 
@@ -658,6 +679,14 @@
 	V4L2_CID_PRIVATE_SPUR_SELECTION,
 	V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE,
 	V4L2_CID_PRIVATE_VALID_CHANNEL,
+	V4L2_CID_PRIVATE_AF_RMSSI_TH,
+	V4L2_CID_PRIVATE_AF_RMSSI_SAMPLES,
+	V4L2_CID_PRIVATE_GOOD_CH_RMSSI_TH,
+	V4L2_CID_PRIVATE_SRCHALGOTYPE,
+	V4L2_CID_PRIVATE_CF0TH12,
+	V4L2_CID_PRIVATE_SINRFIRSTSTAGE,
+	V4L2_CID_PRIVATE_RMSSIFIRSTSTAGE,
+
 
 	/*using private CIDs under userclass*/
 	V4L2_CID_PRIVATE_IRIS_READ_DEFAULT = 0x00980928,
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index efc11bb..c68d427 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -26,7 +26,6 @@
 #define __HCI_CORE_H
 
 #include <net/bluetooth/hci.h>
-#include <linux/wakelock.h>
 /* HCI upper protocols */
 #define HCI_PROTO_L2CAP	0
 #define HCI_PROTO_SCO	1
@@ -327,7 +326,6 @@
 
 	struct work_struct work_add;
 	struct work_struct work_del;
-	struct wake_lock idle_lock;
 	struct device	dev;
 	atomic_t	devref;
 
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 93f0aa90..bc68c24 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -6252,6 +6252,93 @@
 	/* Size in bytes of the variable payload in shared memory */
 } __packed;
 
+/* This module represents the Rx processing of Feedback speaker protection.
+ * It contains the excursion control, thermal protection,
+ * analog clip manager features in it.
+ * This module id will support following param ids.
+ * - AFE_PARAM_ID_FBSP_MODE_RX_CFG
+ */
+
+#define AFE_MODULE_FB_SPKR_PROT_RX 0x0001021C
+
+#define AFE_PARAM_ID_FBSP_MODE_RX_CFG 0x0001021D
+
+struct asm_fbsp_mode_rx_cfg {
+	uint32_t minor_version;
+	uint32_t mode;
+} __packed;
+
+/* This module represents the VI processing of feedback speaker protection.
+ * It will receive Vsens and Isens from codec and generates necessary
+ * parameters needed by Rx processing.
+ * This module id will support following param ids.
+ * - AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG
+ * - AFE_PARAM_ID_CALIB_RES_CFG
+ * - AFE_PARAM_ID_FEEDBACK_PATH_CFG
+ */
+
+#define AFE_MODULE_FB_SPKR_PROT_VI_PROC 0x00010226
+
+#define AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG 0x0001022A
+
+struct asm_spkr_calib_vi_proc_cfg {
+	uint32_t minor_version;
+	int32_t	r0_cali_q24;
+	int16_t	t0_cali_q6;
+	int16_t	reserved;
+} __packed;
+
+#define AFE_PARAM_ID_CALIB_RES_CFG 0x0001022B
+
+struct asm_calib_res_cfg {
+	uint32_t minor_version;
+	int32_t	r0_cali_q24;
+	uint32_t th_vi_ca_state;
+} __packed;
+
+#define AFE_PARAM_ID_FEEDBACK_PATH_CFG 0x0001022C
+
+struct asm_feedback_path_cfg {
+	uint32_t minor_version;
+	int32_t	dst_portid;
+	int32_t	num_channels;
+	int32_t	chan_info[4];
+} __packed;
+
+#define AFE_PARAM_ID_MODE_VI_PROC_CFG 0x00010227
+
+struct asm_mode_vi_proc_cfg {
+	uint32_t minor_version;
+	uint32_t cal_mode;
+} __packed;
+
+union afe_spkr_prot_config {
+	struct asm_fbsp_mode_rx_cfg mode_rx_cfg;
+	struct asm_spkr_calib_vi_proc_cfg vi_proc_cfg;
+	struct asm_feedback_path_cfg feedback_path_cfg;
+	struct asm_mode_vi_proc_cfg mode_vi_proc_cfg;
+} __packed;
+
+struct afe_spkr_prot_config_command {
+	struct apr_hdr hdr;
+	struct afe_port_cmd_set_param_v2 param;
+	struct afe_port_param_data_v2 pdata;
+	union afe_spkr_prot_config prot_config;
+} __packed;
+
+struct afe_spkr_prot_get_vi_calib {
+	struct afe_port_cmd_get_param_v2 get_param;
+	struct afe_port_param_data_v2 pdata;
+	struct asm_calib_res_cfg res_cfg;
+} __packed;
+
+struct afe_spkr_prot_calib_get_resp {
+	uint32_t status;
+	struct afe_port_param_data_v2 pdata;
+	struct asm_calib_res_cfg res_cfg;
+} __packed;
+
+
 /* SRS TRUMEDIA start */
 /* topology */
 #define SRS_TRUMEDIA_TOPOLOGY_ID			0x00010D90
@@ -6355,8 +6442,6 @@
 } __packed;
 /* SRS TruMedia end */
 
-
-
 /* ERROR CODES */
 /* Success. The operation completed with no errors. */
 #define ADSP_EOK          0x00000000
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 506e877..feac314 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -145,6 +145,9 @@
 int afe_rt_proxy_port_read(u32 buf_addr_p, u32 mem_map_handle, int bytes);
 int afe_port_start(u16 port_id, union afe_port_config *afe_config,
 	u32 rate);
+int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
+	int l_ch, int r_ch);
+int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib);
 int afe_port_stop_nowait(int port_id);
 int afe_apply_gain(u16 port_id, u16 gain);
 int afe_q6_interface_prepare(void);
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 1878b6e..371ddf6 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -103,6 +103,33 @@
 	select HOTPLUG
 	select HOTPLUG_CPU
 
+config PM_AUTOSLEEP
+	bool "Opportunistic sleep"
+	depends on PM_SLEEP
+	default n
+	---help---
+	Allow the kernel to trigger a system transition into a global sleep
+	state automatically whenever there are no active wakeup sources.
+
+config PM_WAKELOCKS
+	bool "User space wakeup sources interface"
+	depends on PM_SLEEP
+	default n
+	---help---
+	Allow user space to create, activate and deactivate wakeup source
+	objects with the help of a sysfs-based interface.
+
+config PM_WAKELOCKS_LIMIT
+	int "Maximum number of user space wakeup sources (0 = no limit)"
+	range 0 100000
+	default 100
+	depends on PM_WAKELOCKS
+
+config PM_WAKELOCKS_GC
+	bool "Garbage collector for user space wakeup sources"
+	depends on PM_WAKELOCKS
+	default y
+
 config PM_RUNTIME
 	bool "Run-time PM core functionality"
 	depends on !IA64_HP_SIM
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 5ad8c75..29472bf 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -9,11 +9,7 @@
 obj-$(CONFIG_PM_TEST_SUSPEND)	+= suspend_test.o
 obj-$(CONFIG_HIBERNATION)	+= hibernate.o snapshot.o swap.o user.o \
 				   block_io.o
-obj-$(CONFIG_WAKELOCK)		+= wakelock.o
-obj-$(CONFIG_USER_WAKELOCK)	+= userwakelock.o
-obj-$(CONFIG_EARLYSUSPEND)	+= earlysuspend.o
-obj-$(CONFIG_CONSOLE_EARLYSUSPEND)	+= consoleearlysuspend.o
-obj-$(CONFIG_FB_EARLYSUSPEND)	+= fbearlysuspend.o
-obj-$(CONFIG_SUSPEND_TIME)	+= suspend_time.o
+obj-$(CONFIG_PM_AUTOSLEEP)	+= autosleep.o
+obj-$(CONFIG_PM_WAKELOCKS)	+= wakelock.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/autosleep.c b/kernel/power/autosleep.c
new file mode 100644
index 0000000..ca304046
--- /dev/null
+++ b/kernel/power/autosleep.c
@@ -0,0 +1,127 @@
+/*
+ * kernel/power/autosleep.c
+ *
+ * Opportunistic sleep support.
+ *
+ * Copyright (C) 2012 Rafael J. Wysocki <rjw@sisk.pl>
+ */
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/pm_wakeup.h>
+
+#include "power.h"
+
+static suspend_state_t autosleep_state;
+static struct workqueue_struct *autosleep_wq;
+/*
+ * Note: it is only safe to mutex_lock(&autosleep_lock) if a wakeup_source
+ * is active, otherwise a deadlock with try_to_suspend() is possible.
+ * Alternatively mutex_lock_interruptible() can be used.  This will then fail
+ * if an auto_sleep cycle tries to freeze processes.
+ */
+static DEFINE_MUTEX(autosleep_lock);
+static struct wakeup_source *autosleep_ws;
+
+static void try_to_suspend(struct work_struct *work)
+{
+	unsigned int initial_count, final_count;
+
+	if (!pm_get_wakeup_count(&initial_count, true))
+		goto out;
+
+	mutex_lock(&autosleep_lock);
+
+	if (!pm_save_wakeup_count(initial_count)) {
+		mutex_unlock(&autosleep_lock);
+		goto out;
+	}
+
+	if (autosleep_state == PM_SUSPEND_ON) {
+		mutex_unlock(&autosleep_lock);
+		return;
+	}
+	if (autosleep_state >= PM_SUSPEND_MAX)
+		hibernate();
+	else
+		pm_suspend(autosleep_state);
+
+	mutex_unlock(&autosleep_lock);
+
+	if (!pm_get_wakeup_count(&final_count, false))
+		goto out;
+
+	/*
+	 * If the wakeup occured for an unknown reason, wait to prevent the
+	 * system from trying to suspend and waking up in a tight loop.
+	 */
+	if (final_count == initial_count)
+		schedule_timeout_uninterruptible(HZ / 2);
+
+ out:
+	queue_up_suspend_work();
+}
+
+static DECLARE_WORK(suspend_work, try_to_suspend);
+
+void queue_up_suspend_work(void)
+{
+	if (!work_pending(&suspend_work) && autosleep_state > PM_SUSPEND_ON)
+		queue_work(autosleep_wq, &suspend_work);
+}
+
+suspend_state_t pm_autosleep_state(void)
+{
+	return autosleep_state;
+}
+
+int pm_autosleep_lock(void)
+{
+	return mutex_lock_interruptible(&autosleep_lock);
+}
+
+void pm_autosleep_unlock(void)
+{
+	mutex_unlock(&autosleep_lock);
+}
+
+int pm_autosleep_set_state(suspend_state_t state)
+{
+
+#ifndef CONFIG_HIBERNATION
+	if (state >= PM_SUSPEND_MAX)
+		return -EINVAL;
+#endif
+
+	__pm_stay_awake(autosleep_ws);
+
+	mutex_lock(&autosleep_lock);
+
+	autosleep_state = state;
+
+	__pm_relax(autosleep_ws);
+
+	if (state > PM_SUSPEND_ON) {
+		pm_wakep_autosleep_enabled(true);
+		queue_up_suspend_work();
+	} else {
+		pm_wakep_autosleep_enabled(false);
+	}
+
+	mutex_unlock(&autosleep_lock);
+	return 0;
+}
+
+int __init pm_autosleep_init(void)
+{
+	autosleep_ws = wakeup_source_register("autosleep");
+	if (!autosleep_ws)
+		return -ENOMEM;
+
+	autosleep_wq = alloc_ordered_workqueue("autosleep", 0);
+	if (autosleep_wq)
+		return 0;
+
+	wakeup_source_unregister(autosleep_ws);
+	return -ENOMEM;
+}
diff --git a/kernel/power/main.c b/kernel/power/main.c
index a1d13f5..b54da02 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -354,8 +354,7 @@
 	return (s - buf);
 }
 
-static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
-			   const char *buf, size_t n)
+static suspend_state_t decode_state(const char *buf, size_t n)
 {
 #ifdef CONFIG_SUSPEND
 #ifdef CONFIG_EARLYSUSPEND
@@ -367,34 +366,48 @@
 #endif
 	char *p;
 	int len;
-	int error = -EINVAL;
 
 	p = memchr(buf, '\n', n);
 	len = p ? p - buf : n;
 
-	/* First, check if we are requested to hibernate */
-	if (len == 4 && !strncmp(buf, "disk", len)) {
-		error = hibernate();
-		goto Exit;
-	}
+	/* Check hibernation first. */
+	if (len == 4 && !strncmp(buf, "disk", len))
+		return PM_SUSPEND_MAX;
 
 #ifdef CONFIG_SUSPEND
-	for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
-		if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) {
-#ifdef CONFIG_EARLYSUSPEND
-			if (state == PM_SUSPEND_ON || valid_state(state)) {
-				error = 0;
-				request_suspend_state(state);
-				break;
-			}
-#else
-			error = pm_suspend(state);
-#endif
-		}
-	}
+	for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++)
+		if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
+			return state;
 #endif
 
- Exit:
+	return PM_SUSPEND_ON;
+}
+
+static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
+			   const char *buf, size_t n)
+{
+	suspend_state_t state;
+	int error;
+
+	error = pm_autosleep_lock();
+	if (error)
+		return error;
+
+	if (pm_autosleep_state() > PM_SUSPEND_ON) {
+		error = -EBUSY;
+		goto out;
+	}
+
+	state = decode_state(buf, n);
+	if (state < PM_SUSPEND_MAX)
+		error = pm_suspend(state);
+	else if (state == PM_SUSPEND_MAX)
+		error = hibernate();
+	else
+		error = -EINVAL;
+
+ out:
+	pm_autosleep_unlock();
 	return error ? error : n;
 }
 
@@ -435,7 +448,8 @@
 {
 	unsigned int val;
 
-	return pm_get_wakeup_count(&val) ? sprintf(buf, "%u\n", val) : -EINTR;
+	return pm_get_wakeup_count(&val, true) ?
+		sprintf(buf, "%u\n", val) : -EINTR;
 }
 
 static ssize_t wakeup_count_store(struct kobject *kobj,
@@ -443,15 +457,106 @@
 				const char *buf, size_t n)
 {
 	unsigned int val;
+	int error;
 
+	error = pm_autosleep_lock();
+	if (error)
+		return error;
+
+	if (pm_autosleep_state() > PM_SUSPEND_ON) {
+		error = -EBUSY;
+		goto out;
+	}
+
+	error = -EINVAL;
 	if (sscanf(buf, "%u", &val) == 1) {
 		if (pm_save_wakeup_count(val))
-			return n;
+			error = n;
 	}
-	return -EINVAL;
+
+ out:
+	pm_autosleep_unlock();
+	return error;
 }
 
 power_attr(wakeup_count);
+
+#ifdef CONFIG_PM_AUTOSLEEP
+static ssize_t autosleep_show(struct kobject *kobj,
+			      struct kobj_attribute *attr,
+			      char *buf)
+{
+	suspend_state_t state = pm_autosleep_state();
+
+	if (state == PM_SUSPEND_ON)
+		return sprintf(buf, "off\n");
+
+#ifdef CONFIG_SUSPEND
+	if (state < PM_SUSPEND_MAX)
+		return sprintf(buf, "%s\n", valid_state(state) ?
+						pm_states[state] : "error");
+#endif
+#ifdef CONFIG_HIBERNATION
+	return sprintf(buf, "disk\n");
+#else
+	return sprintf(buf, "error");
+#endif
+}
+
+static ssize_t autosleep_store(struct kobject *kobj,
+			       struct kobj_attribute *attr,
+			       const char *buf, size_t n)
+{
+	suspend_state_t state = decode_state(buf, n);
+	int error;
+
+	if (state == PM_SUSPEND_ON
+	    && !(strncmp(buf, "off", 3) && strncmp(buf, "off\n", 4)))
+		return -EINVAL;
+
+	error = pm_autosleep_set_state(state);
+	return error ? error : n;
+}
+
+power_attr(autosleep);
+#endif /* CONFIG_PM_AUTOSLEEP */
+
+#ifdef CONFIG_PM_WAKELOCKS
+static ssize_t wake_lock_show(struct kobject *kobj,
+			      struct kobj_attribute *attr,
+			      char *buf)
+{
+	return pm_show_wakelocks(buf, true);
+}
+
+static ssize_t wake_lock_store(struct kobject *kobj,
+			       struct kobj_attribute *attr,
+			       const char *buf, size_t n)
+{
+	int error = pm_wake_lock(buf);
+	return error ? error : n;
+}
+
+power_attr(wake_lock);
+
+static ssize_t wake_unlock_show(struct kobject *kobj,
+				struct kobj_attribute *attr,
+				char *buf)
+{
+	return pm_show_wakelocks(buf, false);
+}
+
+static ssize_t wake_unlock_store(struct kobject *kobj,
+				 struct kobj_attribute *attr,
+				 const char *buf, size_t n)
+{
+	int error = pm_wake_unlock(buf);
+	return error ? error : n;
+}
+
+power_attr(wake_unlock);
+
+#endif /* CONFIG_PM_WAKELOCKS */
 #endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_PM_TRACE
@@ -502,8 +607,6 @@
 #endif
 
 static struct attribute *g[] = {
-	&touch_event_attr.attr,
-	&touch_event_timer_attr.attr,
 	&state_attr.attr,
 #ifdef CONFIG_PM_TRACE
 	&pm_trace_attr.attr,
@@ -512,6 +615,15 @@
 #ifdef CONFIG_PM_SLEEP
 	&pm_async_attr.attr,
 	&wakeup_count_attr.attr,
+#ifdef CONFIG_PM_AUTOSLEEP
+	&autosleep_attr.attr,
+#endif
+#ifdef CONFIG_PM_WAKELOCKS
+	&wake_lock_attr.attr,
+	&wake_unlock_attr.attr,
+#endif
+	&touch_event_attr.attr,
+	&touch_event_timer_attr.attr,
 #ifdef CONFIG_PM_DEBUG
 	&pm_test_attr.attr,
 #endif
@@ -558,7 +670,10 @@
 	power_kobj = kobject_create_and_add("power", NULL);
 	if (!power_kobj)
 		return -ENOMEM;
-	return sysfs_create_group(power_kobj, &attr_group);
+	error = sysfs_create_group(power_kobj, &attr_group);
+	if (error)
+		return error;
+	return pm_autosleep_init();
 }
 
 core_initcall(pm_init);
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 32e08a1..b0bd4be 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -265,31 +265,29 @@
 }
 #endif
 
-#ifdef CONFIG_WAKELOCK
+#ifdef CONFIG_PM_AUTOSLEEP
+
+/* kernel/power/autosleep.c */
+extern int pm_autosleep_init(void);
+extern int pm_autosleep_lock(void);
+extern void pm_autosleep_unlock(void);
+extern suspend_state_t pm_autosleep_state(void);
+extern int pm_autosleep_set_state(suspend_state_t state);
+
+#else /* !CONFIG_PM_AUTOSLEEP */
+
+static inline int pm_autosleep_init(void) { return 0; }
+static inline int pm_autosleep_lock(void) { return 0; }
+static inline void pm_autosleep_unlock(void) {}
+static inline suspend_state_t pm_autosleep_state(void) { return PM_SUSPEND_ON; }
+
+#endif /* !CONFIG_PM_AUTOSLEEP */
+
+#ifdef CONFIG_PM_WAKELOCKS
+
 /* kernel/power/wakelock.c */
-extern struct workqueue_struct *suspend_work_queue;
-extern struct wake_lock main_wake_lock;
-extern suspend_state_t requested_suspend_state;
-extern void suspend_sys_sync_queue(void);
-extern int suspend_sys_sync_wait(void);
-#else
-static inline void suspend_sys_sync_queue(void) {}
-static inline int suspend_sys_sync_wait(void) { return 0; }
-#endif
+extern ssize_t pm_show_wakelocks(char *buf, bool show_active);
+extern int pm_wake_lock(const char *buf);
+extern int pm_wake_unlock(const char *buf);
 
-#ifdef CONFIG_USER_WAKELOCK
-ssize_t wake_lock_show(struct kobject *kobj, struct kobj_attribute *attr,
-			char *buf);
-ssize_t wake_lock_store(struct kobject *kobj, struct kobj_attribute *attr,
-			const char *buf, size_t n);
-ssize_t wake_unlock_show(struct kobject *kobj, struct kobj_attribute *attr,
-			char *buf);
-ssize_t  wake_unlock_store(struct kobject *kobj, struct kobj_attribute *attr,
-			const char *buf, size_t n);
-#endif
-
-#ifdef CONFIG_EARLYSUSPEND
-/* kernel/power/earlysuspend.c */
-void request_suspend_state(suspend_state_t state);
-suspend_state_t get_suspend_state(void);
-#endif
+#endif /* !CONFIG_PM_WAKELOCKS */
diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
index 2583856..c8fba33 100644
--- a/kernel/power/wakelock.c
+++ b/kernel/power/wakelock.c
@@ -1,712 +1,259 @@
-/* kernel/power/wakelock.c
+/*
+ * kernel/power/wakelock.c
  *
- * Copyright (C) 2005-2008 Google, Inc.
+ * User space wakeup sources support.
  *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
+ * Copyright (C) 2012 Rafael J. Wysocki <rjw@sisk.pl>
  *
- * 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 code is based on the analogous interface allowing user space to
+ * manipulate wakelocks on Android.
  */
 
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/rtc.h>
-#include <linux/suspend.h>
-#include <linux/syscalls.h> /* sys_sync */
-#include <linux/wakelock.h>
-#ifdef CONFIG_WAKELOCK_STAT
-#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <linux/slab.h>
+
+static DEFINE_MUTEX(wakelocks_lock);
+
+struct wakelock {
+	char			*name;
+	struct rb_node		node;
+	struct wakeup_source	ws;
+#ifdef CONFIG_PM_WAKELOCKS_GC
+	struct list_head	lru;
 #endif
-#include "power.h"
-
-enum {
-	DEBUG_EXIT_SUSPEND = 1U << 0,
-	DEBUG_WAKEUP = 1U << 1,
-	DEBUG_SUSPEND = 1U << 2,
-	DEBUG_EXPIRE = 1U << 3,
-	DEBUG_WAKE_LOCK = 1U << 4,
 };
-static int debug_mask = DEBUG_EXIT_SUSPEND | DEBUG_WAKEUP;
-module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
 
-#define WAKE_LOCK_TYPE_MASK              (0x0f)
-#define WAKE_LOCK_INITIALIZED            (1U << 8)
-#define WAKE_LOCK_ACTIVE                 (1U << 9)
-#define WAKE_LOCK_AUTO_EXPIRE            (1U << 10)
-#define WAKE_LOCK_PREVENTING_SUSPEND     (1U << 11)
+static struct rb_root wakelocks_tree = RB_ROOT;
 
-static DEFINE_SPINLOCK(list_lock);
-static LIST_HEAD(inactive_locks);
-static struct list_head active_wake_locks[WAKE_LOCK_TYPE_COUNT];
-static int current_event_num;
-static int suspend_sys_sync_count;
-static DEFINE_SPINLOCK(suspend_sys_sync_lock);
-static struct workqueue_struct *suspend_sys_sync_work_queue;
-static DECLARE_COMPLETION(suspend_sys_sync_comp);
-struct workqueue_struct *suspend_work_queue;
-struct wake_lock main_wake_lock;
-suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
-static struct wake_lock unknown_wakeup;
-static struct wake_lock suspend_backoff_lock;
-
-#define SUSPEND_BACKOFF_THRESHOLD	10
-#define SUSPEND_BACKOFF_INTERVAL	10000
-
-static unsigned suspend_short_count;
-
-#ifdef CONFIG_WAKELOCK_STAT
-static struct wake_lock deleted_wake_locks;
-static ktime_t last_sleep_time_update;
-static int wait_for_wakeup;
-
-int get_expired_time(struct wake_lock *lock, ktime_t *expire_time)
+ssize_t pm_show_wakelocks(char *buf, bool show_active)
 {
-	struct timespec ts;
-	struct timespec kt;
-	struct timespec tomono;
-	struct timespec delta;
-	struct timespec sleep;
-	long timeout;
+	struct rb_node *node;
+	struct wakelock *wl;
+	char *str = buf;
+	char *end = buf + PAGE_SIZE;
 
-	if (!(lock->flags & WAKE_LOCK_AUTO_EXPIRE))
-		return 0;
-	get_xtime_and_monotonic_and_sleep_offset(&kt, &tomono, &sleep);
-	timeout = lock->expires - jiffies;
-	if (timeout > 0)
-		return 0;
-	jiffies_to_timespec(-timeout, &delta);
-	set_normalized_timespec(&ts, kt.tv_sec + tomono.tv_sec - delta.tv_sec,
-				kt.tv_nsec + tomono.tv_nsec - delta.tv_nsec);
-	*expire_time = timespec_to_ktime(ts);
-	return 1;
-}
+	mutex_lock(&wakelocks_lock);
 
-
-static int print_lock_stat(struct seq_file *m, struct wake_lock *lock)
-{
-	int lock_count = lock->stat.count;
-	int expire_count = lock->stat.expire_count;
-	ktime_t active_time = ktime_set(0, 0);
-	ktime_t total_time = lock->stat.total_time;
-	ktime_t max_time = lock->stat.max_time;
-
-	ktime_t prevent_suspend_time = lock->stat.prevent_suspend_time;
-	if (lock->flags & WAKE_LOCK_ACTIVE) {
-		ktime_t now, add_time;
-		int expired = get_expired_time(lock, &now);
-		if (!expired)
-			now = ktime_get();
-		add_time = ktime_sub(now, lock->stat.last_time);
-		lock_count++;
-		if (!expired)
-			active_time = add_time;
-		else
-			expire_count++;
-		total_time = ktime_add(total_time, add_time);
-		if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND)
-			prevent_suspend_time = ktime_add(prevent_suspend_time,
-					ktime_sub(now, last_sleep_time_update));
-		if (add_time.tv64 > max_time.tv64)
-			max_time = add_time;
+	for (node = rb_first(&wakelocks_tree); node; node = rb_next(node)) {
+		wl = rb_entry(node, struct wakelock, node);
+		if (wl->ws.active == show_active)
+			str += scnprintf(str, end - str, "%s ", wl->name);
 	}
+	if (str > buf)
+		str--;
 
-	return seq_printf(m,
-		     "\"%s\"\t%d\t%d\t%d\t%lld\t%lld\t%lld\t%lld\t%lld\n",
-		     lock->name, lock_count, expire_count,
-		     lock->stat.wakeup_count, ktime_to_ns(active_time),
-		     ktime_to_ns(total_time),
-		     ktime_to_ns(prevent_suspend_time), ktime_to_ns(max_time),
-		     ktime_to_ns(lock->stat.last_time));
+	str += scnprintf(str, end - str, "\n");
+
+	mutex_unlock(&wakelocks_lock);
+	return (str - buf);
 }
 
-static int wakelock_stats_show(struct seq_file *m, void *unused)
+#if CONFIG_PM_WAKELOCKS_LIMIT > 0
+static unsigned int number_of_wakelocks;
+
+static inline bool wakelocks_limit_exceeded(void)
 {
-	unsigned long irqflags;
-	struct wake_lock *lock;
-	int ret;
-	int type;
-
-	spin_lock_irqsave(&list_lock, irqflags);
-
-	ret = seq_puts(m, "name\tcount\texpire_count\twake_count\tactive_since"
-			"\ttotal_time\tsleep_time\tmax_time\tlast_change\n");
-	list_for_each_entry(lock, &inactive_locks, link)
-		ret = print_lock_stat(m, lock);
-	for (type = 0; type < WAKE_LOCK_TYPE_COUNT; type++) {
-		list_for_each_entry(lock, &active_wake_locks[type], link)
-			ret = print_lock_stat(m, lock);
-	}
-	spin_unlock_irqrestore(&list_lock, irqflags);
-	return 0;
+	return number_of_wakelocks > CONFIG_PM_WAKELOCKS_LIMIT;
 }
 
-static void wake_unlock_stat_locked(struct wake_lock *lock, int expired)
+static inline void increment_wakelocks_number(void)
 {
-	ktime_t duration;
+	number_of_wakelocks++;
+}
+
+static inline void decrement_wakelocks_number(void)
+{
+	number_of_wakelocks--;
+}
+#else /* CONFIG_PM_WAKELOCKS_LIMIT = 0 */
+static inline bool wakelocks_limit_exceeded(void) { return false; }
+static inline void increment_wakelocks_number(void) {}
+static inline void decrement_wakelocks_number(void) {}
+#endif /* CONFIG_PM_WAKELOCKS_LIMIT */
+
+#ifdef CONFIG_PM_WAKELOCKS_GC
+#define WL_GC_COUNT_MAX	100
+#define WL_GC_TIME_SEC	300
+
+static LIST_HEAD(wakelocks_lru_list);
+static unsigned int wakelocks_gc_count;
+
+static inline void wakelocks_lru_add(struct wakelock *wl)
+{
+	list_add(&wl->lru, &wakelocks_lru_list);
+}
+
+static inline void wakelocks_lru_most_recent(struct wakelock *wl)
+{
+	list_move(&wl->lru, &wakelocks_lru_list);
+}
+
+static void wakelocks_gc(void)
+{
+	struct wakelock *wl, *aux;
 	ktime_t now;
-	if (!(lock->flags & WAKE_LOCK_ACTIVE))
-		return;
-	if (get_expired_time(lock, &now))
-		expired = 1;
-	else
-		now = ktime_get();
-	lock->stat.count++;
-	if (expired)
-		lock->stat.expire_count++;
-	duration = ktime_sub(now, lock->stat.last_time);
-	lock->stat.total_time = ktime_add(lock->stat.total_time, duration);
-	if (ktime_to_ns(duration) > ktime_to_ns(lock->stat.max_time))
-		lock->stat.max_time = duration;
-	lock->stat.last_time = ktime_get();
-	if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
-		duration = ktime_sub(now, last_sleep_time_update);
-		lock->stat.prevent_suspend_time = ktime_add(
-			lock->stat.prevent_suspend_time, duration);
-		lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
-	}
-}
 
-static void update_sleep_wait_stats_locked(int done)
-{
-	struct wake_lock *lock;
-	ktime_t now, etime, elapsed, add;
-	int expired;
+	if (++wakelocks_gc_count <= WL_GC_COUNT_MAX)
+		return;
 
 	now = ktime_get();
-	elapsed = ktime_sub(now, last_sleep_time_update);
-	list_for_each_entry(lock, &active_wake_locks[WAKE_LOCK_SUSPEND], link) {
-		expired = get_expired_time(lock, &etime);
-		if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
-			if (expired)
-				add = ktime_sub(etime, last_sleep_time_update);
+	list_for_each_entry_safe_reverse(wl, aux, &wakelocks_lru_list, lru) {
+		u64 idle_time_ns;
+		bool active;
+
+		spin_lock_irq(&wl->ws.lock);
+		idle_time_ns = ktime_to_ns(ktime_sub(now, wl->ws.last_time));
+		active = wl->ws.active;
+		spin_unlock_irq(&wl->ws.lock);
+
+		if (idle_time_ns < ((u64)WL_GC_TIME_SEC * NSEC_PER_SEC))
+			break;
+
+		if (!active) {
+			wakeup_source_remove(&wl->ws);
+			rb_erase(&wl->node, &wakelocks_tree);
+			list_del(&wl->lru);
+			kfree(wl->name);
+			kfree(wl);
+			decrement_wakelocks_number();
+		}
+	}
+	wakelocks_gc_count = 0;
+}
+#else /* !CONFIG_PM_WAKELOCKS_GC */
+static inline void wakelocks_lru_add(struct wakelock *wl) {}
+static inline void wakelocks_lru_most_recent(struct wakelock *wl) {}
+static inline void wakelocks_gc(void) {}
+#endif /* !CONFIG_PM_WAKELOCKS_GC */
+
+static struct wakelock *wakelock_lookup_add(const char *name, size_t len,
+					    bool add_if_not_found)
+{
+	struct rb_node **node = &wakelocks_tree.rb_node;
+	struct rb_node *parent = *node;
+	struct wakelock *wl;
+
+	while (*node) {
+		int diff;
+
+		parent = *node;
+		wl = rb_entry(*node, struct wakelock, node);
+		diff = strncmp(name, wl->name, len);
+		if (diff == 0) {
+			if (wl->name[len])
+				diff = -1;
 			else
-				add = elapsed;
-			lock->stat.prevent_suspend_time = ktime_add(
-				lock->stat.prevent_suspend_time, add);
+				return wl;
 		}
-		if (done || expired)
-			lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
+		if (diff < 0)
+			node = &(*node)->rb_left;
 		else
-			lock->flags |= WAKE_LOCK_PREVENTING_SUSPEND;
+			node = &(*node)->rb_right;
 	}
-	last_sleep_time_update = now;
-}
-#endif
+	if (!add_if_not_found)
+		return ERR_PTR(-EINVAL);
 
+	if (wakelocks_limit_exceeded())
+		return ERR_PTR(-ENOSPC);
 
-static void expire_wake_lock(struct wake_lock *lock)
-{
-#ifdef CONFIG_WAKELOCK_STAT
-	wake_unlock_stat_locked(lock, 1);
-#endif
-	lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
-	list_del(&lock->link);
-	list_add(&lock->link, &inactive_locks);
-	if (debug_mask & (DEBUG_WAKE_LOCK | DEBUG_EXPIRE))
-		pr_info("expired wake lock %s\n", lock->name);
-}
+	/* Not found, we have to add a new one. */
+	wl = kzalloc(sizeof(*wl), GFP_KERNEL);
+	if (!wl)
+		return ERR_PTR(-ENOMEM);
 
-/* Caller must acquire the list_lock spinlock */
-static void print_active_locks(int type)
-{
-	struct wake_lock *lock;
-	bool print_expired = true;
-
-	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
-	list_for_each_entry(lock, &active_wake_locks[type], link) {
-		if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
-			long timeout = lock->expires - jiffies;
-			if (timeout > 0)
-				pr_info("active wake lock %s, time left %ld\n",
-					lock->name, timeout);
-			else if (print_expired)
-				pr_info("wake lock %s, expired\n", lock->name);
-		} else {
-			pr_info("active wake lock %s\n", lock->name);
-			if (!(debug_mask & DEBUG_EXPIRE))
-				print_expired = false;
-		}
+	wl->name = kstrndup(name, len, GFP_KERNEL);
+	if (!wl->name) {
+		kfree(wl);
+		return ERR_PTR(-ENOMEM);
 	}
+	wl->ws.name = wl->name;
+	wakeup_source_add(&wl->ws);
+	rb_link_node(&wl->node, parent, node);
+	rb_insert_color(&wl->node, &wakelocks_tree);
+	wakelocks_lru_add(wl);
+	increment_wakelocks_number();
+	return wl;
 }
 
-static long has_wake_lock_locked(int type)
+int pm_wake_lock(const char *buf)
 {
-	struct wake_lock *lock, *n;
-	long max_timeout = 0;
+	const char *str = buf;
+	struct wakelock *wl;
+	u64 timeout_ns = 0;
+	size_t len;
+	int ret = 0;
 
-	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
-	list_for_each_entry_safe(lock, n, &active_wake_locks[type], link) {
-		if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
-			long timeout = lock->expires - jiffies;
-			if (timeout <= 0)
-				expire_wake_lock(lock);
-			else if (timeout > max_timeout)
-				max_timeout = timeout;
-		} else
-			return -1;
+	while (*str && !isspace(*str))
+		str++;
+
+	len = str - buf;
+	if (!len)
+		return -EINVAL;
+
+	if (*str && *str != '\n') {
+		/* Find out if there's a valid timeout string appended. */
+		ret = kstrtou64(skip_spaces(str), 10, &timeout_ns);
+		if (ret)
+			return -EINVAL;
 	}
-	return max_timeout;
-}
 
-long has_wake_lock(int type)
-{
-	long ret;
-	unsigned long irqflags;
-	spin_lock_irqsave(&list_lock, irqflags);
-	ret = has_wake_lock_locked(type);
-	if (ret && (debug_mask & DEBUG_WAKEUP) && type == WAKE_LOCK_SUSPEND)
-		print_active_locks(type);
-	spin_unlock_irqrestore(&list_lock, irqflags);
+	mutex_lock(&wakelocks_lock);
+
+	wl = wakelock_lookup_add(buf, len, true);
+	if (IS_ERR(wl)) {
+		ret = PTR_ERR(wl);
+		goto out;
+	}
+	if (timeout_ns) {
+		u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1;
+
+		do_div(timeout_ms, NSEC_PER_MSEC);
+		__pm_wakeup_event(&wl->ws, timeout_ms);
+	} else {
+		__pm_stay_awake(&wl->ws);
+	}
+
+	wakelocks_lru_most_recent(wl);
+
+ out:
+	mutex_unlock(&wakelocks_lock);
 	return ret;
 }
 
-static void suspend_sys_sync(struct work_struct *work)
+int pm_wake_unlock(const char *buf)
 {
-	if (debug_mask & DEBUG_SUSPEND)
-		pr_info("PM: Syncing filesystems...\n");
+	struct wakelock *wl;
+	size_t len;
+	int ret = 0;
 
-	sys_sync();
+	len = strlen(buf);
+	if (!len)
+		return -EINVAL;
 
-	if (debug_mask & DEBUG_SUSPEND)
-		pr_info("sync done.\n");
+	if (buf[len-1] == '\n')
+		len--;
 
-	spin_lock(&suspend_sys_sync_lock);
-	suspend_sys_sync_count--;
-	spin_unlock(&suspend_sys_sync_lock);
-}
-static DECLARE_WORK(suspend_sys_sync_work, suspend_sys_sync);
+	if (!len)
+		return -EINVAL;
 
-void suspend_sys_sync_queue(void)
-{
-	int ret;
+	mutex_lock(&wakelocks_lock);
 
-	spin_lock(&suspend_sys_sync_lock);
-	ret = queue_work(suspend_sys_sync_work_queue, &suspend_sys_sync_work);
-	if (ret)
-		suspend_sys_sync_count++;
-	spin_unlock(&suspend_sys_sync_lock);
-}
-
-static bool suspend_sys_sync_abort;
-static void suspend_sys_sync_handler(unsigned long);
-static DEFINE_TIMER(suspend_sys_sync_timer, suspend_sys_sync_handler, 0, 0);
-/* value should be less then half of input event wake lock timeout value
- * which is currently set to 5*HZ (see drivers/input/evdev.c)
- */
-#define SUSPEND_SYS_SYNC_TIMEOUT (HZ/4)
-static void suspend_sys_sync_handler(unsigned long arg)
-{
-	if (suspend_sys_sync_count == 0) {
-		complete(&suspend_sys_sync_comp);
-	} else if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
-		suspend_sys_sync_abort = true;
-		complete(&suspend_sys_sync_comp);
-	} else {
-		mod_timer(&suspend_sys_sync_timer, jiffies +
-				SUSPEND_SYS_SYNC_TIMEOUT);
+	wl = wakelock_lookup_add(buf, len, false);
+	if (IS_ERR(wl)) {
+		ret = PTR_ERR(wl);
+		goto out;
 	}
-}
+	__pm_relax(&wl->ws);
 
-int suspend_sys_sync_wait(void)
-{
-	suspend_sys_sync_abort = false;
+	wakelocks_lru_most_recent(wl);
+	wakelocks_gc();
 
-	if (suspend_sys_sync_count != 0) {
-		mod_timer(&suspend_sys_sync_timer, jiffies +
-				SUSPEND_SYS_SYNC_TIMEOUT);
-		wait_for_completion(&suspend_sys_sync_comp);
-	}
-	if (suspend_sys_sync_abort) {
-		pr_info("suspend aborted....while waiting for sys_sync\n");
-		return -EAGAIN;
-	}
-
-	return 0;
-}
-
-static void suspend_backoff(void)
-{
-	pr_info("suspend: too many immediate wakeups, back off\n");
-	wake_lock_timeout(&suspend_backoff_lock,
-			  msecs_to_jiffies(SUSPEND_BACKOFF_INTERVAL));
-}
-
-static void suspend(struct work_struct *work)
-{
-	int ret;
-	int entry_event_num;
-	struct timespec ts_entry, ts_exit;
-
-	if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
-		if (debug_mask & DEBUG_SUSPEND)
-			pr_info("suspend: abort suspend\n");
-		return;
-	}
-
-	entry_event_num = current_event_num;
-	suspend_sys_sync_queue();
-	if (debug_mask & DEBUG_SUSPEND)
-		pr_info("suspend: enter suspend\n");
-	getnstimeofday(&ts_entry);
-	ret = pm_suspend(requested_suspend_state);
-	getnstimeofday(&ts_exit);
-
-	if (debug_mask & DEBUG_EXIT_SUSPEND) {
-		struct rtc_time tm;
-		rtc_time_to_tm(ts_exit.tv_sec, &tm);
-		pr_info("suspend: exit suspend, ret = %d "
-			"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n", ret,
-			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-			tm.tm_hour, tm.tm_min, tm.tm_sec, ts_exit.tv_nsec);
-	}
-
-	if (ts_exit.tv_sec - ts_entry.tv_sec <= 1) {
-		++suspend_short_count;
-
-		if (suspend_short_count == SUSPEND_BACKOFF_THRESHOLD) {
-			suspend_backoff();
-			suspend_short_count = 0;
-		}
-	} else {
-		suspend_short_count = 0;
-	}
-
-	if (current_event_num == entry_event_num) {
-		if (debug_mask & DEBUG_SUSPEND)
-			pr_info("suspend: pm_suspend returned with no event\n");
-		wake_lock_timeout(&unknown_wakeup, HZ / 2);
-	}
-}
-static DECLARE_WORK(suspend_work, suspend);
-
-static void expire_wake_locks(unsigned long data)
-{
-	long has_lock;
-	unsigned long irqflags;
-	if (debug_mask & DEBUG_EXPIRE)
-		pr_info("expire_wake_locks: start\n");
-	spin_lock_irqsave(&list_lock, irqflags);
-	if (debug_mask & DEBUG_SUSPEND)
-		print_active_locks(WAKE_LOCK_SUSPEND);
-	has_lock = has_wake_lock_locked(WAKE_LOCK_SUSPEND);
-	if (debug_mask & DEBUG_EXPIRE)
-		pr_info("expire_wake_locks: done, has_lock %ld\n", has_lock);
-	if (has_lock == 0)
-		queue_work(suspend_work_queue, &suspend_work);
-	spin_unlock_irqrestore(&list_lock, irqflags);
-}
-static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);
-
-static int power_suspend_late(struct device *dev)
-{
-	int ret = has_wake_lock(WAKE_LOCK_SUSPEND) ? -EAGAIN : 0;
-#ifdef CONFIG_WAKELOCK_STAT
-	wait_for_wakeup = !ret;
-#endif
-	if (debug_mask & DEBUG_SUSPEND)
-		pr_info("power_suspend_late return %d\n", ret);
+ out:
+	mutex_unlock(&wakelocks_lock);
 	return ret;
 }
-
-static struct dev_pm_ops power_driver_pm_ops = {
-	.suspend_noirq = power_suspend_late,
-};
-
-static struct platform_driver power_driver = {
-	.driver.name = "power",
-	.driver.pm = &power_driver_pm_ops,
-};
-static struct platform_device power_device = {
-	.name = "power",
-};
-
-void wake_lock_init(struct wake_lock *lock, int type, const char *name)
-{
-	unsigned long irqflags = 0;
-
-	if (name)
-		lock->name = name;
-	BUG_ON(!lock->name);
-
-	if (debug_mask & DEBUG_WAKE_LOCK)
-		pr_info("wake_lock_init name=%s\n", lock->name);
-#ifdef CONFIG_WAKELOCK_STAT
-	lock->stat.count = 0;
-	lock->stat.expire_count = 0;
-	lock->stat.wakeup_count = 0;
-	lock->stat.total_time = ktime_set(0, 0);
-	lock->stat.prevent_suspend_time = ktime_set(0, 0);
-	lock->stat.max_time = ktime_set(0, 0);
-	lock->stat.last_time = ktime_set(0, 0);
-#endif
-	lock->flags = (type & WAKE_LOCK_TYPE_MASK) | WAKE_LOCK_INITIALIZED;
-
-	INIT_LIST_HEAD(&lock->link);
-	spin_lock_irqsave(&list_lock, irqflags);
-	list_add(&lock->link, &inactive_locks);
-	spin_unlock_irqrestore(&list_lock, irqflags);
-}
-EXPORT_SYMBOL(wake_lock_init);
-
-void wake_lock_destroy(struct wake_lock *lock)
-{
-	unsigned long irqflags;
-	if (debug_mask & DEBUG_WAKE_LOCK)
-		pr_info("wake_lock_destroy name=%s\n", lock->name);
-	spin_lock_irqsave(&list_lock, irqflags);
-	lock->flags &= ~WAKE_LOCK_INITIALIZED;
-#ifdef CONFIG_WAKELOCK_STAT
-	if (lock->stat.count) {
-		deleted_wake_locks.stat.count += lock->stat.count;
-		deleted_wake_locks.stat.expire_count += lock->stat.expire_count;
-		deleted_wake_locks.stat.total_time =
-			ktime_add(deleted_wake_locks.stat.total_time,
-				  lock->stat.total_time);
-		deleted_wake_locks.stat.prevent_suspend_time =
-			ktime_add(deleted_wake_locks.stat.prevent_suspend_time,
-				  lock->stat.prevent_suspend_time);
-		deleted_wake_locks.stat.max_time =
-			ktime_add(deleted_wake_locks.stat.max_time,
-				  lock->stat.max_time);
-	}
-#endif
-	list_del(&lock->link);
-	spin_unlock_irqrestore(&list_lock, irqflags);
-}
-EXPORT_SYMBOL(wake_lock_destroy);
-
-static void wake_lock_internal(
-	struct wake_lock *lock, long timeout, int has_timeout)
-{
-	int type;
-	unsigned long irqflags;
-	long expire_in;
-
-	spin_lock_irqsave(&list_lock, irqflags);
-	type = lock->flags & WAKE_LOCK_TYPE_MASK;
-	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
-	BUG_ON(!(lock->flags & WAKE_LOCK_INITIALIZED));
-#ifdef CONFIG_WAKELOCK_STAT
-	if (type == WAKE_LOCK_SUSPEND && wait_for_wakeup) {
-		if (debug_mask & DEBUG_WAKEUP)
-			pr_info("wakeup wake lock: %s\n", lock->name);
-		wait_for_wakeup = 0;
-		lock->stat.wakeup_count++;
-	}
-	if ((lock->flags & WAKE_LOCK_AUTO_EXPIRE) &&
-	    (long)(lock->expires - jiffies) <= 0) {
-		wake_unlock_stat_locked(lock, 0);
-		lock->stat.last_time = ktime_get();
-	}
-#endif
-	if (!(lock->flags & WAKE_LOCK_ACTIVE)) {
-		lock->flags |= WAKE_LOCK_ACTIVE;
-#ifdef CONFIG_WAKELOCK_STAT
-		lock->stat.last_time = ktime_get();
-#endif
-	}
-	list_del(&lock->link);
-	if (has_timeout) {
-		if (debug_mask & DEBUG_WAKE_LOCK)
-			pr_info("wake_lock: %s, type %d, timeout %ld.%03lu\n",
-				lock->name, type, timeout / HZ,
-				(timeout % HZ) * MSEC_PER_SEC / HZ);
-		lock->expires = jiffies + timeout;
-		lock->flags |= WAKE_LOCK_AUTO_EXPIRE;
-		list_add_tail(&lock->link, &active_wake_locks[type]);
-	} else {
-		if (debug_mask & DEBUG_WAKE_LOCK)
-			pr_info("wake_lock: %s, type %d\n", lock->name, type);
-		lock->expires = LONG_MAX;
-		lock->flags &= ~WAKE_LOCK_AUTO_EXPIRE;
-		list_add(&lock->link, &active_wake_locks[type]);
-	}
-	if (type == WAKE_LOCK_SUSPEND) {
-		current_event_num++;
-#ifdef CONFIG_WAKELOCK_STAT
-		if (lock == &main_wake_lock)
-			update_sleep_wait_stats_locked(1);
-		else if (!wake_lock_active(&main_wake_lock))
-			update_sleep_wait_stats_locked(0);
-#endif
-		if (has_timeout)
-			expire_in = has_wake_lock_locked(type);
-		else
-			expire_in = -1;
-		if (expire_in > 0) {
-			if (debug_mask & DEBUG_EXPIRE)
-				pr_info("wake_lock: %s, start expire timer, "
-					"%ld\n", lock->name, expire_in);
-			mod_timer(&expire_timer, jiffies + expire_in);
-		} else {
-			if (del_timer(&expire_timer))
-				if (debug_mask & DEBUG_EXPIRE)
-					pr_info("wake_lock: %s, stop expire timer\n",
-						lock->name);
-			if (expire_in == 0)
-				queue_work(suspend_work_queue, &suspend_work);
-		}
-	}
-	spin_unlock_irqrestore(&list_lock, irqflags);
-}
-
-void wake_lock(struct wake_lock *lock)
-{
-	wake_lock_internal(lock, 0, 0);
-}
-EXPORT_SYMBOL(wake_lock);
-
-void wake_lock_timeout(struct wake_lock *lock, long timeout)
-{
-	wake_lock_internal(lock, timeout, 1);
-}
-EXPORT_SYMBOL(wake_lock_timeout);
-
-void wake_unlock(struct wake_lock *lock)
-{
-	int type;
-	unsigned long irqflags;
-	spin_lock_irqsave(&list_lock, irqflags);
-	type = lock->flags & WAKE_LOCK_TYPE_MASK;
-#ifdef CONFIG_WAKELOCK_STAT
-	wake_unlock_stat_locked(lock, 0);
-#endif
-	if (debug_mask & DEBUG_WAKE_LOCK)
-		pr_info("wake_unlock: %s\n", lock->name);
-	lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
-	list_del(&lock->link);
-	list_add(&lock->link, &inactive_locks);
-	if (type == WAKE_LOCK_SUSPEND) {
-		long has_lock = has_wake_lock_locked(type);
-		if (has_lock > 0) {
-			if (debug_mask & DEBUG_EXPIRE)
-				pr_info("wake_unlock: %s, start expire timer, "
-					"%ld\n", lock->name, has_lock);
-			mod_timer(&expire_timer, jiffies + has_lock);
-		} else {
-			if (del_timer(&expire_timer))
-				if (debug_mask & DEBUG_EXPIRE)
-					pr_info("wake_unlock: %s, stop expire "
-						"timer\n", lock->name);
-			if (has_lock == 0)
-				queue_work(suspend_work_queue, &suspend_work);
-		}
-		if (lock == &main_wake_lock) {
-			if (debug_mask & DEBUG_SUSPEND)
-				print_active_locks(WAKE_LOCK_SUSPEND);
-#ifdef CONFIG_WAKELOCK_STAT
-			update_sleep_wait_stats_locked(0);
-#endif
-		}
-	}
-	spin_unlock_irqrestore(&list_lock, irqflags);
-}
-EXPORT_SYMBOL(wake_unlock);
-
-int wake_lock_active(struct wake_lock *lock)
-{
-	return !!(lock->flags & WAKE_LOCK_ACTIVE);
-}
-EXPORT_SYMBOL(wake_lock_active);
-
-static int wakelock_stats_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, wakelock_stats_show, NULL);
-}
-
-static const struct file_operations wakelock_stats_fops = {
-	.owner = THIS_MODULE,
-	.open = wakelock_stats_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static int __init wakelocks_init(void)
-{
-	int ret;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(active_wake_locks); i++)
-		INIT_LIST_HEAD(&active_wake_locks[i]);
-
-#ifdef CONFIG_WAKELOCK_STAT
-	wake_lock_init(&deleted_wake_locks, WAKE_LOCK_SUSPEND,
-			"deleted_wake_locks");
-#endif
-	wake_lock_init(&main_wake_lock, WAKE_LOCK_SUSPEND, "main");
-	wake_lock(&main_wake_lock);
-	wake_lock_init(&unknown_wakeup, WAKE_LOCK_SUSPEND, "unknown_wakeups");
-	wake_lock_init(&suspend_backoff_lock, WAKE_LOCK_SUSPEND,
-		       "suspend_backoff");
-
-	ret = platform_device_register(&power_device);
-	if (ret) {
-		pr_err("wakelocks_init: platform_device_register failed\n");
-		goto err_platform_device_register;
-	}
-	ret = platform_driver_register(&power_driver);
-	if (ret) {
-		pr_err("wakelocks_init: platform_driver_register failed\n");
-		goto err_platform_driver_register;
-	}
-
-	INIT_COMPLETION(suspend_sys_sync_comp);
-	suspend_sys_sync_work_queue =
-		create_singlethread_workqueue("suspend_sys_sync");
-	if (suspend_sys_sync_work_queue == NULL) {
-		ret = -ENOMEM;
-		goto err_suspend_sys_sync_work_queue;
-	}
-
-	suspend_work_queue = create_singlethread_workqueue("suspend");
-	if (suspend_work_queue == NULL) {
-		ret = -ENOMEM;
-		goto err_suspend_work_queue;
-	}
-
-#ifdef CONFIG_WAKELOCK_STAT
-	proc_create("wakelocks", S_IRUGO, NULL, &wakelock_stats_fops);
-#endif
-
-	return 0;
-
-err_suspend_work_queue:
-err_suspend_sys_sync_work_queue:
-	platform_driver_unregister(&power_driver);
-err_platform_driver_register:
-	platform_device_unregister(&power_device);
-err_platform_device_register:
-	wake_lock_destroy(&suspend_backoff_lock);
-	wake_lock_destroy(&unknown_wakeup);
-	wake_lock_destroy(&main_wake_lock);
-#ifdef CONFIG_WAKELOCK_STAT
-	wake_lock_destroy(&deleted_wake_locks);
-#endif
-	return ret;
-}
-
-static void  __exit wakelocks_exit(void)
-{
-#ifdef CONFIG_WAKELOCK_STAT
-	remove_proc_entry("wakelocks", NULL);
-#endif
-	destroy_workqueue(suspend_work_queue);
-	destroy_workqueue(suspend_sys_sync_work_queue);
-	platform_driver_unregister(&power_driver);
-	platform_device_unregister(&power_device);
-	wake_lock_destroy(&suspend_backoff_lock);
-	wake_lock_destroy(&unknown_wakeup);
-	wake_lock_destroy(&main_wake_lock);
-#ifdef CONFIG_WAKELOCK_STAT
-	wake_lock_destroy(&deleted_wake_locks);
-#endif
-}
-
-core_initcall(wakelocks_init);
-module_exit(wakelocks_exit);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 50f73be..7ffcc1b 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -543,7 +543,6 @@
 	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
 	conn->conn_valid = true;
 	spin_lock_init(&conn->lock);
-	wake_lock_init(&conn->idle_lock, WAKE_LOCK_SUSPEND, "bt_idle");
 
 	switch (type) {
 	case ACL_LINK:
@@ -621,7 +620,6 @@
 
 	/* Make sure no timers are running */
 	del_timer(&conn->idle_timer);
-	wake_lock_destroy(&conn->idle_lock);
 	del_timer(&conn->disc_timer);
 	del_timer(&conn->smp_timer);
 	__cancel_delayed_work(&conn->rssi_update_work);
@@ -1082,7 +1080,6 @@
 		if (conn->conn_valid) {
 			mod_timer(&conn->idle_timer,
 				jiffies + msecs_to_jiffies(hdev->idle_timeout));
-			wake_lock(&conn->idle_lock);
 		}
 		spin_unlock_bh(&conn->lock);
 	}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 198773c..d243646 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2596,9 +2596,6 @@
 			else
 				conn->power_save = 0;
 		}
-		if (conn->mode == HCI_CM_SNIFF)
-			if (wake_lock_active(&conn->idle_lock))
-				wake_unlock(&conn->idle_lock);
 
 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
 			hci_sco_setup(conn, ev->status);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 5190c0b..b57532d 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -736,7 +736,6 @@
 		}
 #if IS_ENABLED(CONFIG_IPV6)
 		else if (skb->protocol == htons(ETH_P_IPV6)) {
-			struct neighbour *neigh = dst_get_neighbour(skb_dst(skb));
 			const struct in6_addr *addr6;
 			struct neighbour *neigh;
 			bool do_tx_error_icmp;
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index af268bd..f4ea679 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -83,6 +83,7 @@
 	AIF2_CAP,
 	AIF3_PB,
 	AIF3_CAP,
+	AIF4_VIFEED,
 	NUM_CODEC_DAIS,
 };
 
@@ -2671,6 +2672,7 @@
 	{"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
 	{"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
 	{"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
+	{"AIF4 VI", NULL, "SPK_OUT"},
 
 	/* SLIM_MIXER("AIF1_CAP Mixer"),*/
 	{"AIF1_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
@@ -3143,6 +3145,7 @@
 	{"MIC BIAS3 Internal2", NULL, "LDO_H"},
 	{"MIC BIAS3 External", NULL, "LDO_H"},
 	{"MIC BIAS4 External", NULL, "LDO_H"},
+
 };
 
 static int taiko_readable(struct snd_soc_codec *ssc, unsigned int reg)
@@ -3367,6 +3370,7 @@
 				unsigned int rx_num, unsigned int *rx_slot)
 
 {
+	struct wcd9xxx_codec_dai_data *dai_data = NULL;
 	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
 	struct wcd9xxx *core = dev_get_drvdata(dai->codec->dev->parent);
 	if (!tx_slot && !rx_slot) {
@@ -3378,9 +3382,18 @@
 		 __func__, dai->name, dai->id, tx_num, rx_num,
 		 taiko->intf_type);
 
-	if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+	if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
 		wcd9xxx_init_slimslave(core, core->slim->laddr,
-				       tx_num, tx_slot, rx_num, rx_slot);
+					   tx_num, tx_slot, rx_num, rx_slot);
+		/*Reserve tx11 and tx12 for VI feedback path*/
+		dai_data = &taiko->dai[AIF4_VIFEED];
+		if (dai_data) {
+			list_add_tail(&core->tx_chs[TAIKO_TX11].list,
+			&dai_data->wcd9xxx_ch_list);
+			list_add_tail(&core->tx_chs[TAIKO_TX12].list,
+			&dai_data->wcd9xxx_ch_list);
+		}
+	}
 	return 0;
 }
 
@@ -3414,6 +3427,7 @@
 	case AIF1_CAP:
 	case AIF2_CAP:
 	case AIF3_CAP:
+	case AIF4_VIFEED:
 		if (!tx_slot || !tx_num) {
 			pr_err("%s: Invalid tx_slot %d or tx_num %d\n",
 				 __func__, (u32) tx_slot, (u32) tx_num);
@@ -3639,12 +3653,14 @@
 
 	switch (substream->stream) {
 	case SNDRV_PCM_STREAM_CAPTURE:
-		ret = taiko_set_decimator_rate(dai, tx_fs_rate,
-					       params_rate(params));
-		if (ret < 0) {
-			pr_err("%s: set decimator rate failed %d\n", __func__,
-				ret);
-			return ret;
+		if (dai->id != AIF4_VIFEED) {
+			ret = taiko_set_decimator_rate(dai, tx_fs_rate,
+							   params_rate(params));
+			if (ret < 0) {
+				pr_err("%s: set decimator rate failed %d\n",
+					__func__, ret);
+				return ret;
+			}
 		}
 
 		if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
@@ -3828,6 +3844,20 @@
 		},
 		.ops = &taiko_dai_ops,
 	},
+	{
+		.name = "taiko_vifeedback",
+		.id = AIF4_VIFEED,
+		.capture = {
+			.stream_name = "VIfeed",
+			.rates = SNDRV_PCM_RATE_48000,
+			.formats = TAIKO_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 48000,
+			.channels_min = 2,
+			.channels_max = 2,
+	 },
+		.ops = &taiko_dai_ops,
+	},
 };
 
 static struct snd_soc_dai_driver taiko_i2s_dai[] = {
@@ -3967,6 +3997,89 @@
 	return ret;
 }
 
+static int taiko_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol,
+				int event)
+{
+	struct wcd9xxx *core = NULL;
+	struct snd_soc_codec *codec = NULL;
+	struct taiko_priv *taiko_p = NULL;
+	u32 ret = 0;
+	struct wcd9xxx_codec_dai_data *dai = NULL;
+
+	if (!w || !w->codec) {
+		pr_err("%s invalid params\n", __func__);
+		return -EINVAL;
+	}
+	codec = w->codec;
+	taiko_p = snd_soc_codec_get_drvdata(codec);
+	core = dev_get_drvdata(codec->dev->parent);
+
+	pr_debug("%s: event called! codec name %s num_dai %d stream name %s\n",
+		__func__, w->codec->name, w->codec->num_dai, w->sname);
+
+	/* Execute the callback only if interface type is slimbus */
+	if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
+		pr_err("%s Interface is not correct", __func__);
+		return 0;
+	}
+
+	pr_debug("%s(): w->name %s event %d w->shift %d\n",
+		__func__, w->name, event, w->shift);
+	if (w->shift != AIF4_VIFEED) {
+		pr_err("%s Error in enabling the tx path\n", __func__);
+		ret = -EINVAL;
+		goto out_vi;
+	}
+	dai = &taiko_p->dai[w->shift];
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		/*Enable Clip Detection*/
+		snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_CLIP_DET,
+				0x8, 0x8);
+		/*Enable V&I sensing*/
+		snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
+				0x88, 0x88);
+		/*Enable spkr VI clocks*/
+		snd_soc_update_bits(codec,
+		TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0xC, 0xC);
+		/*Enable Voltage Decimator*/
+		snd_soc_update_bits(codec,
+		TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x1F, 0x12);
+		/*Enable Current Decimator*/
+		snd_soc_update_bits(codec,
+		TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x1F, 0x13);
+		ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
+					dai->rate, dai->bit_width,
+					&dai->grph);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
+						dai->grph);
+		if (ret)
+			pr_err("%s error in close_slim_sch_tx %d\n",
+				__func__, ret);
+		/*Disable Voltage decimator*/
+		snd_soc_update_bits(codec,
+		TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x1F, 0x0);
+		/*Disable Current decimator*/
+		snd_soc_update_bits(codec,
+		TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x1F, 0x0);
+		/*Disable spkr VI clocks*/
+		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL,
+				0xC, 0x0);
+		/*Disable V&I sensing*/
+		snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
+				0x88, 0x00);
+		/*Disable clip detection*/
+		snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_CLIP_DET,
+				0x8, 0x0);
+		break;
+	}
+out_vi:
+	return ret;
+}
+
 static int taiko_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
 				     struct snd_kcontrol *kcontrol,
 				     int event)
@@ -4440,6 +4553,10 @@
 		AIF3_CAP, 0, taiko_codec_enable_slimtx,
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
+		AIF4_VIFEED, 0, taiko_codec_enable_slimvi_feedback,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
 		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
 
@@ -4529,7 +4646,6 @@
 
 	SND_SOC_DAPM_MIXER("LINEOUT4_PA_MIXER", SND_SOC_NOPM, 0, 0,
 		lineout4_pa_mix, ARRAY_SIZE(lineout4_pa_mix)),
-
 };
 
 static irqreturn_t taiko_slimbus_irq(int irq, void *data)
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index f1b6203..916ff1a 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -139,7 +139,7 @@
 	if (on && (++cp_count == 1)) {
 		snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
 							0x01, 0x01);
-		dev_info(codec->dev, "%s: Charge Pump enabled, count = %d\n",
+		dev_dbg(codec->dev, "%s: Charge Pump enabled, count = %d\n",
 				__func__, cp_count);
 	}
 
@@ -149,7 +149,7 @@
 					__func__);
 			if (snd_soc_read(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL)
 					& 0x01) {
-				dev_info(codec->dev, "%s: Actual chargepump is ON\n",
+				dev_dbg(codec->dev, "%s: Actual chargepump is ON\n",
 						__func__);
 			}
 			cp_count = 0;
@@ -526,7 +526,7 @@
 		(*clsh_state_fp[new_state]) (codec, cdc_clsh_d,
 							req_state, req_type);
 		cdc_clsh_d->state = new_state;
-		dev_info(codec->dev, "%s: ClassH state transition from %s to %s\n",
+		dev_dbg(codec->dev, "%s: ClassH state transition from %s to %s\n",
 			__func__, state_to_str(old_state),
 			state_to_str(cdc_clsh_d->state));
 
@@ -546,7 +546,7 @@
 				(*clsh_state_fp[new_state]) (codec, cdc_clsh_d,
 							req_state, req_type);
 				cdc_clsh_d->state = new_state;
-				dev_info(codec->dev, "%s: ClassH state transition from %s to %s\n",
+				dev_dbg(codec->dev, "%s: ClassH state transition from %s to %s\n",
 					__func__, state_to_str(old_state),
 					state_to_str(cdc_clsh_d->state));
 
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 39afb73..4e6cbaa 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -788,7 +788,7 @@
 	runtime->private_data = compr;
 	atomic_set(&prtd->eos, 0);
 	compressed_audio.prtd =  &compr->prtd;
-	ret = compressed_set_volume(compressed_audio.volume);
+	ret = compressed_set_volume(0);
 	if (ret < 0)
 		pr_err("%s : Set Volume failed : %d", __func__, ret);
 
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 4462213..747e027 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -1802,13 +1802,13 @@
 		.name = LPASS_BE_SLIMBUS_4_TX,
 		.stream_name = "Slimbus4 Capture",
 		.cpu_dai_name = "msm-dai-q6-dev.16393",
-		.platform_name = "msm-pcm-routing",
+		.platform_name = "msm-pcm-hostless",
 		.codec_name = "taiko_codec",
-		.codec_dai_name	= "taiko_tx1",
-		.no_pcm = 1,
+		.codec_dai_name	= "taiko_vifeedback",
 		.be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
 		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm8974_be_ops,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 	},
 	/* Incall Record Uplink BACK END DAI Link */
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index b71132e..ccaf39d 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -85,6 +85,9 @@
 	atomic64_t			paddr;
 	atomic64_t			kvaddr;
 	atomic64_t			mem_len;
+
+	/* Speaker protection */
+	struct msm_spk_prot_cfg spk_prot_cfg;
 };
 
 static struct acdb_data		acdb_data;
@@ -767,6 +770,34 @@
 done:
 	return;
 }
+void get_spk_protection_cfg(struct msm_spk_prot_cfg *prot_cfg)
+{
+	mutex_lock(&acdb_data.acdb_mutex);
+	if (prot_cfg) {
+		prot_cfg->mode = acdb_data.spk_prot_cfg.mode;
+		prot_cfg->r0 = acdb_data.spk_prot_cfg.r0;
+		prot_cfg->t0 = acdb_data.spk_prot_cfg.t0;
+	} else
+		pr_err("%s prot_cfg is NULL\n", __func__);
+	mutex_unlock(&acdb_data.acdb_mutex);
+}
+static void get_spk_protection_status(struct msm_spk_prot_status *status)
+{
+	/*Call AFE function here to query the status*/
+	struct afe_spkr_prot_get_vi_calib calib_resp;
+	if (status) {
+		status->status = -EINVAL;
+		if (!afe_spk_prot_get_calib_data(&calib_resp)) {
+			if (calib_resp.res_cfg.th_vi_ca_state == 1)
+				status->status = -EAGAIN;
+			else if (calib_resp.res_cfg.th_vi_ca_state == 2) {
+				status->status = 0;
+				status->r0 = calib_resp.res_cfg.r0_cali_q24;
+			}
+		 }
+	} else
+		pr_err("%s invalid params\n", __func__);
+}
 
 static int acdb_open(struct inode *inode, struct file *f)
 {
@@ -880,6 +911,8 @@
 	int32_t			map_fd;
 	uint32_t		topology;
 	uint32_t		data[MAX_IOCTL_DATA];
+	struct msm_spk_prot_status prot_status;
+	struct msm_spk_prot_status acdb_spk_status;
 	pr_debug("%s\n", __func__);
 
 	switch (cmd) {
@@ -943,6 +976,43 @@
 		}
 		store_asm_topology(topology);
 		goto done;
+	case AUDIO_SET_SPEAKER_PROT:
+		mutex_lock(&acdb_data.acdb_mutex);
+		if (copy_from_user(&acdb_data.spk_prot_cfg, (void *)arg,
+				sizeof(acdb_data.spk_prot_cfg))) {
+			pr_err("%s fail to copy spk_prot_cfg\n", __func__);
+			result = -EFAULT;
+		}
+		mutex_unlock(&acdb_data.acdb_mutex);
+		goto done;
+	case AUDIO_GET_SPEAKER_PROT:
+		mutex_lock(&acdb_data.acdb_mutex);
+		/*Indicates calibration was succesfull*/
+		if (!acdb_data.spk_prot_cfg.mode) {
+			prot_status.r0 = acdb_data.spk_prot_cfg.r0;
+			prot_status.status = 0;
+		} else if (acdb_data.spk_prot_cfg.mode == 1) {
+			/*Call AFE to query the status*/
+			acdb_spk_status.status = -EINVAL;
+			acdb_spk_status.r0 = -1;
+			get_spk_protection_status(&acdb_spk_status);
+			prot_status.r0 = acdb_spk_status.r0;
+			prot_status.status = acdb_spk_status.status;
+			if (!acdb_spk_status.status) {
+				acdb_data.spk_prot_cfg.mode = 0;
+				acdb_data.spk_prot_cfg.r0 = prot_status.r0;
+			}
+		} else {
+			/*Indicates calibration data is invalid*/
+			prot_status.status = -EINVAL;
+			prot_status.r0 = -1;
+		}
+		if (copy_to_user((void *)arg, &prot_status,
+			sizeof(prot_status))) {
+			pr_err("%s Failed to update prot_status\n", __func__);
+		}
+		mutex_unlock(&acdb_data.acdb_mutex);
+		goto done;
 	}
 
 	if (copy_from_user(&size, (void *) arg, sizeof(size))) {
@@ -1110,6 +1180,8 @@
 static int __init acdb_init(void)
 {
 	memset(&acdb_data, 0, sizeof(acdb_data));
+	/*Speaker protection disabled*/
+	acdb_data.spk_prot_cfg.mode = -1;
 	mutex_init(&acdb_data.acdb_mutex);
 	atomic_set(&usage_count, 0);
 	atomic_set(&acdb_data.valid_adm_custom_top, 1);
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.h b/sound/soc/msm/qdsp6v2/audio_acdb.h
index 0b6110d..4834855 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.h
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.h
@@ -63,5 +63,6 @@
 void get_vocstrm_cal(struct acdb_cal_block *cal_block);
 void get_vocvol_cal(struct acdb_cal_block *cal_block);
 void get_sidetone_cal(struct sidetone_cal *cal_data);
+void get_spk_protection_cfg(struct msm_spk_prot_cfg *prot_cfg);
 
 #endif
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index d0b5500..f6e571b8 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -754,7 +754,7 @@
 			prtd->session_id,
 			substream->stream);
 
-		ret = compressed_set_volume(compressed_audio.volume);
+		ret = compressed_set_volume(0);
 		if (ret < 0)
 			pr_err("%s : Set Volume failed : %d", __func__, ret);
 
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index c300a9f..557ec65 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -485,6 +485,7 @@
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
+	case SNDRV_PCM_FMTBIT_SPECIAL:
 		dai_data->port_config.i2s.bit_width = 16;
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
@@ -560,6 +561,7 @@
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
+	case SNDRV_PCM_FMTBIT_SPECIAL:
 		dai_data->port_config.slim_sch.bit_width = 16;
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index e05e58d..4ca96d7 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -459,19 +459,20 @@
 
 	pr_debug("%s\n", __func__);
 
-	dir = IN;
-	ret = wait_event_timeout(the_locks.eos_wait,
-				prtd->cmd_ack, 5 * HZ);
-	if (ret < 0)
-		pr_err("%s: CMD_EOS failed\n", __func__);
-	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
-	q6asm_audio_client_buf_free_contiguous(dir,
-				prtd->audio_client);
-
+	if (prtd->audio_client) {
+		dir = IN;
+		ret = wait_event_timeout(the_locks.eos_wait,
+					prtd->cmd_ack, 5 * HZ);
+		if (ret < 0)
+			pr_err("%s: CMD_EOS failed\n", __func__);
+		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+		q6asm_audio_client_buf_free_contiguous(dir,
+					prtd->audio_client);
+		pcm_audio.prtd = NULL;
+		q6asm_audio_client_free(prtd->audio_client);
+	}
 	msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
 						SNDRV_PCM_STREAM_PLAYBACK);
-	pcm_audio.prtd = NULL;
-	q6asm_audio_client_free(prtd->audio_client);
 	kfree(prtd);
 	return 0;
 }
@@ -678,7 +679,7 @@
 		if (ret < 0) {
 			pr_err("%s: q6asm_open_write_v2 failed\n", __func__);
 			q6asm_audio_client_free(prtd->audio_client);
-			kfree(prtd);
+			prtd->audio_client = NULL;
 			return -ENOMEM;
 		}
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 02c3457..9fe438c 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -2004,6 +2004,60 @@
 	msm_routing_put_eq_band_audio_mixer),
 };
 
+static int spkr_prot_put_vi_lch_port(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	int ret = 0;
+	int item;
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	pr_debug("%s item is %d\n", __func__,
+		   ucontrol->value.enumerated.item[0]);
+	mutex_lock(&routing_lock);
+	item = ucontrol->value.enumerated.item[0];
+	if (item < e->max) {
+		pr_debug("%s RX DAI ID %d TX DAI id %d\n",
+			__func__, e->shift_l , e->values[item]);
+		if (e->shift_l < MSM_BACKEND_DAI_MAX &&
+			e->values[item] < MSM_BACKEND_DAI_MAX)
+			ret = afe_spk_prot_feed_back_cfg(
+			   msm_bedais[e->values[item]].port_id,
+			   msm_bedais[e->shift_l].port_id, 1, 0);
+		else {
+			pr_err("%s values are out of range\n", __func__);
+			ret = -EINVAL;
+		}
+	} else {
+		pr_err("%s item value is out of range\n", __func__);
+		ret = -EINVAL;
+	}
+	mutex_unlock(&routing_lock);
+	return ret;
+}
+
+static int spkr_prot_get_vi_lch_port(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s\n", __func__);
+	return 0;
+}
+
+static const char * const slim0_rx_vi_fb_tx_lch_mux_text[] = {
+	"SLIM4_TX",
+};
+
+static const int const slim0_rx_vi_fb_tx_lch_value[] = {
+	MSM_BACKEND_DAI_SLIMBUS_4_TX,
+};
+static const struct soc_enum slim0_rx_vi_fb_lch_mux_enum =
+	SOC_VALUE_ENUM_DOUBLE(0, MSM_BACKEND_DAI_SLIMBUS_0_RX, 0, 0,
+	ARRAY_SIZE(slim0_rx_vi_fb_tx_lch_mux_text),
+	slim0_rx_vi_fb_tx_lch_mux_text, slim0_rx_vi_fb_tx_lch_value);
+
+static const struct snd_kcontrol_new slim0_rx_vi_fb_lch_mux =
+	SOC_DAPM_ENUM_EXT("SLIM0_RX_VI_FB_LCH_MUX",
+	slim0_rx_vi_fb_lch_mux_enum, spkr_prot_get_vi_lch_port,
+	spkr_prot_put_vi_lch_port);
+
 static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
 	/* Frontend AIF */
 	/* Widget name equals to Front-End DAI name<Need confirmation>,
@@ -2249,6 +2303,9 @@
 	SND_SOC_DAPM_OUTPUT("BE_OUT"),
 	SND_SOC_DAPM_INPUT("BE_IN"),
 
+	SND_SOC_DAPM_MUX("SLIM0_RX_VI_FB_LCH_MUX", SND_SOC_NOPM, 0, 0,
+				&slim0_rx_vi_fb_lch_mux),
+
 };
 
 static const struct snd_soc_dapm_route intercon[] = {
@@ -2554,7 +2611,9 @@
 	{"AUX_PCM_TX", NULL, "BE_IN"},
 	{"INCALL_RECORD_TX", NULL, "BE_IN"},
 	{"INCALL_RECORD_RX", NULL, "BE_IN"},
-	{"BE_OUT", NULL, "VOICE_PLAYBACK_TX"}
+	{"BE_OUT", NULL, "VOICE_PLAYBACK_TX"},
+	{"SLIM0_RX_VI_FB_LCH_MUX", "SLIM4_TX", "SLIMBUS_4_TX"},
+	{"SLIMBUS_0_RX", NULL, "SLIM0_RX_VI_FB_LCH_MUX"},
 };
 
 static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 1b5ad17..5e1da59 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -25,7 +25,6 @@
 
 #include "audio_acdb.h"
 
-
 struct afe_ctl {
 	void *apr;
 	atomic_t state;
@@ -44,6 +43,8 @@
 	atomic_t mem_map_cal_handles[MAX_AUDPROC_TYPES];
 	atomic_t mem_map_cal_index;
 	u16 dtmf_gen_rx_portid;
+	struct afe_spkr_prot_calib_get_resp calib_data;
+	int vi_tx_port;
 };
 
 static struct afe_ctl this_afe;
@@ -56,6 +57,10 @@
 
 static int32_t afe_callback(struct apr_client_data *data, void *priv)
 {
+	if (!data) {
+		pr_err("%s: Invalid param data\n", __func__);
+		return -EINVAL;
+	}
 	if (data->opcode == RESET_EVENTS) {
 		pr_debug("q6afe: reset event = %d %d apr[%p]\n",
 			data->reset_event, data->reset_proc, this_afe.apr);
@@ -69,11 +74,30 @@
 			this_afe.task->comm, this_afe.task->pid);
 		return 0;
 	}
-	pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x\n",
-				__func__, data->opcode,
-				((uint32_t *)(data->payload))[0],
-				((uint32_t *)(data->payload))[1]);
-	if (data->payload_size) {
+	pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x size = %d\n",
+			__func__, data->opcode,
+			((uint32_t *)(data->payload))[0],
+			((uint32_t *)(data->payload))[1],
+			 data->payload_size);
+	if (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V2) {
+		u8 *payload = data->payload;
+		if ((data->payload_size < sizeof(this_afe.calib_data))
+			|| !payload || (data->token >= AFE_MAX_PORTS)) {
+			pr_err("%s size %d payload %p token %d\n",
+			__func__, data->payload_size, payload, data->token);
+			return -EINVAL;
+		}
+		memcpy(&this_afe.calib_data, payload,
+			   sizeof(this_afe.calib_data));
+		if (!this_afe.calib_data.status) {
+			atomic_set(&this_afe.state, 0);
+			pr_err("%s rest %d state %x\n" , __func__
+			, this_afe.calib_data.res_cfg.r0_cali_q24,
+			this_afe.calib_data.res_cfg.th_vi_ca_state);
+		} else
+			atomic_set(&this_afe.state, -1);
+		wake_up(&this_afe.wait[data->token]);
+	} else if (data->payload_size) {
 		uint32_t *payload;
 		uint16_t port_id = 0;
 		payload = data->payload;
@@ -346,14 +370,140 @@
 	return;
 }
 
+static int afe_spk_prot_prepare(int port, int param_id,
+		union afe_spkr_prot_config *prot_config)
+{
+	int ret = -EINVAL;
+	int index = 0;
+	struct afe_spkr_prot_config_command config;
+
+	if (!prot_config) {
+		pr_err("%s Invalid params\n", __func__);
+		goto fail_cmd;
+	}
+	if ((q6audio_validate_port(port) < 0)) {
+		pr_err("%s invalid port %d", __func__, port);
+		goto fail_cmd;
+	}
+	memset(&config, 0 , sizeof(config));
+	index = q6audio_get_port_index(port);
+	switch (param_id) {
+	case AFE_PARAM_ID_FBSP_MODE_RX_CFG:
+		config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_RX;
+		break;
+	case AFE_PARAM_ID_FEEDBACK_PATH_CFG:
+		this_afe.vi_tx_port = port;
+	case AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG:
+	case AFE_PARAM_ID_MODE_VI_PROC_CFG:
+		config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC;
+		break;
+	default:
+		goto fail_cmd;
+		break;
+	}
+
+	config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	config.hdr.pkt_size = sizeof(config);
+	config.hdr.src_port = 0;
+	config.hdr.dest_port = 0;
+	config.hdr.token = index;
+
+	config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+	config.param.port_id = q6audio_get_port_id(port);
+	config.param.payload_size = sizeof(config) - sizeof(config.hdr)
+		- sizeof(config.param);
+	config.pdata.param_id = param_id;
+	config.pdata.param_size = sizeof(config.prot_config);
+	config.prot_config = *prot_config;
+	atomic_set(&this_afe.state, 1);
+	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
+	if (ret < 0) {
+		pr_err("%s: Setting param for port %d param[0x%x]failed\n",
+		 __func__, port, param_id);
+		goto fail_cmd;
+	}
+	ret = wait_event_timeout(this_afe.wait[index],
+		(atomic_read(&this_afe.state) == 0),
+		msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: wait_event timeout\n", __func__);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+	if (atomic_read(&this_afe.status) != 0) {
+		pr_err("%s: config cmd failed\n", __func__);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+	ret = 0;
+fail_cmd:
+	pr_err("%s config.pdata.param_id %x status %d\n",
+	__func__, config.pdata.param_id, ret);
+	return ret;
+}
+
+static void afe_send_cal_spkr_prot_tx(int port_id)
+{
+	struct msm_spk_prot_cfg prot_cfg;
+	union afe_spkr_prot_config afe_spk_config;
+
+	/*Get spkr protection cfg data*/
+	get_spk_protection_cfg(&prot_cfg);
+
+	if ((!prot_cfg.mode || prot_cfg.mode == 1) &&
+		(this_afe.vi_tx_port == port_id)) {
+		afe_spk_config.mode_rx_cfg.minor_version = 1;
+		afe_spk_config.mode_rx_cfg.mode =
+		(uint32_t)prot_cfg.mode;
+		if (afe_spk_prot_prepare(port_id,
+			AFE_PARAM_ID_MODE_VI_PROC_CFG,
+			&afe_spk_config))
+			pr_err("%s TX VI_PROC_CFG failed\n", __func__);
+		afe_spk_config.vi_proc_cfg.minor_version = 1;
+		afe_spk_config.vi_proc_cfg.r0_cali_q24 =
+		(uint32_t) prot_cfg.r0;
+		afe_spk_config.vi_proc_cfg.t0_cali_q6 =
+		(uint32_t) prot_cfg.t0;
+		if (afe_spk_prot_prepare(port_id,
+			AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG,
+			&afe_spk_config))
+			pr_err("%s SPKR_CALIB_VI_PROC_CFG failed\n",
+				__func__);
+	}
+}
+
+static void afe_send_cal_spkr_prot_rx(int port_id)
+{
+	struct msm_spk_prot_cfg prot_cfg;
+	union afe_spkr_prot_config afe_spk_config;
+
+	/*Get spkr protection cfg data*/
+	get_spk_protection_cfg(&prot_cfg);
+
+	if (!prot_cfg.mode || prot_cfg.mode == 1) {
+		afe_spk_config.mode_rx_cfg.mode =
+		(uint32_t)prot_cfg.mode;
+		afe_spk_config.mode_rx_cfg.minor_version = 1;
+		if (afe_spk_prot_prepare(port_id,
+			AFE_PARAM_ID_FBSP_MODE_RX_CFG,
+			&afe_spk_config))
+			pr_err("%s RX MODE_VI_PROC_CFG failed\n",
+				   __func__);
+	}
+}
+
 void afe_send_cal(u16 port_id)
 {
 	pr_debug("%s\n", __func__);
 
-	if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
+	if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) {
+		afe_send_cal_spkr_prot_tx(port_id);
 		afe_send_cal_block(TX_CAL, port_id);
-	else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
+	} else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) {
+		afe_send_cal_spkr_prot_rx(port_id);
 		afe_send_cal_block(RX_CAL, port_id);
+	}
 }
 
 int afe_port_start(u16 port_id, union afe_port_config *afe_config,
@@ -2299,6 +2449,107 @@
 	return ret;
 }
 
+int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp)
+{
+	int ret = -EINVAL;
+	int index = 0, port = SLIMBUS_4_TX;
+
+	if (!calib_resp) {
+		pr_err("%s Invalid params\n", __func__);
+		goto fail_cmd;
+	}
+	if ((q6audio_validate_port(port) < 0)) {
+		pr_err("%s invalid port %d\n", __func__, port);
+		goto fail_cmd;
+	}
+	index = q6audio_get_port_index(port);
+	calib_resp->get_param.hdr.hdr_field =
+	APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+	APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	calib_resp->get_param.hdr.pkt_size = sizeof(*calib_resp);
+	calib_resp->get_param.hdr.src_port = 0;
+	calib_resp->get_param.hdr.dest_port = 0;
+	calib_resp->get_param.hdr.token = index;
+	calib_resp->get_param.hdr.opcode =  AFE_PORT_CMD_GET_PARAM_V2;
+	calib_resp->get_param.mem_map_handle = 0;
+	calib_resp->get_param.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC;
+	calib_resp->get_param.param_id = AFE_PARAM_ID_CALIB_RES_CFG;
+	calib_resp->get_param.payload_address_lsw = 0;
+	calib_resp->get_param.payload_address_msw = 0;
+	calib_resp->get_param.payload_size = sizeof(*calib_resp)
+		- sizeof(calib_resp->get_param);
+	calib_resp->get_param.port_id = q6audio_get_port_id(port);
+	calib_resp->pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC;
+	calib_resp->pdata.param_id = AFE_PARAM_ID_CALIB_RES_CFG;
+	calib_resp->pdata.param_size = sizeof(calib_resp->res_cfg);
+	atomic_set(&this_afe.state, 1);
+	ret = apr_send_pkt(this_afe.apr, (uint32_t *)calib_resp);
+	if (ret < 0) {
+		pr_err("%s: get param port %d param id[0x%x]failed\n",
+			   __func__, port, calib_resp->get_param.param_id);
+		goto fail_cmd;
+	}
+	ret = wait_event_timeout(this_afe.wait[index],
+		(atomic_read(&this_afe.state) == 0),
+		msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: wait_event timeout\n", __func__);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+	if (atomic_read(&this_afe.status) != 0) {
+		pr_err("%s: config cmd failed\n", __func__);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+	memcpy(&calib_resp->res_cfg , &this_afe.calib_data.res_cfg,
+		sizeof(this_afe.calib_data.res_cfg));
+	pr_debug("%s state %d resistance %d\n", __func__,
+			 calib_resp->res_cfg.th_vi_ca_state,
+			 calib_resp->res_cfg.r0_cali_q24);
+	ret = 0;
+fail_cmd:
+	return ret;
+}
+
+int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
+	int l_ch, int r_ch)
+{
+	int ret = -EINVAL;
+	union afe_spkr_prot_config prot_config;
+	int index = 0;
+
+	if ((q6audio_validate_port(src_port) < 0) ||
+		(q6audio_validate_port(dst_port) < 0)) {
+		pr_err("%s invalid ports src %d dst %d",
+			__func__, src_port, dst_port);
+		goto fail_cmd;
+	}
+	if (!l_ch && !r_ch) {
+		pr_err("%s error ch values zero\n", __func__);
+		goto fail_cmd;
+	}
+	pr_debug("%s src_port %x  dst_port %x l_ch %d r_ch %d\n",
+		 __func__, src_port, dst_port, l_ch, r_ch);
+	memset(&prot_config, 0, sizeof(prot_config));
+	prot_config.feedback_path_cfg.dst_portid =
+		q6audio_get_port_id(dst_port);
+	if (l_ch) {
+		prot_config.feedback_path_cfg.chan_info[index++] = 1;
+		prot_config.feedback_path_cfg.chan_info[index++] = 2;
+	}
+	if (r_ch) {
+		prot_config.feedback_path_cfg.chan_info[index++] = 3;
+		prot_config.feedback_path_cfg.chan_info[index++] = 4;
+	}
+	prot_config.feedback_path_cfg.num_channels = index;
+	prot_config.feedback_path_cfg.minor_version = 1;
+	ret = afe_spk_prot_prepare(src_port,
+			AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config);
+fail_cmd:
+	return ret;
+}
+
 static int __init afe_init(void)
 {
 	int i = 0;
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 4e7455b..0549671 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -2344,7 +2344,7 @@
 	fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
 					sizeof(fmt.fmt_blk);
 	fmt.num_channels = channels;
-	fmt.bits_per_sample = 16;
+	fmt.bits_per_sample = bits_per_sample;
 	fmt.sample_rate = rate;
 	fmt.is_signed = 1;
 
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index 99cb6a6..4ed0fb7 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -43,6 +43,7 @@
 	case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
 	case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
 	case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
+	case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
 	case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
 	case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
 	case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
@@ -89,6 +90,7 @@
 	case SLIMBUS_1_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_TX;
 	case SLIMBUS_2_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX;
 	case SLIMBUS_2_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_TX;
+	case SLIMBUS_4_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX;
 	case INT_BT_SCO_RX: return AFE_PORT_ID_INTERNAL_BT_SCO_RX;
 	case INT_BT_SCO_TX: return AFE_PORT_ID_INTERNAL_BT_SCO_TX;
 	case INT_BT_A2DP_RX: return AFE_PORT_ID_INTERNAL_BT_A2DP_RX;
@@ -182,6 +184,7 @@
 	case SLIMBUS_1_TX:
 	case SLIMBUS_2_RX:
 	case SLIMBUS_2_TX:
+	case SLIMBUS_4_TX:
 	case INT_BT_SCO_RX:
 	case INT_BT_SCO_TX:
 	case INT_BT_A2DP_RX: