Merge "arm/dt: 8610: Increase EBI1 buffer reservation size"
diff --git a/Documentation/devicetree/bindings/arm/msm/acpuclock/acpuclock-a7.txt b/Documentation/devicetree/bindings/arm/msm/acpuclock/acpuclock-a7.txt
index a77d435..6c7a7d8 100644
--- a/Documentation/devicetree/bindings/arm/msm/acpuclock/acpuclock-a7.txt
+++ b/Documentation/devicetree/bindings/arm/msm/acpuclock/acpuclock-a7.txt
@@ -11,6 +11,9 @@
 	     is expected.
 - a7_cpu-supply: regulator to supply a7 cpu
 
+Optional properties:
+- reg-names: "pte_efuse". Registers indicate maximum cpu speed.
+
 Example:
 	qcom,acpuclk@f9011050 {
 		compatible = "qcom,acpuclk-a7";
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt b/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt
new file mode 100644
index 0000000..9b69037
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt
@@ -0,0 +1,26 @@
+* RPM RBCPR
+
+The RBCPR(Rapid Bridge Core Power Reduction) is  module on RPM that controls
+the voltage level on the chip based on feedback received through various
+sensors on the chip that allow compensation of the chip process variation,
+temperature etc.
+RPM maintains RBCPR (Rapid Bridge Core Power Reduction) related stats in
+data memory. This module allows users to read those stats.
+
+The required properties for rpm-stats are:
+
+- compatible: "qcom,rpmrbcpr-stats"
+- reg: Pointer to the start of the RPM Data Memory. The size of the memory
+		is inclusive of the entire RPM data memory.
+- qcom,start_offset: The offset at which the RBCPR stats are maintained. The
+			driver module reads this parameter to get another offset
+			that contain the rbcpr stats.
+
+
+Example:
+
+qcom,rpm-rbcpr-stats@fc000000 {
+	compatible = "qcom,rpmrbcpr-stats";
+	reg = <0xfc000000 0x1a0000>;
+	qcom,start-offset = <0x190010>;
+};
diff --git a/Documentation/devicetree/bindings/input/misc/kxtj9.txt b/Documentation/devicetree/bindings/input/misc/kxtj9.txt
new file mode 100644
index 0000000..250ee7a
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/kxtj9.txt
@@ -0,0 +1,67 @@
+Kionis KXTIK-series accelerometer driver
+
+Required properties:
+
+ - compatible		: Should be "kionix,kxtj9".
+ - reg			: i2c slave address of the device.
+ - interrupt-parent	: Parent of interrupt.
+ - interrupts		: Accelerometer sample interrupt to indicate new data ready.
+ - vdd-supply		: Analog power supply needed to power device.
+ - vio-supply		: Digital IO power supply needed for IO and I2C.
+ - kionix,min-interval	: Minimal data polling interval in millisecond.
+ - kionix,init-interval	: Initial data polling interval in millisecond.
+ - kionix,axis-map-x	: Select which data will be X-axis of reading.
+				The sensor measures and reports three axis of
+				data, this property selset which data will be
+				interpretd as X-axis gravity data of phone.
+				e.g. Give "0" to this property means the first
+				measurement data will be used as X-axis data
+ - kionix,axis-map-y	: Select which data will be Y-axis of reading.
+				Similar to property above, this property selet
+				Y-axis data.
+ - kionix,axis-map-z	: Select which data will be Z-axis of reading.
+				Similar to property above, this property selet
+				Z-axis data.
+ - kionix,g-range	: Select initial range of measurement. This define
+				the initial configuration of maxinum
+				measurement range of the sensor.Where 2 is 2G,
+				4 is 4G, 8 is 8G, 2G will be used for any other
+				values.
+
+Optional properties:
+
+ - kionix,negate-x	: Boolean to select negate of X-axis data is
+				required, if this property is defined, X-axis
+				data will be negated.
+ - kionix,negate-y	: Boolean to select negate of Y-axis data is
+				required, if this property is defined, Y-axis
+				data will be negated.
+ - kionix,negate-z	: Boolean to select negate of Z-axis data is
+				required, if this property is defined, Z-axis
+				data will be negated.
+ - kionix,res-12bit;	: Boolean to select output data resolution, if this
+				property is defined, sensor will be configured
+				to output 12 bits of data, otherwise sensor will
+				be configured to output 8 bits data.
+
+Example:
+	i2c@f9925000 { /* BLSP-1 QUP-3 */
+		kionix@f {
+			compatible = "kionix,kxtj9";
+			reg = <0x0f>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <81 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vio-supply = <&pm8110_l14>;
+			kionix,min-interval = <5>;
+			kionix,init-interval = <200>;
+			kionix,axis-map-x = <1>;
+			kionix,axis-map-y = <0>;
+			kionix,axis-map-z = <2>;
+			kionix,g-range = <2>;
+			kionix,negate-x;
+			kionix,negate-y;
+			kionix,negate-z;
+			kionix,res-12bit;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
index adb93b8..3095b0a 100644
--- a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
@@ -12,11 +12,11 @@
 - reg:		Specifies the SPMI address and size for this PON (power-on) peripheral
 - interrupts:	Specifies the interrupt associated with PON.
 - interrupt-names:	Specify the interrupt names associated with interrupts. Must be
-			one of "kpdpwr", "kpdpwr-bark", "resin", "resin-bark", "cblpwr".
-			Bark interrupts are associated with system reset configuration
-			to allow default reset configuration to be activated. If system
-			reset configuration is not supported then bark interrupts are
-			nops.
+			one of "kpdpwr", "kpdpwr-bark", "resin", "resin-bark", "cblpwr",
+			"kpdpwr-resin-bark". Bark interrupts are associated with system
+			reset configuration to allow default reset configuration to be
+			activated. If system reset configuration is not supported then
+			bark interrupts are nops.
 
 Optional properties:
 - qcom,pon-dbc-delay		The debounce delay for the power-key interrupt
@@ -34,6 +34,8 @@
 				to reset the system. This property can only be
 				used by one device on the system. It is an error
 				to include it more than once.
+- qcom,s3-debounce		The debounce delay for stage3 reset trigger in
+				secs. The values range from 0 to 128.
 
 All the below properties are in the sub-node section (properties of the child
 node).
@@ -82,9 +84,13 @@
 		reg = <0x800 0x100>;
 		interrupts = <0x0 0x8 0x0>,
 			     <0x0 0x8 0x1>,
-			     <0x0 0x8 0x4>;
-		interrupt-names = "kpdpwr", "resin", "resin-bark";
+			     <0x0 0x8 0x4>,
+			     <0x0 0x8 0x5>;
+		interrupt-names = "kpdpwr", "resin",
+				"resin-bark", "kpdpwr-resin-bark";
 		qcom,pon-dbc-delay = <15625>;
+		qcom,system-reset;
+		qcom,s3-debounce = <32>;
 
 		qcom,pon_1 {
 			qcom,pon-type = <0>;
@@ -96,9 +102,18 @@
 			qcom,pon-type = <1>;
 			qcom,support-reset = <1>;
 			qcom,pull-up = <1>;
-			qcom,s1-timer = <3072>;
+			qcom,s1-timer = <0>;
 			qcom,s2-timer = <2000>;
 			qcom,s2-type = <1>;
 			linux,code = <114>;
 		};
-	}
+
+		qcom,pon_3 {
+			qcom,pon-type = <3>;
+			qcom,support-reset = <1>;
+			qcom,s1-timer = <6720>;
+			qcom,s2-timer = <2000>;
+			qcom,s2-type = <7>;
+			qcom,pull-up = <1>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/prng/msm-rng.txt b/Documentation/devicetree/bindings/prng/msm-rng.txt
index 28dfe50..b46f159 100644
--- a/Documentation/devicetree/bindings/prng/msm-rng.txt
+++ b/Documentation/devicetree/bindings/prng/msm-rng.txt
@@ -3,6 +3,11 @@
 Required properties:
 - compatible : Should be "qcom,msm-rng"
 - reg        : Offset and length of the register set for the device
+- qcom, msm_bus,name: Should be "msm-rng-noc"
+- qcom, msm_bus,num_cases: Depends on the use cases for bus scaling
+- qcom, msm_bus,num_paths: The paths for source and destination ports
+- qcom, msm_bus,vectors: Vectors for bus topology.
+
 
 Optional property:
 - qcom,msm-rng-iface-clk : If the device uses iface-clk.
@@ -13,4 +18,10 @@
 		compatible = "qcom,msm-rng";
 		reg = <0xf9bff000 0x200>;
 		qcom,msm-rng-iface-clk;
+		qcom,msm-bus,name = "msm-rng-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<1 618 0 0>,
+				<1 618 0 800>;
 	};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 8d41295..8fa9f4a 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -24,6 +24,7 @@
 idt	Integrated Device Technologies, Inc.
 intercontrol	Inter Control Group
 linux	Linux-specific binding
+kionix	Kionix Inc.
 marvell	Marvell Technology Group Ltd.
 maxim	Maxim Integrated Products
 mosaixtech	Mosaix Technologies, Inc.
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index a8b3065..4b20e9f 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -638,6 +638,9 @@
 	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
 	cd-gpios = <&msmgpio 62 0x1>;
 
+	qcom,vdd-always-on;
+	qcom,vdd-lpm-sup;
+
 	vdd-supply = <&pm8941_l21>;
 	vdd-io-supply = <&pm8941_l13>;
 
diff --git a/arch/arm/boot/dts/apq8074-v2.dtsi b/arch/arm/boot/dts/apq8074-v2.dtsi
index 76eb14b..c700a5c 100644
--- a/arch/arm/boot/dts/apq8074-v2.dtsi
+++ b/arch/arm/boot/dts/apq8074-v2.dtsi
@@ -50,3 +50,8 @@
 	status = "disabled";
 };
 
+&sdcc3 {
+	qcom,sup-voltages = <2000 2000>;
+	status = "ok";
+};
+
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index b39f569..e5f083a 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -190,6 +190,18 @@
 		compatible = "qcom,android-usb";
 	};
 
+	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 = <11>;
+		qcom,slope = <3200 3200 3200 3200 3200 3200 3200 3200 3200
+				3200 3200>;
+		qcom,calib-mode = "fuse_map1";
+	};
+
 	qcom,ocmem@fdd00000 {
 		compatible = "qcom,msm-ocmem";
 		reg = <0xfdd00000 0x2000>,
@@ -274,3 +286,67 @@
 
 /include/ "msm-pma8084.dtsi"
 /include/ "apq8084-regulator.dtsi"
+
+&pma8084_vadc {
+	chan@b0 {
+		label = "apq_therm";
+		reg = <0xb0>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@b3 {
+		label = "quiet_therm";
+		reg = <0xb3>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+};
+
+&pma8084_adc_tm {
+	chan@8 {
+		label = "die_temp";
+		reg = <8>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <3>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <3>;
+		qcom,btm-channel-number = <0x48>;
+	};
+
+	chan@b0 {
+		label = "apq_therm";
+		reg = <0xb0>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <3>;
+		qcom,btm-channel-number = <0x68>;
+		qcom,thermal-node;
+	};
+
+	chan@b3 {
+		label = "quiet_therm";
+		reg = <0xb3>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <3>;
+		qcom,btm-channel-number = <0x70>;
+		qcom,thermal-node;
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
new file mode 100644
index 0000000..1ecad71
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
@@ -0,0 +1,580 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	qcom,mdss_dsi_nt35596_1080p_video {
+		compatible = "qcom,mdss-dsi-panel";
+		label = "nt35596 1080p video mode dsi panel";
+		status = "disable";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+		qcom,rst-gpio = <&msmgpio 25 0>;
+		qcom,mdss-pan-res = <1080 1920>;
+		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
+		qcom,mdss-pan-porch-values = <32 8 32 18 2 2>;
+		qcom,mdss-pan-underflow-clr = <0xff>;
+		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+		qcom,mdss-pan-bl-levels = <1 4095>;
+		qcom,mdss-pan-dsi-mode = <0>;
+		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
+		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+		qcom,mdss-pan-dsi-traffic-mode = <2>;
+		qcom,mdss-pan-dsi-dst-format = <3>;
+		qcom,mdss-pan-dsi-vc = <0>;
+		qcom,mdss-pan-dsi-rgb-swap = <0>;
+		qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
+		qcom,mdss-pan-dsi-dlane-swap = <0>;
+		qcom,mdss-pan-dsi-t-clk = <0x38 0x1e>;
+		qcom,mdss-pan-dsi-stream = <0>;
+		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
+		qcom,mdss-pan-dsi-dma-tr = <0x04>;
+		qcom,mdss-pan-dsi-frame-rate = <60>;
+		qcom,panel-phy-regulatorSettings = [07 09 03 00  /* Regualotor settings */
+						    20 00 01];
+		qcom,panel-phy-timingSettings = [f9 3d 34 00 58 4d
+						    36 3f 53 03 04 00];
+		qcom,panel-phy-strengthCtrl = [ff 06];
+		qcom,panel-phy-bistCtrl = [00 00 b1 ff           /* BIST Ctrl settings */
+					   00 00];
+		qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
+					     00 00 00 00 05 00 00 01 97 /* lane1 config */
+					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
+					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
+					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
+		qcom,panel-on-cmds = [29 01 00 00 00 00 02 FF EE
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 1F 45
+			29 01 00 00 00 00 02 24 4F
+			29 01 00 00 00 00 02 38 C8
+			29 01 00 00 00 00 02 39 2C
+			29 01 00 00 00 00 02 1E BB
+			29 01 00 00 00 00 02 1D 0F
+			29 01 00 00 00 00 02 7E B1
+			29 01 00 00 00 00 02 FF 00
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 35 01
+			29 01 00 00 00 00 02 BA 03
+			29 01 00 00 00 00 02 FF 01
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 00 01
+			29 01 00 00 00 00 02 01 55
+			29 01 00 00 00 00 02 02 40
+			29 01 00 00 00 00 02 05 00
+			29 01 00 00 00 00 02 06 1B
+			29 01 00 00 00 00 02 07 24
+			29 01 00 00 00 00 02 08 0C
+			29 01 00 00 00 00 02 0B 87
+			29 01 00 00 00 00 02 0C 87
+			29 01 00 00 00 00 02 0E B0
+			29 01 00 00 00 00 02 0F B3
+			29 01 00 00 00 00 02 11 10
+			29 01 00 00 00 00 02 12 10
+			29 01 00 00 00 00 02 13 05
+			29 01 00 00 00 00 02 14 4A
+			29 01 00 00 00 00 02 15 18
+			29 01 00 00 00 00 02 16 18
+			29 01 00 00 00 00 02 18 00
+			29 01 00 00 00 00 02 19 77
+			29 01 00 00 00 00 02 1A 55
+			29 01 00 00 00 00 02 1B 13
+			29 01 00 00 00 00 02 1C 00
+			29 01 00 00 00 00 02 1D 00
+			29 01 00 00 00 00 02 1E 13
+			29 01 00 00 00 00 02 1F 00
+			29 01 00 00 00 00 02 23 00
+			29 01 00 00 00 00 02 24 00
+			29 01 00 00 00 00 02 25 00
+			29 01 00 00 00 00 02 26 00
+			29 01 00 00 00 00 02 27 00
+			29 01 00 00 00 00 02 28 00
+			29 01 00 00 00 00 02 35 00
+			29 01 00 00 00 00 02 66 00
+			29 01 00 00 00 00 02 58 82
+			29 01 00 00 00 00 02 59 02
+			29 01 00 00 00 00 02 5A 02
+			29 01 00 00 00 00 02 5B 02
+			29 01 00 00 00 00 02 5C 82
+			29 01 00 00 00 00 02 5D 82
+			29 01 00 00 00 00 02 5E 02
+			29 01 00 00 00 00 02 5F 02
+			29 01 00 00 00 00 02 72 31
+			29 01 00 00 00 00 02 FF 05
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 00 01
+			29 01 00 00 00 00 02 01 0B
+			29 01 00 00 00 00 02 02 0C
+			29 01 00 00 00 00 02 03 09
+			29 01 00 00 00 00 02 04 0A
+			29 01 00 00 00 00 02 05 00
+			29 01 00 00 00 00 02 06 0F
+			29 01 00 00 00 00 02 07 10
+			29 01 00 00 00 00 02 08 00
+			29 01 00 00 00 00 02 09 00
+			29 01 00 00 00 00 02 0A 00
+			29 01 00 00 00 00 02 0B 00
+			29 01 00 00 00 00 02 0C 00
+			29 01 00 00 00 00 02 0D 13
+			29 01 00 00 00 00 02 0E 15
+			29 01 00 00 00 00 02 0F 17
+			29 01 00 00 00 00 02 10 01
+			29 01 00 00 00 00 02 11 0B
+			29 01 00 00 00 00 02 12 0C
+			29 01 00 00 00 00 02 13 09
+			29 01 00 00 00 00 02 14 0A
+			29 01 00 00 00 00 02 15 00
+			29 01 00 00 00 00 02 16 0F
+			29 01 00 00 00 00 02 17 10
+			29 01 00 00 00 00 02 18 00
+			29 01 00 00 00 00 02 19 00
+			29 01 00 00 00 00 02 1A 00
+			29 01 00 00 00 00 02 1B 00
+			29 01 00 00 00 00 02 1C 00
+			29 01 00 00 00 00 02 1D 13
+			29 01 00 00 00 00 02 1E 15
+			29 01 00 00 00 00 02 1F 17
+			29 01 00 00 00 00 02 20 00
+			29 01 00 00 00 00 02 21 03
+			29 01 00 00 00 00 02 22 01
+			29 01 00 00 00 00 02 23 40
+			29 01 00 00 00 00 02 24 40
+			29 01 00 00 00 00 02 25 ED
+			29 01 00 00 00 00 02 29 58
+			29 01 00 00 00 00 02 2A 12
+			29 01 00 00 00 00 02 2B 01
+			29 01 00 00 00 00 02 4B 06
+			29 01 00 00 00 00 02 4C 11
+			29 01 00 00 00 00 02 4D 20
+			29 01 00 00 00 00 02 4E 02
+			29 01 00 00 00 00 02 4F 02
+			29 01 00 00 00 00 02 50 20
+			29 01 00 00 00 00 02 51 61
+			29 01 00 00 00 00 02 52 01
+			29 01 00 00 00 00 02 53 63
+			29 01 00 00 00 00 02 54 77
+			29 01 00 00 00 00 02 55 ED
+			29 01 00 00 00 00 02 5B 00
+			29 01 00 00 00 00 02 5C 00
+			29 01 00 00 00 00 02 5D 00
+			29 01 00 00 00 00 02 5E 00
+			29 01 00 00 00 00 02 5F 15
+			29 01 00 00 00 00 02 60 75
+			29 01 00 00 00 00 02 61 00
+			29 01 00 00 00 00 02 62 00
+			29 01 00 00 00 00 02 63 00
+			29 01 00 00 00 00 02 64 00
+			29 01 00 00 00 00 02 65 00
+			29 01 00 00 00 00 02 66 00
+			29 01 00 00 00 00 02 67 00
+			29 01 00 00 00 00 02 68 04
+			29 01 00 00 00 00 02 69 00
+			29 01 00 00 00 00 02 6A 00
+			29 01 00 00 00 00 02 6C 40
+			29 01 00 00 00 00 02 75 01
+			29 01 00 00 00 00 02 76 01
+			29 01 00 00 00 00 02 7A 80
+			29 01 00 00 00 00 02 7B C5
+			29 01 00 00 00 00 02 7C D8
+			29 01 00 00 00 00 02 7D 60
+			29 01 00 00 00 00 02 7F 10
+			29 01 00 00 00 00 02 80 81
+			29 01 00 00 00 00 02 83 05
+			29 01 00 00 00 00 02 93 08
+			29 01 00 00 00 00 02 94 10
+			29 01 00 00 00 00 02 8A 00
+			29 01 00 00 00 00 02 9B 0F
+			29 01 00 00 00 00 02 EA FF
+			29 01 00 00 00 00 02 EC 00
+			29 01 00 00 00 00 02 FF 01
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 75 00
+			29 01 00 00 00 00 02 76 8E
+			29 01 00 00 00 00 02 77 00
+			29 01 00 00 00 00 02 78 90
+			29 01 00 00 00 00 02 79 00
+			29 01 00 00 00 00 02 7A B2
+			29 01 00 00 00 00 02 7B 00
+			29 01 00 00 00 00 02 7C C7
+			29 01 00 00 00 00 02 7D 00
+			29 01 00 00 00 00 02 7E D7
+			29 01 00 00 00 00 02 7F 00
+			29 01 00 00 00 00 02 80 E9
+			29 01 00 00 00 00 02 81 00
+			29 01 00 00 00 00 02 82 F9
+			29 01 00 00 00 00 02 83 01
+			29 01 00 00 00 00 02 84 01
+			29 01 00 00 00 00 02 85 01
+			29 01 00 00 00 00 02 86 0B
+			29 01 00 00 00 00 02 87 01
+			29 01 00 00 00 00 02 88 3A
+			29 01 00 00 00 00 02 89 01
+			29 01 00 00 00 00 02 8A 5D
+			29 01 00 00 00 00 02 8B 01
+			29 01 00 00 00 00 02 8C 94
+			29 01 00 00 00 00 02 8D 01
+			29 01 00 00 00 00 02 8E BC
+			29 01 00 00 00 00 02 8F 02
+			29 01 00 00 00 00 02 90 00
+			29 01 00 00 00 00 02 91 02
+			29 01 00 00 00 00 02 92 39
+			29 01 00 00 00 00 02 93 02
+			29 01 00 00 00 00 02 94 3A
+			29 01 00 00 00 00 02 95 02
+			29 01 00 00 00 00 02 96 6B
+			29 01 00 00 00 00 02 97 02
+			29 01 00 00 00 00 02 98 A2
+			29 01 00 00 00 00 02 99 02
+			29 01 00 00 00 00 02 9A C7
+			29 01 00 00 00 00 02 9B 02
+			29 01 00 00 00 00 02 9C FB
+			29 01 00 00 00 00 02 9D 03
+			29 01 00 00 00 00 02 9E 20
+			29 01 00 00 00 00 02 9F 03
+			29 01 00 00 00 00 02 A0 54
+			29 01 00 00 00 00 02 A2 03
+			29 01 00 00 00 00 02 A3 6D
+			29 01 00 00 00 00 02 A4 03
+			29 01 00 00 00 00 02 A5 80
+			29 01 00 00 00 00 02 A6 03
+			29 01 00 00 00 00 02 A7 81
+			29 01 00 00 00 00 02 A9 03
+			29 01 00 00 00 00 02 AA C7
+			29 01 00 00 00 00 02 AB 03
+			29 01 00 00 00 00 02 AC F0
+			29 01 00 00 00 00 02 AD 03
+			29 01 00 00 00 00 02 AE F8
+			29 01 00 00 00 00 02 AF 03
+			29 01 00 00 00 00 02 B0 FD
+			29 01 00 00 00 00 02 B1 03
+			29 01 00 00 00 00 02 B2 FE
+			29 01 00 00 00 00 02 B3 00
+			29 01 00 00 00 00 02 B4 8E
+			29 01 00 00 00 00 02 B5 00
+			29 01 00 00 00 00 02 B6 90
+			29 01 00 00 00 00 02 B7 00
+			29 01 00 00 00 00 02 B8 B2
+			29 01 00 00 00 00 02 B9 00
+			29 01 00 00 00 00 02 BA C7
+			29 01 00 00 00 00 02 BB 00
+			29 01 00 00 00 00 02 BC D7
+			29 01 00 00 00 00 02 BD 00
+			29 01 00 00 00 00 02 BE E9
+			29 01 00 00 00 00 02 BF 00
+			29 01 00 00 00 00 02 C0 F9
+			29 01 00 00 00 00 02 C1 01
+			29 01 00 00 00 00 02 C2 01
+			29 01 00 00 00 00 02 C3 01
+			29 01 00 00 00 00 02 C4 0B
+			29 01 00 00 00 00 02 C5 01
+			29 01 00 00 00 00 02 C6 3A
+			29 01 00 00 00 00 02 C7 01
+			29 01 00 00 00 00 02 C8 5D
+			29 01 00 00 00 00 02 C9 01
+			29 01 00 00 00 00 02 CA 94
+			29 01 00 00 00 00 02 CB 01
+			29 01 00 00 00 00 02 CC BC
+			29 01 00 00 00 00 02 CD 02
+			29 01 00 00 00 00 02 CE 00
+			29 01 00 00 00 00 02 CF 02
+			29 01 00 00 00 00 02 D0 39
+			29 01 00 00 00 00 02 D1 02
+			29 01 00 00 00 00 02 D2 3A
+			29 01 00 00 00 00 02 D3 02
+			29 01 00 00 00 00 02 D4 6B
+			29 01 00 00 00 00 02 D5 02
+			29 01 00 00 00 00 02 D6 A2
+			29 01 00 00 00 00 02 D7 02
+			29 01 00 00 00 00 02 D8 C7
+			29 01 00 00 00 00 02 D9 02
+			29 01 00 00 00 00 02 DA FB
+			29 01 00 00 00 00 02 DB 03
+			29 01 00 00 00 00 02 DC 20
+			29 01 00 00 00 00 02 DD 03
+			29 01 00 00 00 00 02 DE 54
+			29 01 00 00 00 00 02 DF 03
+			29 01 00 00 00 00 02 E0 6D
+			29 01 00 00 00 00 02 E1 03
+			29 01 00 00 00 00 02 E2 80
+			29 01 00 00 00 00 02 E3 03
+			29 01 00 00 00 00 02 E4 81
+			29 01 00 00 00 00 02 E5 03
+			29 01 00 00 00 00 02 E6 C7
+			29 01 00 00 00 00 02 E7 03
+			29 01 00 00 00 00 02 E8 F0
+			29 01 00 00 00 00 02 E9 03
+			29 01 00 00 00 00 02 EA F8
+			29 01 00 00 00 00 02 EB 03
+			29 01 00 00 00 00 02 EC FD
+			29 01 00 00 00 00 02 ED 03
+			29 01 00 00 00 00 02 EE FE
+			29 01 00 00 00 00 02 EF 00
+			29 01 00 00 00 00 02 F0 03
+			29 01 00 00 00 00 02 F1 00
+			29 01 00 00 00 00 02 F2 0B
+			29 01 00 00 00 00 02 F3 00
+			29 01 00 00 00 00 02 F4 0D
+			29 01 00 00 00 00 02 F5 00
+			29 01 00 00 00 00 02 F6 4A
+			29 01 00 00 00 00 02 F7 00
+			29 01 00 00 00 00 02 F8 71
+			29 01 00 00 00 00 02 F9 00
+			29 01 00 00 00 00 02 FA 8C
+			29 01 00 00 00 00 02 FF 02
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 00 00
+			29 01 00 00 00 00 02 01 A1
+			29 01 00 00 00 00 02 02 00
+			29 01 00 00 00 00 02 03 B6
+			29 01 00 00 00 00 02 04 00
+			29 01 00 00 00 00 02 05 C9
+			29 01 00 00 00 00 02 06 00
+			29 01 00 00 00 00 02 07 FD
+			29 01 00 00 00 00 02 08 01
+			29 01 00 00 00 00 02 09 29
+			29 01 00 00 00 00 02 0A 01
+			29 01 00 00 00 00 02 0B 6B
+			29 01 00 00 00 00 02 0C 01
+			29 01 00 00 00 00 02 0D 9E
+			29 01 00 00 00 00 02 0E 01
+			29 01 00 00 00 00 02 0F EB
+			29 01 00 00 00 00 02 10 02
+			29 01 00 00 00 00 02 11 25
+			29 01 00 00 00 00 02 12 02
+			29 01 00 00 00 00 02 13 27
+			29 01 00 00 00 00 02 14 02
+			29 01 00 00 00 00 02 15 5C
+			29 01 00 00 00 00 02 16 02
+			29 01 00 00 00 00 02 17 95
+			29 01 00 00 00 00 02 18 02
+			29 01 00 00 00 00 02 19 BA
+			29 01 00 00 00 00 02 1A 02
+			29 01 00 00 00 00 02 1B EC
+			29 01 00 00 00 00 02 1C 03
+			29 01 00 00 00 00 02 1D 0C
+			29 01 00 00 00 00 02 1E 03
+			29 01 00 00 00 00 02 1F 34
+			29 01 00 00 00 00 02 20 03
+			29 01 00 00 00 00 02 21 3F
+			29 01 00 00 00 00 02 22 03
+			29 01 00 00 00 00 02 23 48
+			29 01 00 00 00 00 02 24 03
+			29 01 00 00 00 00 02 25 49
+			29 01 00 00 00 00 02 26 03
+			29 01 00 00 00 00 02 27 6B
+			29 01 00 00 00 00 02 28 03
+			29 01 00 00 00 00 02 29 7E
+			29 01 00 00 00 00 02 2A 03
+			29 01 00 00 00 00 02 2B 8F
+			29 01 00 00 00 00 02 2D 03
+			29 01 00 00 00 00 02 2F 9E
+			29 01 00 00 00 00 02 30 03
+			29 01 00 00 00 00 02 31 A0
+			29 01 00 00 00 00 02 32 00
+			29 01 00 00 00 00 02 33 03
+			29 01 00 00 00 00 02 34 00
+			29 01 00 00 00 00 02 35 0B
+			29 01 00 00 00 00 02 36 00
+			29 01 00 00 00 00 02 37 0D
+			29 01 00 00 00 00 02 38 00
+			29 01 00 00 00 00 02 39 4A
+			29 01 00 00 00 00 02 3A 00
+			29 01 00 00 00 00 02 3B 71
+			29 01 00 00 00 00 02 3D 00
+			29 01 00 00 00 00 02 3F 8C
+			29 01 00 00 00 00 02 40 00
+			29 01 00 00 00 00 02 41 A1
+			29 01 00 00 00 00 02 42 00
+			29 01 00 00 00 00 02 43 B6
+			29 01 00 00 00 00 02 44 00
+			29 01 00 00 00 00 02 45 C9
+			29 01 00 00 00 00 02 46 00
+			29 01 00 00 00 00 02 47 FD
+			29 01 00 00 00 00 02 48 01
+			29 01 00 00 00 00 02 49 29
+			29 01 00 00 00 00 02 4A 01
+			29 01 00 00 00 00 02 4B 6B
+			29 01 00 00 00 00 02 4C 01
+			29 01 00 00 00 00 02 4D 9E
+			29 01 00 00 00 00 02 4E 01
+			29 01 00 00 00 00 02 4F EB
+			29 01 00 00 00 00 02 50 02
+			29 01 00 00 00 00 02 51 25
+			29 01 00 00 00 00 02 52 02
+			29 01 00 00 00 00 02 53 27
+			29 01 00 00 00 00 02 54 02
+			29 01 00 00 00 00 02 55 5C
+			29 01 00 00 00 00 02 56 02
+			29 01 00 00 00 00 02 58 95
+			29 01 00 00 00 00 02 59 02
+			29 01 00 00 00 00 02 5A BA
+			29 01 00 00 00 00 02 5B 02
+			29 01 00 00 00 00 02 5C EC
+			29 01 00 00 00 00 02 5D 03
+			29 01 00 00 00 00 02 5E 0C
+			29 01 00 00 00 00 02 5F 03
+			29 01 00 00 00 00 02 60 34
+			29 01 00 00 00 00 02 61 03
+			29 01 00 00 00 00 02 62 3F
+			29 01 00 00 00 00 02 63 03
+			29 01 00 00 00 00 02 64 48
+			29 01 00 00 00 00 02 65 03
+			29 01 00 00 00 00 02 66 49
+			29 01 00 00 00 00 02 67 03
+			29 01 00 00 00 00 02 68 6B
+			29 01 00 00 00 00 02 69 03
+			29 01 00 00 00 00 02 6A 7E
+			29 01 00 00 00 00 02 6B 03
+			29 01 00 00 00 00 02 6C 8F
+			29 01 00 00 00 00 02 6D 03
+			29 01 00 00 00 00 02 6E 9E
+			29 01 00 00 00 00 02 6F 03
+			29 01 00 00 00 00 02 70 A0
+			29 01 00 00 00 00 02 71 00
+			29 01 00 00 00 00 02 72 FB
+			29 01 00 00 00 00 02 73 00
+			29 01 00 00 00 00 02 74 FD
+			29 01 00 00 00 00 02 75 01
+			29 01 00 00 00 00 02 76 05
+			29 01 00 00 00 00 02 77 01
+			29 01 00 00 00 00 02 78 0D
+			29 01 00 00 00 00 02 79 01
+			29 01 00 00 00 00 02 7A 17
+			29 01 00 00 00 00 02 7B 01
+			29 01 00 00 00 00 02 7C 1F
+			29 01 00 00 00 00 02 7D 01
+			29 01 00 00 00 00 02 7E 28
+			29 01 00 00 00 00 02 7F 01
+			29 01 00 00 00 00 02 80 32
+			29 01 00 00 00 00 02 81 01
+			29 01 00 00 00 00 02 82 38
+			29 01 00 00 00 00 02 83 01
+			29 01 00 00 00 00 02 84 53
+			29 01 00 00 00 00 02 85 01
+			29 01 00 00 00 00 02 86 72
+			29 01 00 00 00 00 02 87 01
+			29 01 00 00 00 00 02 88 9B
+			29 01 00 00 00 00 02 89 01
+			29 01 00 00 00 00 02 8A C3
+			29 01 00 00 00 00 02 8B 02
+			29 01 00 00 00 00 02 8C 01
+			29 01 00 00 00 00 02 8D 02
+			29 01 00 00 00 00 02 8E 36
+			29 01 00 00 00 00 02 8F 02
+			29 01 00 00 00 00 02 90 37
+			29 01 00 00 00 00 02 91 02
+			29 01 00 00 00 00 02 92 69
+			29 01 00 00 00 00 02 93 02
+			29 01 00 00 00 00 02 94 A1
+			29 01 00 00 00 00 02 95 02
+			29 01 00 00 00 00 02 96 C8
+			29 01 00 00 00 00 02 97 02
+			29 01 00 00 00 00 02 98 FF
+			29 01 00 00 00 00 02 99 03
+			29 01 00 00 00 00 02 9A 26
+			29 01 00 00 00 00 02 9B 03
+			29 01 00 00 00 00 02 9C 69
+			29 01 00 00 00 00 02 9D 03
+			29 01 00 00 00 00 02 9E 88
+			29 01 00 00 00 00 02 9F 03
+			29 01 00 00 00 00 02 A0 F8
+			29 01 00 00 00 00 02 A2 03
+			29 01 00 00 00 00 02 A3 F9
+			29 01 00 00 00 00 02 A4 03
+			29 01 00 00 00 00 02 A5 FE
+			29 01 00 00 00 00 02 A6 03
+			29 01 00 00 00 00 02 A7 FE
+			29 01 00 00 00 00 02 A9 03
+			29 01 00 00 00 00 02 AA FE
+			29 01 00 00 00 00 02 AB 03
+			29 01 00 00 00 00 02 AC FE
+			29 01 00 00 00 00 02 AD 03
+			29 01 00 00 00 00 02 AE FE
+			29 01 00 00 00 00 02 AF 00
+			29 01 00 00 00 00 02 B0 FB
+			29 01 00 00 00 00 02 B1 00
+			29 01 00 00 00 00 02 B2 FD
+			29 01 00 00 00 00 02 B3 01
+			29 01 00 00 00 00 02 B4 05
+			29 01 00 00 00 00 02 B5 01
+			29 01 00 00 00 00 02 B6 0D
+			29 01 00 00 00 00 02 B7 01
+			29 01 00 00 00 00 02 B8 17
+			29 01 00 00 00 00 02 B9 01
+			29 01 00 00 00 00 02 BA 1F
+			29 01 00 00 00 00 02 BB 01
+			29 01 00 00 00 00 02 BC 28
+			29 01 00 00 00 00 02 BD 01
+			29 01 00 00 00 00 02 BE 32
+			29 01 00 00 00 00 02 BF 01
+			29 01 00 00 00 00 02 C0 38
+			29 01 00 00 00 00 02 C1 01
+			29 01 00 00 00 00 02 C2 53
+			29 01 00 00 00 00 02 C3 01
+			29 01 00 00 00 00 02 C4 72
+			29 01 00 00 00 00 02 C5 01
+			29 01 00 00 00 00 02 C6 9B
+			29 01 00 00 00 00 02 C7 01
+			29 01 00 00 00 00 02 C8 C3
+			29 01 00 00 00 00 02 C9 02
+			29 01 00 00 00 00 02 CA 01
+			29 01 00 00 00 00 02 CB 02
+			29 01 00 00 00 00 02 CC 36
+			29 01 00 00 00 00 02 CD 02
+			29 01 00 00 00 00 02 CE 37
+			29 01 00 00 00 00 02 CF 02
+			29 01 00 00 00 00 02 D0 69
+			29 01 00 00 00 00 02 D1 02
+			29 01 00 00 00 00 02 D2 A1
+			29 01 00 00 00 00 02 D3 02
+			29 01 00 00 00 00 02 D4 C8
+			29 01 00 00 00 00 02 D5 02
+			29 01 00 00 00 00 02 D6 FF
+			29 01 00 00 00 00 02 D7 03
+			29 01 00 00 00 00 02 D8 26
+			29 01 00 00 00 00 02 D9 03
+			29 01 00 00 00 00 02 DA 69
+			29 01 00 00 00 00 02 DB 03
+			29 01 00 00 00 00 02 DC 88
+			29 01 00 00 00 00 02 DD 03
+			29 01 00 00 00 00 02 DE F8
+			29 01 00 00 00 00 02 DF 03
+			29 01 00 00 00 00 02 E0 F9
+			29 01 00 00 00 00 02 E1 03
+			29 01 00 00 00 00 02 E2 FE
+			29 01 00 00 00 00 02 E3 03
+			29 01 00 00 00 00 02 E4 FE
+			29 01 00 00 00 00 02 E5 03
+			29 01 00 00 00 00 02 E6 FE
+			29 01 00 00 00 00 02 E7 03
+			29 01 00 00 00 00 02 E8 FE
+			29 01 00 00 00 00 02 E9 03
+			29 01 00 00 00 00 02 EA FE
+			29 01 00 00 00 00 02 FF 01
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 FF 02
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 FF 04
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 FF 00
+			29 01 00 00 00 00 02 D3 14
+			29 01 00 00 00 00 02 D4 14
+			29 01 00 00 96 00 02 11 00
+			29 01 00 00 00 00 02 FF 00
+			29 01 00 00 00 00 02 35 00
+			29 01 00 00 78 00 02 29 00];
+
+		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+		qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
+					05 01 00 00 78 00 02 10 00];
+		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+	};
+};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index b4e557e..ce050a4 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -46,10 +46,13 @@
 			reg = <0x800 0x100>;
 			interrupts = <0x0 0x8 0x0>,
 				     <0x0 0x8 0x1>,
-				     <0x0 0x8 0x4>;
-			interrupt-names = "kpdpwr", "resin", "resin-bark";
+				     <0x0 0x8 0x4>,
+				     <0x0 0x8 0x5>;
+			interrupt-names = "kpdpwr", "resin",
+					"resin-bark", "kpdpwr-resin-bark";
 			qcom,pon-dbc-delay = <15625>;
 			qcom,system-reset;
+			qcom,s3-debounce = <32>;
 
 			qcom,pon_1 {
 				qcom,pon-type = <0>;
@@ -66,6 +69,15 @@
 				qcom,s2-type = <1>;
 				linux,code = <114>;
 			};
+
+			qcom,pon_3 {
+				qcom,pon-type = <3>;
+				qcom,support-reset = <1>;
+				qcom,s1-timer = <6720>;
+				qcom,s2-timer = <2000>;
+				qcom,s2-type = <7>;
+				qcom,pull-up = <1>;
+			};
 		};
 
 		bif_ctrl: qcom,bsi@1b00 {
diff --git a/arch/arm/boot/dts/msm-pma8084.dtsi b/arch/arm/boot/dts/msm-pma8084.dtsi
index 30525aa..42c48f8 100644
--- a/arch/arm/boot/dts/msm-pma8084.dtsi
+++ b/arch/arm/boot/dts/msm-pma8084.dtsi
@@ -191,6 +191,76 @@
 				qcom,pin-num = <8>;
 			};
 		};
+
+		pma8084_vadc: vadc@3100 {
+			compatible = "qcom,qpnp-vadc";
+			reg = <0x3100 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0x0 0x31 0x0>;
+			interrupt-names = "eoc-int-en-set";
+			qcom,adc-bit-resolution = <15>;
+			qcom,adc-vdd-reference = <1800>;
+
+			chan@8 {
+				label = "die_temp";
+				reg = <8>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <3>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@9 {
+				label = "ref_625mv";
+				reg = <9>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@a {
+				label = "ref_1250v";
+				reg = <0xa>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@c {
+				label = "ref_buf_625mv";
+				reg = <0xc>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+		};
+
+		pma8084_adc_tm: vadc@3400 {
+			compatible = "qcom,qpnp-adc-tm";
+			reg = <0x3400 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts =	<0x0 0x34 0x0>,
+					<0x0 0x34 0x3>,
+				     <0x0 0x34 0x4>;
+			interrupt-names =	"eoc-int-en-set",
+						"high-thr-en-set",
+						"low-thr-en-set";
+			qcom,adc-bit-resolution = <15>;
+			qcom,adc-vdd-reference = <1800>;
+		};
 	};
 
 	qcom,pma8084@1 {
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index 2f3fae2..308a6f5 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -367,6 +367,12 @@
 	};
 
 	mpp@a400 { /* MPP 5 */
+		/* PA_THERM0 config */
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <0>; /* AMUX 5 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
 	};
 
 	mpp@a500 { /* MPP 6 */
@@ -376,14 +382,48 @@
 	};
 
 	mpp@a700 { /* MPP 8 */
+		/* PA_THERM1 config */
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <3>; /* AMUX 8 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
 	};
 };
 
 &pm8226_chg {
 	qcom,charging-disabled;
 	qcom,use-default-batt-values;
+
+	qcom,bat-if@1200 {
+		status = "disabled";
+	};
 };
 
 &usb_otg_sw {
 	status = "okay";
 };
+
+&pm8226_vadc {
+	chan@14 {
+		label = "pa_therm0";
+		reg = <0x14>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@17 {
+		label = "pa_therm1";
+		reg = <0x17>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226-v1.dtsi b/arch/arm/boot/dts/msm8226-v1.dtsi
index d471bec..7d3977f 100644
--- a/arch/arm/boot/dts/msm8226-v1.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1.dtsi
@@ -17,3 +17,9 @@
  */
 
 /include/ "msm8226.dtsi"
+&soc {
+	qcom,acpuclk@f9011050 {
+		reg =	<0xf9011050 0x8>;
+		reg-names = "rcg_base";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226-v2-cdp.dts b/arch/arm/boot/dts/msm8226-v2-cdp.dts
index 2b18491..ef14249 100644
--- a/arch/arm/boot/dts/msm8226-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-cdp.dts
@@ -13,6 +13,7 @@
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
 /include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 CDP";
diff --git a/arch/arm/boot/dts/msm8226-v2-mtp.dts b/arch/arm/boot/dts/msm8226-v2-mtp.dts
index f15dd4c..24f822b 100644
--- a/arch/arm/boot/dts/msm8226-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-mtp.dts
@@ -13,6 +13,7 @@
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
 /include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 MTP";
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd.dts b/arch/arm/boot/dts/msm8226-v2-qrd.dts
index 1a89d78..ad6d154 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd.dts
@@ -13,6 +13,7 @@
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
 /include/ "msm8226-qrd.dtsi"
+/include/ "msm8226-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 QRD";
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index d471bec..db2f4e6 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -17,3 +17,44 @@
  */
 
 /include/ "msm8226.dtsi"
+/include/ "msm8226-camera.dtsi"
+
+&pm8226_l3 {
+	regulator-min-microvolt = <750000>;
+	regulator-max-microvolt = <1287500>;
+};
+
+&pm8226_l3_ao {
+	regulator-min-microvolt = <750000>;
+	regulator-max-microvolt = <1287500>;
+};
+
+&pm8226_l3_so {
+	regulator-min-microvolt = <750000>;
+	regulator-max-microvolt = <1287500>;
+};
+
+&pm8226_s2 {
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <1280000>;
+};
+
+&apc_vreg_corner {
+	qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
+				2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3>;
+	qcom,pvs-corner-ceiling-slow = <1160000 1160000 1280000>;
+	qcom,pvs-corner-ceiling-nom  =  <980000 1080000 1200000>;
+	qcom,pvs-corner-ceiling-fast =  <900000 1000000 1140000>;
+	qcom,cpr-step-quotient = <30>;
+	qcom,cpr-up-threshold = <0>;
+	qcom,cpr-down-threshold = <5>;
+	qcom,cpr-apc-volt-step = <10000>;
+};
+
+&soc {
+	qcom,acpuclk@f9011050 {
+		reg =	<0xf9011050 0x8>,
+			<0xfc4b80b0 0x8>;
+		reg-names = "rcg_base", "pte_efuse";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 7c98104..e22f590 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -741,8 +741,6 @@
 
 	qcom,acpuclk@f9011050 {
 		compatible = "qcom,acpuclk-a7";
-		reg = <0xf9011050 0x8>;
-		reg-names = "rcg_base";
 		a7_cpu-supply = <&apc_vreg_corner>;
 	};
 
@@ -918,6 +916,12 @@
                 compatible = "qcom,msm-rng";
                 reg = <0xf9bff000 0x200>;
                 qcom,msm-rng-iface-clk;
+                qcom,msm-bus,name = "msm-rng-noc";
+                qcom,msm-bus,num-cases = <2>;
+                qcom,msm-bus,num-paths = <1>;
+                qcom,msm-bus,vectors-KBps =
+                                <1 618 0 0>,
+                                <1 618 0 800>;
 	};
 
 	qcom,tz-log@fe805720 {
diff --git a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
index d057260..1b4a594 100644
--- a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
@@ -113,4 +113,42 @@
 		qcom,cci-master = <0>;
 		status = "ok";
 	};
+
+	qcom,camera@78 {
+		compatible = "qcom,sp1628";
+		reg = <0x78>;
+		qcom,slave-id = <0x78 0x0 0x1628>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "sp1628";
+		cam_vdig-supply = <&pm8110_l2>;
+		cam_vana-supply = <&pm8110_l19>;
+		cam_vio-supply = <&pm8110_l14>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-type = <0 0 0>;
+		qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-op-mode = <200000 80000 80000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 14 0>,
+			<&msmgpio 15 0>,
+			<&msmgpio 8 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+					  "CAM_RESET",
+					  "CAM_STANDBY";
+		qcom,gpio-set-tbl-num = <1 1>;
+		qcom,gpio-set-tbl-flags = <0 2>;
+		qcom,gpio-set-tbl-delay = <1000 4000>;
+		qcom,csi-lane-assign = <0xe4>;
+		qcom,csi-lane-mask = <0x3>;
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+	};
+
 };
diff --git a/arch/arm/boot/dts/msm8610-ion.dtsi b/arch/arm/boot/dts/msm8610-ion.dtsi
index 456b60c..d625b95 100644
--- a/arch/arm/boot/dts/msm8610-ion.dtsi
+++ b/arch/arm/boot/dts/msm8610-ion.dtsi
@@ -33,6 +33,21 @@
 			reg = <27>;
 			linux,contiguous-region = <&qsecom_mem>;
 		};
+
+		qcom,ion-heap@23 { /* OTHER PIL HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <23>;
+			qcom,heap-align = <0x1000>;
+			qcom,memory-fixed = <0x0bf00000 0x1A00000>;
+		};
+
+		qcom,ion-heap@26 { /* MODEM HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <26>;
+			qcom,heap-align = <0x1000>;
+			qcom,memory-fixed = <0x08000000 0x3F00000>;
+		};
+
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8610-mdss.dtsi b/arch/arm/boot/dts/msm8610-mdss.dtsi
index af0e3e4..d0fc1dc 100644
--- a/arch/arm/boot/dts/msm8610-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8610-mdss.dtsi
@@ -20,8 +20,6 @@
 		mdss_fb0: qcom,mdss_fb_primary {
 			cell-index = <0>;
 			compatible = "qcom,mdss-fb";
-			qcom,memory-reservation-type = "EBI1";
-			qcom,memory-reservation-size = <0x300000>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi b/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi
new file mode 100644
index 0000000..e3bd631
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&i2c {
+        qcom,camera@7d {
+                compatible = "qcom,hi256";
+                reg = <0x7d>;
+                qcom,slave-id = <0x40 0x04 0xc0>;
+                qcom,csiphy-sd-index = <0>;
+                qcom,csid-sd-index = <0>;
+                qcom,mount-angle = <270>;
+                qcom,sensor-name = "hi256";
+                cam_vdig-supply = <&pm8110_l2>;
+                cam_vana-supply = <&pm8110_l19>;
+                cam_vio-supply = <&pm8110_l14>;
+                qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+                qcom,cam-vreg-type = <0 0 0>;
+                qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+                qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+                qcom,cam-vreg-op-mode = <200000 8000 80000>;
+                qcom,gpio-no-mux = <0>;
+                gpios = <&msmgpio 13 0>,
+                        <&msmgpio 21 0>,
+                        <&msmgpio 20 0>;
+                qcom,gpio-reset = <1>;
+                qcom,gpio-standby = <2>;
+                qcom,gpio-req-tbl-num = <0 1 2>;
+                qcom,gpio-req-tbl-flags = <1 0 0>;
+                qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+                        "CAM_RESET1",
+                        "CAM_STANDBY";
+                qcom,csi-lane-assign = <0xe4>;
+                qcom,csi-lane-mask = <0x03>;
+                qcom,sensor-position = <0>;
+                qcom,sensor-mode = <1>;
+                qcom,cci-master = <0>;
+        };
+
+
+};
+
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dts
index 4d7a38a..90225c0 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dts
@@ -14,6 +14,7 @@
 
 /include/ "msm8610.dtsi"
 /include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
+/include/ "msm8610-qrd-camera-sensor.dtsi"
 
 / {
 	model = "Qualcomm MSM 8610 QRD";
@@ -56,6 +57,27 @@
 		status = "ok";
 	};
 
+	i2c@f9925000 { /* BLSP-1 QUP-3 */
+		kionix@f {
+			compatible = "kionix,kxtj9";
+			reg = <0x0f>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <81 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vio-supply = <&pm8110_l14>;
+			kionix,min_interval = <5>;
+			kionix,init_interval = <200>;
+			kionix,axis_map_x = <1>;
+			kionix,axis_map_y = <0>;
+			kionix,axis_map_z = <2>;
+			kionix,g-range = <2>;
+			kionix,negate-x;
+			kionix,negate-y;
+			kionix,negate-z;
+			kionix,res-12bit;
+		};
+	};
+
 	gpio_keys {
                 compatible = "gpio-keys";
                 input-name = "gpio-keys";
@@ -267,3 +289,33 @@
 		status = "ok";
 	};
 };
+
+&pm8110_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+	};
+
+	gpio@c300 { /* GPIO 4 */
+	};
+};
+
+&pm8110_mpps {
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+		status = "disabled";
+	};
+
+	mpp@a200 { /* MPP 3 */
+		status = "disabled";
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 1f7045b..72d9317 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -237,6 +237,7 @@
 	android_usb@fe8050c8 {
 		compatible = "qcom,android-usb";
 		reg = <0xfe8050c8 0xc8>;
+		qcom,android-usb-swfi-latency = <1>;
 	};
 
 	sdcc1: qcom,sdcc@f9824000 {
@@ -418,7 +419,7 @@
 
 	qcom,msm-mem-hole {
 		compatible = "qcom,msm-mem-hole";
-		qcom,memblock-remove = <0x07B00000 0x6400000>; /* Address and Size of Hole */
+		qcom,memblock-remove = <0x07b00000 0x6400000>; /* Address and Size of Hole */
 	};
 
 	qcom,wdt@f9017000 {
@@ -804,6 +805,12 @@
                 compatible = "qcom,msm-rng";
                 reg = <0xf9bff000 0x200>;
                 qcom,msm-rng-iface-clk;
+                qcom,msm-bus,name = "msm-rng-noc";
+                qcom,msm-bus,num-cases = <2>;
+                qcom,msm-bus,num-paths = <1>;
+                qcom,msm-bus,vectors-KBps =
+                                <1 618 0 0>,
+                                <1 618 0 800>;
         };
 
 	qcom,msm-rtb {
diff --git a/arch/arm/boot/dts/msm8926-cdp.dts b/arch/arm/boot/dts/msm8926-cdp.dts
index 7a91d40..48d3ea9 100644
--- a/arch/arm/boot/dts/msm8926-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-cdp.dts
@@ -14,9 +14,21 @@
 /dts-v1/;
 /include/ "msm8926.dtsi"
 /include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8926 CDP";
 	compatible = "qcom,msm8926-cdp", "qcom,msm8926", "qcom,cdp";
 	qcom,msm-id = <200 1 0>;
 };
+
+&pm8226_chg {
+	status = "ok";
+	qcom,charging-disabled;
+	qcom,use-default-batt-values;
+
+	qcom,bat-if@1200 {
+		status = "disabled";
+	};
+
+};
diff --git a/arch/arm/boot/dts/msm8926-mtp.dts b/arch/arm/boot/dts/msm8926-mtp.dts
index fea925d..dc6e60e 100644
--- a/arch/arm/boot/dts/msm8926-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-mtp.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 /include/ "msm8926.dtsi"
 /include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8926 MTP";
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-qrd.dts
index e056b7e..8497ba2 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-qrd.dts
@@ -13,6 +13,7 @@
 /dts-v1/;
 /include/ "msm8926.dtsi"
 /include/ "msm8226-qrd.dtsi"
+/include/ "msm8226-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8926 QRD";
diff --git a/arch/arm/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index 6f3f592..a26c1d9 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -17,6 +17,7 @@
  */
 
 /include/ "msm8226.dtsi"
+/include/ "msm8226-camera.dtsi"
 
 / {
 	model = "Qualcomm MSM 8926";
@@ -27,4 +28,42 @@
 	qcom,mss@fc880000 {
 		vdd_mss-supply = <&pm8226_s5>;
 	};
+
+	qcom,acpuclk@f9011050 {
+		reg =	<0xf9011050 0x8>,
+			<0xfc4b80b0 0x8>;
+		reg-names = "rcg_base", "pte_efuse";
+	};
+};
+
+&pm8226_l3 {
+	regulator-min-microvolt = <750000>;
+	regulator-max-microvolt = <1287500>;
+};
+
+&pm8226_l3_ao {
+	regulator-min-microvolt = <750000>;
+	regulator-max-microvolt = <1287500>;
+};
+
+&pm8226_l3_so {
+	regulator-min-microvolt = <750000>;
+	regulator-max-microvolt = <1287500>;
+};
+
+&pm8226_s2 {
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <1280000>;
+};
+
+&apc_vreg_corner {
+	qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
+				2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3>;
+	qcom,pvs-corner-ceiling-slow = <1160000 1160000 1280000>;
+	qcom,pvs-corner-ceiling-nom  =  <980000 1080000 1200000>;
+	qcom,pvs-corner-ceiling-fast =  <900000 1000000 1140000>;
+	qcom,cpr-step-quotient = <30>;
+	qcom,cpr-up-threshold = <0>;
+	qcom,cpr-down-threshold = <5>;
+	qcom,cpr-apc-volt-step = <10000>;
 };
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
index 4a9820d..26c5b8f 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
@@ -15,7 +15,7 @@
 
 	actuator0: qcom,actuator@18 {
 		cell-index = <0>;
-		reg = <0x18 0x0>;
+		reg = <0x18>;
 		compatible = "qcom,actuator";
 		qcom,cci-master = <0>;
 	};
@@ -29,7 +29,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>;
@@ -116,7 +116,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 = <2>;
@@ -153,7 +153,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-dragonboard.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
index e84a47d..31f3a90 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
@@ -15,7 +15,7 @@
 
 	actuator0: qcom,actuator@18 {
 		cell-index = <0>;
-		reg = <0x18 0x0>;
+		reg = <0x18>;
 		compatible = "qcom,actuator";
 		qcom,cci-master = <0>;
 	};
@@ -29,7 +29,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>;
@@ -105,7 +105,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>;
@@ -140,7 +140,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-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index a822af5..3d2308d 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -403,6 +403,10 @@
 };
 
 &pm8941_bms {
+	qcom,enable-fcc-learning;
+	qcom,min-fcc-learning-soc = <20>;
+	qcom,min-fcc-ocv-pc = <30>;
+	qcom,min-fcc-learning-samples = <5>;
 	status = "ok";
 };
 
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index e798fc0..28111fa 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -352,6 +352,10 @@
 };
 
 &pm8941_bms {
+	qcom,enable-fcc-learning;
+	qcom,min-fcc-learning-soc = <20>;
+	qcom,min-fcc-ocv-pc = <30>;
+	qcom,min-fcc-learning-samples = <5>;
 	status = "ok";
 };
 
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 178a1ee..eed1aae 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -328,18 +328,23 @@
 			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<0xff 56>,  /* modem_watchdog */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
 			<0xff 58>,  /* mss_to_apps_irq(1) */
 			<0xff 59>,  /* mss_to_apps_irq(2) */
 			<0xff 60>,  /* mss_to_apps_irq(3) */
+			<0xff 70>,  /* iommu_pmon_nonsecure_irq */
+			<0xff 97>,  /* iommu_nonsecure_irq */
+			<0xff 105>, /* iommu_pmon_nonsecure_irq */
 			<0xff 173>, /* o_wcss_apss_smd_hi */
 			<0xff 174>, /* o_wcss_apss_smd_med */
 			<0xff 175>, /* o_wcss_apss_smd_low */
 			<0xff 176>, /* o_wcss_apss_smsm_irq */
 			<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
 			<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
-			<0xff 179>, /* o_wcss_apss_asic_intr
+			<0xff 179>, /* o_wcss_apss_asic_intr */
 
+			<0xff 181>, /* wcnss watchdog */
 			<0xff 188>, /* lpass_irq_out_apcs(0) */
 			<0xff 189>, /* lpass_irq_out_apcs(1) */
 			<0xff 190>, /* lpass_irq_out_apcs(2) */
@@ -358,6 +363,7 @@
 			<0xff 205>, /* rpm_ipc(25) */
 			<0xff 206>, /* rpm_ipc(26) */
 			<0xff 207>, /* rpm_ipc(27) */
+			<0xff 211>, /* usb_dwc3_otg */
 			<0xff 240>; /* summary_irq_kpss */
 
 		qcom,gpio-parent = <&msmgpio>;
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 96e78ac..0240039 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -115,12 +115,12 @@
 		<49880000 1496000>;
 	qcom,dec-ddr-ab-ib = <0 0>,
 		<208000 303000>,
-		<536000 303000>,
-		<1012000 303000>,
-		<2024000 606000>,
-		<3240000 970000>,
-		<4048000 1212000>,
-		<4264000 1279000>;
+		<536000 1600000>,
+		<1012000 1600000>,
+		<2024000 1600000>,
+		<3240000 1600000>,
+		<4048000 1600000>,
+		<4264000 1600000>;
 	qcom,iommu-groups = <&venus_domain_ns &venus_domain_sec_bitstream
 			&venus_domain_sec_pixel &venus_domain_sec_non_pixel>;
 	qcom,iommu-group-buffer-types = <0xfff 0x91 0x42 0x120>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index fc0636e..a098ce9 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -878,7 +878,6 @@
 			interrupt-parent = <&intc>;
 			interrupts = <0 131 0>, <0 179 0>;
 			interrupt-names = "irq", "otg_irq";
-			tx-fifo-resize;
 		};
 	};
 
@@ -1223,7 +1222,7 @@
 		qcom,iris-vddxo-supply = <&pm8941_l6>;
 		qcom,iris-vddrfa-supply = <&pm8941_l11>;
 		qcom,iris-vddpa-supply = <&pm8941_l19>;
-		qcom,iris-vdddig-supply = <&pm8941_l3>;
+		qcom,iris-vdddig-supply = <&pm8941_s3>;
 
 		gpios = <&msmgpio 36 0>, <&msmgpio 37 0>, <&msmgpio 38 0>, <&msmgpio 39 0>, <&msmgpio 40 0>;
 		qcom,has-48mhz-xo;
@@ -1273,8 +1272,14 @@
 	};
 
         qcom,msm-rng@f9bff000 {
-               compatible = "qcom,msm-rng";
-               reg = <0xf9bff000 0x200>;
+		compatible = "qcom,msm-rng";
+		reg = <0xf9bff000 0x200>;
+		qcom,msm-bus,name = "msm-rng-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<1 618 0 0>,
+				<1 618 0 800>;
         };
 
 	qseecom: qcom,qseecom@7f00000 {
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index 7bbd528..ba6377c 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -45,6 +45,11 @@
 		qcom,direct-connect-irqs = <8>;
 	};
 
+	qcom,msm-imem@fe805000 {
+		compatible = "qcom,msm-imem";
+		reg = <0xfe807800 0x1000>; /* Address and size of IMEM */
+	};
+
 	timer@f9020000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
index 81699b6..968daff 100644
--- a/arch/arm/boot/dts/msmsamarium.dtsi
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -87,4 +87,13 @@
 		qcom,bus-width = <4>;
 		status = "disabled";
 	};
+
+	qcom,wdt@f9017000 {
+		compatible = "qcom,msm-watchdog";
+		reg = <0xf9017000 0x1000>;
+		interrupts = <0 3 0>, <0 4 0>;
+		qcom,bark-time = <11000>;
+		qcom,pet-time = <10000>;
+		qcom,ipi-ping;
+	};
 };
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index ae26f96..a9fc578 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -205,6 +205,15 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_QSEECOM=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
@@ -400,3 +409,5 @@
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=y
 CONFIG_CRYPTO_DEV_QCEDEV=m
+CONFIG_MOBICORE_SUPPORT=m
+CONFIG_MOBICORE_API=m
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index f8fbdb7..8d06c59 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -205,6 +205,15 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_QSEECOM=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
@@ -427,6 +436,8 @@
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
 CONFIG_KEYS=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_ARC4=y
@@ -434,3 +445,5 @@
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=y
 CONFIG_CRYPTO_DEV_QCEDEV=m
+CONFIG_MOBICORE_SUPPORT=m
+CONFIG_MOBICORE_API=m
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 5cad31e..9d104fd 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -271,15 +271,19 @@
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 # CONFIG_MSM_CAMERA is not set
 CONFIG_OV8825=y
+CONFIG_HI256=y
 CONFIG_MSM_CAMERA_SENSOR=y
-CONFIG_MSM_CPP=y
+# CONFIG_MSM_CPP is not set
 CONFIG_MSM_CCI=y
-CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSI22_HEADER=y
 CONFIG_MSM_CSIPHY=y
 CONFIG_MSM_CSID=y
 CONFIG_MSM_ISPIF=y
+CONFIG_MSM_ISPIF_V1=y
 CONFIG_MSMB_CAMERA=y
 CONFIG_OV9724=y
+CONFIG_SP1628=y
+CONFIG_GC0339=y
 CONFIG_MSMB_JPEG=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_WFD=y
@@ -375,3 +379,4 @@
 CONFIG_CRYPTO_TWOFISH=y
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=y
+CONFIG_INPUT_KXTJ9=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 95b4f0c..0587e50 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -269,15 +269,18 @@
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 # CONFIG_MSM_CAMERA is not set
 CONFIG_OV8825=y
+CONFIG_HI256=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_CCI=y
-CONFIG_MSM_CSI20_HEADER=y
 CONFIG_MSM_CSIPHY=y
 CONFIG_MSM_CSID=y
 CONFIG_MSM_ISPIF=y
+CONFIG_MSM_ISPIF_V1=y
 CONFIG_MSMB_CAMERA=y
 CONFIG_MSM_CSI22_HEADER=y
 CONFIG_OV9724=y
+CONFIG_SP1628=y
+CONFIG_GC0339=y
 CONFIG_MSMB_JPEG=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_WFD=y
@@ -418,3 +421,4 @@
 CONFIG_CRYPTO_DEV_QCE=y
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
+CONFIG_INPUT_KXTJ9=y
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index cf10056..a70b300 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -573,6 +573,8 @@
 	local_fiq_disable();
 	local_irq_disable();
 
+	flush_cache_all();
+
 	while (1)
 		cpu_relax();
 }
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 85fa764..e0f9e8a 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1312,6 +1312,14 @@
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to the serial port on MSM SAMARIUM devices.
+
+	config DEBUG_MSM8226_UART
+		bool "Kernel low-level debugging messages via MSM 8226 UART"
+		depends on ARCH_MSM8226
+		select MSM_HAS_DEBUG_UART_HS_V14
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on MSM 8226 devices.
 endchoice
 
 choice
@@ -2372,6 +2380,15 @@
           RBCPR (Rapid Bridge Core Power Reduction) information . The drivers
           outputs the message via a debugfs node.
 
+config MSM_RPM_RBCPR_STATS_V2_LOG
+        tristate "MSM Resource Power Manager RPBCPR Stat Driver"
+        depends on DEBUG_FS
+          help
+          This option enables v2 of the rpmrbcpr_stats driver which reads RPM
+          memory for statistics pertaining to RPM's RBCPR(Rapid Bridge Core
+          Power Reduction) driver. The drivers outputs the message via a
+          debugfs node.
+
 config MSM_DIRECT_SCLK_ACCESS
 	bool "Direct access to the SCLK timer"
 	default n
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 1c07dc1..e9a236e 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -333,6 +333,7 @@
 obj-$(CONFIG_MSM_MPM) += mpm.o
 obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o rpm_master_stat.o
 obj-$(CONFIG_MSM_RPM_RBCPR_STATS_LOG) += rpm_rbcpr_stats.o
+obj-$(CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG) += rpm_rbcpr_stats_v2.o
 obj-$(CONFIG_MSM_RPM_LOG) += rpm_log.o
 obj-$(CONFIG_MSM_TZ_LOG) += tz_log.o
 obj-$(CONFIG_MSM_XO) += msm_xo.o
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index 0028d6e..59c682f 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -59,12 +59,7 @@
 	.name = "acpuclock",
 };
 
-/* TODO:
- * 1) Update MX voltage when data is avaiable
- * 2) Update bus bandwidth
- * 3) Depending on Frodo version, may need minimum of LVL_NOM
- */
-static struct clkctl_acpu_speed acpu_freq_tbl_8226[] = {
+static struct clkctl_acpu_speed acpu_freq_tbl_8226_1p1[] = {
 	{ 1,  300000, PLL0,    4, 2,   CPR_CORNER_SVS,    0, 4 },
 	{ 1,  384000, ACPUPLL, 5, 2,   CPR_CORNER_SVS,    0, 4 },
 	{ 1,  600000, PLL0,    4, 0,   CPR_CORNER_NORMAL, 0, 6 },
@@ -75,6 +70,46 @@
 	{ 0 }
 };
 
+static struct clkctl_acpu_speed acpu_freq_tbl_8226_1p2[] = {
+	{ 1,  300000, PLL0,    4, 2,   CPR_CORNER_SVS,    0, 4 },
+	{ 1,  384000, ACPUPLL, 5, 2,   CPR_CORNER_SVS,    0, 4 },
+	{ 1,  600000, PLL0,    4, 0,   CPR_CORNER_NORMAL, 0, 6 },
+	{ 1,  787200, ACPUPLL, 5, 0,   CPR_CORNER_NORMAL, 0, 7 },
+	{ 1,  998400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1094400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1190400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 0 }
+};
+
+static struct clkctl_acpu_speed acpu_freq_tbl_8226_1p4[] = {
+	{ 1,  300000, PLL0,    4, 2,   CPR_CORNER_SVS,    0, 4 },
+	{ 1,  384000, ACPUPLL, 5, 2,   CPR_CORNER_SVS,    0, 4 },
+	{ 1,  600000, PLL0,    4, 0,   CPR_CORNER_NORMAL, 0, 6 },
+	{ 1,  787200, ACPUPLL, 5, 0,   CPR_CORNER_NORMAL, 0, 7 },
+	{ 1,  998400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1094400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1190400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1305600, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1344000, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1401600, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 0 }
+};
+
+static struct clkctl_acpu_speed acpu_freq_tbl_8226_1p5[] = {
+	{ 1,  300000, PLL0,    4, 2,   CPR_CORNER_SVS,    0, 4 },
+	{ 1,  384000, ACPUPLL, 5, 2,   CPR_CORNER_SVS,    0, 4 },
+	{ 1,  600000, PLL0,    4, 0,   CPR_CORNER_NORMAL, 0, 6 },
+	{ 1,  787200, ACPUPLL, 5, 0,   CPR_CORNER_NORMAL, 0, 7 },
+	{ 1,  998400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1094400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1190400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1305600, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1344000, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1401600, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	/* No support for 1p5 GHz yet */
+	{ 0 }
+};
+
 static struct clkctl_acpu_speed acpu_freq_tbl_8610[] = {
 	{ 1,  300000, PLL0,    4, 2,   CPR_CORNER_SVS,    0, 3 },
 	{ 1,  384000, ACPUPLL, 5, 2,   CPR_CORNER_SVS,    0, 3 },
@@ -85,8 +120,18 @@
 	{ 0 }
 };
 
+static struct clkctl_acpu_speed *pvs_tables_8226[NUM_SPEED_BIN] = {
+	[0] = acpu_freq_tbl_8226_1p2,
+	[6] = acpu_freq_tbl_8226_1p2,
+	[2] = acpu_freq_tbl_8226_1p4,
+	[5] = acpu_freq_tbl_8226_1p4,
+	[3] = acpu_freq_tbl_8226_1p5,
+	[4] = acpu_freq_tbl_8226_1p5,
+};
+
 static struct acpuclk_drv_data drv_data = {
-	.freq_tbl = acpu_freq_tbl_8226,
+	.freq_tbl = acpu_freq_tbl_8226_1p1,
+	.pvs_tables = pvs_tables_8226,
 	.bus_scale = &bus_client_pdata,
 	.vdd_max_cpu = CPR_CORNER_TURBO,
 	.src_clocks = {
@@ -121,6 +166,14 @@
 
 	drv_data.apcs_rcg_config = drv_data.apcs_rcg_cmd + 4;
 
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pte_efuse");
+	if (res) {
+		drv_data.pte_efuse_base = devm_ioremap(&pdev->dev, res->start,
+			resource_size(res));
+		if (!drv_data.pte_efuse_base)
+			return -ENOMEM;
+	}
+
 	drv_data.vdd_cpu = devm_regulator_get(&pdev->dev, "a7_cpu");
 	if (IS_ERR(drv_data.vdd_cpu)) {
 		dev_err(&pdev->dev, "regulator for %s get failed\n", "a7_cpu");
diff --git a/arch/arm/mach-msm/acpuclock-9625.c b/arch/arm/mach-msm/acpuclock-9625.c
index a4a5b2a..f2e7602 100644
--- a/arch/arm/mach-msm/acpuclock-9625.c
+++ b/arch/arm/mach-msm/acpuclock-9625.c
@@ -80,8 +80,8 @@
 		.update_mask = RCG_CONFIG_PGM_DATA_BIT | RCG_CONFIG_PGM_ENA_BIT,
 		.poll_mask = RCG_CONFIG_PGM_DATA_BIT,
 	},
-	.power_collapse_khz = 19200,
-	.wait_for_irq_khz = 19200,
+	.power_collapse_khz = 300000,
+	.wait_for_irq_khz = 300000,
 };
 
 static int __init acpuclk_9625_probe(struct platform_device *pdev)
@@ -137,6 +137,9 @@
 	regval |= GPLL0_TO_A5_ALWAYS_ENABLE;
 	writel_relaxed(regval, drv_data.apcs_cpu_pwr_ctl);
 
+	/* Enable the always on source */
+	clk_prepare_enable(drv_data.src_clocks[PLL0].clk);
+
 	return acpuclk_cortex_init(pdev, &drv_data);
 }
 
diff --git a/arch/arm/mach-msm/acpuclock-cortex.c b/arch/arm/mach-msm/acpuclock-cortex.c
index 2c3f97b..baa1c7b 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.c
+++ b/arch/arm/mach-msm/acpuclock-cortex.c
@@ -368,6 +368,40 @@
 	.get_rate = acpuclk_cortex_get_rate,
 };
 
+void __init get_speed_bin(void __iomem *base, struct bin_info *bin)
+{
+	u32 pte_efuse, redundant_sel;
+
+	pte_efuse = readl_relaxed(base);
+	redundant_sel = (pte_efuse >> 24) & 0x7;
+	bin->speed = pte_efuse & 0x7;
+
+	if (redundant_sel == 1)
+		bin->speed = (pte_efuse >> 27) & 0x7;
+
+	bin->speed_valid = !!(pte_efuse & BIT(3));
+}
+
+static struct clkctl_acpu_speed *__init select_freq_plan(void)
+{
+	struct bin_info bin;
+
+	if (!priv->pte_efuse_base)
+		return priv->freq_tbl;
+
+	get_speed_bin(priv->pte_efuse_base, &bin);
+
+	if (bin.speed_valid) {
+		pr_info("SPEED BIN: %d\n", bin.speed);
+	} else {
+		bin.speed = 0;
+		pr_warn("SPEED BIN: Defaulting to %d\n",
+			 bin.speed);
+	}
+
+	return priv->pvs_tables[bin.speed];
+}
+
 int __init acpuclk_cortex_init(struct platform_device *pdev,
 	struct acpuclk_drv_data *data)
 {
@@ -380,6 +414,12 @@
 	acpuclk_cortex_data.power_collapse_khz = priv->wait_for_irq_khz;
 	acpuclk_cortex_data.wait_for_irq_khz = priv->wait_for_irq_khz;
 
+	priv->freq_tbl = select_freq_plan();
+	if (!priv->freq_tbl) {
+		pr_err("Invalid freq table selected\n");
+		BUG();
+	}
+
 	bus_perf_client = msm_bus_scale_register_client(priv->bus_scale);
 	if (!bus_perf_client) {
 		pr_err("Unable to register bus client\n");
diff --git a/arch/arm/mach-msm/acpuclock-cortex.h b/arch/arm/mach-msm/acpuclock-cortex.h
index 89a0a84..00f182d 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.h
+++ b/arch/arm/mach-msm/acpuclock-cortex.h
@@ -17,6 +17,8 @@
 #define LVL_NOM         RPM_REGULATOR_CORNER_NORMAL
 #define LVL_HIGH        RPM_REGULATOR_CORNER_SUPER_TURBO
 
+#define NUM_SPEED_BIN	8
+
 enum clk_src {
 	CXO,
 	PLL0,
@@ -52,6 +54,8 @@
 struct acpuclk_drv_data {
 	struct mutex			lock;
 	struct clkctl_acpu_speed	*freq_tbl;
+	struct clkctl_acpu_speed	**pvs_tables;
+	void __iomem			*pte_efuse_base;
 	struct clkctl_acpu_speed	*current_speed;
 	struct msm_bus_scale_pdata	*bus_scale;
 	void __iomem			*apcs_rcg_config;
@@ -67,6 +71,11 @@
 	unsigned long                   wait_for_irq_khz;
 };
 
+struct bin_info {
+	bool speed_valid;
+	int speed;
+};
+
 /* Instantaneous bandwidth requests in MB/s. */
 #define BW_MBPS(_bw) \
 	{ \
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index b2dcd7a..318e933 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -481,7 +481,7 @@
 	.enable_fcc_learning		= 1,
 	.min_fcc_learning_soc		= 20,
 	.min_fcc_ocv_pc			= 30,
-	.max_fcc_learning_samples	= 5,
+	.min_fcc_learning_samples	= 5,
 };
 
 static struct pm8921_platform_data
diff --git a/arch/arm/mach-msm/board-8084.c b/arch/arm/mach-msm/board-8084.c
index 67c05ba..7dc9a90 100644
--- a/arch/arm/mach-msm/board-8084.c
+++ b/arch/arm/mach-msm/board-8084.c
@@ -16,6 +16,7 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/memory.h>
+#include <linux/msm_tsens.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
@@ -86,6 +87,7 @@
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_clock_init(&msm8084_clock_init_data);
+	tsens_tm_init_driver();
 }
 
 static void __init apq8084_map_io(void)
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index d7e678e..31937a0 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -484,7 +484,7 @@
 	.enable_fcc_learning		= 1,
 	.min_fcc_learning_soc		= 20,
 	.min_fcc_ocv_pc			= 30,
-	.max_fcc_learning_samples	= 5,
+	.min_fcc_learning_samples	= 5,
 };
 
 static struct pm8038_platform_data pm8038_platform_data __devinitdata = {
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 8e758bf..7a5c74c 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -441,7 +441,7 @@
 	.enable_fcc_learning		= 1,
 	.min_fcc_learning_soc		= 20,
 	.min_fcc_ocv_pc			= 30,
-	.max_fcc_learning_samples	= 5,
+	.min_fcc_learning_samples	= 5,
 };
 
 #define	PM8921_LC_LED_MAX_CURRENT	4	/* I = 4mA */
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index fd3ba14..8c3a75b 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -2816,6 +2816,9 @@
 	F_APCS_PLL( 998400000, 52, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1094400000, 57, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1190400000, 62, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1305600000, 68, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1344000000, 70, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1401600000, 73, 0x0, 0x1, 0x0, 0x0, 0x0),
 	PLL_F_END
 };
 
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 58c5745..1025aa4 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -3016,49 +3016,45 @@
 		"fda01000.qcom,csiphy"),
 
 	/* CSID clocks */
-
-	CLK_LOOKUP("csi_ahb_clk", csi_ahb_clk.c, "fda00000.qcom,csid"),
+	CLK_LOOKUP("csi_clk", csi0_clk.c, "fda00000.qcom,csid"),
 	CLK_LOOKUP("csi_src_clk", csi0_clk_src.c, "fda00000.qcom,csid"),
-	CLK_LOOKUP("csi_clk", csi0_clk.c,         "fda00000.qcom,csid"),
-	CLK_LOOKUP("csi_phy_clk", csi0phy_clk.c,  "fda00000.qcom,csid"),
-	CLK_LOOKUP("csi_pix_clk", csi0pix_clk.c,  "fda00000.qcom,csid"),
-	CLK_LOOKUP("csi_rdi_clk", csi0rdi_clk.c,  "fda00000.qcom,csid"),
+	CLK_LOOKUP("csi_ahb_clk", csi_ahb_clk.c, "fda00000.qcom,csid"),
+	CLK_LOOKUP("csi0phy_mux_clk", csi0phy_cam_mux_clk.c,
+		 "fda00000.qcom,csid"),
+	CLK_LOOKUP("csi1phy_mux_clk", csi1phy_cam_mux_clk.c,
+		 "fda00000.qcom,csid"),
+	CLK_LOOKUP("csi0pix_mux_clk", csi0pix_cam_mux_clk.c,
+		 "fda00000.qcom,csid"),
+	CLK_LOOKUP("csi0rdi_mux_clk", rdi0_cam_mux_clk.c,
+		 "fda00000.qcom,csid"),
+	CLK_LOOKUP("csi1rdi_mux_clk", rdi1_cam_mux_clk.c,
+		 "fda00000.qcom,csid"),
+	CLK_LOOKUP("csi2rdi_mux_clk", rdi2_cam_mux_clk.c,
+		 "fda00000.qcom,csid"),
 
-	/*CLK_LOOKUP("csi0_phy_mux_sel", csi0phy_mux_clk.c,
-		"fda00000.qcom,csid"),
-	CLK_LOOKUP("csi0_pix_mux_sel", csi0pix_mux_clk.c,
-		"fda00000.qcom,csid"),
-	CLK_LOOKUP("csi0_rdi_mux_sel", rdi0_mux_clk.c,
-		"fda00000.qcom,csid"),*/
-
-	CLK_LOOKUP("csi_ahb_clk", csi_ahb_clk.c, "fda00400.qcom,csid"),
+	CLK_LOOKUP("csi_clk", csi1_clk.c, "fda00400.qcom,csid"),
 	CLK_LOOKUP("csi_src_clk", csi1_clk_src.c, "fda00400.qcom,csid"),
-	CLK_LOOKUP("csi_clk", csi1_clk.c,         "fda00400.qcom,csid"),
-	CLK_LOOKUP("csi_phy_clk", csi1phy_clk.c,  "fda00400.qcom,csid"),
-	CLK_LOOKUP("csi_pix_clk", csi1pix_clk.c,  "fda00400.qcom,csid"),
-	CLK_LOOKUP("csi_rdi_clk", csi1rdi_clk.c,  "fda00400.qcom,csid"),
+	CLK_LOOKUP("csi_ahb_clk", csi_ahb_clk.c, "fda00400.qcom,csid"),
+	CLK_LOOKUP("csi0phy_mux_clk", csi0phy_cam_mux_clk.c,
+		 "fda00400.qcom,csid"),
+	CLK_LOOKUP("csi1phy_mux_clk", csi1phy_cam_mux_clk.c,
+		 "fda00400.qcom,csid"),
+	CLK_LOOKUP("csi0pix_mux_clk", csi0pix_cam_mux_clk.c,
+		 "fda00400.qcom,csid"),
+	CLK_LOOKUP("csi0rdi_mux_clk", rdi0_cam_mux_clk.c,
+		 "fda00400.qcom,csid"),
+	CLK_LOOKUP("csi1rdi_mux_clk", rdi1_cam_mux_clk.c,
+		 "fda00400.qcom,csid"),
+	CLK_LOOKUP("csi2rdi_mux_clk", rdi2_cam_mux_clk.c,
+		 "fda00400.qcom,csid"),
 
-	/*CLK_LOOKUP("csi1_phy_mux_sel", csi1phy_mux_clk.c,
-		"fda00400.qcom,csid"),
-	CLK_LOOKUP("csi1_pix_mux_sel", csi0pix_mux_clk.c,
-		"fda00400.qcom,csid"),
-	CLK_LOOKUP("csi1_rdi_mux_sel", rdi1_mux_clk.c,
-		"fda00400.qcom,csid"),*/
-
-	/* ISPIF clocks */
-	CLK_LOOKUP("csi_src_clk", csi0_clk_src.c, "fda00800.qcom,ispif"),
-	CLK_LOOKUP("csi_src_clk", csi1_clk_src.c, "fda00800.qcom,ispif"),
-
-	CLK_LOOKUP("csi_pix_clk", csi0pix_clk.c,
-		"fda00800.qcom,ispif"),
-	CLK_LOOKUP("csi_rdi_clk", csi0rdi_clk.c,
-		"fda00800.qcom,ispif"),
-	CLK_LOOKUP("csi_pix1_clk", csi1pix_clk.c,
-		"fda00800.qcom,ispif"),
-	CLK_LOOKUP("csi_rdi1_clk", csi1rdi_clk.c,
-		"fda00800.qcom,ispif"),
-	CLK_LOOKUP("csi_rdi2_clk", csi1rdi_clk.c,
-		"fda00800.qcom,ispif"),
+	CLK_LOOKUP("csi_phy_src_clk", csi0phy_clk.c, "fda00000.qcom,csid"),
+	CLK_LOOKUP("csi_phy_src_clk", csi1phy_clk.c, "fda00400.qcom,csid"),
+	CLK_LOOKUP("csi_pix_src_clk", csi0pix_clk.c, "fda00000.qcom,csid"),
+	CLK_LOOKUP("csi_pix_src_clk", csi1pix_clk.c, "fda00400.qcom,csid"),
+	CLK_LOOKUP("csi_rdi_src_clk", csi0rdi_clk.c, "fda00000.qcom,csid"),
+	CLK_LOOKUP("csi_rdi_src_clk", csi1rdi_clk.c, "fda00400.qcom,csid"),
+	/* ISPIF need no clock */
 
 	CLK_LOOKUP("vfe_clk_src", vfe_clk_src.c, "fde00000.qcom,vfe"),
 	CLK_LOOKUP("vfe_clk", vfe_clk.c, "fde00000.qcom,vfe"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 3aef106..628250d 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -66,6 +66,15 @@
 #define GPLL1_TEST_CTL_REG             0x0058
 #define GPLL1_STATUS_REG               0x005C
 
+#define GPLL4_MODE_REG                 0x1DC0
+#define GPLL4_L_REG                    0x1DC4
+#define GPLL4_M_REG                    0x1DC8
+#define GPLL4_N_REG                    0x1DCC
+#define GPLL4_USER_CTL_REG             0x1DD0
+#define GPLL4_CONFIG_CTL_REG           0x1DD4
+#define GPLL4_TEST_CTL_REG             0x1DD8
+#define GPLL4_STATUS_REG               0x1DDC
+
 #define MMPLL0_MODE_REG                0x0000
 #define MMPLL0_L_REG                   0x0004
 #define MMPLL0_M_REG                   0x0008
@@ -519,6 +528,7 @@
 #define cxo_source_val	0
 #define gpll0_source_val 1
 #define gpll1_source_val 2
+#define gpll4_source_val 5
 #define gnd_source_val	5
 #define mmpll0_mm_source_val 1
 #define mmpll1_mm_source_val 2
@@ -736,6 +746,21 @@
 	},
 };
 
+static struct pll_vote_clk gpll4_clk_src = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
+	.en_mask = BIT(4),
+	.status_reg = (void __iomem *)GPLL4_STATUS_REG,
+	.status_mask = BIT(17),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.parent = &cxo_clk_src.c,
+		.rate = 800000000,
+		.dbg_name = "gpll4_clk_src",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(gpll4_clk_src.c),
+	},
+};
+
 static struct pll_vote_clk mmpll0_clk_src = {
 	.en_reg = (void __iomem *)MMSS_PLL_VOTE_APCS_REG,
 	.en_mask = BIT(0),
@@ -1373,6 +1398,14 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_gcc_ce1_v3_clk[] = {
+	F( 50000000,  gpll0,  12,   0,   0),
+	F( 75000000,  gpll0,   8,   0,   0),
+	F(100000000,  gpll0,   6,   0,   0),
+	F(150000000,  gpll0,   4,   0,   0),
+	F_END
+};
+
 static struct rcg_clk ce1_clk_src = {
 	.cmd_rcgr_reg = CE1_CMD_RCGR,
 	.set_rate = set_rate_hid,
@@ -1393,6 +1426,14 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_gcc_ce2_v3_clk[] = {
+	F( 50000000,  gpll0,  12,   0,   0),
+	F( 75000000,  gpll0,   8,   0,   0),
+	F(100000000,  gpll0,   6,   0,   0),
+	F(150000000,  gpll0,   4,   0,   0),
+	F_END
+};
+
 static struct rcg_clk ce2_clk_src = {
 	.cmd_rcgr_reg = CE2_CMD_RCGR,
 	.set_rate = set_rate_hid,
@@ -1480,7 +1521,7 @@
 	},
 };
 
-static struct clk_freq_tbl ftbl_gcc_sdcc1_2_apps_clk[] = {
+static struct clk_freq_tbl ftbl_gcc_sdcc1_4_apps_clk[] = {
 	F(   144000,    cxo,  16,   3,  25),
 	F(   400000,    cxo,  12,   1,   4),
 	F( 20000000,  gpll0,  15,   1,   2),
@@ -1488,16 +1529,7 @@
 	F( 50000000,  gpll0,  12,   0,   0),
 	F(100000000,  gpll0,   6,   0,   0),
 	F(200000000,  gpll0,   3,   0,   0),
-	F_END
-};
-
-static struct clk_freq_tbl ftbl_gcc_sdcc3_4_apps_clk[] = {
-	F(   144000,    cxo,  16,   3,  25),
-	F(   400000,    cxo,  12,   1,   4),
-	F( 20000000,  gpll0,  15,   1,   2),
-	F( 25000000,  gpll0,  12,   1,   2),
-	F( 50000000,  gpll0,  12,   0,   0),
-	F(100000000,  gpll0,   6,   0,   0),
+	F(400000000,  gpll4,   2,   0,   0),
 	F_END
 };
 
@@ -1510,7 +1542,7 @@
 static struct rcg_clk sdcc1_apps_clk_src = {
 	.cmd_rcgr_reg = SDCC1_APPS_CMD_RCGR,
 	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_sdcc1_2_apps_clk,
+	.freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
 	.current_freq = &rcg_dummy_freq,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
@@ -1524,7 +1556,7 @@
 static struct rcg_clk sdcc2_apps_clk_src = {
 	.cmd_rcgr_reg = SDCC2_APPS_CMD_RCGR,
 	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_sdcc1_2_apps_clk,
+	.freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
 	.current_freq = &rcg_dummy_freq,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
@@ -1538,7 +1570,7 @@
 static struct rcg_clk sdcc3_apps_clk_src = {
 	.cmd_rcgr_reg = SDCC3_APPS_CMD_RCGR,
 	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_sdcc3_4_apps_clk,
+	.freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
 	.current_freq = &rcg_dummy_freq,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
@@ -1552,7 +1584,7 @@
 static struct rcg_clk sdcc4_apps_clk_src = {
 	.cmd_rcgr_reg = SDCC4_APPS_CMD_RCGR,
 	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_sdcc3_4_apps_clk,
+	.freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
 	.current_freq = &rcg_dummy_freq,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
@@ -2706,6 +2738,7 @@
 	F_MM(228570000, mmpll0, 3.5,   0,   0),
 	F_MM(266670000, mmpll0,   3,   0,   0),
 	F_MM(320000000, mmpll0, 2.5,   0,   0),
+	F_MM(465000000, mmpll3,   2,   0,   0),
 	F_END
 };
 
@@ -2887,6 +2920,21 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_camss_mclk0_3_v3_clk[] = {
+	F_MM( 4800000,    cxo,    4,   0,   0),
+	F_MM( 6000000,  gpll0,   10,   1,  10),
+	F_MM( 8000000,  gpll0,   15,   1,   5),
+	F_MM( 9600000,    cxo,    2,   0,   0),
+	F_MM(16000000,  gpll0,   10,   1,   5),
+	F_MM(19200000,    cxo,    1,   0,   0),
+	F_MM(24000000,  gpll0,    5,   1,   5),
+	F_MM(32000000, mmpll0,    5,   1,   5),
+	F_MM(48000000,  gpll0, 12.5,   0,   0),
+	F_MM(64000000, mmpll0, 12.5,   0,   0),
+	F_MM(66670000,  gpll0,    9,   0,   0),
+	F_END
+};
+
 static struct rcg_clk mclk0_clk_src = {
 	.cmd_rcgr_reg = MCLK0_CMD_RCGR,
 	.set_rate = set_rate_hid,
@@ -2995,6 +3043,7 @@
 	F_MM(150000000,  gpll0,   4,   0,   0),
 	F_MM(266670000, mmpll0,   3,   0,   0),
 	F_MM(320000000, mmpll0, 2.5,   0,   0),
+	F_MM(465000000, mmpll3,   2,   0,   0),
 	F_END
 };
 
@@ -4802,6 +4851,7 @@
 	CLK_LOOKUP("xo", cxo_pil_pronto_clk.c,     "fb21b000.qcom,pronto"),
 	CLK_LOOKUP("xo",       cxo_dwc3_clk.c,                 "msm_dwc3"),
 	CLK_LOOKUP("xo",  cxo_ehci_host_clk.c,            "msm_ehci_host"),
+	CLK_LOOKUP("pll",     gpll4_clk_src.c,                         ""),
 
 	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
 
@@ -4881,6 +4931,11 @@
 	CLK_LOOKUP("ce_drv_bus_clk",      gcc_ce2_axi_clk.c,     "qseecom"),
 	CLK_LOOKUP("ce_drv_core_clk_src", ce2_clk_src.c,         "qseecom"),
 
+	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,         "mcd"),
+	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c,     "mcd"),
+	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,     "mcd"),
+	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,         "mcd"),
+
 	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,         "scm"),
 	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c,     "scm"),
 	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,     "scm"),
@@ -5538,6 +5593,67 @@
 	{&gcc_blsp2_qup6_i2c_apps_clk.c, &blsp2_qup6_i2c_apps_clk_src.c,},
 };
 
+/* v1 to v2 clock changes */
+static void __init msm8974_v2_clock_override(void)
+{
+	int i;
+
+	mmpll3_clk_src.c.rate =  930000000;
+	mmpll1_clk_src.c.rate = 1167000000;
+	mmpll1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 1167000000;
+
+	ocmemnoc_clk_src.freq_tbl = ftbl_ocmemnoc_v2_clk;
+	ocmemnoc_clk_src.c.fmax[VDD_DIG_NOMINAL] = 291750000;
+
+	axi_clk_src.freq_tbl = ftbl_mmss_axi_v2_clk;
+	axi_clk_src.c.fmax[VDD_DIG_NOMINAL] = 291750000;
+	axi_clk_src.c.fmax[VDD_DIG_HIGH] = 466800000;
+
+	vcodec0_clk_src.freq_tbl = ftbl_venus0_vcodec0_v2_clk;
+	vcodec0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+
+	mdp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 240000000;
+
+	/* The parent of each of the QUP I2C clocks is an RCG on V2 */
+	for (i = 0; i < ARRAY_SIZE(qup_i2c_clks); i++)
+		qup_i2c_clks[i][0]->parent =  qup_i2c_clks[i][1];
+}
+
+/* v2 to v3 clock changes */
+static void __init msm8974_v3_clock_override(void)
+{
+	ce1_clk_src.c.fmax[VDD_DIG_LOW] = 75000000;
+	ce1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 150000000;
+	ce1_clk_src.freq_tbl = ftbl_gcc_ce1_v3_clk;
+	ce2_clk_src.c.fmax[VDD_DIG_LOW] = 75000000;
+	ce2_clk_src.c.fmax[VDD_DIG_NOMINAL] = 150000000;
+	ce2_clk_src.freq_tbl = ftbl_gcc_ce2_v3_clk;
+
+	sdcc1_apps_clk_src.c.fmax[VDD_DIG_LOW] = 200000000;
+	sdcc1_apps_clk_src.c.fmax[VDD_DIG_NOMINAL] = 400000000;
+
+	vfe0_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
+	vfe0_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
+	vfe0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+	vfe1_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
+	vfe1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
+	vfe1_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+	cpp_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
+	cpp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
+	cpp_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+
+	mdp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 266670000;
+
+	mclk0_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
+	mclk1_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
+	mclk2_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
+	mclk3_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
+	mclk0_clk_src.set_rate = set_rate_mnd;
+	mclk1_clk_src.set_rate = set_rate_mnd;
+	mclk2_clk_src.set_rate = set_rate_mnd;
+	mclk3_clk_src.set_rate = set_rate_mnd;
+}
+
 static void __init msm8974_clock_pre_init(void)
 {
 	virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
@@ -5566,30 +5682,11 @@
 
 	reg_init();
 
-	/* v2 specific changes */
-	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
-		int i;
-
-		mmpll3_clk_src.c.rate =  930000000;
-		mmpll1_clk_src.c.rate = 1167000000;
-		mmpll1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 1167000000;
-
-		ocmemnoc_clk_src.freq_tbl = ftbl_ocmemnoc_v2_clk;
-		ocmemnoc_clk_src.c.fmax[VDD_DIG_NOMINAL] = 291750000;
-
-		axi_clk_src.freq_tbl = ftbl_mmss_axi_v2_clk;
-		axi_clk_src.c.fmax[VDD_DIG_NOMINAL] = 291750000;
-		axi_clk_src.c.fmax[VDD_DIG_HIGH] = 466800000;
-
-		vcodec0_clk_src.freq_tbl = ftbl_venus0_vcodec0_v2_clk;
-		vcodec0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
-
-		mdp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 240000000;
-
-		/* The parent of each of the QUP I2C clocks is an RCG on V2 */
-		for (i = 0; i < ARRAY_SIZE(qup_i2c_clks); i++)
-			qup_i2c_clks[i][0]->parent =  qup_i2c_clks[i][1];
-	}
+	/* version specific changes */
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
+		msm8974_v2_clock_override();
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 3)
+		msm8974_v3_clock_override();
 
 	clk_ops_pixel_clock = clk_ops_pixel;
 	clk_ops_pixel_clock.set_rate = set_rate_pixel;
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index facd6ba..70cd640 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -1997,12 +1997,6 @@
 	regval = readl_relaxed(GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
 	regval |= BIT(0);
 	writel_relaxed(regval, GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
-
-	/*
-	 * TODO: Confirm that no clocks need to be voted on in this sleep vote
-	 * register.
-	 */
-	writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
 }
 
 static void __init msm9625_clock_post_init(void)
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 6840f1c..5d25134 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -65,6 +65,75 @@
 #endif
 	bx	lr
 #endif
+ENTRY(msm_pm_pc_hotplug)
+	stmfd	sp!, {lr}
+#if defined(CONFIG_MSM_FIQ_SUPPORT)
+	cpsid   f
+#endif
+
+#if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
+	bl      msm_jtag_save_state
+#endif
+	mov	r1, #0
+	mcr	p15, 2, r1, c0, c0, 0 /*CCSELR*/
+	isb
+	mrc	p15, 1, r1, c0, c0, 0 /*CCSIDR*/
+	mov	r2, #1
+	and	r1, r2, r1, ASR #30 /* Check if the cache is write back */
+	cmp	r1, #1
+	bleq	v7_flush_kern_cache_all
+
+	mrc	p15, 0, r0, c0, c0, 5	/* MPIDR */
+	and	r0, r0, #15		/* what CPU am I */
+
+	ldr	r1, =msm_pc_debug_counters /*load the IMEM debug location */
+	ldr	r1, [r1]
+	cmp	r1, #0
+	beq	skip_hp_debug1
+	add	r1, r1, r0, LSL #4	/* debug location for this CPU */
+	ldr	r2, [r1]
+	add	r2, #1
+	str	r2, [r1]
+skip_hp_debug1:
+
+#ifdef CONFIG_MSM_SCM
+	ldr	r0, =SCM_SVC_BOOT
+	ldr	r1, =SCM_CMD_TERMINATE_PC
+	mov	r2, #0
+	bl	scm_call_atomic1
+#else
+	mrc     p15, 0, r3, c1, c0, 0    /* read current CR    */
+	bic     r0, r3, #(1 << 2)        /* clear dcache bit   */
+	bic     r0, r0, #(1 << 12)       /* clear icache bit   */
+	mcr     p15, 0, r0, c1, c0, 0    /* disable d/i cache  */
+	isb
+	wfi
+	mcr     p15, 0, r3, c1, c0, 0    /* restore d/i cache  */
+	isb
+#endif
+
+#if defined(CONFIG_MSM_FIQ_SUPPORT)
+	cpsie   f
+#endif
+	mrc	p15, 0, r0, c0, c0, 5 /* MPIDR */
+	and	r0, r0, #15              /* what CPU am I                  */
+
+	ldr	r1, =msm_pc_debug_counters /*load the IMEM debug location */
+	ldr	r1, [r1]
+	cmp	r1, #0
+	beq	skip_hp_debug2
+	add	r1, r1, r0, LSL #4	/* debug location for this CPU */
+	add	r1, #8
+	ldr	r2, [r1]
+	add	r2, #1
+	str	r2, [r1]
+skip_hp_debug2:
+#if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
+	bl	msm_jtag_restore_state
+#endif
+	mov     r0, #0                   /* return power collapse failed */
+	ldmfd	sp!, {lr}
+	bx      lr
 
 ENTRY(msm_pm_collapse)
 #if defined(CONFIG_MSM_FIQ_SUPPORT)
diff --git a/arch/arm/mach-msm/idle.h b/arch/arm/mach-msm/idle.h
index ead86a1..72f1a03 100644
--- a/arch/arm/mach-msm/idle.h
+++ b/arch/arm/mach-msm/idle.h
@@ -26,6 +26,7 @@
 
 int msm_arch_idle(void);
 int msm_pm_collapse(void);
+int msm_pm_pc_hotplug(void);
 void msm_pm_collapse_exit(void);
 extern void *msm_saved_state;
 extern void (*msm_pm_disable_l2_fn)(void);
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 68cfb2e..eeda7ce 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -188,21 +188,31 @@
 	int attach_count;
 };
 
-struct msm_iommu_context_regs {
-	uint32_t far;
-	uint32_t par;
-	uint32_t fsr;
-	uint32_t fsynr0;
-	uint32_t fsynr1;
-	uint32_t ttbr0;
-	uint32_t ttbr1;
-	uint32_t sctlr;
-	uint32_t actlr;
-	uint32_t prrr;
-	uint32_t nmrr;
+enum dump_reg {
+	DUMP_REG_FAR0,
+	DUMP_REG_FAR1,
+	DUMP_REG_PAR0,
+	DUMP_REG_PAR1,
+	DUMP_REG_FSR,
+	DUMP_REG_FSYNR0,
+	DUMP_REG_FSYNR1,
+	DUMP_REG_TTBR0,
+	DUMP_REG_TTBR1,
+	DUMP_REG_SCTLR,
+	DUMP_REG_ACTLR,
+	DUMP_REG_PRRR,
+	DUMP_REG_NMRR,
+	MAX_DUMP_REGS,
 };
 
-void print_ctx_regs(struct msm_iommu_context_regs *regs);
+#define COMBINE_DUMP_REG(upper, lower) (((u64) upper << 32) | lower)
+
+struct msm_iommu_context_reg {
+	uint32_t val;
+	bool valid;
+};
+
+void print_ctx_regs(struct msm_iommu_context_reg regs[]);
 
 /*
  * Interrupt handler for the IOMMU context fault interrupt. Hooking the
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
index ac3e912..327c1ea 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
@@ -38,8 +38,8 @@
 #define MSM8226_MPM2_PSHOLD_SIZE	SZ_4K
 
 #ifdef CONFIG_DEBUG_MSM8226_UART
-#define MSM_DEBUG_UART_BASE	IOMEM(0xFA71E000)
-#define MSM_DEBUG_UART_PHYS	0xF991E000
+#define MSM_DEBUG_UART_BASE	IOMEM(0xFA71F000)
+#define MSM_DEBUG_UART_PHYS	0xF991F000
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 56eaa2b..9ec8395 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -192,8 +192,6 @@
 
 static uint32_t next_port_id;
 static DEFINE_MUTEX(next_port_id_lock_lha1);
-static atomic_t pending_close_count = ATOMIC_INIT(0);
-static wait_queue_head_t subsystem_restart_wait;
 static struct workqueue_struct *msm_ipc_router_workqueue;
 
 enum {
@@ -2882,10 +2880,7 @@
 
 	msm_ipc_cleanup_routing_table(xprt_work->xprt->priv);
 	msm_ipc_router_remove_xprt(xprt_work->xprt);
-
-	if (atomic_dec_return(&pending_close_count) == 0)
-		wake_up(&subsystem_restart_wait);
-
+	xprt_work->xprt->sft_close_done(xprt_work->xprt);
 	kfree(xprt_work);
 }
 
@@ -2924,7 +2919,6 @@
 
 	case IPC_ROUTER_XPRT_EVENT_CLOSE:
 		D("close event for '%s'\n", xprt->name);
-		atomic_inc(&pending_close_count);
 		xprt_work = kmalloc(sizeof(struct msm_ipc_router_xprt_work),
 				GFP_ATOMIC);
 		if (xprt_work) {
@@ -2957,45 +2951,6 @@
 	queue_work(xprt_info->workqueue, &xprt_info->read_data);
 }
 
-static int modem_restart_notifier_cb(struct notifier_block *this,
-				unsigned long code,
-				void *data);
-static struct notifier_block msm_ipc_router_nb = {
-	.notifier_call = modem_restart_notifier_cb,
-};
-
-static int modem_restart_notifier_cb(struct notifier_block *this,
-				unsigned long code,
-				void *data)
-{
-	switch (code) {
-	case SUBSYS_BEFORE_SHUTDOWN:
-		D("%s: SUBSYS_BEFORE_SHUTDOWN\n", __func__);
-		break;
-
-	case SUBSYS_BEFORE_POWERUP:
-		D("%s: waiting for RPC restart to complete\n", __func__);
-		wait_event(subsystem_restart_wait,
-			atomic_read(&pending_close_count) == 0);
-		D("%s: finished restart wait\n", __func__);
-		break;
-
-	default:
-		break;
-	}
-
-	return NOTIFY_DONE;
-}
-
-static void *restart_notifier_handle;
-static __init int msm_ipc_router_modem_restart_late_init(void)
-{
-	restart_notifier_handle = subsys_notif_register_notifier("modem",
-							&msm_ipc_router_nb);
-	return 0;
-}
-late_initcall(msm_ipc_router_modem_restart_late_init);
-
 static int __init msm_ipc_router_init(void)
 {
 	int i, ret;
@@ -3030,7 +2985,6 @@
 	}
 	up_write(&routing_table_lock_lha3);
 
-	init_waitqueue_head(&subsystem_restart_wait);
 	ret = msm_ipc_router_init_sockets();
 	if (ret < 0)
 		pr_err("%s: Init sockets failed\n", __func__);
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index 32832dd..55aeade 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -122,6 +122,7 @@
 	int (*write)(void *data, uint32_t len,
 		     struct msm_ipc_router_xprt *xprt);
 	int (*close)(struct msm_ipc_router_xprt *xprt);
+	void (*sft_close_done)(struct msm_ipc_router_xprt *xprt);
 };
 
 void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt,
diff --git a/arch/arm/mach-msm/ipc_router_smd_xprt.c b/arch/arm/mach-msm/ipc_router_smd_xprt.c
index b2ec816..d6a3e03 100644
--- a/arch/arm/mach-msm/ipc_router_smd_xprt.c
+++ b/arch/arm/mach-msm/ipc_router_smd_xprt.c
@@ -54,6 +54,7 @@
 	spinlock_t ss_reset_lock;	/*Subsystem reset lock*/
 	int ss_reset;
 	void *pil;
+	struct completion sft_close_complete;
 };
 
 struct msm_ipc_router_smd_xprt_work {
@@ -217,6 +218,14 @@
 	return rc;
 }
 
+static void smd_xprt_sft_close_done(struct msm_ipc_router_xprt *xprt)
+{
+	struct msm_ipc_router_smd_xprt *smd_xprtp =
+		container_of(xprt, struct msm_ipc_router_smd_xprt, xprt);
+
+	complete_all(&smd_xprtp->sft_close_complete);
+}
+
 static void smd_xprt_read_data(struct work_struct *work)
 {
 	int pkt_size, sz_read, sz;
@@ -322,7 +331,14 @@
 {
 	struct msm_ipc_router_smd_xprt_work *xprt_work =
 		container_of(work, struct msm_ipc_router_smd_xprt_work, work);
+	struct msm_ipc_router_smd_xprt *smd_xprtp =
+		container_of(xprt_work->xprt,
+			     struct msm_ipc_router_smd_xprt, xprt);
+	unsigned long flags;
 
+	spin_lock_irqsave(&smd_xprtp->ss_reset_lock, flags);
+	smd_xprtp->ss_reset = 0;
+	spin_unlock_irqrestore(&smd_xprtp->ss_reset_lock, flags);
 	msm_ipc_router_xprt_notify(xprt_work->xprt,
 				IPC_ROUTER_XPRT_EVENT_OPEN, NULL);
 	D("%s: Notified IPC Router of %s OPEN\n",
@@ -334,11 +350,16 @@
 {
 	struct msm_ipc_router_smd_xprt_work *xprt_work =
 		container_of(work, struct msm_ipc_router_smd_xprt_work, work);
+	struct msm_ipc_router_smd_xprt *smd_xprtp =
+		container_of(xprt_work->xprt,
+			     struct msm_ipc_router_smd_xprt, xprt);
 
+	init_completion(&smd_xprtp->sft_close_complete);
 	msm_ipc_router_xprt_notify(xprt_work->xprt,
 				IPC_ROUTER_XPRT_EVENT_CLOSE, NULL);
 	D("%s: Notified IPC Router of %s CLOSE\n",
 	   __func__, xprt_work->xprt->name);
+	wait_for_completion(&smd_xprtp->sft_close_complete);
 	kfree(xprt_work);
 }
 
@@ -362,9 +383,6 @@
 		break;
 
 	case SMD_EVENT_OPEN:
-		spin_lock_irqsave(&smd_xprtp->ss_reset_lock, flags);
-		smd_xprtp->ss_reset = 0;
-		spin_unlock_irqrestore(&smd_xprtp->ss_reset_lock, flags);
 		xprt_work = kmalloc(sizeof(struct msm_ipc_router_smd_xprt_work),
 				    GFP_ATOMIC);
 		if (!xprt_work) {
@@ -441,6 +459,7 @@
 		msm_ipc_router_smd_remote_write_avail;
 	smd_remote_xprt[id].xprt.write = msm_ipc_router_smd_remote_write;
 	smd_remote_xprt[id].xprt.close = msm_ipc_router_smd_remote_close;
+	smd_remote_xprt[id].xprt.sft_close_done = smd_xprt_sft_close_done;
 	smd_remote_xprt[id].xprt.priv = NULL;
 
 	init_waitqueue_head(&smd_remote_xprt[id].write_avail_wait_q);
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 475e8a1..c572291 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -113,6 +113,7 @@
  * @region_end: address where relocatable region ends or highest address for
  * non-relocatable images
  * @region: region allocated for relocatable images
+ * @unvoted_flag: flag to keep track if we have unvoted or not.
  *
  * This struct contains data for a pil_desc that should not be exposed outside
  * of this file. This structure points to the descriptor and the descriptor
@@ -132,6 +133,7 @@
 	struct ion_handle *region;
 	struct pil_image_info __iomem *info;
 	int id;
+	int unvoted_flag;
 };
 
 /**
@@ -184,15 +186,21 @@
 }
 EXPORT_SYMBOL(pil_get_entry_addr);
 
-static void pil_proxy_work(struct work_struct *work)
+static void __pil_proxy_unvote(struct pil_priv *priv)
 {
-	struct delayed_work *delayed = to_delayed_work(work);
-	struct pil_priv *priv = container_of(delayed, struct pil_priv, proxy);
 	struct pil_desc *desc = priv->desc;
 
 	desc->ops->proxy_unvote(desc);
 	wake_unlock(&priv->wlock);
 	module_put(desc->owner);
+
+}
+
+static void pil_proxy_unvote_work(struct work_struct *work)
+{
+	struct delayed_work *delayed = to_delayed_work(work);
+	struct pil_priv *priv = container_of(delayed, struct pil_priv, proxy);
+	__pil_proxy_unvote(priv);
 }
 
 static int pil_proxy_vote(struct pil_desc *desc)
@@ -206,6 +214,10 @@
 		if (ret)
 			wake_unlock(&priv->wlock);
 	}
+
+	if (desc->proxy_unvote_irq)
+		enable_irq(desc->proxy_unvote_irq);
+
 	return ret;
 }
 
@@ -237,8 +249,13 @@
 static irqreturn_t proxy_unvote_intr_handler(int irq, void *dev_id)
 {
 	struct pil_desc *desc = dev_id;
+	struct pil_priv *priv = desc->priv;
 
-	schedule_delayed_work(&desc->priv->proxy, 0);
+	if (!desc->priv->unvoted_flag) {
+		desc->priv->unvoted_flag = 1;
+		__pil_proxy_unvote(priv);
+	}
+
 	return IRQ_HANDLED;
 }
 
@@ -651,6 +668,7 @@
 			goto release_fw;
 	}
 
+	desc->priv->unvoted_flag = 0;
 	ret = pil_proxy_vote(desc);
 	if (ret) {
 		pil_err(desc, "Failed to proxy vote\n");
@@ -687,10 +705,19 @@
 void pil_shutdown(struct pil_desc *desc)
 {
 	struct pil_priv *priv = desc->priv;
+
 	if (desc->ops->shutdown)
 		desc->ops->shutdown(desc);
-	if (proxy_timeout_ms == 0 && desc->ops->proxy_unvote)
-		desc->ops->proxy_unvote(desc);
+
+	if (desc->proxy_unvote_irq) {
+		disable_irq(desc->proxy_unvote_irq);
+		if (!desc->priv->unvoted_flag)
+			pil_proxy_unvote(desc, 1);
+		return;
+	}
+
+	if (!proxy_timeout_ms)
+		pil_proxy_unvote(desc, 1);
 	else
 		flush_delayed_work(&priv->proxy);
 }
@@ -741,7 +768,8 @@
 	__iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4);
 
 	if (desc->proxy_unvote_irq > 0) {
-		ret = request_irq(desc->proxy_unvote_irq,
+		ret = request_threaded_irq(desc->proxy_unvote_irq,
+				  NULL,
 				  proxy_unvote_intr_handler,
 				  IRQF_TRIGGER_RISING|IRQF_SHARED,
 				  desc->name, desc);
@@ -751,11 +779,12 @@
 				ret);
 			goto err;
 		}
+		disable_irq(desc->proxy_unvote_irq);
 	}
 
 	snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name);
 	wake_lock_init(&priv->wlock, WAKE_LOCK_SUSPEND, priv->wname);
-	INIT_DELAYED_WORK(&priv->proxy, pil_proxy_work);
+	INIT_DELAYED_WORK(&priv->proxy, pil_proxy_unvote_work);
 	INIT_LIST_HEAD(&priv->segs);
 
 	return 0;
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 8cf6011..b83202b 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -628,15 +628,8 @@
 	if (ret)
 		return ret;
 	ret = pil_boot(&drv->desc);
-	if (ret) {
+	if (ret)
 		pil_shutdown(&drv->q6->desc);
-		/*
-		 * We know now that the unvote interrupt is not coming.
-		 * Remove the proxy votes immediately.
-		 */
-		if (drv->q6->desc.proxy_unvote_irq)
-			pil_q6v5_mss_remove_proxy_votes(&drv->q6->desc);
-	}
 	return ret;
 }
 
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index a054077..6799cbf 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/debugfs.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -480,6 +481,7 @@
 	void *entry;
 	bool collapsed = 0;
 	int ret;
+	bool save_cpu_regs = !cpu || from_idle;
 
 	if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
 		pr_info("CPU%u: %s: notify_rpm %d\n",
@@ -492,8 +494,8 @@
 			MSM_SPM_MODE_POWER_COLLAPSE, notify_rpm);
 	WARN_ON(ret);
 
-	entry = (!cpu || from_idle) ?
-		msm_pm_collapse_exit : msm_secondary_startup;
+	entry = save_cpu_regs ?  msm_pm_collapse_exit : msm_secondary_startup;
+
 	msm_pm_boot_config_before_pc(cpu, virt_to_phys(entry));
 
 	if (MSM_PM_DEBUG_RESET_VECTOR & msm_pm_debug_mask)
@@ -502,7 +504,7 @@
 	if (from_idle && msm_pm_pc_reset_timer)
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
-	collapsed = msm_pm_collapse();
+	collapsed = save_cpu_regs ? msm_pm_collapse() : msm_pm_pc_hotplug();
 
 	if (from_idle && msm_pm_pc_reset_timer)
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
@@ -1290,6 +1292,7 @@
 	pmd_t *pmd;
 	unsigned long pmdval;
 	unsigned long exit_phys;
+	dma_addr_t temp_phys;
 
 	/* Page table for cores to come back up safely. */
 	pc_pgd = pgd_alloc(&init_mm);
@@ -1305,17 +1308,21 @@
 	pmd[0] = __pmd(pmdval);
 	pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
 
-	msm_saved_state_phys =
-		allocate_contiguous_ebi_nomap(CPU_SAVED_STATE_SIZE *
-					      num_possible_cpus(), 4);
-	if (!msm_saved_state_phys)
-		return -ENOMEM;
-	msm_saved_state = ioremap_nocache(msm_saved_state_phys,
-					  CPU_SAVED_STATE_SIZE *
-					  num_possible_cpus());
+	msm_saved_state = dma_zalloc_coherent(NULL, CPU_SAVED_STATE_SIZE *
+						num_possible_cpus(),
+						&temp_phys, 0);
+
 	if (!msm_saved_state)
 		return -ENOMEM;
 
+	/*
+	 * Explicitly cast here since msm_saved_state_phys is defined
+	 * in assembly and we want to avoid any kind of truncation
+	 * or endian problems.
+	 */
+	msm_saved_state_phys = (unsigned long)temp_phys;
+
+
 	/* It is remotely possible that the code in msm_pm_collapse_exit()
 	 * which turns on the MMU with this mapping is in the
 	 * next even-numbered megabyte beyond the
@@ -1330,7 +1337,7 @@
 
 	return 0;
 }
-core_initcall(msm_pm_setup_saved_state);
+arch_initcall(msm_pm_setup_saved_state);
 
 static void setup_broadcast_timer(void *arg)
 {
diff --git a/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c b/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c
index 4610b97..4681437 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c
@@ -176,7 +176,11 @@
 	atomic_add(payload[9], &audio->in_samples);
 
 	spin_lock_irqsave(&audio->dsp_lock, flags);
-	BUG_ON(list_empty(&audio->in_queue));
+	if (list_empty(&audio->in_queue)) {
+		spin_unlock_irqrestore(&audio->dsp_lock, flags);
+		pr_warning("%s unexpected ack from dsp\n", __func__);
+		return;
+	}
 	filled_buf = list_first_entry(&audio->in_queue,
 					struct audio_aio_buffer_node, list);
 
diff --git a/arch/arm/mach-msm/rpm_rbcpr_stats_v2.c b/arch/arm/mach-msm/rpm_rbcpr_stats_v2.c
new file mode 100644
index 0000000..8f0ccd4
--- /dev/null
+++ b/arch/arm/mach-msm/rpm_rbcpr_stats_v2.c
@@ -0,0 +1,430 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/sort.h>
+#include <asm/uaccess.h>
+#include <mach/msm_iomap.h>
+
+#define RBCPR_BUF_LEN 8000
+#define RBCPR_STATS_MAX_SIZE SZ_2K
+#define RBCPR_MAX_RAILS 4
+#define RBCPR_NUM_RECMNDS 3
+#define RBCPR_NUM_CORNERS 3
+
+#define FIELD(a)     ((strnstr(#a, "->", 80) + 2))
+#define PRINT(buf, pos, format, ...) \
+	((pos < RBCPR_BUF_LEN) ? snprintf((buf + pos), (RBCPR_BUF_LEN - pos),\
+	format, ## __VA_ARGS__) : 0)
+
+enum {
+	CORNER_OFF,
+	CORNER_SVS,
+	CORNER_NOMINAL,
+	CORNER_TURBO,
+	CORNER_MAX,
+};
+
+struct rbcpr_recmnd_data_type {
+	uint32_t microvolts;
+	uint64_t timestamp;
+};
+
+struct rbcpr_corners_data_type {
+	uint32_t efuse_adjustment;
+	uint32_t programmed_voltage;
+	uint32_t isr_count;
+	uint32_t min_count;
+	uint32_t max_count;
+	struct rbcpr_recmnd_data_type rbcpr_recmnd[RBCPR_NUM_RECMNDS];
+};
+
+struct rbcpr_rail_stats_type {
+	uint32_t num_corners;
+	uint32_t num_latest_recommends;
+	struct rbcpr_corners_data_type rbcpr_corners[RBCPR_NUM_CORNERS];
+	uint32_t current_corner;
+	uint32_t railway_voltage;
+	uint32_t off_corner;
+	uint32_t margin;
+};
+
+struct rbcpr_stats_type {
+	uint32_t num_rails;
+	uint32_t status;
+	struct rbcpr_rail_stats_type *rbcpr_rail;
+};
+
+struct rbcpr_data_type {
+	void __iomem *start;
+	uint32_t len;
+	char buf[RBCPR_BUF_LEN];
+};
+
+static char *rbcpr_rail_labels[] = {
+	[0] = "VDD-CX",
+	[1] = "VDD-GFX",
+};
+
+static char *rbcpr_corner_string[] = {
+	[CORNER_OFF] = "CORNERS_OFF",
+	[CORNER_SVS] = "SVS",
+	[CORNER_NOMINAL] = "NOMINAL",
+	[CORNER_TURBO] = "TURBO",
+};
+#define CORNER_STRING(a)	\
+	((a >= CORNER_MAX) ? "INVALID Corner" : rbcpr_corner_string[a])
+
+static struct rbcpr_data_type *rbcpr_data;
+static struct rbcpr_stats_type *rbcpr_stats;
+
+static void msm_rpmrbcpr_read_rpm_data(void)
+{
+	uint32_t start_offset;
+	uint32_t stats_size;
+
+	start_offset = offsetof(struct rbcpr_stats_type, rbcpr_rail);
+	stats_size =
+		rbcpr_stats->num_rails * sizeof(struct rbcpr_rail_stats_type);
+
+	if (stats_size > RBCPR_STATS_MAX_SIZE) {
+		pr_err("%s: Max copy size exceeded. stats size %d max %d",
+			__func__, stats_size, RBCPR_STATS_MAX_SIZE);
+		return;
+	}
+
+	memcpy_fromio(rbcpr_stats->rbcpr_rail,
+		(rbcpr_data->start + start_offset), stats_size);
+}
+
+static uint32_t msm_rpmrbcpr_print_data(void)
+{
+	uint32_t pos = 0;
+	uint32_t i, j, k;
+	struct rbcpr_rail_stats_type *rail;
+	struct rbcpr_corners_data_type *corner;
+	struct rbcpr_recmnd_data_type *rbcpr_recmnd;
+	char *buf = rbcpr_data->buf;
+
+	pos += PRINT(buf, pos, ":RBCPR STATS\n");
+	pos += PRINT(buf, pos, "(%s: %d)", FIELD(rbcpr_stats->num_rails),
+				rbcpr_stats->num_rails);
+	pos += PRINT(buf, pos, "(%s: %d)\n", FIELD(rbcpr_stats->status),
+				rbcpr_stats->status);
+
+
+	for (i = 0; i < rbcpr_stats->num_rails; i++) {
+		rail = &rbcpr_stats->rbcpr_rail[i];
+		pos += PRINT(buf, pos, ":%s Rail Data\n", rbcpr_rail_labels[i]);
+		pos += PRINT(buf, pos, "(%s: %s)",
+			FIELD(rail->current_corner),
+			CORNER_STRING(rail->current_corner));
+		pos += PRINT(buf, pos, "(%s: %d)",
+			FIELD(rail->railway_voltage), rail->railway_voltage);
+		pos += PRINT(buf, pos, "(%s: %d)",
+			FIELD(rail->off_corner), rail->off_corner);
+		pos += PRINT(buf, pos, "(%s: %d)\n",
+			FIELD(rail->margin), rail->margin);
+
+		for (j = 0; j < RBCPR_NUM_CORNERS; j++) {
+			pos += PRINT(buf, pos, "\t\tCorner Data:%s ",
+							CORNER_STRING(j + 1));
+			corner = &rail->rbcpr_corners[j];
+			pos += PRINT(buf, pos, "(%s: %d)",
+				FIELD(corner->efuse_adjustment),
+						corner->efuse_adjustment);
+			pos += PRINT(buf, pos, "(%s: %d)",
+				FIELD(corner->programmed_voltage),
+						corner->programmed_voltage);
+			pos += PRINT(buf, pos, "(%s: %d)",
+				FIELD(corner->isr_count), corner->isr_count);
+			pos += PRINT(buf, pos, "(%s: %d)",
+				FIELD(corner->min_count), corner->min_count);
+			pos += PRINT(buf, pos, "(%s: %d)\n",
+				FIELD(corner->max_count), corner->max_count);
+
+
+			for (k = 0; k < RBCPR_NUM_RECMNDS; k++) {
+				rbcpr_recmnd = &corner->rbcpr_recmnd[k];
+				pos += PRINT(buf, pos,
+					"\t\t\t\tVoltage History[%d] ", k);
+				pos += PRINT(buf, pos, " (%s: %d) ",
+					FIELD(rbcpr_recmd->microvolts),
+						rbcpr_recmnd->microvolts);
+				pos += PRINT(buf, pos, " (%s: %lld)\n",
+					FIELD(rbcpr_recmd->timestamp),
+						rbcpr_recmnd->timestamp);
+			}
+		}
+	}
+
+	return pos;
+}
+
+
+static int msm_rpmrbcpr_file_read(struct file *file, char __user *bufu,
+					size_t count, loff_t *ppos)
+{
+	struct rbcpr_data_type *pdata = file->private_data;
+	int ret = 0;
+	int status_counter;
+	static DEFINE_MUTEX(rbcpr_lock);
+
+	mutex_lock(&rbcpr_lock);
+	if (!pdata) {
+		pr_err("%s pdata is null", __func__);
+		ret = -EINVAL;
+		goto exit_rpmrbcpr_file_read;
+	}
+
+	if (!bufu || count < 0) {
+		pr_err("%s count %d ", __func__, count);
+		ret = -EINVAL;
+		goto exit_rpmrbcpr_file_read;
+	}
+
+	if (*ppos > pdata->len || !*ppos) {
+		/* Read RPM stats */
+		status_counter = readl_relaxed(pdata->start +
+			offsetof(struct rbcpr_stats_type, status));
+		if (status_counter != rbcpr_stats->status) {
+			msm_rpmrbcpr_read_rpm_data();
+			rbcpr_stats->status = status_counter;
+		}
+		pdata->len = msm_rpmrbcpr_print_data();
+		*ppos = 0;
+	}
+
+	/* copy to user data*/
+	ret = simple_read_from_buffer(bufu, count, ppos, pdata->buf,
+					pdata->len);
+exit_rpmrbcpr_file_read:
+	mutex_unlock(&rbcpr_lock);
+	return ret;
+}
+
+static int msm_rpmrbcpr_file_open(struct inode *inode, struct file *file)
+{
+	file->private_data = rbcpr_data;
+
+	if (!rbcpr_data->start)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int msm_rpmrbcpr_file_close(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static const struct file_operations msm_rpmrbcpr_fops = {
+	.owner    = THIS_MODULE,
+	.open     = msm_rpmrbcpr_file_open,
+	.read     = msm_rpmrbcpr_file_read,
+	.release  = msm_rpmrbcpr_file_close,
+	.llseek   = no_llseek,
+};
+
+static int msm_rpmrbcpr_memalloc(struct platform_device *pdev)
+{
+	void *addr = NULL;
+	int ret = 0;
+	uint32_t num_latest_recommends = 0;
+	uint32_t num_corners = 0;
+
+	rbcpr_stats->num_rails = readl_relaxed(rbcpr_data->start);
+
+	if (rbcpr_stats->num_rails > RBCPR_MAX_RAILS) {
+		pr_err("%s: Invalid number of RPM RBCPR rails %d",
+				__func__, rbcpr_stats->num_rails);
+		rbcpr_stats->num_rails = 0;
+		ret = -EFAULT;
+		goto rbcpr_memalloc_fail;
+	}
+
+	rbcpr_stats->rbcpr_rail =
+		devm_kzalloc(&pdev->dev,
+			sizeof(struct rbcpr_rail_stats_type) *
+			rbcpr_stats->num_rails, GFP_KERNEL);
+
+	if (!rbcpr_stats->rbcpr_rail) {
+		ret = -ENOMEM;
+		goto rbcpr_memalloc_fail;
+	}
+
+	addr = rbcpr_data->start + offsetof(struct rbcpr_stats_type,
+								rbcpr_rail);
+
+	/* Each rail has the same number of corners and number of latest
+	   recommended values. Read these from the first rail and check them
+	   to make sure the values are valid. (RPM doesn't 0 initialize this
+	   memory region, so its possible we end up with bogus values if the
+	   rbcpr driver is not initialized.).
+	*/
+	num_corners = readl_relaxed(addr);
+	num_latest_recommends = readl_relaxed(addr +
+				offsetof(struct rbcpr_rail_stats_type,
+						num_latest_recommends));
+
+	if ((num_latest_recommends != RBCPR_NUM_RECMNDS)
+		|| (num_corners != RBCPR_NUM_CORNERS)) {
+		pr_err("%s: Invalid num corners %d, num recmnds %d",
+			__func__, num_corners, num_latest_recommends);
+		ret = -EFAULT;
+		goto rbcpr_memalloc_fail;
+	}
+
+rbcpr_memalloc_fail:
+	return ret;
+}
+
+static  int __devinit msm_rpmrbcpr_probe(struct platform_device *pdev)
+{
+	struct dentry *dent;
+	int ret = 0;
+	struct resource *res = NULL;
+	void __iomem *start_ptr = NULL;
+	uint32_t rbcpr_start_addr = 0;
+	char *key = NULL;
+	uint32_t start_addr;
+
+	rbcpr_data = devm_kzalloc(&pdev->dev,
+				sizeof(struct rbcpr_data_type), GFP_KERNEL);
+
+	if (!rbcpr_data)
+		return -ENOMEM;
+
+	rbcpr_stats = devm_kzalloc(&pdev->dev,
+				sizeof(struct rbcpr_stats_type), GFP_KERNEL);
+
+	if (!rbcpr_stats) {
+		pr_err("%s: Failed to allocate memory for RBCPR stats",
+						__func__);
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!res) {
+		pr_err("%s: Failed to get IO resource from platform device",
+				__func__);
+		ret = -ENXIO;
+		goto rbcpr_probe_fail;
+	}
+
+	key = "qcom,start-offset";
+	ret = of_property_read_u32(pdev->dev.of_node, key, &start_addr);
+
+	if (ret) {
+		pr_err("%s: Failed to get start offset", __func__);
+		goto rbcpr_probe_fail;
+	}
+
+	start_addr += res->start;
+	start_ptr = ioremap_nocache(start_addr, 4);
+
+	if (!start_ptr) {
+		pr_err("%s: Failed to remap RBCPR start pointer",
+					__func__);
+		goto rbcpr_probe_fail;
+	}
+
+	rbcpr_start_addr = res->start + readl_relaxed(start_ptr);
+
+	if ((rbcpr_start_addr > (res->end - RBCPR_STATS_MAX_SIZE)) ||
+			(rbcpr_start_addr < start_addr)) {
+		pr_err("%s: Invalid start address for rbcpr stats 0x%x",
+			__func__, rbcpr_start_addr);
+		goto rbcpr_probe_fail;
+	}
+
+	rbcpr_data->start = devm_ioremap_nocache(&pdev->dev, rbcpr_start_addr,
+							RBCPR_STATS_MAX_SIZE);
+
+	if (!rbcpr_data->start) {
+		pr_err("%s: Failed to remap RBCPR start address",
+				__func__);
+		goto rbcpr_probe_fail;
+	}
+
+	ret = msm_rpmrbcpr_memalloc(pdev);
+
+	if (ret)
+		goto rbcpr_probe_fail;
+
+	dent = debugfs_create_file("rpm_rbcpr", S_IRUGO, NULL,
+			pdev->dev.platform_data, &msm_rpmrbcpr_fops);
+
+	if (!dent) {
+		pr_err("%s: error debugfs_create_file failed\n", __func__);
+		ret = -ENOMEM;
+		goto rbcpr_probe_fail;
+	}
+
+	platform_set_drvdata(pdev, dent);
+rbcpr_probe_fail:
+	iounmap(start_ptr);
+	return ret;
+}
+
+static int __devexit msm_rpmrbcpr_remove(struct platform_device *pdev)
+{
+	struct dentry *dent;
+
+	dent = platform_get_drvdata(pdev);
+	debugfs_remove(dent);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct of_device_id rpmrbcpr_stats_table[] = {
+	{.compatible = "qcom,rpmrbcpr-stats"},
+	{},
+};
+
+static struct platform_driver msm_rpmrbcpr_driver = {
+	.probe  = msm_rpmrbcpr_probe,
+	.remove = __devexit_p(msm_rpmrbcpr_remove),
+	.driver = {
+		.name = "msm_rpmrbcpr_stats",
+		.owner = THIS_MODULE,
+		.of_match_table = rpmrbcpr_stats_table,
+	},
+};
+
+static int __init msm_rpmrbcpr_init(void)
+{
+	return platform_driver_register(&msm_rpmrbcpr_driver);
+}
+
+static void __exit msm_rpmrbcpr_exit(void)
+{
+	platform_driver_unregister(&msm_rpmrbcpr_driver);
+}
+
+module_init(msm_rpmrbcpr_init);
+module_exit(msm_rpmrbcpr_exit);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index e98fff2..83d94f1 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -87,7 +87,7 @@
 static inline int buf_get_pages(void *addr, int sz, int nr_pages, int access,
 				  struct smq_phy_page *pages, int nr_elems)
 {
-	struct vm_area_struct *vma;
+	struct vm_area_struct *vma, *vmaend;
 	uint32_t start = buf_page_start(addr);
 	uint32_t end = buf_page_start((void *)((uint32_t)addr + sz - 1));
 	uint32_t len = nr_pages << PAGE_SHIFT;
@@ -101,14 +101,14 @@
 	VERIFY(err, 0 != (vma = find_vma(current->mm, start)));
 	if (err)
 		goto bail;
-	VERIFY(err, ((uint32_t)addr + sz) <= vma->vm_end);
+	VERIFY(err, 0 != (vmaend = find_vma(current->mm, end)));
 	if (err)
 		goto bail;
 	n = 0;
 	VERIFY(err, 0 == follow_pfn(vma, start, &pfn));
 	if (err)
 		goto bail;
-	VERIFY(err, 0 == follow_pfn(vma, end, &pfnend));
+	VERIFY(err, 0 == follow_pfn(vmaend, end, &pfnend));
 	if (err)
 		goto bail;
 	VERIFY(err, (pfn + nr_pages - 1) == pfnend);
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index fa0e9d7..94c3554 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -118,6 +118,7 @@
 	if (i != DCI_CLIENT_INDEX_INVALID) {
 		/* copy pkt rsp in client buf */
 		entry = &(driver->dci_client_tbl[i]);
+		mutex_lock(&entry->data_mutex);
 		if (DCI_CHK_CAPACITY(entry, 8+write_len)) {
 			pr_alert("diag: create capacity for pkt rsp\n");
 			entry->total_capacity += 8+write_len;
@@ -125,6 +126,7 @@
 			entry->total_capacity, GFP_KERNEL);
 			if (!temp_buf) {
 				pr_err("diag: DCI realloc failed\n");
+				mutex_unlock(&entry->data_mutex);
 				return;
 			} else {
 				entry->dci_data = temp_buf;
@@ -139,6 +141,7 @@
 		memcpy(entry->dci_data+entry->data_len,
 			buf+4+cmd_code_len, write_len);
 		entry->data_len += write_len;
+		mutex_unlock(&entry->data_mutex);
 		/* delete immediate response entry */
 		if (smd_info->buf_in_1[8+cmd_code_len] != 0x80)
 			driver->req_tracking_tbl[index].pid = 0;
@@ -213,6 +216,7 @@
 				event_mask_ptr = entry->dci_event_mask +
 								 byte_index;
 				mutex_lock(&dci_health_mutex);
+				mutex_lock(&entry->data_mutex);
 				if (*event_mask_ptr & byte_mask) {
 					/* copy to client buffer */
 					if (DCI_CHK_CAPACITY(entry,
@@ -221,6 +225,8 @@
 						driver->dci_client_tbl[i].
 							dropped_events++;
 						mutex_unlock(
+							&entry->data_mutex);
+						mutex_unlock(
 							&dci_health_mutex);
 						break;
 					}
@@ -234,6 +240,7 @@
 						, total_event_len);
 					entry->data_len += 4 + total_event_len;
 				}
+				mutex_unlock(&entry->data_mutex);
 				mutex_unlock(&dci_health_mutex);
 			}
 		}
@@ -270,6 +277,7 @@
 				return;
 			log_mask_ptr = log_mask_ptr + byte_offset;
 			mutex_lock(&dci_health_mutex);
+			mutex_lock(&entry->data_mutex);
 			if (*log_mask_ptr & byte_mask) {
 				pr_debug("\t log code %x needed by client %d",
 					 log_code, entry->client->tgid);
@@ -280,6 +288,8 @@
 						driver->dci_client_tbl[i].
 								dropped_logs++;
 						mutex_unlock(
+							&entry->data_mutex);
+						mutex_unlock(
 							&dci_health_mutex);
 						return;
 				}
@@ -290,6 +300,7 @@
 					    buf + 4, *(uint16_t *)(buf + 2));
 				entry->data_len += 4 + *(uint16_t *)(buf + 2);
 			}
+			mutex_unlock(&entry->data_mutex);
 			mutex_unlock(&dci_health_mutex);
 		}
 	}
@@ -1214,8 +1225,10 @@
 	platform_driver_unregister(&msm_diag_dci_driver);
 
 	if (driver->dci_client_tbl) {
-		for (i = 0; i < MAX_DCI_CLIENTS; i++)
+		for (i = 0; i < MAX_DCI_CLIENTS; i++) {
 			kfree(driver->dci_client_tbl[i].dci_data);
+			mutex_destroy(&driver->dci_client_tbl[i].data_mutex);
+		}
 	}
 
 	if (driver->supports_separate_cmdrsp) {
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index d530de9..cc7f93d 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -61,6 +61,7 @@
 	int dropped_events;
 	int received_logs;
 	int received_events;
+	struct mutex data_mutex;
 };
 
 /* This is used for DCI health stats */
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 90a4154..71f3cb4 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -976,6 +976,8 @@
 				driver->dci_client_tbl[i].dropped_events = 0;
 				driver->dci_client_tbl[i].received_logs = 0;
 				driver->dci_client_tbl[i].received_events = 0;
+				mutex_init(&driver->dci_client_tbl[i].
+								data_mutex);
 				break;
 			}
 		}
@@ -1019,6 +1021,8 @@
 			driver->dci_client_tbl[result].client = NULL;
 			kfree(driver->dci_client_tbl[result].dci_data);
 			driver->dci_client_tbl[result].dci_data = NULL;
+			mutex_destroy(&driver->dci_client_tbl[result].
+								data_mutex);
 			driver->num_dci_client--;
 		}
 		mutex_unlock(&driver->dci_mutex);
@@ -1360,11 +1364,13 @@
 			entry = &(driver->dci_client_tbl[i]);
 			if (entry && entry->client) {
 				if (current->tgid == entry->client->tgid) {
+					mutex_lock(&entry->data_mutex);
 					COPY_USER_SPACE_OR_EXIT(buf+4,
 							entry->data_len, 4);
 					COPY_USER_SPACE_OR_EXIT(buf+8,
 					*(entry->dci_data), entry->data_len);
 					entry->data_len = 0;
+					mutex_unlock(&entry->data_mutex);
 					break;
 				}
 			}
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index 261af7d..369477f 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -24,6 +24,7 @@
 #include <linux/types.h>
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
+#include <mach/msm_bus.h>
 
 #define DRIVER_NAME "msm_rng"
 
@@ -47,6 +48,7 @@
 	struct platform_device *pdev;
 	void __iomem *base;
 	struct clk *prng_clk;
+	uint32_t qrng_perf_client;
 };
 
 static int msm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
@@ -77,7 +79,12 @@
 		dev_err(&pdev->dev, "failed to enable clock in callback\n");
 		return 0;
 	}
-
+	if (msm_rng_dev->qrng_perf_client) {
+		ret = msm_bus_scale_client_update_request(
+					msm_rng_dev->qrng_perf_client, 1);
+		if (ret)
+			pr_err("bus_scale_client_update_req failed!\n");
+	}
 	/* read random data from h/w */
 	do {
 		/* check status bit if data is available */
@@ -97,7 +104,9 @@
 		if ((maxsize - currsize) < 4)
 			break;
 	} while (currsize < maxsize);
-
+	if (msm_rng_dev->qrng_perf_client)
+		ret = msm_bus_scale_client_update_request(
+					msm_rng_dev->qrng_perf_client, 0);
 	/* vote to turn off clock */
 	clk_disable_unprepare(msm_rng_dev->prng_clk);
 
@@ -115,6 +124,12 @@
 	unsigned long reg_val = 0;
 	int ret = 0;
 
+	if (msm_rng_dev->qrng_perf_client) {
+		ret = msm_bus_scale_client_update_request(
+				msm_rng_dev->qrng_perf_client, 1);
+		if (ret)
+			pr_err("bus_scale_client_update_req failed!\n");
+	}
 	/* Enable the PRNG CLK */
 	ret = clk_prepare_enable(msm_rng_dev->prng_clk);
 	if (ret) {
@@ -145,8 +160,10 @@
 		*/
 		mb();
 	}
-
 	clk_disable_unprepare(msm_rng_dev->prng_clk);
+	if (msm_rng_dev->qrng_perf_client)
+		ret = msm_bus_scale_client_update_request(
+					msm_rng_dev->qrng_perf_client, 0);
 
 	return 0;
 }
@@ -157,6 +174,7 @@
 	struct msm_rng_device *msm_rng_dev = NULL;
 	void __iomem *base = NULL;
 	int error = 0;
+	struct msm_bus_scale_pdata *qrng_platform_support = NULL;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL) {
@@ -197,6 +215,15 @@
 	msm_rng_dev->pdev = pdev;
 	platform_set_drvdata(pdev, msm_rng_dev);
 
+	if (pdev->dev.of_node) {
+		/* Register bus client */
+		qrng_platform_support = msm_bus_cl_get_pdata(pdev);
+		msm_rng_dev->qrng_perf_client = msm_bus_scale_register_client(
+						qrng_platform_support);
+		if (!msm_rng_dev->qrng_perf_client)
+			pr_err("Unable to register bus client\n");
+	}
+
 	/* Enable rng h/w */
 	error = msm_rng_enable_hw(msm_rng_dev);
 
@@ -232,6 +259,8 @@
 	clk_put(msm_rng_dev->prng_clk);
 	iounmap(msm_rng_dev->base);
 	platform_set_drvdata(pdev, NULL);
+	if (msm_rng_dev->qrng_perf_client)
+		msm_bus_scale_unregister_client(msm_rng_dev->qrng_perf_client);
 	kfree(msm_rng_dev);
 	return 0;
 }
diff --git a/drivers/crypto/msm/qce.h b/drivers/crypto/msm/qce.h
index c14143f..afd5141 100644
--- a/drivers/crypto/msm/qce.h
+++ b/drivers/crypto/msm/qce.h
@@ -73,7 +73,6 @@
 	QCE_HASH_SHA1_HMAC   = 2,
 	QCE_HASH_SHA256_HMAC = 3,
 	QCE_HASH_AES_CMAC = 4,
-	QCE_AEAD_SHA1_HMAC = 5,
 	QCE_HASH_LAST
 };
 
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index bff9db5..eae16fa 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -372,6 +372,191 @@
 	return 0;
 }
 
+static struct qce_cmdlist_info *_ce_get_aead_cmdlistinfo(
+			struct qce_device *pce_dev, struct qce_req *creq)
+{
+	switch (creq->alg) {
+	case CIPHER_ALG_DES:
+		switch (creq->mode) {
+		case QCE_MODE_ECB:
+			return &pce_dev->ce_sps.
+				cmdlistptr.aead_hmac_sha1_ecb_des;
+			break;
+		case QCE_MODE_CBC:
+			return &pce_dev->ce_sps.
+				cmdlistptr.aead_hmac_sha1_cbc_des;
+			break;
+		default:
+			return NULL;
+		}
+		break;
+	case CIPHER_ALG_3DES:
+		switch (creq->mode) {
+		case QCE_MODE_ECB:
+			return &pce_dev->ce_sps.
+				cmdlistptr.aead_hmac_sha1_ecb_3des;
+			break;
+		case QCE_MODE_CBC:
+			return &pce_dev->ce_sps.
+				cmdlistptr.aead_hmac_sha1_cbc_3des;
+			break;
+		default:
+			return NULL;
+		}
+		break;
+	case CIPHER_ALG_AES:
+		switch (creq->mode) {
+		case QCE_MODE_ECB:
+			if (creq->encklen ==  AES128_KEY_SIZE)
+				return &pce_dev->ce_sps.
+					cmdlistptr.aead_hmac_sha1_ecb_aes_128;
+			else if (creq->encklen ==  AES256_KEY_SIZE)
+				return &pce_dev->ce_sps.
+					cmdlistptr.aead_hmac_sha1_ecb_aes_256;
+			else
+				return NULL;
+			break;
+		case QCE_MODE_CBC:
+			if (creq->encklen ==  AES128_KEY_SIZE)
+				return &pce_dev->ce_sps.
+					cmdlistptr.aead_hmac_sha1_cbc_aes_128;
+			else if (creq->encklen ==  AES256_KEY_SIZE)
+				return &pce_dev->ce_sps.
+					cmdlistptr.aead_hmac_sha1_cbc_aes_256;
+			else
+				return NULL;
+			break;
+		default:
+			return NULL;
+		}
+		break;
+
+	default:
+		return NULL;
+	}
+	return NULL;
+}
+
+static int _ce_setup_aead(struct qce_device *pce_dev, struct qce_req *q_req,
+		uint32_t totallen_in, uint32_t coffset,
+		struct qce_cmdlist_info *cmdlistinfo)
+{
+	int32_t authk_size_in_word = q_req->authklen/sizeof(uint32_t);
+	int i;
+	uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = {0};
+	struct sps_command_element *pce;
+	uint32_t a_cfg;
+	uint32_t enckey32[(MAX_CIPHER_KEY_SIZE*2)/sizeof(uint32_t)] = {0};
+	uint32_t enciv32[MAX_IV_LENGTH/sizeof(uint32_t)] = {0};
+	uint32_t enck_size_in_word = 0;
+	uint32_t enciv_in_word;
+	uint32_t key_size;
+	uint32_t encr_cfg = 0;
+	uint32_t ivsize = q_req->ivsize;
+
+	key_size = q_req->encklen;
+	enck_size_in_word = key_size/sizeof(uint32_t);
+
+	switch (q_req->alg) {
+	case CIPHER_ALG_DES:
+		enciv_in_word = 2;
+		break;
+	case CIPHER_ALG_3DES:
+		enciv_in_word = 2;
+		break;
+	case CIPHER_ALG_AES:
+		if ((key_size != AES128_KEY_SIZE) &&
+				(key_size != AES256_KEY_SIZE))
+			return -EINVAL;
+		enciv_in_word = 4;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (q_req->mode) {
+	case QCE_MODE_ECB:
+	case QCE_MODE_CBC:
+	case QCE_MODE_CTR:
+		pce_dev->mode = q_req->mode;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (q_req->mode !=  QCE_MODE_ECB) {
+		_byte_stream_to_net_words(enciv32, q_req->iv, ivsize);
+		pce = cmdlistinfo->encr_cntr_iv;
+		for (i = 0; i < enciv_in_word; i++, pce++)
+			pce->data = enciv32[i];
+	}
+
+	/*
+	 * write encr key
+	 * do not use  hw key or pipe key
+	 */
+	_byte_stream_to_net_words(enckey32, q_req->enckey, key_size);
+	pce = cmdlistinfo->encr_key;
+	for (i = 0; i < enck_size_in_word; i++, pce++)
+		pce->data = enckey32[i];
+
+	/* write encr seg cfg */
+	pce = cmdlistinfo->encr_seg_cfg;
+	encr_cfg = pce->data;
+	if (q_req->dir == QCE_ENCRYPT)
+		encr_cfg |= (1 << CRYPTO_ENCODE);
+	else
+		encr_cfg &= ~(1 << CRYPTO_ENCODE);
+	pce->data = encr_cfg;
+
+	/* we only support sha1-hmac at this point */
+	_byte_stream_to_net_words(mackey32, q_req->authkey,
+					q_req->authklen);
+	pce = cmdlistinfo->auth_key;
+	for (i = 0; i < authk_size_in_word; i++, pce++)
+		pce->data = mackey32[i];
+	pce = cmdlistinfo->auth_iv;
+	for (i = 0; i < 5; i++, pce++)
+		pce->data = _std_init_vector_sha1[i];
+
+	/* write auth_bytecnt 0/1, start with 0 */
+	pce = cmdlistinfo->auth_bytecount;
+	for (i = 0; i < 2; i++, pce++)
+		pce->data = 0;
+
+	pce = cmdlistinfo->auth_seg_cfg;
+	a_cfg = pce->data;
+	a_cfg &= ~(CRYPTO_AUTH_POS_MASK);
+	if (q_req->dir == QCE_ENCRYPT)
+		a_cfg |= (CRYPTO_AUTH_POS_AFTER << CRYPTO_AUTH_POS);
+	else
+		a_cfg |= (CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+	pce->data = a_cfg;
+
+	/* write auth seg size */
+	pce = cmdlistinfo->auth_seg_size;
+	pce->data = totallen_in;
+
+	/* write auth seg size start*/
+	pce = cmdlistinfo->auth_seg_start;
+	pce->data = 0;
+
+	/* write seg size */
+	pce = cmdlistinfo->seg_size;
+	pce->data = totallen_in;
+
+	/* write encr seg size */
+	pce = cmdlistinfo->encr_seg_size;
+	pce->data = q_req->cryptlen;
+
+	/* write encr seg start */
+	pce = cmdlistinfo->encr_seg_start;
+	pce->data = (coffset & 0xffff);
+
+	return 0;
+
+};
+
 static int _ce_get_cipher_cmdlistinfo(struct qce_device *pce_dev,
 				struct qce_req *creq,
 				struct qce_cmdlist_info **cmdlistinfo)
@@ -881,6 +1066,190 @@
 	return 0;
 }
 
+static int _ce_setup_aead_direct(struct qce_device *pce_dev,
+		struct qce_req *q_req, uint32_t totallen_in, uint32_t coffset)
+{
+	int32_t authk_size_in_word = q_req->authklen/sizeof(uint32_t);
+	int i;
+	uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = {0};
+	uint32_t a_cfg;
+	uint32_t enckey32[(MAX_CIPHER_KEY_SIZE*2)/sizeof(uint32_t)] = {0};
+	uint32_t enciv32[MAX_IV_LENGTH/sizeof(uint32_t)] = {0};
+	uint32_t enck_size_in_word = 0;
+	uint32_t enciv_in_word;
+	uint32_t key_size;
+	uint32_t ivsize = q_req->ivsize;
+	uint32_t encr_cfg;
+
+
+	/* clear status */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_STATUS_REG);
+
+	writel_relaxed(pce_dev->reg.crypto_cfg_be, (pce_dev->iobase +
+							CRYPTO_CONFIG_REG));
+	/*
+	 * Ensure previous instructions (setting the CONFIG register)
+	 * was completed before issuing starting to set other config register
+	 * This is to ensure the configurations are done in correct endian-ness
+	 * as set in the CONFIG registers
+	 */
+	mb();
+
+	key_size = q_req->encklen;
+	enck_size_in_word = key_size/sizeof(uint32_t);
+
+	switch (q_req->alg) {
+
+	case CIPHER_ALG_DES:
+
+		switch (q_req->mode) {
+		case QCE_MODE_ECB:
+			encr_cfg = pce_dev->reg.encr_cfg_des_ecb;
+			break;
+		case QCE_MODE_CBC:
+			encr_cfg = pce_dev->reg.encr_cfg_des_cbc;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		enciv_in_word = 2;
+		break;
+
+	case CIPHER_ALG_3DES:
+
+		switch (q_req->mode) {
+		case QCE_MODE_ECB:
+			encr_cfg =  pce_dev->reg.encr_cfg_3des_ecb;
+			break;
+		case QCE_MODE_CBC:
+			encr_cfg = pce_dev->reg.encr_cfg_3des_cbc;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		enciv_in_word = 2;
+
+		break;
+
+	case CIPHER_ALG_AES:
+
+		switch (q_req->mode) {
+		case QCE_MODE_ECB:
+			if (key_size == AES128_KEY_SIZE)
+				encr_cfg = pce_dev->reg.encr_cfg_aes_ecb_128;
+			else if (key_size  == AES256_KEY_SIZE)
+				encr_cfg = pce_dev->reg.encr_cfg_aes_ecb_256;
+			else
+				return -EINVAL;
+			break;
+		case QCE_MODE_CBC:
+			if (key_size == AES128_KEY_SIZE)
+				encr_cfg = pce_dev->reg.encr_cfg_aes_cbc_128;
+			else if (key_size  == AES256_KEY_SIZE)
+				encr_cfg = pce_dev->reg.encr_cfg_aes_cbc_256;
+			else
+				return -EINVAL;
+			break;
+		default:
+		return -EINVAL;
+		}
+
+		enciv_in_word = 4;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+
+	pce_dev->mode = q_req->mode;
+
+
+	/* write CNTR0_IV0_REG */
+	if (q_req->mode !=  QCE_MODE_ECB) {
+		_byte_stream_to_net_words(enciv32, q_req->iv, ivsize);
+		for (i = 0; i < enciv_in_word; i++)
+			writel_relaxed(enciv32[i], pce_dev->iobase +
+				(CRYPTO_CNTR0_IV0_REG + i * sizeof(uint32_t)));
+	}
+
+	/*
+	 * write encr key
+	 * do not use  hw key or pipe key
+	 */
+	_byte_stream_to_net_words(enckey32, q_req->enckey, key_size);
+	for (i = 0; i < enck_size_in_word; i++)
+		writel_relaxed(enckey32[i], pce_dev->iobase +
+				(CRYPTO_ENCR_KEY0_REG + i * sizeof(uint32_t)));
+
+	/* write encr seg cfg */
+	if (q_req->dir == QCE_ENCRYPT)
+		encr_cfg |= (1 << CRYPTO_ENCODE);
+	writel_relaxed(encr_cfg, pce_dev->iobase + CRYPTO_ENCR_SEG_CFG_REG);
+
+	/* we only support sha1-hmac at this point */
+	_byte_stream_to_net_words(mackey32, q_req->authkey,
+					q_req->authklen);
+	for (i = 0; i < authk_size_in_word; i++)
+		writel_relaxed(mackey32[i], pce_dev->iobase +
+			(CRYPTO_AUTH_KEY0_REG + i * sizeof(uint32_t)));
+
+	for (i = 0; i < 5; i++)
+		writel_relaxed(_std_init_vector_sha1[i], pce_dev->iobase +
+				(CRYPTO_AUTH_IV0_REG + i * sizeof(uint32_t)));
+
+	/* write auth_bytecnt 0/1, start with 0 */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_AUTH_BYTECNT0_REG);
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_AUTH_BYTECNT1_REG);
+
+	/* write encr seg size    */
+	writel_relaxed(q_req->cryptlen, pce_dev->iobase +
+			CRYPTO_ENCR_SEG_SIZE_REG);
+
+	/* write encr start   */
+	writel_relaxed(coffset & 0xffff, pce_dev->iobase +
+			CRYPTO_ENCR_SEG_START_REG);
+
+	a_cfg = (CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE) |
+			(CRYPTO_AUTH_SIZE_SHA1 << CRYPTO_AUTH_SIZE) |
+			(1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST) |
+			(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG);
+
+	if (q_req->dir == QCE_ENCRYPT)
+		a_cfg |= (CRYPTO_AUTH_POS_AFTER << CRYPTO_AUTH_POS);
+	else
+		a_cfg |= (CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+
+	/* write auth seg_cfg */
+	writel_relaxed(a_cfg, pce_dev->iobase + CRYPTO_AUTH_SEG_CFG_REG);
+
+	/* write auth seg_size   */
+	writel_relaxed(totallen_in, pce_dev->iobase + CRYPTO_AUTH_SEG_SIZE_REG);
+
+	/* write auth_seg_start   */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_AUTH_SEG_START_REG);
+
+
+	/* write seg_size   */
+	writel_relaxed(totallen_in, pce_dev->iobase + CRYPTO_SEG_SIZE_REG);
+
+
+	writel_relaxed(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase +
+
+							CRYPTO_CONFIG_REG));
+	/* issue go to crypto   */
+	writel_relaxed(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
+				pce_dev->iobase + CRYPTO_GOPROC_REG);
+	/*
+	 * Ensure previous instructions (setting the GO register)
+	 * was completed before issuing a DMA transfer request
+	 */
+	mb();
+	return 0;
+};
+
 static int _ce_setup_cipher_direct(struct qce_device *pce_dev,
 		struct qce_req *creq, uint32_t totallen_in, uint32_t coffset)
 {
@@ -1208,6 +1577,7 @@
 	struct aead_request *areq;
 	unsigned char mac[SHA256_DIGEST_SIZE];
 	uint32_t status;
+	int32_t result_status;
 
 	areq = (struct aead_request *) pce_dev->areq;
 	if (areq->src != areq->dst) {
@@ -1229,61 +1599,53 @@
 	if (_qce_unlock_other_pipes(pce_dev))
 		return -EINVAL;
 
-	if (pce_dev->mode == QCE_MODE_CCM) {
-		int32_t result_status;
+	/*
+	 * Don't use result dump status. The operation may not
+	 * be complete.
+	 * Instead, use the status we just read of device.
+	 * In case, we need to use result_status from result
+	 * dump the result_status needs to be byte swapped,
+	 * since we set the device to little endian.
+	 */
+	result_status = 0;
+	pce_dev->ce_sps.result->status = 0;
 
-		/*
-		 * Don't use result dump status. The operation may not
-		 * be complete.
-		 * Instead, use the status we just read of device.
-		 * In case, we need to use result_status from result
-		 * dump the result_status needs to be byte swapped,
-		 * since we set the device to little endian.
-		 */
-
-		result_status = pce_dev->ce_sps.result->status;
-		pce_dev->ce_sps.result->status = 0;
-
-		if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+	if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
 			| (1 <<  CRYPTO_HSD_ERR))) {
-
-			pr_err("aead operation error. Status %x\n",
-				status);
-			result_status = -ENXIO;
-		} else if (pce_dev->ce_sps.consumer_status |
+		pr_err("aead operation error. Status %x\n", status);
+		result_status = -ENXIO;
+	} else if (pce_dev->ce_sps.consumer_status |
 				pce_dev->ce_sps.producer_status)  {
-			pr_err("aead sps operation error. sps status %x %x\n",
+		pr_err("aead sps operation error. sps status %x %x\n",
 				pce_dev->ce_sps.consumer_status,
 				pce_dev->ce_sps.producer_status);
-			result_status = -ENXIO;
-		} else if ((status & (1 << CRYPTO_OPERATION_DONE)) == 0) {
-			pr_err("aead operation not done? Status %x, sps status %x %x\n",
+		result_status = -ENXIO;
+	} else if ((status & (1 << CRYPTO_OPERATION_DONE)) == 0) {
+		pr_err("aead operation not done? Status %x, sps status %x %x\n",
 				status,
 				pce_dev->ce_sps.consumer_status,
 				pce_dev->ce_sps.producer_status);
-			result_status = -ENXIO;
+		result_status = -ENXIO;
+	}
 
-		} else if (status & (1 << CRYPTO_MAC_FAILED)) {
+	if (pce_dev->mode == QCE_MODE_CCM) {
+
+		if (result_status == 0 && (status & (1 << CRYPTO_MAC_FAILED)))
 			result_status = -EBADMSG;
-		} else {
-			result_status = 0;
-		}
-
 		pce_dev->qce_cb(areq, mac, NULL, result_status);
 
 	} else {
 		uint32_t ivsize = 0;
 		struct crypto_aead *aead;
 		unsigned char iv[NUM_OF_CRYPTO_CNTR_IV_REG * CRYPTO_REG_SIZE];
-
 		aead = crypto_aead_reqtfm(areq);
 		ivsize = crypto_aead_ivsize(aead);
-		dma_unmap_single(pce_dev->pdev, pce_dev->phy_iv_in,
-				ivsize, DMA_TO_DEVICE);
+		if (pce_dev->ce_sps.minor_version != 0)
+			dma_unmap_single(pce_dev->pdev, pce_dev->phy_iv_in,
+							ivsize, DMA_TO_DEVICE);
 		memcpy(iv, (char *)(pce_dev->ce_sps.result->encr_cntr_iv),
 			sizeof(iv));
-		pce_dev->qce_cb(areq, mac, iv, pce_dev->ce_sps.consumer_status |
-			pce_dev->ce_sps.producer_status);
+		pce_dev->qce_cb(areq, mac, iv, result_status);
 
 	}
 	return 0;
@@ -2381,24 +2743,6 @@
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 	break;
-	case QCE_AEAD_SHA1_HMAC:
-		cmdlistptr->aead_sha1_hmac.cmdlist = (uint32_t)ce_vaddr;
-		pcl_info = &(cmdlistptr->aead_sha1_hmac);
-
-		auth_cfg = pdev->reg.auth_cfg_aead_sha1_hmac;
-		key_reg = 16;
-		iv_reg = 5;
-
-		/* clear status register */
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
-					0, NULL);
-
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
-		/* 1 dummy write */
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
-								0, NULL);
-	break;
 	case QCE_HASH_SHA256_HMAC:
 		cmdlistptr->auth_sha256_hmac.cmdlist = (uint32_t)ce_vaddr;
 		pcl_info = &(cmdlistptr->auth_sha256_hmac);
@@ -2496,8 +2840,7 @@
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 					pdev->reg.crypto_cfg_le, NULL);
 
-	if (alg != QCE_AEAD_SHA1_HMAC)
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
 			((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
 			&pcl_info->go_proc);
 
@@ -2508,6 +2851,210 @@
 }
 
 static int _setup_aead_cmdlistptrs(struct qce_device *pdev,
+				unsigned char **pvaddr,
+				uint32_t alg,
+				uint32_t mode,
+				uint32_t key_size)
+{
+	struct sps_command_element *ce_vaddr;
+	uint32_t ce_vaddr_start;
+	struct qce_cmdlistptr_ops *cmdlistptr = &pdev->ce_sps.cmdlistptr;
+	struct qce_cmdlist_info *pcl_info = NULL;
+	uint32_t key_reg;
+	uint32_t iv_reg;
+	uint32_t i;
+	uint32_t  enciv_in_word;
+	uint32_t encr_cfg;
+
+	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
+					pdev->ce_sps.ce_burst_size);
+
+	ce_vaddr_start = (uint32_t)(*pvaddr);
+	ce_vaddr = (struct sps_command_element *)(*pvaddr);
+
+	switch (alg) {
+
+	case CIPHER_ALG_DES:
+
+		switch (mode) {
+
+		case QCE_MODE_ECB:
+			cmdlistptr->aead_hmac_sha1_ecb_des.cmdlist =
+				 (uint32_t)ce_vaddr;
+			pcl_info = &(cmdlistptr->aead_hmac_sha1_ecb_des);
+			encr_cfg = pdev->reg.encr_cfg_des_ecb;
+
+			break;
+
+		case QCE_MODE_CBC:
+			cmdlistptr->aead_hmac_sha1_cbc_des.cmdlist =
+				 (uint32_t)ce_vaddr;
+			pcl_info = &(cmdlistptr->aead_hmac_sha1_cbc_des);
+			encr_cfg = pdev->reg.encr_cfg_des_cbc;
+			break;
+		default:
+			return -EINVAL;
+		};
+
+		enciv_in_word = 2;
+
+		break;
+
+	case CIPHER_ALG_3DES:
+		switch (mode) {
+
+		case QCE_MODE_ECB:
+			cmdlistptr->aead_hmac_sha1_ecb_3des.cmdlist =
+				 (uint32_t)ce_vaddr;
+			pcl_info = &(cmdlistptr->aead_hmac_sha1_ecb_3des);
+			encr_cfg = pdev->reg.encr_cfg_3des_ecb;
+
+			break;
+
+		case QCE_MODE_CBC:
+			cmdlistptr->aead_hmac_sha1_cbc_3des.cmdlist =
+				 (uint32_t)ce_vaddr;
+			pcl_info = &(cmdlistptr->aead_hmac_sha1_cbc_3des);
+			encr_cfg = pdev->reg.encr_cfg_3des_cbc;
+			break;
+		default:
+			return -EINVAL;
+		};
+
+		enciv_in_word = 2;
+
+		break;
+
+	case CIPHER_ALG_AES:
+		switch (mode) {
+
+		case QCE_MODE_ECB:
+			if (key_size ==  AES128_KEY_SIZE) {
+				cmdlistptr->aead_hmac_sha1_ecb_aes_128.cmdlist =
+					(uint32_t)ce_vaddr;
+				pcl_info = &(cmdlistptr->
+						aead_hmac_sha1_ecb_aes_128);
+
+				encr_cfg = pdev->reg.encr_cfg_aes_ecb_128;
+
+			} else if (key_size ==  AES256_KEY_SIZE) {
+				cmdlistptr->aead_hmac_sha1_ecb_aes_256.cmdlist =
+					(uint32_t)ce_vaddr;
+				pcl_info = &(cmdlistptr->
+						aead_hmac_sha1_ecb_aes_256);
+				encr_cfg = pdev->reg.encr_cfg_aes_ecb_256;
+			} else {
+				return -EINVAL;
+			}
+			break;
+
+		case QCE_MODE_CBC:
+			if (key_size ==  AES128_KEY_SIZE) {
+				cmdlistptr->aead_hmac_sha1_cbc_aes_128.cmdlist =
+					(uint32_t)ce_vaddr;
+				pcl_info = &(cmdlistptr->
+						aead_hmac_sha1_cbc_aes_128);
+				encr_cfg = pdev->reg.encr_cfg_aes_cbc_128;
+			} else if (key_size ==  AES256_KEY_SIZE) {
+				cmdlistptr->aead_hmac_sha1_cbc_aes_256.cmdlist =
+					(uint32_t)ce_vaddr;
+				pcl_info = &(cmdlistptr->
+						aead_hmac_sha1_cbc_aes_256);
+				encr_cfg = pdev->reg.encr_cfg_aes_cbc_256;
+			} else {
+				return -EINVAL;
+			}
+			break;
+		default:
+			return -EINVAL;
+		};
+
+		enciv_in_word = 4;
+
+		break;
+
+	default:
+		return -EINVAL;
+	};
+
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0, NULL);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
+
+
+	key_reg = key_size/sizeof(uint32_t);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_KEY0_REG, 0,
+			&pcl_info->encr_key);
+	for (i = 1; i < key_reg; i++)
+		qce_add_cmd_element(pdev, &ce_vaddr,
+			(CRYPTO_ENCR_KEY0_REG + i * sizeof(uint32_t)),
+			0, NULL);
+
+	if (mode != QCE_MODE_ECB) {
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CNTR0_IV0_REG, 0,
+			&pcl_info->encr_cntr_iv);
+		for (i = 1; i < enciv_in_word; i++)
+			qce_add_cmd_element(pdev, &ce_vaddr,
+				(CRYPTO_CNTR0_IV0_REG + i * sizeof(uint32_t)),
+				0, NULL);
+	};
+
+	iv_reg = 5;
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_IV0_REG, 0,
+				&pcl_info->auth_iv);
+	for (i = 1; i < iv_reg; i++)
+		qce_add_cmd_element(pdev, &ce_vaddr,
+			(CRYPTO_AUTH_IV0_REG + i*sizeof(uint32_t)),
+				0, NULL);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_BYTECNT0_REG,
+				0, &pcl_info->auth_bytecount);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_BYTECNT1_REG, 0, NULL);
+
+	key_reg = SHA_HMAC_KEY_SIZE/sizeof(uint32_t);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_KEY0_REG, 0,
+			 &pcl_info->auth_key);
+	for (i = 1; i < key_reg; i++)
+		qce_add_cmd_element(pdev, &ce_vaddr,
+			(CRYPTO_AUTH_KEY0_REG + i*sizeof(uint32_t)), 0, NULL);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_SEG_SIZE_REG, 0,
+			&pcl_info->seg_size);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_CFG_REG, encr_cfg,
+			&pcl_info->encr_seg_cfg);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG, 0,
+			&pcl_info->encr_seg_size);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_START_REG, 0,
+			&pcl_info->encr_seg_start);
+
+	qce_add_cmd_element(
+		pdev,
+		&ce_vaddr,
+		CRYPTO_AUTH_SEG_CFG_REG,
+		pdev->reg.auth_cfg_aead_sha1_hmac,
+		&pcl_info->auth_seg_cfg);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_SIZE_REG, 0,
+			&pcl_info->auth_seg_size);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_START_REG, 0,
+			&pcl_info->auth_seg_start);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+					pdev->reg.crypto_cfg_le, NULL);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
+			((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
+			&pcl_info->go_proc);
+
+	pcl_info->size = (uint32_t)ce_vaddr - (uint32_t)ce_vaddr_start;
+	*pvaddr = (unsigned char *) ce_vaddr;
+	return 0;
+}
+
+static int _setup_aead_ccm_cmdlistptrs(struct qce_device *pdev,
 				unsigned char **pvaddr, bool key_128)
 {
 	struct sps_command_element *ce_vaddr;
@@ -2696,10 +3243,25 @@
 	_setup_auth_cmdlistptrs(pdev, pvaddr, QCE_HASH_AES_CMAC, true);
 	_setup_auth_cmdlistptrs(pdev, pvaddr, QCE_HASH_AES_CMAC, false);
 
-	_setup_auth_cmdlistptrs(pdev, pvaddr, QCE_AEAD_SHA1_HMAC, false);
+	_setup_aead_cmdlistptrs(pdev, pvaddr, CIPHER_ALG_DES, QCE_MODE_CBC,
+					DES_KEY_SIZE);
+	_setup_aead_cmdlistptrs(pdev, pvaddr, CIPHER_ALG_DES, QCE_MODE_ECB,
+					DES_KEY_SIZE);
+	_setup_aead_cmdlistptrs(pdev, pvaddr, CIPHER_ALG_3DES, QCE_MODE_CBC,
+					DES3_EDE_KEY_SIZE);
+	_setup_aead_cmdlistptrs(pdev, pvaddr, CIPHER_ALG_3DES, QCE_MODE_ECB,
+					DES3_EDE_KEY_SIZE);
+	_setup_aead_cmdlistptrs(pdev, pvaddr, CIPHER_ALG_AES, QCE_MODE_CBC,
+					AES128_KEY_SIZE);
+	_setup_aead_cmdlistptrs(pdev, pvaddr, CIPHER_ALG_AES, QCE_MODE_ECB,
+					AES128_KEY_SIZE);
+	_setup_aead_cmdlistptrs(pdev, pvaddr, CIPHER_ALG_AES, QCE_MODE_CBC,
+					AES256_KEY_SIZE);
+	_setup_aead_cmdlistptrs(pdev, pvaddr, CIPHER_ALG_AES, QCE_MODE_ECB,
+					AES256_KEY_SIZE);
 
-	_setup_aead_cmdlistptrs(pdev, pvaddr, true);
-	_setup_aead_cmdlistptrs(pdev, pvaddr, false);
+	_setup_aead_ccm_cmdlistptrs(pdev, pvaddr, true);
+	_setup_aead_ccm_cmdlistptrs(pdev, pvaddr, false);
 	_setup_unlock_pipe_cmdlistptrs(pdev, pvaddr);
 
 	return 0;
@@ -2797,7 +3359,8 @@
 	pce_dev->reg.encr_cfg_aes_ccm_128 =
 		(CRYPTO_ENCR_KEY_SZ_AES128 << CRYPTO_ENCR_KEY_SZ) |
 		(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
-		((CRYPTO_ENCR_MODE_CCM << CRYPTO_ENCR_MODE));
+		(CRYPTO_ENCR_MODE_CCM << CRYPTO_ENCR_MODE)|
+		(CRYPTO_LAST_CCM_XFR << CRYPTO_LAST_CCM);
 
 	pce_dev->reg.encr_cfg_aes_ccm_256 =
 		(CRYPTO_ENCR_KEY_SZ_AES256 << CRYPTO_ENCR_KEY_SZ) |
@@ -2872,7 +3435,12 @@
 		(CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE)|
 		(CRYPTO_AUTH_SIZE_SHA1 << CRYPTO_AUTH_SIZE) |
 		(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
-		(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS) |
+		(1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST);
+
+	pce_dev->reg.auth_cfg_aead_sha256_hmac =
+		(CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE)|
+		(CRYPTO_AUTH_SIZE_SHA256 << CRYPTO_AUTH_SIZE) |
+		(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
 		(1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST);
 
 	pce_dev->reg.auth_cfg_aes_ccm_128 =
@@ -2894,83 +3462,46 @@
 	return 0;
 }
 
-int qce_aead_sha1_hmac_setup(struct qce_req *creq, struct crypto_aead *aead,
-				struct qce_cmdlist_info *cmdlistinfo)
-{
-	uint32_t authk_size_in_word = creq->authklen/sizeof(uint32_t);
-	uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = {
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	struct sps_command_element *pce = NULL;
-	struct aead_request *areq = (struct aead_request *)creq->areq;
-	int i;
-
-	_byte_stream_to_net_words(mackey32, creq->authkey,
-					creq->authklen);
-	pce = cmdlistinfo->auth_key;
-	for (i = 0; i < authk_size_in_word; i++, pce++)
-		pce->data = mackey32[i];
-	pce = cmdlistinfo->auth_iv;
-	for (i = 0; i < 5; i++, pce++)
-		pce->data = _std_init_vector_sha1[i];
-	/* write auth seg size */
-	pce = cmdlistinfo->auth_seg_size;
-	pce->data = creq->cryptlen + areq->assoclen + crypto_aead_ivsize(aead);
-
-	/* write auth seg size start*/
-	pce = cmdlistinfo->auth_seg_start;
-	pce->data = 0;
-
-	return 0;
-}
-
-int qce_aead_req(void *handle, struct qce_req *q_req)
+static int _qce_aead_ccm_req(void *handle, struct qce_req *q_req)
 {
 	struct qce_device *pce_dev = (struct qce_device *) handle;
 	struct aead_request *areq = (struct aead_request *) q_req->areq;
 	uint32_t authsize = q_req->authsize;
-	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
-	uint32_t ivsize = 0;
 	uint32_t totallen_in, out_len;
 	uint32_t hw_pad_out = 0;
 	int rc = 0;
 	int ce_burst_size;
 	struct qce_cmdlist_info *cmdlistinfo = NULL;
-	struct qce_cmdlist_info *auth_cmdlistinfo = NULL;
-
-	if (q_req->mode != QCE_MODE_CCM) {
-		ivsize = crypto_aead_ivsize(aead);
-		auth_cmdlistinfo = &pce_dev->ce_sps.cmdlistptr.aead_sha1_hmac;
-		if (auth_cmdlistinfo == NULL) {
-			pr_err("Received NULL cmdlist, exiting now\n");
-			return -EINVAL;
-		}
-	}
 
 	ce_burst_size = pce_dev->ce_sps.ce_burst_size;
+	totallen_in = areq->cryptlen + areq->assoclen;
 	if (q_req->dir == QCE_ENCRYPT) {
 		q_req->cryptlen = areq->cryptlen;
-			totallen_in = q_req->cryptlen + areq->assoclen + ivsize;
-		if (q_req->mode == QCE_MODE_CCM) {
-			out_len = areq->cryptlen + authsize;
-			hw_pad_out = ALIGN(authsize, ce_burst_size) - authsize;
-		} else {
-			out_len = areq->cryptlen;
-		}
+		out_len = areq->cryptlen + authsize;
+		hw_pad_out = ALIGN(authsize, ce_burst_size) - authsize;
 	} else {
 		q_req->cryptlen = areq->cryptlen - authsize;
-		if (q_req->mode == QCE_MODE_CCM)
-			totallen_in = areq->cryptlen + areq->assoclen;
-		else
-			totallen_in = q_req->cryptlen + areq->assoclen + ivsize;
 		out_len = q_req->cryptlen;
 		hw_pad_out = authsize;
 	}
 
+	if (pce_dev->ce_sps.minor_version == 0) {
+		/*
+		 * For crypto 5.0 that has burst size alignment requirement
+		 * for data descritpor,
+		 * the agent above(qcrypto) prepares the src scatter list with
+		 * memory starting with associated data, followed by
+		 * data stream to be ciphered.
+		 * The destination scatter list is pointing to the same
+		 * data area as source.
+		 */
+		pce_dev->src_nents = count_sg(areq->src, totallen_in);
+	} else {
+		pce_dev->src_nents = count_sg(areq->src, areq->cryptlen);
+	}
+
 	pce_dev->assoc_nents = count_sg(areq->assoc, areq->assoclen);
-	pce_dev->src_nents = count_sg(areq->src, areq->cryptlen);
-	pce_dev->ivsize = q_req->ivsize;
 	pce_dev->authsize = q_req->authsize;
-	pce_dev->phy_iv_in = 0;
 
 	/* associated data input */
 	qce_dma_map_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
@@ -2981,7 +3512,18 @@
 							DMA_TO_DEVICE);
 	/* cipher + mac output  for encryption    */
 	if (areq->src != areq->dst) {
-		pce_dev->dst_nents = count_sg(areq->dst, out_len);
+		if (pce_dev->ce_sps.minor_version == 0)
+			/*
+			 * The destination scatter list is pointing to the same
+			 * data area as src.
+			 * Note, the associated data will be pass-through
+			 * at the begining of destination area.
+			 */
+			pce_dev->dst_nents = count_sg(areq->dst,
+						out_len + areq->assoclen);
+		else
+			pce_dev->dst_nents = count_sg(areq->dst, out_len);
+
 		qce_dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
 				DMA_FROM_DEVICE);
 	} else {
@@ -2992,26 +3534,15 @@
 		_ce_get_cipher_cmdlistinfo(pce_dev, q_req, &cmdlistinfo);
 		/* set up crypto device */
 		rc = _ce_setup_cipher(pce_dev, q_req, totallen_in,
-					areq->assoclen + ivsize, cmdlistinfo);
+					areq->assoclen, cmdlistinfo);
 	} else {
 		/* set up crypto device */
 		rc = _ce_setup_cipher_direct(pce_dev, q_req, totallen_in,
-					areq->assoclen + ivsize);
+					areq->assoclen);
 	}
 	if (rc < 0)
 		goto bad;
 
-	if (q_req->mode != QCE_MODE_CCM) {
-		rc = qce_aead_sha1_hmac_setup(q_req, aead, auth_cmdlistinfo);
-		if (rc < 0)
-			goto bad;
-		/* overwrite seg size */
-		cmdlistinfo->seg_size->data = totallen_in;
-		/* cipher iv for input */
-		pce_dev->phy_iv_in = dma_map_single(pce_dev->pdev, q_req->iv,
-			ivsize, DMA_TO_DEVICE);
-	}
-
 	/* setup for callback, and issue command to bam */
 	pce_dev->areq = q_req->areq;
 	pce_dev->qce_cb = q_req->qce_cb;
@@ -3039,6 +3570,10 @@
 		_qce_set_flag(&pce_dev->ce_sps.in_transfer,
 				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
 
+		/*
+		 * The destination data should be big enough to
+		 * include  CCM padding.
+		 */
 		if (_qce_sps_add_sg_data(pce_dev, areq->dst, out_len +
 					areq->assoclen + hw_pad_out,
 				&pce_dev->ce_sps.out_transfer))
@@ -3063,6 +3598,211 @@
 		if (_qce_sps_add_sg_data(pce_dev, areq->assoc, areq->assoclen,
 					 &pce_dev->ce_sps.in_transfer))
 			goto bad;
+		if (_qce_sps_add_sg_data(pce_dev, areq->src, areq->cryptlen,
+					&pce_dev->ce_sps.in_transfer))
+			goto bad;
+		_qce_set_flag(&pce_dev->ce_sps.in_transfer,
+				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
+
+		/* Pass through to ignore associated  data*/
+		if (_qce_sps_add_data(
+				GET_PHYS_ADDR(pce_dev->ce_sps.ignore_buffer),
+				areq->assoclen,
+				&pce_dev->ce_sps.out_transfer))
+			goto bad;
+		if (_qce_sps_add_sg_data(pce_dev, areq->dst, out_len,
+					&pce_dev->ce_sps.out_transfer))
+			goto bad;
+		/* Pass through to ignore hw_pad (padding of the MAC data) */
+		if (_qce_sps_add_data(
+				GET_PHYS_ADDR(pce_dev->ce_sps.ignore_buffer),
+				hw_pad_out, &pce_dev->ce_sps.out_transfer))
+			goto bad;
+		if (totallen_in > SPS_MAX_PKT_SIZE) {
+			_qce_set_flag(&pce_dev->ce_sps.out_transfer,
+							SPS_IOVEC_FLAG_INT);
+			pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
+		} else {
+			if (_qce_sps_add_data(
+				GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
+					CRYPTO_RESULT_DUMP_SIZE,
+					  &pce_dev->ce_sps.out_transfer))
+				goto bad;
+			_qce_set_flag(&pce_dev->ce_sps.out_transfer,
+							SPS_IOVEC_FLAG_INT);
+			pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
+		}
+	}
+	rc = _qce_sps_transfer(pce_dev);
+	if (rc)
+		goto bad;
+	return 0;
+
+bad:
+	if (pce_dev->assoc_nents) {
+		qce_dma_unmap_sg(pce_dev->pdev, areq->assoc,
+				pce_dev->assoc_nents, DMA_TO_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 (areq->src != areq->dst) {
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
+				DMA_FROM_DEVICE);
+	}
+
+	return rc;
+}
+
+int qce_aead_req(void *handle, struct qce_req *q_req)
+{
+	struct qce_device *pce_dev;
+	struct aead_request *areq;
+	uint32_t authsize;
+	struct crypto_aead *aead;
+	uint32_t ivsize;
+	uint32_t totallen;
+	int rc;
+	struct qce_cmdlist_info *cmdlistinfo = NULL;
+
+	if (q_req->mode == QCE_MODE_CCM)
+		return _qce_aead_ccm_req(handle, q_req);
+
+	pce_dev = (struct qce_device *) handle;
+	areq = (struct aead_request *) q_req->areq;
+	aead = crypto_aead_reqtfm(areq);
+	ivsize = crypto_aead_ivsize(aead);
+	q_req->ivsize = ivsize;
+	authsize = q_req->authsize;
+	if (q_req->dir == QCE_ENCRYPT)
+		q_req->cryptlen = areq->cryptlen;
+	else
+		q_req->cryptlen = areq->cryptlen - authsize;
+
+	totallen = q_req->cryptlen + areq->assoclen + ivsize;
+
+	if (pce_dev->support_cmd_dscr) {
+		cmdlistinfo = _ce_get_aead_cmdlistinfo(pce_dev, q_req);
+		if (cmdlistinfo == NULL) {
+			pr_err("Unsupported aead ciphering algorithm %d, mode %d, ciphering key length %d, auth digest size %d\n",
+				q_req->alg, q_req->mode, q_req->encklen,
+					q_req->authsize);
+			return -EINVAL;
+		}
+		/* set up crypto device */
+		rc = _ce_setup_aead(pce_dev, q_req, totallen,
+					areq->assoclen + ivsize, cmdlistinfo);
+		if (rc < 0)
+			return -EINVAL;
+	};
+
+
+	pce_dev->assoc_nents = count_sg(areq->assoc, areq->assoclen);
+
+	if (pce_dev->ce_sps.minor_version == 0) {
+		/*
+		 * For crypto 5.0 that has burst size alignment requirement
+		 * for data descritpor,
+		 * the agent above(qcrypto) prepares the src scatter list with
+		 * memory starting with associated data, followed by
+		 * iv, and data stream to be ciphered.
+		 */
+		pce_dev->src_nents = count_sg(areq->src, totallen);
+	} else {
+		pce_dev->src_nents = count_sg(areq->src, q_req->cryptlen);
+	};
+
+	pce_dev->ivsize = q_req->ivsize;
+	pce_dev->authsize = q_req->authsize;
+	pce_dev->phy_iv_in = 0;
+
+	/* associated data input */
+	qce_dma_map_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
+					 DMA_TO_DEVICE);
+	/* cipher input */
+	qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
+							DMA_TO_DEVICE);
+	/* cipher + mac output  for encryption    */
+	if (areq->src != areq->dst) {
+		if (pce_dev->ce_sps.minor_version == 0)
+			/*
+			 * The destination scatter list is pointing to the same
+			 * data area as source.
+			 */
+			pce_dev->dst_nents = count_sg(areq->dst, totallen);
+		else
+			pce_dev->dst_nents = count_sg(areq->dst,
+							 q_req->cryptlen);
+
+		qce_dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
+				DMA_FROM_DEVICE);
+	}
+
+
+	/* cipher iv for input */
+	if (pce_dev->ce_sps.minor_version != 0)
+		pce_dev->phy_iv_in = dma_map_single(pce_dev->pdev, q_req->iv,
+			ivsize, DMA_TO_DEVICE);
+
+	/* setup for callback, and issue command to bam */
+	pce_dev->areq = q_req->areq;
+	pce_dev->qce_cb = q_req->qce_cb;
+
+	/* Register callback event for EOT (End of transfer) event. */
+	pce_dev->ce_sps.producer.event.callback = _aead_sps_producer_callback;
+	pce_dev->ce_sps.producer.event.options = SPS_O_DESC_DONE;
+	rc = sps_register_event(pce_dev->ce_sps.producer.pipe,
+					&pce_dev->ce_sps.producer.event);
+	if (rc) {
+		pr_err("Producer callback registration failed rc = %d\n", rc);
+		goto bad;
+	}
+	_qce_sps_iovec_count_init(pce_dev);
+
+	if (pce_dev->support_cmd_dscr) {
+		_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
+					&pce_dev->ce_sps.in_transfer);
+	} else {
+		rc = _ce_setup_aead_direct(pce_dev, q_req, totallen,
+					areq->assoclen + ivsize);
+		if (rc)
+			goto bad;
+	}
+
+	if (pce_dev->ce_sps.minor_version == 0) {
+		if (_qce_sps_add_sg_data(pce_dev, areq->src, totallen,
+					&pce_dev->ce_sps.in_transfer))
+			goto bad;
+
+		_qce_set_flag(&pce_dev->ce_sps.in_transfer,
+				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
+
+		if (_qce_sps_add_sg_data(pce_dev, areq->dst, totallen,
+				&pce_dev->ce_sps.out_transfer))
+			goto bad;
+		if (totallen > SPS_MAX_PKT_SIZE) {
+			_qce_set_flag(&pce_dev->ce_sps.out_transfer,
+							SPS_IOVEC_FLAG_INT);
+			pce_dev->ce_sps.producer.event.options =
+							SPS_O_DESC_DONE;
+			pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
+		} else {
+			if (_qce_sps_add_data(GET_PHYS_ADDR(
+					pce_dev->ce_sps.result_dump),
+					CRYPTO_RESULT_DUMP_SIZE,
+					&pce_dev->ce_sps.out_transfer))
+				goto bad;
+			_qce_set_flag(&pce_dev->ce_sps.out_transfer,
+							SPS_IOVEC_FLAG_INT);
+			pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
+		}
+	} else {
+		if (_qce_sps_add_sg_data(pce_dev, areq->assoc, areq->assoclen,
+					 &pce_dev->ce_sps.in_transfer))
+			goto bad;
 		if (_qce_sps_add_data((uint32_t)pce_dev->phy_iv_in, ivsize,
 					&pce_dev->ce_sps.in_transfer))
 			goto bad;
@@ -3072,21 +3812,17 @@
 		_qce_set_flag(&pce_dev->ce_sps.in_transfer,
 				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
 
-		/* Pass through to ignore associated (+iv, if applicable) data*/
+		/* Pass through to ignore associated + iv data*/
 		if (_qce_sps_add_data(
 				GET_PHYS_ADDR(pce_dev->ce_sps.ignore_buffer),
 				(ivsize + areq->assoclen),
 				&pce_dev->ce_sps.out_transfer))
 			goto bad;
-		if (_qce_sps_add_sg_data(pce_dev, areq->dst, out_len,
+		if (_qce_sps_add_sg_data(pce_dev, areq->dst, areq->cryptlen,
 					&pce_dev->ce_sps.out_transfer))
 			goto bad;
-		/* Pass through to ignore hw_pad (padding of the MAC data) */
-		if (_qce_sps_add_data(
-				GET_PHYS_ADDR(pce_dev->ce_sps.ignore_buffer),
-				hw_pad_out, &pce_dev->ce_sps.out_transfer))
-			goto bad;
-		if (totallen_in > SPS_MAX_PKT_SIZE) {
+
+		if (totallen > SPS_MAX_PKT_SIZE) {
 			_qce_set_flag(&pce_dev->ce_sps.out_transfer,
 							SPS_IOVEC_FLAG_INT);
 			pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h
index 38515fb..adab5d4 100644
--- a/drivers/crypto/msm/qce50.h
+++ b/drivers/crypto/msm/qce50.h
@@ -103,7 +103,14 @@
 	struct qce_cmdlist_info auth_sha256_hmac;
 	struct qce_cmdlist_info auth_aes_128_cmac;
 	struct qce_cmdlist_info auth_aes_256_cmac;
-	struct qce_cmdlist_info aead_sha1_hmac;
+	struct qce_cmdlist_info aead_hmac_sha1_cbc_aes_128;
+	struct qce_cmdlist_info aead_hmac_sha1_cbc_aes_256;
+	struct qce_cmdlist_info aead_hmac_sha1_cbc_des;
+	struct qce_cmdlist_info aead_hmac_sha1_cbc_3des;
+	struct qce_cmdlist_info aead_hmac_sha1_ecb_aes_128;
+	struct qce_cmdlist_info aead_hmac_sha1_ecb_aes_256;
+	struct qce_cmdlist_info aead_hmac_sha1_ecb_des;
+	struct qce_cmdlist_info aead_hmac_sha1_ecb_3des;
 	struct qce_cmdlist_info aead_aes_128_ccm;
 	struct qce_cmdlist_info aead_aes_256_ccm;
 	struct qce_cmdlist_info unlock_all_pipes;
@@ -146,6 +153,7 @@
 	uint32_t auth_cfg_aes_ccm_128;
 	uint32_t auth_cfg_aes_ccm_256;
 	uint32_t auth_cfg_aead_sha1_hmac;
+	uint32_t auth_cfg_aead_sha256_hmac;
 
 };
 
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index 39b9a46..c98cbba 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -44,7 +44,12 @@
 
 
 #define DEBUG_MAX_FNAME  16
-#define DEBUG_MAX_RW_BUF 1024
+#define DEBUG_MAX_RW_BUF 2048
+
+/*
+ * For crypto 5.0 which has burst size alignment requirement.
+ */
+#define MAX_ALIGN_SIZE  0x40
 
 struct crypto_stat {
 	u32 aead_sha1_aes_enc;
@@ -824,7 +829,14 @@
 	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
 	struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
 	u32 tmp[DES_EXPKEY_WORDS];
-	int ret = des_ekey(tmp, key);
+	int ret;
+
+	if (!key) {
+		pr_err("%s Inavlid key pointer\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = des_ekey(tmp, key);
 
 	if ((ctx->flags & QCRYPTO_CTX_USE_HW_KEY) == QCRYPTO_CTX_USE_HW_KEY) {
 		pr_err("%s HW KEY usage not supported for DES algorithm\n",
@@ -843,14 +855,9 @@
 	}
 
 	ctx->enc_key_len = len;
-	if (!(ctx->flags & QCRYPTO_CTX_USE_PIPE_KEY)) {
-		if (key != NULL) {
-			memcpy(ctx->enc_key, key, len);
-		} else {
-			pr_err("%s Inavlid key pointer\n", __func__);
-			return -EINVAL;
-		}
-	}
+	if (!(ctx->flags & QCRYPTO_CTX_USE_PIPE_KEY))
+		memcpy(ctx->enc_key, key, len);
+
 	return 0;
 };
 
@@ -1087,6 +1094,37 @@
 		areq->assoc = rctx->assoc_sg;
 		areq->assoclen = rctx->assoclen;
 	} else {
+		uint32_t ivsize = crypto_aead_ivsize(aead);
+
+		/* for aead operations, other than aes(ccm) */
+		if (cp->ce_support.aligned_only)  {
+			struct qcrypto_cipher_req_ctx *rctx;
+			uint32_t bytes = 0;
+			uint32_t nbytes = 0;
+			uint32_t num_sg = 0;
+			uint32_t offset = areq->assoclen + ivsize;
+
+			rctx = aead_request_ctx(areq);
+			areq->src = rctx->orig_src;
+			areq->dst = rctx->orig_dst;
+
+			if (rctx->dir == QCE_ENCRYPT)
+				nbytes = areq->cryptlen;
+			else
+				nbytes = areq->cryptlen -
+						crypto_aead_authsize(aead);
+			num_sg = qcrypto_count_sg(areq->dst, nbytes);
+			bytes = qcrypto_sg_copy_from_buffer(
+					areq->dst,
+					num_sg,
+					(char *)rctx->data + offset,
+					nbytes);
+			if (bytes != nbytes)
+				pr_warn("bytes copied=0x%x bytes to copy= 0x%x",
+						bytes, nbytes);
+			kfree(rctx->data);
+		}
+
 		if (ret == 0) {
 			if (rctx->dir  == QCE_ENCRYPT) {
 				/* copy the icv to dst */
@@ -1111,7 +1149,7 @@
 		}
 
 		if (iv)
-			memcpy(ctx->iv, iv, crypto_aead_ivsize(aead));
+			memcpy(ctx->iv, iv, ivsize);
 	}
 
 	if (ret == (-EBADMSG))
@@ -1174,7 +1212,7 @@
 	uint32_t bytes = 0;
 	uint32_t num_sg = 0;
 
-	qreq->assoc = kzalloc((alen + 0x64), (GFP_KERNEL | __GFP_DMA));
+	qreq->assoc = kzalloc((alen + 0x64), GFP_ATOMIC);
 	if (!qreq->assoc) {
 		pr_err("qcrypto Memory allocation of adata FAIL, error %ld\n",
 				PTR_ERR(qreq->assoc));
@@ -1432,6 +1470,68 @@
 		sg_set_buf(req->assoc, qreq.assoc,
 					req->assoclen);
 		sg_mark_end(req->assoc);
+	} else {
+		/* for aead operations, other than aes(ccm) */
+		if (cp->ce_support.aligned_only) {
+			uint32_t bytes = 0;
+			uint32_t num_sg = 0;
+
+			rctx->orig_src = req->src;
+			rctx->orig_dst = req->dst;
+			/*
+			 * The data area should be big enough to
+			 * include  assoicated data, ciphering data stream,
+			 * generated MAC, and CCM padding.
+			 */
+			rctx->data = kzalloc(
+					(req->cryptlen +
+						req->assoclen +
+						qreq.ivsize +
+						MAX_ALIGN_SIZE * 2),
+					GFP_ATOMIC);
+			if (rctx->data == NULL) {
+				pr_err("Mem Alloc fail rctx->data, err %ld\n",
+						PTR_ERR(rctx->data));
+				return -ENOMEM;
+			}
+
+			/* copy associated data */
+			num_sg = qcrypto_count_sg(req->assoc, req->assoclen);
+			bytes = qcrypto_sg_copy_to_buffer(
+				req->assoc, num_sg,
+				rctx->data, req->assoclen);
+
+			if (bytes != req->assoclen)
+				pr_warn("bytes copied=0x%x bytes to copy= 0x%x",
+						bytes, req->assoclen);
+
+			/* copy iv */
+			memcpy(rctx->data + req->assoclen, qreq.iv,
+				qreq.ivsize);
+
+			/* copy src */
+			num_sg = qcrypto_count_sg(req->src, req->cryptlen);
+			bytes = qcrypto_sg_copy_to_buffer(
+					req->src,
+					num_sg,
+					rctx->data + req->assoclen +
+						qreq.ivsize,
+					req->cryptlen);
+			if (bytes != req->cryptlen)
+				pr_warn("bytes copied=0x%x bytes to copy= 0x%x",
+						bytes, req->cryptlen);
+			sg_set_buf(&rctx->ssg, rctx->data,
+				req->cryptlen + req->assoclen
+					+ qreq.ivsize);
+			sg_mark_end(&rctx->ssg);
+
+			sg_set_buf(&rctx->dsg, rctx->data,
+				req->cryptlen + req->assoclen
+					+ qreq.ivsize);
+			sg_mark_end(&rctx->dsg);
+			req->src = &rctx->ssg;
+			req->dst = &rctx->dsg;
+		}
 	}
 	ret =  qce_aead_req(cp->qce, &qreq);
 
@@ -3644,7 +3744,8 @@
 	}
 
 	/* register crypto aead (hmac-sha1) algorithms the device supports */
-	if (cp->ce_support.sha1_hmac_20 || cp->ce_support.sha1_hmac) {
+	if (cp->ce_support.sha1_hmac_20 || cp->ce_support.sha1_hmac
+		|| cp->ce_support.sha_hmac) {
 		for (i = 0; i < ARRAY_SIZE(_qcrypto_aead_sha1_hmac_algos);
 									i++) {
 			struct qcrypto_alg *q_alg;
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 89d779c..f8185df 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -73,7 +73,7 @@
  * @devfreq:	the devfreq instance
  * @freq:	the target frequency
  */
-static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
+int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
 {
 	int lev;
 
@@ -83,6 +83,7 @@
 
 	return -EINVAL;
 }
+EXPORT_SYMBOL(devfreq_get_freq_level);
 
 /**
  * devfreq_update_status() - Update statistics of devfreq behavior
@@ -419,6 +420,32 @@
 }
 
 /**
+ * find_governor_data - Find device specific private data for a governor.
+ * @profile: The profile to search.
+ * @governor_name: The governor to search for.
+ *
+ * Look up the device specific data for a governor.
+ */
+static void *find_governor_data(struct devfreq_dev_profile *profile,
+				const char *governor_name)
+{
+	void *data = NULL;
+	int i;
+
+	if (profile->governor_data == NULL)
+		return NULL;
+
+	for (i = 0; i < profile->num_governor_data; i++) {
+		if (!strncmp(governor_name, profile->governor_data[i].name,
+			     DEVFREQ_NAME_LEN) == 0) {
+			data = profile->governor_data[i].data;
+			break;
+		}
+	}
+	return data;
+}
+
+/**
  * devfreq_add_device() - Add devfreq feature to the device
  * @dev:	the device to add devfreq feature.
  * @profile:	device-specific profile to run devfreq.
@@ -465,7 +492,10 @@
 	devfreq->profile = profile;
 	strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
 	devfreq->previous_freq = profile->initial_freq;
-	devfreq->data = data;
+
+	devfreq->data = data ? data : find_governor_data(devfreq->profile,
+							 governor_name);
+
 	devfreq->nb.notifier_call = devfreq_notifier_call;
 
 	devfreq->trans_table =	devm_kzalloc(dev, sizeof(unsigned int) *
@@ -722,6 +752,7 @@
 			goto out;
 		}
 	}
+	df->data = find_governor_data(df->profile, str_governor);
 	df->governor = governor;
 	strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN);
 	ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h
index fad7d63..ebde695 100644
--- a/drivers/devfreq/governor.h
+++ b/drivers/devfreq/governor.h
@@ -38,4 +38,5 @@
 extern int devfreq_add_governor(struct devfreq_governor *governor);
 extern int devfreq_remove_governor(struct devfreq_governor *governor);
 
+extern int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq);
 #endif /* _GOVERNOR_H */
diff --git a/drivers/gpu/ion/msm/ion_cp_common.c b/drivers/gpu/ion/msm/ion_cp_common.c
index 623a174..d315fc4 100644
--- a/drivers/gpu/ion/msm/ion_cp_common.c
+++ b/drivers/gpu/ion/msm/ion_cp_common.c
@@ -86,6 +86,8 @@
 	int nchunks;
 	int ret;
 	int i;
+	int chunk_list_len;
+	phys_addr_t chunk_list_phys;
 
 	if (usage < 0 || usage >= MAX_USAGE)
 		return -EINVAL;
@@ -97,15 +99,26 @@
 	}
 
 	nchunks = size / V2_CHUNK_SIZE;
+	chunk_list_len = sizeof(unsigned long)*nchunks;
 
-	chunk_list = kmalloc(sizeof(unsigned long)*nchunks, GFP_KERNEL);
+	chunk_list = kmalloc(chunk_list_len, GFP_KERNEL);
 	if (!chunk_list)
 		return -ENOMEM;
 
+	chunk_list_phys = virt_to_phys(chunk_list);
 	for (i = 0; i < nchunks; i++)
 		chunk_list[i] = phy_base + i * V2_CHUNK_SIZE;
 
-	ret = ion_cp_change_chunks_state(__pa(chunk_list),
+	/*
+	 * Flush the chunk list before sending the memory to the
+	 * secure environment to ensure the data is actually present
+	 * in RAM
+	 */
+	dmac_flush_range(chunk_list, chunk_list + chunk_list_len);
+	outer_flush_range(chunk_list_phys,
+			  chunk_list_phys + chunk_list_len);
+
+	ret = ion_cp_change_chunks_state(chunk_list_phys,
 					nchunks, V2_CHUNK_SIZE, usage, lock);
 
 	kfree(chunk_list);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index b917248..65fb9a4 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2596,6 +2596,16 @@
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	unsigned int timestamp;
 
+	/*
+	 * If GPU FT is turned off do not run FT.
+	 * If GPU stall detection is suspected to be false,
+	 * we can use this option to confirm stall detection.
+	 */
+	if (ft_data->ft_policy & KGSL_FT_OFF) {
+		KGSL_FT_ERR(device, "GPU FT turned off\n");
+		return 0;
+	}
+
 	KGSL_FT_INFO(device,
 	"Start Parameters: IB1: 0x%X, "
 	"Bad context_id: %u, global_eop: 0x%x\n",
@@ -2681,11 +2691,6 @@
 
 		/* Get the fault tolerance data as soon as hang is detected */
 		adreno_setup_ft_data(device, &ft_data);
-		/*
-		 * Trigger an automatic dump of the state to
-		 * the console
-		 */
-		kgsl_postmortem_dump(device, 0);
 
 		/*
 		 * If long ib is detected, do not attempt postmortem or
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 531a77c..70b07c4 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -250,11 +250,12 @@
 #define FT_DETECT_REGS_COUNT 12
 
 /* Fault Tolerance policy flags */
-#define  KGSL_FT_DISABLE                  BIT(0)
+#define  KGSL_FT_OFF                      BIT(0)
 #define  KGSL_FT_REPLAY                   BIT(1)
 #define  KGSL_FT_SKIPIB                   BIT(2)
 #define  KGSL_FT_SKIPFRAME                BIT(3)
-#define  KGSL_FT_TEMP_DISABLE             BIT(4)
+#define  KGSL_FT_DISABLE                  BIT(4)
+#define  KGSL_FT_TEMP_DISABLE             BIT(5)
 #define  KGSL_FT_DEFAULT_POLICY           (KGSL_FT_REPLAY + KGSL_FT_SKIPIB)
 
 /* Pagefault policy flags */
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 29855f7..a757a22 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2735,6 +2735,9 @@
 {
 	unsigned int in, out;
 
+	if (countable > 1)
+		return;
+
 	adreno_regread(device, A3XX_RBBM_RBBM_CTL, &in);
 
 	if (countable == 0)
@@ -2790,6 +2793,9 @@
 {
 	unsigned int in, out, bit;
 
+	if (countable > 2)
+		return;
+
 	adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
 	if (countable == 0)
 		bit = VBIF_PERF_PWR_CNT_0;
@@ -2823,12 +2829,6 @@
 	unsigned int val = 0;
 	struct a3xx_perfcounter_register *reg;
 
-	if (group >= ARRAY_SIZE(a3xx_perfcounter_reglist))
-		return;
-
-	if (counter >= a3xx_perfcounter_reglist[group].count)
-		return;
-
 	/* Special cases */
 	if (group == KGSL_PERFCOUNTER_GROUP_PWR)
 		return a3xx_perfcounter_enable_pwr(device, countable);
@@ -2837,6 +2837,12 @@
 	else if (group == KGSL_PERFCOUNTER_GROUP_VBIF_PWR)
 		return a3xx_perfcounter_enable_vbif_pwr(device, countable);
 
+	if (group >= ARRAY_SIZE(a3xx_perfcounter_reglist))
+		return;
+
+	if (counter >= a3xx_perfcounter_reglist[group].count)
+		return;
+
 	reg = &(a3xx_perfcounter_reglist[group].regs[counter]);
 
 	/* Select the desired perfcounter */
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 12b9e7c..f7dae9b 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -51,10 +51,11 @@
 			   &adreno_dev->fast_hang_detect);
 	/*
 	 * FT policy can be set to any of the options below.
-	 * KGSL_FT_DISABLE -> BIT(0) Set to disable FT
+	 * KGSL_FT_OFF -> BIT(0) Set to turn off FT
 	 * KGSL_FT_REPLAY  -> BIT(1) Set to enable replay
 	 * KGSL_FT_SKIPIB  -> BIT(2) Set to skip IB
 	 * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
+	 * KGSL_FT_DISABLE -> BIT(4) Set to disable FT for faulting context
 	 * by default set FT policy to KGSL_FT_DEFAULT_POLICY
 	 */
 	adreno_dev->ft_policy = KGSL_FT_DEFAULT_POLICY;
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 70223db..50ecbb0 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -967,10 +967,8 @@
 					 buffer */
 	struct kgsl_mem_entry *entry;
 
-	spin_lock(&dev_priv->process_priv->mem_lock);
 	entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
 					   gpuaddr, sizedwords * sizeof(uint));
-	spin_unlock(&dev_priv->process_priv->mem_lock);
 	if (entry == NULL) {
 		KGSL_CMD_ERR(dev_priv->device,
 			     "no mapping for gpuaddr: 0x%08x\n", gpuaddr);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index becb4ef..d580e8f 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -59,6 +59,8 @@
 	struct sg_table *table;
 };
 
+static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry);
+
 /**
  * kgsl_hang_check() - Check for GPU hang
  * data: KGSL device structure
@@ -255,6 +257,9 @@
 						    struct kgsl_mem_entry,
 						    refcount);
 
+	/* Detach from process list */
+	kgsl_mem_entry_detach_process(entry);
+
 	if (entry->memtype != KGSL_MEM_ENTRY_KERNEL)
 		kgsl_driver.stats.mapped -= entry->memdesc.size;
 
@@ -286,23 +291,46 @@
 EXPORT_SYMBOL(kgsl_mem_entry_destroy);
 
 /**
- * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree
+ * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and
+ * assign it with a gpu address space before insertion
  * @process: the process that owns the memory
  * @entry: the memory entry
  *
- * Insert a kgsl_mem_entry in to the rb_tree for searching by GPU address.
- * Not all mem_entries will have gpu addresses when first created, so this
- * function may be called after creation when the GPU address is finally
- * assigned.
+ * @returns - 0 on succcess else error code
+ *
+ * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address.
+ * The assignment of gpu address and insertion into list needs to
+ * happen with the memory lock held to avoid race conditions between
+ * gpu address being selected and some other thread looking through the
+ * rb list in search of memory based on gpuaddr
+ * This function should be called with processes memory spinlock held
  */
-static void
+static int
 kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
 				struct kgsl_mem_entry *entry)
 {
+	int ret = 0;
 	struct rb_node **node;
 	struct rb_node *parent = NULL;
 
-	spin_lock(&process->mem_lock);
+	assert_spin_locked(&process->mem_lock);
+	/*
+	 * If cpu=gpu map is used then caller needs to set the
+	 * gpu address
+	 */
+	if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
+		if (!entry->memdesc.gpuaddr)
+			goto done;
+	} else if (entry->memdesc.gpuaddr) {
+		WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
+		ret = kgsl_mmu_get_gpuaddr(process->pagetable, &entry->memdesc);
+		if (ret)
+			goto done;
+	}
 
 	node = &process->mem_rb.rb_node;
 
@@ -321,7 +349,27 @@
 	rb_link_node(&entry->node, parent, node);
 	rb_insert_color(&entry->node, &process->mem_rb);
 
-	spin_unlock(&process->mem_lock);
+done:
+	return ret;
+}
+
+/**
+ * kgsl_mem_entry_untrack_gpuaddr() - Untrack memory that is previously tracked
+ * process - Pointer to process private to which memory belongs
+ * entry - Memory entry to untrack
+ *
+ * Function just does the opposite of kgsl_mem_entry_track_gpuaddr. Needs to be
+ * called with processes spin lock held
+ */
+static void
+kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process,
+				struct kgsl_mem_entry *entry)
+{
+	assert_spin_locked(&process->mem_lock);
+	if (entry->memdesc.gpuaddr) {
+		kgsl_mmu_put_gpuaddr(process->pagetable, &entry->memdesc);
+		rb_erase(&entry->node, &entry->priv->mem_rb);
+	}
 }
 
 /**
@@ -360,8 +408,19 @@
 	}
 	entry->priv = process;
 
-	if (entry->memdesc.gpuaddr != 0)
-		kgsl_mem_entry_track_gpuaddr(process, entry);
+	spin_lock(&process->mem_lock);
+	ret = kgsl_mem_entry_track_gpuaddr(process, entry);
+	if (ret)
+		idr_remove(&process->mem_idr, entry->id);
+	spin_unlock(&process->mem_lock);
+	if (ret)
+		goto err;
+	/* map the memory after unlocking if gpuaddr has been assigned */
+	if (entry->memdesc.gpuaddr) {
+		ret = kgsl_mmu_map(process->pagetable, &entry->memdesc);
+		if (ret)
+			kgsl_mem_entry_detach_process(entry);
+	}
 err:
 	return ret;
 }
@@ -370,37 +429,23 @@
 
 static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
 {
-	bool had_gpuaddr = false;
-
 	if (entry == NULL)
 		return;
 
-	/*
-	 * Unmap the entry first so that there isn't a period of
-	 * time where kgsl doesn't know about the address range
-	 * but it is still present in the pagetable. Unmapping will
-	 * clear the gpuaddr field, so remember if we had a mapping,
-	 * and an rbtree entry for later.
-	 */
-	had_gpuaddr = entry->memdesc.gpuaddr != 0;
-	kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
+	/* Unmap here so that below we can call kgsl_mmu_put_gpuaddr */
+	kgsl_mmu_unmap(entry->priv->pagetable, &entry->memdesc);
 
 	spin_lock(&entry->priv->mem_lock);
 
+	kgsl_mem_entry_untrack_gpuaddr(entry->priv, entry);
 	if (entry->id != 0)
 		idr_remove(&entry->priv->mem_idr, entry->id);
 	entry->id = 0;
 
-	if (had_gpuaddr)
-		rb_erase(&entry->node, &entry->priv->mem_rb);
-
+	entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
 	spin_unlock(&entry->priv->mem_lock);
 
-	entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
 	entry->priv = NULL;
-
-
-	kgsl_mem_entry_put(entry);
 }
 
 /* Allocate a new context id */
@@ -759,7 +804,7 @@
 		rcu_read_unlock();
 		if (entry == NULL)
 			break;
-		kgsl_mem_entry_detach_process(entry);
+		kgsl_mem_entry_put(entry);
 		/*
 		 * Always start back at the beginning, to
 		 * ensure all entries are removed,
@@ -846,10 +891,15 @@
 
 	mutex_lock(&private->process_private_mutex);
 
-	if (!private->mem_rb.rb_node) {
-		private->mem_rb = RB_ROOT;
-		idr_init(&private->mem_idr);
-	}
+	/*
+	 * If debug root initialized then it means the rest of the fields
+	 * are also initialized
+	 */
+	if (private->debug_root)
+		goto done;
+
+	private->mem_rb = RB_ROOT;
+	idr_init(&private->mem_idr);
 
 	if ((!private->pagetable) && kgsl_mmu_enabled()) {
 		unsigned long pt_name;
@@ -865,11 +915,10 @@
 		}
 	}
 
-	if (!private->kobj.ktype)
-		kgsl_process_init_sysfs(private);
-	if (!private->debug_root)
-		kgsl_process_init_debugfs(private);
+	kgsl_process_init_sysfs(private);
+	kgsl_process_init_debugfs(private);
 
+done:
 	mutex_unlock(&private->process_private_mutex);
 
 	return private;
@@ -1069,12 +1118,13 @@
 kgsl_sharedmem_find_region(struct kgsl_process_private *private,
 	unsigned int gpuaddr, size_t size)
 {
-	struct rb_node *node = private->mem_rb.rb_node;
+	struct rb_node *node;
 
 	if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
 		return NULL;
 
 	spin_lock(&private->mem_lock);
+	node = private->mem_rb.rb_node;
 	while (node != NULL) {
 		struct kgsl_mem_entry *entry;
 
@@ -1124,16 +1174,19 @@
  * @size: length of the region.
  *
  * Checks that there are no existing allocations within an address
- * region.
+ * region. This function should be called with processes spin lock
+ * held.
  */
-int
+static int
 kgsl_sharedmem_region_empty(struct kgsl_process_private *private,
 	unsigned int gpuaddr, size_t size)
 {
 	int result = 1;
 	unsigned int gpuaddr_end = gpuaddr + size;
 
-	struct rb_node *node = private->mem_rb.rb_node;
+	struct rb_node *node;
+
+	assert_spin_locked(&private->mem_lock);
 
 	if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
 		return 0;
@@ -1142,7 +1195,6 @@
 	if (gpuaddr_end < gpuaddr)
 		return 0;
 
-	spin_lock(&private->mem_lock);
 	node = private->mem_rb.rb_node;
 	while (node != NULL) {
 		struct kgsl_mem_entry *entry;
@@ -1163,7 +1215,6 @@
 			break;
 		}
 	}
-	spin_unlock(&private->mem_lock);
 	return result;
 }
 
@@ -1191,6 +1242,30 @@
 	return entry;
 }
 
+/**
+ * kgsl_mem_entry_set_pend() - Set the pending free flag of a memory entry
+ * @entry - The memory entry
+ *
+ * @returns - true if pending flag was 0 else false
+ *
+ * This function will set the pending free flag if it is previously unset. Used
+ * to prevent race condition between ioctls calling free/freememontimestamp
+ * on the same entry. Whichever thread set's the flag first will do the free.
+ */
+static inline bool kgsl_mem_entry_set_pend(struct kgsl_mem_entry *entry)
+{
+	bool ret = false;
+	spin_lock(&entry->priv->mem_lock);
+	if (entry && entry->pending_free) {
+		ret = false;
+	} else if (entry) {
+		entry->pending_free = 1;
+		ret = true;
+	}
+	spin_unlock(&entry->priv->mem_lock);
+	return ret;
+}
+
 /*call all ioctl sub functions with driver locked*/
 static long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
 					  unsigned int cmd, void *data)
@@ -1469,7 +1544,7 @@
 {
 	struct kgsl_mem_entry *entry = priv;
 	trace_kgsl_mem_timestamp_free(device, entry, id, timestamp, 0);
-	kgsl_mem_entry_detach_process(entry);
+	kgsl_mem_entry_put(entry);
 }
 
 static long _cmdstream_freememontimestamp(struct kgsl_device_private *dev_priv,
@@ -1488,11 +1563,12 @@
 				"invalid gpuaddr %08x\n", gpuaddr);
 		return -EINVAL;
 	}
-	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+	if (!kgsl_mem_entry_set_pend(entry)) {
+		KGSL_DRV_WARN(dev_priv->device,
+		"Cannot set pending bit for gpuaddr %08x\n", gpuaddr);
 		kgsl_mem_entry_put(entry);
 		return -EBUSY;
 	}
-	entry->memdesc.priv |= KGSL_MEMDESC_FREE_PENDING;
 
 	trace_kgsl_mem_timestamp_queue(device, entry, context_id,
 				       kgsl_readtimestamp(device, context,
@@ -1592,8 +1668,7 @@
 				param->gpuaddr);
 		return -EINVAL;
 	}
-
-	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+	if (!kgsl_mem_entry_set_pend(entry)) {
 		kgsl_mem_entry_put(entry);
 		return -EBUSY;
 	}
@@ -1605,7 +1680,12 @@
 				    entry->memdesc.size,
 				    entry->memdesc.flags);
 
-	kgsl_mem_entry_detach_process(entry);
+	/*
+	 * First kgsl_mem_entry_put is for the reference that we took in
+	 * this function when calling kgsl_sharedmem_find, second one is
+	 * to free the memory since this is a free ioctl
+	 */
+	kgsl_mem_entry_put(entry);
 	kgsl_mem_entry_put(entry);
 	return 0;
 }
@@ -1624,7 +1704,7 @@
 		return -EINVAL;
 	}
 
-	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+	if (!kgsl_mem_entry_set_pend(entry)) {
 		kgsl_mem_entry_put(entry);
 		return -EBUSY;
 	}
@@ -1636,7 +1716,12 @@
 				    entry->memdesc.size,
 				    entry->memdesc.flags);
 
-	kgsl_mem_entry_detach_process(entry);
+	/*
+	 * First kgsl_mem_entry_put is for the reference that we took in
+	 * this function when calling kgsl_sharedmem_find_id, second one is
+	 * to free the memory since this is a free ioctl
+	 */
+	kgsl_mem_entry_put(entry);
 	kgsl_mem_entry_put(entry);
 	return 0;
 }
@@ -2111,18 +2196,15 @@
 	else if (entry->memdesc.size >= SZ_64K)
 		kgsl_memdesc_set_align(&entry->memdesc, ilog2(SZ_64));
 
-	result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
-	if (result)
-		goto error_put_file_ptr;
-
-	/* Adjust the returned value for a non 4k aligned offset */
-	param->gpuaddr = entry->memdesc.gpuaddr + (param->offset & ~PAGE_MASK);
 	/* echo back flags */
 	param->flags = entry->memdesc.flags;
 
 	result = kgsl_mem_entry_attach_process(entry, private);
 	if (result)
-		goto error_unmap;
+		goto error_attach;
+
+	/* Adjust the returned value for a non 4k aligned offset */
+	param->gpuaddr = entry->memdesc.gpuaddr + (param->offset & ~PAGE_MASK);
 
 	KGSL_STATS_ADD(param->len, kgsl_driver.stats.mapped,
 		kgsl_driver.stats.mapped_max);
@@ -2133,9 +2215,7 @@
 
 	return result;
 
-error_unmap:
-	kgsl_mmu_unmap(private->pagetable, &entry->memdesc);
-error_put_file_ptr:
+error_attach:
 	switch (entry->memtype) {
 	case KGSL_MEM_ENTRY_PMEM:
 	case KGSL_MEM_ENTRY_ASHMEM:
@@ -2395,10 +2475,6 @@
 	if (result)
 		return result;
 
-	result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
-	if (result)
-		goto err;
-
 	result = kgsl_mem_entry_attach_process(entry, private);
 	if (result != 0)
 		goto err;
@@ -2432,12 +2508,6 @@
 	if (result != 0)
 		goto err;
 
-	if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
-		result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
-		if (result)
-			goto err;
-	}
-
 	result = kgsl_mem_entry_attach_process(entry, private);
 	if (result != 0)
 		goto err;
@@ -3009,7 +3079,7 @@
 			 */
 			if (!retry && (ret == (unsigned long)-ENOMEM)
 				&& (align > PAGE_SHIFT)) {
-				align = PAGE_SHIFT;
+				align = 0;
 				addr = 0;
 				len = orig_len;
 				retry = 1;
@@ -3021,8 +3091,30 @@
 			ret = ALIGN(ret, (1 << align));
 
 		/*make sure there isn't a GPU only mapping at this address */
-		if (kgsl_sharedmem_region_empty(private, ret, orig_len))
+		spin_lock(&private->mem_lock);
+		if (kgsl_sharedmem_region_empty(private, ret, orig_len)) {
+			int ret_val;
+			/*
+			 * We found a free memory map, claim it here with
+			 * memory lock held
+			 */
+			entry->memdesc.gpuaddr = ret;
+			/* This should never fail */
+			ret_val = kgsl_mem_entry_track_gpuaddr(private, entry);
+			spin_unlock(&private->mem_lock);
+			BUG_ON(ret_val);
+			/* map cannot be called with lock held */
+			ret_val = kgsl_mmu_map(private->pagetable,
+						&entry->memdesc);
+			if (ret_val) {
+				spin_lock(&private->mem_lock);
+				kgsl_mem_entry_untrack_gpuaddr(private, entry);
+				spin_unlock(&private->mem_lock);
+				ret = ret_val;
+			}
 			break;
+		}
+		spin_unlock(&private->mem_lock);
 
 		trace_kgsl_mem_unmapped_area_collision(entry, addr, orig_len,
 							ret);
@@ -3048,7 +3140,7 @@
 	} while (mmap_range_valid(addr, len));
 
 	if (IS_ERR_VALUE(ret))
-		KGSL_MEM_INFO(device,
+		KGSL_MEM_ERR(device,
 				"pid %d pgoff %lx len %ld failed error %ld\n",
 				private->pid, pgoff, len, ret);
 put:
@@ -3079,17 +3171,6 @@
 	if (ret)
 		return ret;
 
-	if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
-		entry->memdesc.gpuaddr = vma->vm_start;
-
-		ret = kgsl_mmu_map(private->pagetable, &entry->memdesc);
-		if (ret) {
-			kgsl_mem_entry_put(entry);
-			return ret;
-		}
-		kgsl_mem_entry_track_gpuaddr(private, entry);
-	}
-
 	vma->vm_flags |= entry->memdesc.ops->vmflags(&entry->memdesc);
 
 	vma->vm_private_data = entry;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 0983111..d05d391 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -156,8 +156,8 @@
 #define KGSL_MEMDESC_GLOBAL BIT(1)
 /* The memdesc is frozen during a snapshot */
 #define KGSL_MEMDESC_FROZEN BIT(2)
-/* The memdesc is scheduled to be freed on a timestamp */
-#define KGSL_MEMDESC_FREE_PENDING BIT(3)
+/* The memdesc is mapped into a pagetable */
+#define KGSL_MEMDESC_MAPPED BIT(3)
 
 /* shared memory allocation */
 struct kgsl_memdesc {
@@ -195,6 +195,8 @@
 	/* back pointer to private structure under whose context this
 	* allocation is made */
 	struct kgsl_process_private *priv;
+	/* Initialized to 0, set to 1 when entry is marked for freeing */
+	int pending_free;
 };
 
 #ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index 99f4235..b07a1cad 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -424,10 +424,8 @@
 
 	if (memdesc == NULL) {
 		struct kgsl_mem_entry *entry;
-		spin_lock(&dev_priv->process_priv->mem_lock);
 		entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
 			gpuaddr, sizebytes);
-		spin_unlock(&dev_priv->process_priv->mem_lock);
 		if (entry == NULL) {
 			KGSL_CORE_ERR("did not find mapping "
 				"for gpuaddr: 0x%08x\n", gpuaddr);
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 007f89a..daeefd0 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -224,10 +224,23 @@
 				return result;
 			}
 
+			result = kgsl_mmu_get_gpuaddr(priv->pagetable,
+							&priv->memdesc);
+			if (result) {
+				DRM_ERROR(
+				"kgsl_mmu_get_gpuaddr failed. result = %d\n",
+				result);
+				ion_free(kgsl_drm_ion_client,
+					priv->ion_handle);
+				priv->ion_handle = NULL;
+				return result;
+			}
 			result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
 			if (result) {
 				DRM_ERROR(
 				"kgsl_mmu_map failed.  result = %d\n", result);
+				kgsl_mmu_put_gpuaddr(priv->pagetable,
+							&priv->memdesc);
 				ion_free(kgsl_drm_ion_client,
 					priv->ion_handle);
 				priv->ion_handle = NULL;
@@ -273,10 +286,17 @@
 			priv->memdesc.sglen++;
 		}
 
+		result = kgsl_mmu_get_gpuaddr(priv->pagetable, &priv->memdesc);
+		if (result) {
+			DRM_ERROR(
+			"kgsl_mmu_get_gpuaddr failed.  result = %d\n", result);
+			goto memerr;
+		}
 		result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
 		if (result) {
 			DRM_ERROR(
 			"kgsl_mmu_map failed.  result = %d\n", result);
+			kgsl_mmu_put_gpuaddr(priv->pagetable, &priv->memdesc);
 			goto memerr;
 		}
 
@@ -311,8 +331,10 @@
 	if (!kgsl_gem_memory_allocated(obj) || TYPE_IS_FD(priv->type))
 		return;
 
-	if (priv->memdesc.gpuaddr)
+	if (priv->memdesc.gpuaddr) {
 		kgsl_mmu_unmap(priv->memdesc.pagetable, &priv->memdesc);
+		kgsl_mmu_put_gpuaddr(priv->memdesc.pagetable, &priv->memdesc);
+	}
 
 	/* ION will take care of freeing the sg table. */
 	priv->memdesc.sg = NULL;
@@ -645,9 +667,21 @@
 		priv->memdesc.sglen++;
 	}
 
+	ret = kgsl_mmu_get_gpuaddr(priv->pagetable, &priv->memdesc);
+	if (ret) {
+		DRM_ERROR("kgsl_mmu_get_gpuaddr failed.  ret = %d\n", ret);
+		ion_free(kgsl_drm_ion_client,
+			priv->ion_handle);
+		priv->ion_handle = NULL;
+		kgsl_mmu_putpagetable(priv->pagetable);
+		drm_gem_object_release(obj);
+		kfree(priv);
+		return -ENOMEM;
+	}
 	ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
 	if (ret) {
 		DRM_ERROR("kgsl_mmu_map failed.  ret = %d\n", ret);
+		kgsl_mmu_put_gpuaddr(priv->pagetable, &priv->memdesc);
 		ion_free(kgsl_drm_ion_client,
 			priv->ion_handle);
 		priv->ion_handle = NULL;
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 12a4b25..952019f 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -613,15 +613,20 @@
 }
 EXPORT_SYMBOL(kgsl_mh_start);
 
+/**
+ * kgsl_mmu_get_gpuaddr - Assign a memdesc with a gpuadddr from the gen pool
+ * @pagetable - pagetable whose pool is to be used
+ * @memdesc - memdesc to which gpuaddr is assigned
+ *
+ * returns - 0 on success else error code
+ */
 int
-kgsl_mmu_map(struct kgsl_pagetable *pagetable,
-				struct kgsl_memdesc *memdesc)
+kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable,
+			struct kgsl_memdesc *memdesc)
 {
-	int ret;
 	struct gen_pool *pool = NULL;
 	int size;
 	int page_align = ilog2(PAGE_SIZE);
-	unsigned int protflags = kgsl_memdesc_protflags(memdesc);
 
 	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
 		if (memdesc->sglen == 1) {
@@ -693,6 +698,28 @@
 			return -ENOMEM;
 		}
 	}
+	return 0;
+}
+EXPORT_SYMBOL(kgsl_mmu_get_gpuaddr);
+
+int
+kgsl_mmu_map(struct kgsl_pagetable *pagetable,
+				struct kgsl_memdesc *memdesc)
+{
+	int ret = 0;
+	int size;
+	unsigned int protflags = kgsl_memdesc_protflags(memdesc);
+
+	if (!memdesc->gpuaddr)
+		return -EINVAL;
+	/* Only global mappings should be mapped multiple times */
+	if (!kgsl_memdesc_is_global(memdesc) &&
+		(KGSL_MEMDESC_MAPPED & memdesc->priv))
+		return -EINVAL;
+	/* Add space for the guard page when allocating the mmu VA. */
+	size = memdesc->size;
+	if (kgsl_memdesc_has_guard_page(memdesc))
+		size += PAGE_SIZE;
 
 	if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
 		spin_lock(&pagetable->lock);
@@ -702,7 +729,7 @@
 		spin_lock(&pagetable->lock);
 
 	if (ret)
-		goto err_free_gpuaddr;
+		goto done;
 
 	/* Keep track of the statistics for the sysfs files */
 
@@ -713,34 +740,76 @@
 		       pagetable->stats.max_mapped);
 
 	spin_unlock(&pagetable->lock);
+	memdesc->priv |= KGSL_MEMDESC_MAPPED;
 
 	return 0;
 
-err_free_gpuaddr:
+done:
 	spin_unlock(&pagetable->lock);
-	if (pool)
-		gen_pool_free(pool, memdesc->gpuaddr, size);
-	memdesc->gpuaddr = 0;
 	return ret;
 }
 EXPORT_SYMBOL(kgsl_mmu_map);
 
+/**
+ * kgsl_mmu_put_gpuaddr - Free a gpuaddress from memory pool
+ * @pagetable - pagetable whose pool memory is freed from
+ * @memdesc - memdesc whose gpuaddress is freed
+ *
+ * returns - 0 on success else error code
+ */
+int
+kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
+			struct kgsl_memdesc *memdesc)
+{
+	struct gen_pool *pool;
+	int size;
+
+	if (memdesc->size == 0 || memdesc->gpuaddr == 0)
+		return 0;
+
+	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
+		goto done;
+
+	/* Add space for the guard page when freeing the mmu VA. */
+	size = memdesc->size;
+	if (kgsl_memdesc_has_guard_page(memdesc))
+		size += PAGE_SIZE;
+
+	pool = pagetable->pool;
+
+	if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
+		if (kgsl_memdesc_is_global(memdesc))
+			pool = pagetable->kgsl_pool;
+		else if (kgsl_memdesc_use_cpu_map(memdesc))
+			pool = NULL;
+	}
+	if (pool)
+		gen_pool_free(pool, memdesc->gpuaddr, size);
+	/*
+	 * Don't clear the gpuaddr on global mappings because they
+	 * may be in use by other pagetables
+	 */
+done:
+	if (!kgsl_memdesc_is_global(memdesc))
+		memdesc->gpuaddr = 0;
+	return 0;
+}
+EXPORT_SYMBOL(kgsl_mmu_put_gpuaddr);
+
 int
 kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
 		struct kgsl_memdesc *memdesc)
 {
-	struct gen_pool *pool;
 	int size;
 	unsigned int start_addr = 0;
 	unsigned int end_addr = 0;
 
-	if (memdesc->size == 0 || memdesc->gpuaddr == 0)
-		return 0;
+	if (memdesc->size == 0 || memdesc->gpuaddr == 0 ||
+		!(KGSL_MEMDESC_MAPPED & memdesc->priv))
+		return -EINVAL;
 
-	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
-		memdesc->gpuaddr = 0;
+	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
 		return 0;
-	}
 
 	/* Add space for the guard page when freeing the mmu VA. */
 	size = memdesc->size;
@@ -767,24 +836,8 @@
 	pagetable->stats.mapped -= size;
 
 	spin_unlock(&pagetable->lock);
-
-	pool = pagetable->pool;
-
-	if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
-		if (kgsl_memdesc_is_global(memdesc))
-			pool = pagetable->kgsl_pool;
-		else if (kgsl_memdesc_use_cpu_map(memdesc))
-			pool = NULL;
-	}
-	if (pool)
-		gen_pool_free(pool, memdesc->gpuaddr, size);
-
-	/*
-	 * Don't clear the gpuaddr on global mappings because they
-	 * may be in use by other pagetables
-	 */
 	if (!kgsl_memdesc_is_global(memdesc))
-		memdesc->gpuaddr = 0;
+		memdesc->priv &= ~KGSL_MEMDESC_MAPPED;
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_mmu_unmap);
@@ -805,9 +858,12 @@
 	gpuaddr = memdesc->gpuaddr;
 	memdesc->priv |= KGSL_MEMDESC_GLOBAL;
 
-	result = kgsl_mmu_map(pagetable, memdesc);
+	result = kgsl_mmu_get_gpuaddr(pagetable, memdesc);
 	if (result)
 		goto error;
+	result = kgsl_mmu_map(pagetable, memdesc);
+	if (result)
+		goto error_put_gpuaddr;
 
 	/*global mappings must have the same gpu address in all pagetables*/
 	if (gpuaddr && gpuaddr != memdesc->gpuaddr) {
@@ -818,6 +874,8 @@
 	return result;
 error_unmap:
 	kgsl_mmu_unmap(pagetable, memdesc);
+error_put_gpuaddr:
+	kgsl_mmu_put_gpuaddr(pagetable, memdesc);
 error:
 	return result;
 }
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 27cfc40..faba81e 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -222,10 +222,14 @@
 int kgsl_mmu_close(struct kgsl_device *device);
 int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
 		 struct kgsl_memdesc *memdesc);
+int kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable,
+		 struct kgsl_memdesc *memdesc);
 int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
 			struct kgsl_memdesc *memdesc);
 int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
 		    struct kgsl_memdesc *memdesc);
+int kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
+		 struct kgsl_memdesc *memdesc);
 unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
 void kgsl_setstate(struct kgsl_mmu *mmu, unsigned int context_id,
 			uint32_t flags);
diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
index cfc409c..40649d2 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
@@ -28,8 +28,6 @@
 
 struct tz_priv {
 	int governor;
-	unsigned int no_switch_cnt;
-	unsigned int skip_cnt;
 	struct kgsl_power_stats bin;
 	unsigned int idle_dcvs;
 };
@@ -43,9 +41,6 @@
  * frame length, but less than the idle timer.
  */
 #define CEILING			50000
-#define SWITCH_OFF		200
-#define SWITCH_OFF_RESET_TH	40
-#define SKIP_COUNTER		500
 #define TZ_RESET_ID		0x3
 #define TZ_UPDATE_ID		0x4
 #define TZ_INIT_ID		0x6
@@ -164,22 +159,6 @@
 		(priv->bin.total_time < FLOOR))
 		return;
 
-	/* If the GPU has stayed in turbo mode for a while, *
-	 * stop writing out values. */
-	if (pwr->active_pwrlevel == 0) {
-		if (priv->no_switch_cnt > SWITCH_OFF) {
-			priv->skip_cnt++;
-			if (priv->skip_cnt > SKIP_COUNTER) {
-				priv->no_switch_cnt -= SWITCH_OFF_RESET_TH;
-				priv->skip_cnt = 0;
-			}
-			return;
-		}
-		priv->no_switch_cnt++;
-	} else {
-		priv->no_switch_cnt = 0;
-	}
-
 	/* If there is an extended block of busy processing,
 	 * increase frequency.  Otherwise run the normal algorithm.
 	 */
@@ -225,7 +204,6 @@
 	struct tz_priv *priv = pwrscale->priv;
 
 	__secure_tz_entry2(TZ_RESET_ID, 0, 0);
-	priv->no_switch_cnt = 0;
 	priv->bin.total_time = 0;
 	priv->bin.busy_time = 0;
 }
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 01f0768..2939df6 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -781,8 +781,10 @@
 	if (memdesc == NULL || memdesc->size == 0)
 		return;
 
-	if (memdesc->gpuaddr)
+	if (memdesc->gpuaddr) {
 		kgsl_mmu_unmap(memdesc->pagetable, memdesc);
+		kgsl_mmu_put_gpuaddr(memdesc->pagetable, memdesc);
+	}
 
 	if (memdesc->ops && memdesc->ops->free)
 		memdesc->ops->free(memdesc);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 985b9b8..9f84690 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -260,6 +260,11 @@
 	ret = kgsl_sharedmem_page_alloc(memdesc, pagetable, size);
 	if (ret)
 		return ret;
+	ret = kgsl_mmu_get_gpuaddr(pagetable, memdesc);
+	if (ret) {
+		kgsl_sharedmem_free(memdesc);
+		return ret;
+	}
 	ret = kgsl_mmu_map(pagetable, memdesc);
 	if (ret)
 		kgsl_sharedmem_free(memdesc);
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index 51ffd21..a587ed2 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -937,7 +937,7 @@
 	return rc;
 }
 
-static int epm_psoc_timestamp(struct epm_adc_drv *epm_adc,
+static int epm_psoc_get_timestamp(struct epm_adc_drv *epm_adc,
 		struct epm_psoc_system_time_stamp *psoc_timestamp)
 {
 	struct spi_message m;
@@ -955,15 +955,51 @@
 	spi_message_init(&m);
 	spi_message_add_tail(&t, &m);
 
-	if (psoc_timestamp->cmd == EPM_PSOC_SET_SYSTEM_TIMESTAMP_CMD) {
-		tx_buf[0] = psoc_timestamp->cmd;
-		tx_buf[1] = (psoc_timestamp->timestamp & 0xff000000) >> 24;
-		tx_buf[2] = (psoc_timestamp->timestamp & 0xff0000) >> 16;
-		tx_buf[3] = (psoc_timestamp->timestamp & 0xff00) >> 8;
-		tx_buf[4] = (psoc_timestamp->timestamp & 0xff);
-	} else if (psoc_timestamp->cmd == EPM_PSOC_GET_SYSTEM_TIMESTAMP_CMD) {
-		tx_buf[0] = psoc_timestamp->cmd;
-	}
+	psoc_timestamp->cmd = EPM_PSOC_GET_SYSTEM_TIMESTAMP_CMD;
+	tx_buf[0] = psoc_timestamp->cmd;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	psoc_timestamp->cmd		= rx_buf[0];
+	psoc_timestamp->timestamp = rx_buf[1] << 24 | rx_buf[2] << 16 |
+					rx_buf[3] << 8 | rx_buf[4];
+
+	return rc;
+}
+
+static int epm_psoc_set_timestamp(struct epm_adc_drv *epm_adc,
+		struct epm_psoc_system_time_stamp *psoc_timestamp)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[10], rx_buf[10];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	psoc_timestamp->cmd = EPM_PSOC_SET_SYSTEM_TIMESTAMP_CMD;
+	tx_buf[0] = psoc_timestamp->cmd;
+	tx_buf[1] = (psoc_timestamp->timestamp >> 24) & 0xff;
+	tx_buf[2] = (psoc_timestamp->timestamp >> 16) & 0xff;
+	tx_buf[3] = (psoc_timestamp->timestamp >> 8) & 0xff;
+	tx_buf[4] = (psoc_timestamp->timestamp & 0xff);
 
 	t.len = sizeof(tx_buf);
 	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
@@ -1199,7 +1235,7 @@
 	if (rc)
 		return rc;
 
-	rc = rx_buf[2];
+	rc = rx_buf[1];
 
 	return rc;
 }
@@ -1378,6 +1414,26 @@
 			break;
 		}
 	case EPM_PSOC_ADC_GET_SYSTEM_TIMESTAMP:
+		{
+			struct epm_psoc_system_time_stamp psoc_timestamp;
+			int rc;
+
+			if (copy_from_user(&psoc_timestamp,
+				(void __user *)arg,
+				sizeof(struct epm_psoc_system_time_stamp)))
+				return -EFAULT;
+
+			rc = epm_psoc_get_timestamp(epm_adc, &psoc_timestamp);
+			if (rc) {
+				pr_err("PSOC get timestamp failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg, &psoc_timestamp,
+				sizeof(struct epm_psoc_system_time_stamp)))
+				return -EFAULT;
+			break;
+		}
 	case EPM_PSOC_ADC_SET_SYSTEM_TIMESTAMP:
 		{
 			struct epm_psoc_system_time_stamp psoc_timestamp;
@@ -1388,9 +1444,9 @@
 				sizeof(struct epm_psoc_system_time_stamp)))
 				return -EFAULT;
 
-			rc = epm_psoc_timestamp(epm_adc, &psoc_timestamp);
+			rc = epm_psoc_set_timestamp(epm_adc, &psoc_timestamp);
 			if (rc) {
-				pr_err("PSOC buffered measurement failed\n");
+				pr_err("PSOC set timestamp failed\n");
 				return -EINVAL;
 			}
 
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index f46139f..f54707c 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -25,6 +25,11 @@
 #include <linux/slab.h>
 #include <linux/input/kxtj9.h>
 #include <linux/input-polldev.h>
+#include <linux/regulator/consumer.h>
+
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif /* CONFIG_OF */
 
 #define NAME			"kxtj9"
 #define G_MAX			8000
@@ -62,6 +67,11 @@
 #define RES_CTRL_REG1		1
 #define RES_INT_CTRL1		2
 #define RESUME_ENTRIES		3
+/* POWER SUPPLY VOLTAGE RANGE */
+#define KXTJ9_VDD_MIN_UV	2000000
+#define KXTJ9_VDD_MAX_UV	3300000
+#define KXTJ9_VIO_MIN_UV	1750000
+#define KXTJ9_VIO_MAX_UV	1950000
 
 /*
  * The following table lists the maximum appropriate poll interval for each
@@ -88,10 +98,14 @@
 	struct input_polled_dev *poll_dev;
 #endif
 	unsigned int last_poll_interval;
+	bool	enable;
 	u8 shift;
 	u8 ctrl_reg1;
 	u8 data_ctrl;
 	u8 int_ctrl;
+	bool	power_enabled;
+	struct regulator *vdd;
+	struct regulator *vio;
 };
 
 static int kxtj9_i2c_read(struct kxtj9_data *tj9, u8 addr, u8 *data, int len)
@@ -203,12 +217,130 @@
 	return 0;
 }
 
-static int kxtj9_device_power_on(struct kxtj9_data *tj9)
+static int kxtj9_power_on(struct kxtj9_data *data, bool on)
 {
-	if (tj9->pdata.power_on)
-		return tj9->pdata.power_on();
+	int rc = 0;
+
+	if (!on && data->power_enabled) {
+		rc = regulator_disable(data->vdd);
+		if (rc) {
+			dev_err(&data->client->dev,
+				"Regulator vdd disable failed rc=%d\n", rc);
+			return rc;
+		}
+
+		rc = regulator_disable(data->vio);
+		if (rc) {
+			dev_err(&data->client->dev,
+				"Regulator vio disable failed rc=%d\n", rc);
+			regulator_enable(data->vdd);
+		}
+		data->power_enabled = false;
+	} else if (on && !data->power_enabled) {
+		rc = regulator_enable(data->vdd);
+		if (rc) {
+			dev_err(&data->client->dev,
+				"Regulator vdd enable failed rc=%d\n", rc);
+			return rc;
+		}
+
+		rc = regulator_enable(data->vio);
+		if (rc) {
+			dev_err(&data->client->dev,
+				"Regulator vio enable failed rc=%d\n", rc);
+			regulator_disable(data->vdd);
+		}
+		data->power_enabled = true;
+	} else {
+		dev_warn(&data->client->dev,
+				"Power on=%d. enabled=%d\n",
+				on, data->power_enabled);
+	}
+
+	return rc;
+}
+
+static int kxtj9_power_init(struct kxtj9_data *data, bool on)
+{
+	int rc;
+
+	if (!on) {
+		if (regulator_count_voltages(data->vdd) > 0)
+			regulator_set_voltage(data->vdd, 0, KXTJ9_VDD_MAX_UV);
+
+		regulator_put(data->vdd);
+
+		if (regulator_count_voltages(data->vio) > 0)
+			regulator_set_voltage(data->vio, 0, KXTJ9_VIO_MAX_UV);
+
+		regulator_put(data->vio);
+	} else {
+		data->vdd = regulator_get(&data->client->dev, "vdd");
+		if (IS_ERR(data->vdd)) {
+			rc = PTR_ERR(data->vdd);
+			dev_err(&data->client->dev,
+				"Regulator get failed vdd rc=%d\n", rc);
+			return rc;
+		}
+
+		if (regulator_count_voltages(data->vdd) > 0) {
+			rc = regulator_set_voltage(data->vdd, KXTJ9_VDD_MIN_UV,
+						   KXTJ9_VDD_MAX_UV);
+			if (rc) {
+				dev_err(&data->client->dev,
+					"Regulator set failed vdd rc=%d\n",
+					rc);
+				goto reg_vdd_put;
+			}
+		}
+
+		data->vio = regulator_get(&data->client->dev, "vio");
+		if (IS_ERR(data->vio)) {
+			rc = PTR_ERR(data->vio);
+			dev_err(&data->client->dev,
+				"Regulator get failed vio rc=%d\n", rc);
+			goto reg_vdd_set;
+		}
+
+		if (regulator_count_voltages(data->vio) > 0) {
+			rc = regulator_set_voltage(data->vio, KXTJ9_VIO_MIN_UV,
+						   KXTJ9_VIO_MAX_UV);
+			if (rc) {
+				dev_err(&data->client->dev,
+				"Regulator set failed vio rc=%d\n", rc);
+				goto reg_vio_put;
+			}
+		}
+	}
 
 	return 0;
+
+reg_vio_put:
+	regulator_put(data->vio);
+reg_vdd_set:
+	if (regulator_count_voltages(data->vdd) > 0)
+		regulator_set_voltage(data->vdd, 0, KXTJ9_VDD_MAX_UV);
+reg_vdd_put:
+	regulator_put(data->vdd);
+	return rc;
+}
+static int kxtj9_device_power_on(struct kxtj9_data *tj9)
+{
+	int err = 0;
+	if (tj9->pdata.power_on) {
+		err = tj9->pdata.power_on();
+	} else {
+		err = kxtj9_power_on(tj9, true);
+		if (err) {
+			dev_err(&tj9->client->dev, "power on failed");
+			goto err_exit;
+		}
+		msleep(20);
+	}
+
+err_exit:
+	dev_dbg(&tj9->client->dev, "soft power on complete err=%d.\n", err);
+	return err;
 }
 
 static void kxtj9_device_power_off(struct kxtj9_data *tj9)
@@ -222,6 +354,11 @@
 
 	if (tj9->pdata.power_off)
 		tj9->pdata.power_off();
+	else
+		kxtj9_power_on(tj9, false);
+
+	dev_dbg(&tj9->client->dev, "soft power off complete.\n");
+	return ;
 }
 
 static int kxtj9_enable(struct kxtj9_data *tj9)
@@ -269,16 +406,19 @@
 		}
 	}
 
+	tj9->enable = true;
 	return 0;
 
 fail:
 	kxtj9_device_power_off(tj9);
+	tj9->enable = false;
 	return err;
 }
 
 static void kxtj9_disable(struct kxtj9_data *tj9)
 {
 	kxtj9_device_power_off(tj9);
+	tj9->enable = false;
 }
 
 static int kxtj9_input_open(struct input_dev *input)
@@ -339,6 +479,49 @@
 	return 0;
 }
 
+static ssize_t kxtj9_enable_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+
+	return snprintf(buf, 4, "%d\n", tj9->enable);
+}
+
+static ssize_t kxtj9_enable_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+	struct input_dev *input_dev = tj9->input_dev;
+	unsigned long data;
+	int error;
+
+	error = kstrtoul(buf, 10, &data);
+	if (error)
+		return error;
+	mutex_lock(&input_dev->mutex);
+	disable_irq(client->irq);
+
+	if (data == 0)
+		kxtj9_disable(tj9);
+	else if (data == 1)
+		kxtj9_enable(tj9);
+	else {
+		dev_err(&tj9->client->dev,
+			"Invalid value of input, input=%ld\n", data);
+	}
+
+	enable_irq(client->irq);
+	mutex_unlock(&input_dev->mutex);
+
+	return count;
+}
+
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR|S_IWGRP,
+			kxtj9_enable_show, kxtj9_enable_store);
+
 /*
  * When IRQ mode is selected, we need to provide an interface to allow the user
  * to change the output data rate of the part.  For consistency, we are using
@@ -396,6 +579,7 @@
 static DEVICE_ATTR(poll, S_IRUGO|S_IWUSR, kxtj9_get_poll, kxtj9_set_poll);
 
 static struct attribute *kxtj9_attributes[] = {
+	&dev_attr_enable.attr,
 	&dev_attr_poll.attr,
 	NULL
 };
@@ -489,10 +673,6 @@
 {
 	int retval;
 
-	retval = kxtj9_device_power_on(tj9);
-	if (retval < 0)
-		return retval;
-
 	retval = i2c_smbus_read_byte_data(tj9->client, WHO_AM_I);
 	if (retval < 0) {
 		dev_err(&tj9->client->dev, "read err int source\n");
@@ -502,14 +682,98 @@
 	retval = (retval != 0x07 && retval != 0x08) ? -EIO : 0;
 
 out:
-	kxtj9_device_power_off(tj9);
 	return retval;
 }
+#ifdef CONFIG_OF
+static int kxtj9_parse_dt(struct device *dev,
+				struct kxtj9_platform_data *kxtj9_pdata)
+{
+	struct device_node *np = dev->of_node;
+	u32 temp_val;
+	int rc;
+
+	rc = of_property_read_u32(np, "kionix,min-interval", &temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read min-interval\n");
+		return rc;
+	} else {
+		kxtj9_pdata->min_interval = temp_val;
+	}
+
+	rc = of_property_read_u32(np, "kionix,init-interval", &temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read init-interval\n");
+		return rc;
+	} else {
+		kxtj9_pdata->init_interval = temp_val;
+	}
+
+	rc = of_property_read_u32(np, "kionix,axis-map-x", &temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read axis-map_x\n");
+		return rc;
+	} else {
+		kxtj9_pdata->axis_map_x = (u8)temp_val;
+	}
+
+	rc = of_property_read_u32(np, "kionix,axis-map-y", &temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read axis_map_y\n");
+		return rc;
+	} else {
+		kxtj9_pdata->axis_map_y = (u8)temp_val;
+	}
+
+	rc = of_property_read_u32(np, "kionix,axis-map-z", &temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read axis-map-z\n");
+		return rc;
+	} else {
+		kxtj9_pdata->axis_map_z = (u8)temp_val;
+	}
+
+	rc = of_property_read_u32(np, "kionix,g-range", &temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read g-range\n");
+		return rc;
+	} else {
+		switch (temp_val) {
+		case 2:
+			kxtj9_pdata->g_range = KXTJ9_G_2G;
+			break;
+		case 4:
+			kxtj9_pdata->g_range = KXTJ9_G_4G;
+			break;
+		case 8:
+			kxtj9_pdata->g_range = KXTJ9_G_8G;
+			break;
+		default:
+			kxtj9_pdata->g_range = KXTJ9_G_2G;
+			break;
+		}
+	}
+
+	kxtj9_pdata->negate_x = of_property_read_bool(np, "kionix,negate-x");
+
+	kxtj9_pdata->negate_y = of_property_read_bool(np, "kionix,negate-y");
+
+	kxtj9_pdata->negate_z = of_property_read_bool(np, "kionix,negate-z");
+
+	kxtj9_pdata->res_12bit = of_property_read_bool(np, "kionix,res-12bit");
+
+	return 0;
+}
+#else
+static int kxtj9_parse_dt(struct device *dev,
+				struct kxtj9_platform_data *kxtj9_pdata)
+{
+	return -ENODEV;
+}
+#endif /* !CONFIG_OF */
 
 static int __devinit kxtj9_probe(struct i2c_client *client,
 				 const struct i2c_device_id *id)
 {
-	const struct kxtj9_platform_data *pdata = client->dev.platform_data;
 	struct kxtj9_data *tj9;
 	int err;
 
@@ -519,11 +783,6 @@
 		return -ENXIO;
 	}
 
-	if (!pdata) {
-		dev_err(&client->dev, "platform data is NULL; exiting\n");
-		return -EINVAL;
-	}
-
 	tj9 = kzalloc(sizeof(*tj9), GFP_KERNEL);
 	if (!tj9) {
 		dev_err(&client->dev,
@@ -531,19 +790,49 @@
 		return -ENOMEM;
 	}
 
-	tj9->client = client;
-	tj9->pdata = *pdata;
+	if (client->dev.of_node) {
+		memset(&tj9->pdata, 0 , sizeof(tj9->pdata));
+		err = kxtj9_parse_dt(&client->dev, &tj9->pdata);
+		if (err) {
+			dev_err(&client->dev,
+				"Unable to parse platfrom data err=%d\n", err);
+			return err;
+		}
+	} else {
+		if (client->dev.platform_data)
+			tj9->pdata = *(struct kxtj9_platform_data *)
+					client->dev.platform_data;
+		else {
+			dev_err(&client->dev,
+				"platform data is NULL; exiting\n");
+			return -EINVAL;
+		}
+	}
 
-	if (pdata->init) {
-		err = pdata->init();
+	tj9->client = client;
+	tj9->power_enabled = false;
+
+	if (tj9->pdata.init) {
+		err = tj9->pdata.init();
 		if (err < 0)
 			goto err_free_mem;
 	}
 
+	err = kxtj9_power_init(tj9, true);
+	if (err < 0) {
+		dev_err(&tj9->client->dev, "power init failed! err=%d", err);
+		goto err_pdata_exit;
+	}
+
+	err = kxtj9_device_power_on(tj9);
+	if (err < 0) {
+		dev_err(&client->dev, "power on failed! err=%d\n", err);
+		goto err_power_deinit;
+	}
 	err = kxtj9_verify(tj9);
 	if (err < 0) {
 		dev_err(&client->dev, "device not recognized\n");
-		goto err_pdata_exit;
+		goto err_power_off;
 	}
 
 	i2c_set_clientdata(client, tj9);
@@ -558,7 +847,7 @@
 
 		err = kxtj9_setup_input_device(tj9);
 		if (err)
-			goto err_pdata_exit;
+			goto err_power_off;
 
 		err = request_threaded_irq(client->irq, NULL, kxtj9_isr,
 					   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -577,20 +866,28 @@
 	} else {
 		err = kxtj9_setup_polled_device(tj9);
 		if (err)
-			goto err_pdata_exit;
+			goto err_power_off;
 	}
 
+	dev_dbg(&client->dev, "%s: kxtj9_probe OK.\n", __func__);
+	kxtj9_device_power_off(tj9);
 	return 0;
 
 err_free_irq:
 	free_irq(client->irq, tj9);
 err_destroy_input:
 	input_unregister_device(tj9->input_dev);
+err_power_off:
+	kxtj9_device_power_off(tj9);
+err_power_deinit:
+	kxtj9_power_init(tj9, false);
 err_pdata_exit:
 	if (tj9->pdata.exit)
 		tj9->pdata.exit();
 err_free_mem:
 	kfree(tj9);
+
+	dev_err(&client->dev, "%s: kxtj9_probe err=%d\n", __func__, err);
 	return err;
 }
 
@@ -606,6 +903,9 @@
 		kxtj9_teardown_polled_device(tj9);
 	}
 
+	kxtj9_device_power_off(tj9);
+	kxtj9_power_init(tj9, false);
+
 	if (tj9->pdata.exit)
 		tj9->pdata.exit();
 
@@ -654,12 +954,19 @@
 	{ },
 };
 
+static struct of_device_id kxtj9_match_table[] = {
+	{ .compatible = "kionix,kxtj9", },
+	{ },
+};
+
+
 MODULE_DEVICE_TABLE(i2c, kxtj9_id);
 
 static struct i2c_driver kxtj9_driver = {
 	.driver = {
 		.name	= NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = kxtj9_match_table,
 		.pm	= &kxtj9_pm_ops,
 	},
 	.probe		= kxtj9_probe,
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index efcace6..8dbac64 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -18,6 +18,7 @@
 
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
@@ -168,7 +169,15 @@
 #define FT_REG_CAL		0x00
 #define FT_CAL_MASK		0x70
 
-#define FT_DEBUG_DIR_NAME	"ft_debug"
+#define FT_INFO_MAX_LEN		200
+
+#define FT_STORE_TS_INFO(buf, id, fw_ver) \
+			snprintf(buf, FT_INFO_MAX_LEN, \
+				"controller\t= focaltech\n" \
+				"model\t\t= 0x%x\n" \
+				"fw_ver\t\t= 0x%x\n", id, fw_ver)
+
+#define FT_DEBUG_DIR_NAME	"ts_debug"
 
 struct ts_event {
 	u16 x[CFG_MAX_TOUCH_POINTS];	/*x coordinate */
@@ -202,6 +211,7 @@
 	struct dentry *dir;
 	u16 addr;
 	bool suspended;
+	char *ts_info;
 #if defined(CONFIG_FB)
 	struct notifier_block fb_notif;
 #elif defined(CONFIG_HAS_EARLYSUSPEND)
@@ -298,17 +308,22 @@
 			event->pressure = 0;
 		}
 
-		input_report_abs(data->input_dev, ABS_MT_POSITION_X,
-				 event->x[i]);
-		input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
-				 event->y[i]);
-		input_report_abs(data->input_dev, ABS_MT_PRESSURE,
-				 event->pressure);
-		input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
-				 event->finger_id[i]);
-		input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
-				 event->pressure);
-		input_mt_sync(data->input_dev);
+		input_mt_slot(data->input_dev, i);
+		input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
+					!!event->pressure);
+
+		if (event->pressure == FT_PRESS) {
+			input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+					 event->x[i]);
+			input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+					 event->y[i]);
+			input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+					 event->pressure);
+			input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
+					 event->finger_id[i]);
+			input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+					 event->pressure);
+		}
 	}
 
 	input_report_key(data->input_dev, BTN_TOUCH, !!fingerdown);
@@ -809,6 +824,7 @@
 		rc = -EIO;
 	}
 
+	FT_STORE_TS_INFO(data->ts_info, data->family_id, FT_FW_FILE_VER(fw));
 rel_fw:
 	release_firmware(fw);
 	return rc;
@@ -1015,6 +1031,27 @@
 DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5x06_debug_suspend_get,
 			ft5x06_debug_suspend_set, "%lld\n");
 
+static int ft5x06_debug_dump_info(struct seq_file *m, void *v)
+{
+	struct ft5x06_ts_data *data = m->private;
+
+	seq_printf(m, "%s\n", data->ts_info);
+
+	return 0;
+}
+
+static int debugfs_dump_info_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ft5x06_debug_dump_info, inode->i_private);
+}
+
+static const struct file_operations debug_dump_info_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debugfs_dump_info_open,
+	.read		= seq_read,
+	.release	= single_release,
+};
+
 #ifdef CONFIG_OF
 static int ft5x06_get_dt_coords(struct device *dev, char *name,
 				struct ft5x06_ts_platform_data *pdata)
@@ -1130,7 +1167,7 @@
 	struct ft5x06_ts_platform_data *pdata;
 	struct ft5x06_ts_data *data;
 	struct input_dev *input_dev;
-	struct dentry *dir, *temp;
+	struct dentry *temp;
 	u8 reg_value;
 	u8 reg_addr;
 	int err;
@@ -1188,12 +1225,11 @@
 	__set_bit(BTN_TOUCH, input_dev->keybit);
 	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
 
+	input_mt_init_slots(input_dev, CFG_MAX_TOUCH_POINTS);
 	input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
 			     pdata->x_max, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
 			     pdata->y_max, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
-			     CFG_MAX_TOUCH_POINTS, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, FT_PRESS, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);
 
@@ -1282,28 +1318,6 @@
 
 	data->family_id = reg_value;
 
-	/*get some register information */
-	reg_addr = FT_REG_FW_VER;
-	err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
-	if (err < 0)
-		dev_err(&client->dev, "version read failed");
-
-	dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
-
-	reg_addr = FT_REG_POINT_RATE;
-	ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
-	if (err < 0)
-		dev_err(&client->dev, "report rate read failed");
-
-	dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
-
-	reg_addr = FT_REG_THGROUP;
-	err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
-	if (err < 0)
-		dev_err(&client->dev, "threshold read failed");
-
-	dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
-
 	err = request_threaded_irq(client->irq, NULL,
 				   ft5x06_ts_interrupt, pdata->irqflags,
 				   client->dev.driver->name, data);
@@ -1330,14 +1344,14 @@
 		goto free_update_fw_sys;
 	}
 
-	dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
-	if (dir == NULL || IS_ERR(dir)) {
-		pr_err("debugfs_create_dir failed: rc=%ld\n", PTR_ERR(dir));
-		err = PTR_ERR(dir);
+	data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
+	if (data->dir == NULL || IS_ERR(data->dir)) {
+		pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir));
+		err = PTR_ERR(data->dir);
 		goto free_force_update_fw_sys;
 	}
 
-	temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, dir, data,
+	temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, data->dir, data,
 				   &debug_addr_fops);
 	if (temp == NULL || IS_ERR(temp)) {
 		pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
@@ -1345,7 +1359,7 @@
 		goto free_debug_dir;
 	}
 
-	temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, dir, data,
+	temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, data->dir, data,
 				   &debug_data_fops);
 	if (temp == NULL || IS_ERR(temp)) {
 		pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
@@ -1353,14 +1367,52 @@
 		goto free_debug_dir;
 	}
 
-	temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, dir, data,
-				   &debug_suspend_fops);
+	temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, data->dir,
+					data, &debug_suspend_fops);
 	if (temp == NULL || IS_ERR(temp)) {
 		pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
 		err = PTR_ERR(temp);
 		goto free_debug_dir;
 	}
 
+	temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, data->dir,
+					data, &debug_dump_info_fops);
+	if (temp == NULL || IS_ERR(temp)) {
+		pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+		err = PTR_ERR(temp);
+		goto free_debug_dir;
+	}
+
+	data->ts_info = kzalloc(FT_INFO_MAX_LEN, GFP_KERNEL);
+	if (!data->ts_info) {
+		dev_err(&client->dev, "Not enough memory\n");
+		goto free_debug_dir;
+	}
+
+	/*get some register information */
+	reg_addr = FT_REG_POINT_RATE;
+	ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+	if (err < 0)
+		dev_err(&client->dev, "report rate read failed");
+
+	dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
+
+	reg_addr = FT_REG_THGROUP;
+	err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+	if (err < 0)
+		dev_err(&client->dev, "threshold read failed");
+
+	dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
+
+	reg_addr = FT_REG_FW_VER;
+	err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+	if (err < 0)
+		dev_err(&client->dev, "version read failed");
+
+	dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
+
+	FT_STORE_TS_INFO(data->ts_info, data->family_id, reg_value);
+
 #if defined(CONFIG_FB)
 	data->fb_notif.notifier_call = fb_notifier_callback;
 
@@ -1449,6 +1501,7 @@
 		ft5x06_power_init(data, false);
 
 	input_unregister_device(data->input_dev);
+	kfree(data->ts_info);
 	kfree(data);
 
 	return 0;
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 653487b..a400b58 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -822,12 +822,18 @@
 	return 0;
 }
 
-void print_ctx_regs(struct msm_iommu_context_regs *regs)
+void print_ctx_regs(struct msm_iommu_context_reg regs[])
 {
-	uint32_t fsr = regs->fsr;
+	uint32_t fsr = regs[DUMP_REG_FSR].val;
 
-	pr_err("FAR    = %08x    PAR    = %08x\n",
-		 regs->far, regs->par);
+	pr_err("FAR    = %016llx\n",
+		COMBINE_DUMP_REG(
+			regs[DUMP_REG_FAR1].val,
+			regs[DUMP_REG_FAR0].val));
+	pr_err("PAR    = %016llx\n",
+		COMBINE_DUMP_REG(
+			regs[DUMP_REG_PAR1].val,
+			regs[DUMP_REG_PAR0].val));
 	pr_err("FSR    = %08x [%s%s%s%s%s%s%s%s%s]\n", fsr,
 			(fsr & 0x02) ? "TF " : "",
 			(fsr & 0x04) ? "AFF " : "",
@@ -840,31 +846,61 @@
 			(fsr & 0x80000000) ? "MULTI " : "");
 
 	pr_err("FSYNR0 = %08x    FSYNR1 = %08x\n",
-		 regs->fsynr0, regs->fsynr1);
+		 regs[DUMP_REG_FSYNR0].val, regs[DUMP_REG_FSYNR1].val);
 	pr_err("TTBR0  = %08x    TTBR1  = %08x\n",
-		 regs->ttbr0, regs->ttbr1);
+		 regs[DUMP_REG_TTBR0].val, regs[DUMP_REG_TTBR1].val);
 	pr_err("SCTLR  = %08x    ACTLR  = %08x\n",
-		 regs->sctlr, regs->actlr);
+		 regs[DUMP_REG_SCTLR].val, regs[DUMP_REG_ACTLR].val);
 	pr_err("PRRR   = %08x    NMRR   = %08x\n",
-		 regs->prrr, regs->nmrr);
+		 regs[DUMP_REG_PRRR].val, regs[DUMP_REG_NMRR].val);
 }
 
 static void __print_ctx_regs(void __iomem *base, int ctx, unsigned int fsr)
 {
-	struct msm_iommu_context_regs regs = {
-		.far = GET_FAR(base, ctx),
-		.par = GET_PAR(base, ctx),
-		.fsr = fsr,
-		.fsynr0 = GET_FSYNR0(base, ctx),
-		.fsynr1 = GET_FSYNR1(base, ctx),
-		.ttbr0 = GET_TTBR0(base, ctx),
-		.ttbr1 = GET_TTBR1(base, ctx),
-		.sctlr = GET_SCTLR(base, ctx),
-		.actlr = GET_ACTLR(base, ctx),
-		.prrr = GET_PRRR(base, ctx),
-		.nmrr = GET_NMRR(base, ctx),
+	struct msm_iommu_context_reg regs[MAX_DUMP_REGS] = {
+		[DUMP_REG_FAR0] = {
+			.val = GET_FAR(base, ctx)
+		},
+		[DUMP_REG_FAR1] = {
+			/* TODO: make GET_FAR 64-bit and take this from that */
+			.val = 0
+		},
+		[DUMP_REG_PAR0] = {
+			.val = GET_PAR(base, ctx)
+		},
+		[DUMP_REG_PAR1] = {
+			/* TODO: make GET_PAR 64-bit and take this from that */
+			.val = 0
+		},
+		[DUMP_REG_FSR] = {
+			.val = fsr
+		},
+		[DUMP_REG_FSYNR0] = {
+			.val = GET_FSYNR0(base, ctx)
+		},
+		[DUMP_REG_FSYNR1] = {
+			.val = GET_FSYNR1(base, ctx)
+		},
+		[DUMP_REG_TTBR0] = {
+			.val = GET_TTBR0(base, ctx)
+		},
+		[DUMP_REG_TTBR1] = {
+			.val = GET_TTBR1(base, ctx)
+		},
+		[DUMP_REG_SCTLR] = {
+			.val = GET_SCTLR(base, ctx)
+		},
+		[DUMP_REG_ACTLR] = {
+			.val = GET_ACTLR(base, ctx)
+		},
+		[DUMP_REG_PRRR] = {
+			.val = GET_PRRR(base, ctx)
+		},
+		[DUMP_REG_NMRR] = {
+			.val = GET_NMRR(base, ctx)
+		},
 	};
-	print_ctx_regs(&regs);
+	print_ctx_regs(regs);
 }
 
 irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id)
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index a17a4e8..50f6df4 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -34,6 +34,7 @@
 #include <mach/msm_iommu_priv.h>
 #include <mach/iommu.h>
 #include <mach/scm.h>
+#include <mach/memory.h>
 
 /* bitmap of the page sizes currently supported */
 #define MSM_IOMMU_PGSIZES	(SZ_4K | SZ_64K | SZ_1M | SZ_16M)
@@ -77,37 +78,19 @@
 	unsigned int flags;
 };
 
+#define NUM_DUMP_REGS 14
+/*
+ * some space to allow the number of registers returned by the secure
+ * environment to grow
+ */
+#define WIGGLE_ROOM (NUM_DUMP_REGS * 2)
+/* Each entry is a (reg_addr, reg_val) pair, hence the * 2 */
+#define SEC_DUMP_SIZE ((NUM_DUMP_REGS * 2) + WIGGLE_ROOM)
+
 struct msm_scm_fault_regs_dump {
 	uint32_t dump_size;
-	uint32_t fsr_addr;
-	uint32_t fsr;
-	uint32_t far0_addr;
-	uint32_t far0;
-	uint32_t far1_addr;
-	uint32_t far1;
-	uint32_t par0_addr;
-	uint32_t par0;
-	uint32_t par1_addr;
-	uint32_t par1;
-	uint32_t fsyn0_addr;
-	uint32_t fsyn0;
-	uint32_t fsyn1_addr;
-	uint32_t fsyn1;
-	uint32_t ttbr0_addr;
-	uint32_t ttbr0;
-	uint32_t ttbr1_addr;
-	uint32_t ttbr1;
-	uint32_t ttbcr_addr;
-	uint32_t ttbcr;
-	uint32_t sctlr_addr;
-	uint32_t sctlr;
-	uint32_t actlr_addr;
-	uint32_t actlr;
-	uint32_t prrr_addr;
-	uint32_t prrr;
-	uint32_t nmrr_addr;
-	uint32_t nmrr;
-};
+	uint32_t dump_data[SEC_DUMP_SIZE];
+} __packed;
 
 void msm_iommu_sec_set_access_ops(struct iommu_access_ops *access_ops)
 {
@@ -135,6 +118,100 @@
 	ret = scm_call(SCM_SVC_UTIL, IOMMU_DUMP_SMMU_FAULT_REGS,
 		&req_info, sizeof(req_info), &resp, 1);
 
+	invalidate_caches((unsigned long) regs, sizeof(*regs),
+			(unsigned long)virt_to_phys(regs));
+
+	return ret;
+}
+
+static struct dump_regs_tbl {
+	/*
+	 * To keep things context-bank-agnostic, we only store the CB
+	 * register offset in `key'
+	 */
+	unsigned long key;
+	const char *name;
+	int offset;
+} dump_regs_tbl[MAX_DUMP_REGS];
+
+#define EXTRACT_DUMP_REG_KEY(addr, ctx) (addr & ((1 << CTX_SHIFT) - 1))
+
+#define DUMP_REG_INIT(dump_reg, cb_reg)				\
+	do {							\
+		dump_regs_tbl[dump_reg].key = cb_reg;		\
+		dump_regs_tbl[dump_reg].name = #cb_reg;		\
+	} while (0)
+
+static void msm_iommu_sec_build_dump_regs_table(void)
+{
+	DUMP_REG_INIT(DUMP_REG_FAR0,	CB_FAR);
+	DUMP_REG_INIT(DUMP_REG_FAR1,	CB_FAR + 4);
+	DUMP_REG_INIT(DUMP_REG_PAR0,	CB_PAR);
+	DUMP_REG_INIT(DUMP_REG_PAR1,	CB_PAR + 4);
+	DUMP_REG_INIT(DUMP_REG_FSR,	CB_FSR);
+	DUMP_REG_INIT(DUMP_REG_FSYNR0,	CB_FSYNR0);
+	DUMP_REG_INIT(DUMP_REG_FSYNR1,	CB_FSYNR1);
+	DUMP_REG_INIT(DUMP_REG_TTBR0,	CB_TTBR0);
+	DUMP_REG_INIT(DUMP_REG_TTBR1,	CB_TTBR1);
+	DUMP_REG_INIT(DUMP_REG_SCTLR,	CB_SCTLR);
+	DUMP_REG_INIT(DUMP_REG_ACTLR,	CB_ACTLR);
+	DUMP_REG_INIT(DUMP_REG_PRRR,	CB_PRRR);
+	DUMP_REG_INIT(DUMP_REG_NMRR,	CB_NMRR);
+}
+
+static int msm_iommu_reg_dump_to_regs(
+	struct msm_iommu_context_reg ctx_regs[],
+	struct msm_scm_fault_regs_dump *dump, int cb_num)
+{
+	int i, j, ret = 0;
+	const uint32_t nvals = (dump->dump_size / sizeof(uint32_t));
+	uint32_t *it = (uint32_t *) dump->dump_data;
+	const uint32_t * const end = ((uint32_t *) dump) + nvals;
+
+	for (i = 1; it < end; it += 2, i += 2) {
+		uint32_t addr	= *it;
+		uint32_t val	= *(it + 1);
+		struct msm_iommu_context_reg *reg = NULL;
+
+		for (j = 0; j < MAX_DUMP_REGS; ++j) {
+			if (dump_regs_tbl[j].key ==
+				EXTRACT_DUMP_REG_KEY(addr, cb_num)) {
+				reg = &ctx_regs[j];
+				break;
+			}
+		}
+
+		if (reg == NULL) {
+			pr_debug("Unknown register in secure CB dump: %x (%x)\n",
+				addr, EXTRACT_DUMP_REG_KEY(addr, cb_num));
+			continue;
+		}
+
+		if (reg->valid) {
+			WARN(1, "Invalid (repeated?) register in CB dump: %x\n",
+				addr);
+			continue;
+		}
+
+		reg->val = val;
+		reg->valid = true;
+	}
+
+	if (i != nvals) {
+		pr_err("Invalid dump! %d != %d\n", i, nvals);
+		ret = 1;
+		goto out;
+	}
+
+	for (i = 0; i < MAX_DUMP_REGS; ++i) {
+		if (!ctx_regs[i].valid) {
+			pr_err("Register missing from dump: %s, %lx\n",
+				dump_regs_tbl[i].name, dump_regs_tbl[i].key);
+			ret = 1;
+		}
+	}
+
+out:
 	return ret;
 }
 
@@ -180,43 +257,40 @@
 	iommu_access_ops->iommu_clk_off(drvdata);
 
 	if (tmp) {
-		pr_err("%s: Couldn't dump fault registers!\n", __func__);
+		pr_err("%s: Couldn't dump fault registers (%d) %s, ctx: %d\n",
+			__func__, tmp, drvdata->name, ctx_drvdata->num);
 		goto free_regs;
-	} else if (regs->fsr) {
-		struct msm_iommu_context_regs ctx_regs = {
-			.far = regs->far0,
-			.par = regs->par0,
-			.fsr = regs->fsr,
-			.fsynr0 = regs->fsyn0,
-			.fsynr1 = regs->fsyn1,
-			.ttbr0 = regs->ttbr0,
-			.ttbr1 = regs->ttbr1,
-			.sctlr = regs->sctlr,
-			.actlr = regs->actlr,
-			.prrr = regs->prrr,
-			.nmrr = regs->nmrr,
-		};
-
-		if (!ctx_drvdata->attached_domain) {
-			pr_err("Bad domain in interrupt handler\n");
-			tmp = -ENOSYS;
-		} else {
-			tmp = report_iommu_fault(ctx_drvdata->attached_domain,
-				&ctx_drvdata->pdev->dev,
-				regs->far0, 0);
-		}
-
-		/* if the fault wasn't handled by someone else: */
-		if (tmp == -ENOSYS) {
-			pr_err("Unexpected IOMMU page fault from secure context bank!\n");
-			pr_err("name = %s\n", drvdata->name);
-			pr_err("context = %s (%d)\n", ctx_drvdata->name,
-				ctx_drvdata->num);
-			pr_err("Interesting registers:\n");
-			print_ctx_regs(&ctx_regs);
-		}
 	} else {
-		ret = IRQ_NONE;
+		struct msm_iommu_context_reg ctx_regs[MAX_DUMP_REGS];
+		memset(ctx_regs, 0, sizeof(ctx_regs));
+		tmp = msm_iommu_reg_dump_to_regs(ctx_regs, regs,
+						ctx_drvdata->num);
+		if (!tmp && ctx_regs[DUMP_REG_FSR].val) {
+			if (!ctx_drvdata->attached_domain) {
+				pr_err("Bad domain in interrupt handler\n");
+				tmp = -ENOSYS;
+			} else {
+				tmp = report_iommu_fault(
+					ctx_drvdata->attached_domain,
+					&ctx_drvdata->pdev->dev,
+					COMBINE_DUMP_REG(
+						ctx_regs[DUMP_REG_FAR1].val,
+						ctx_regs[DUMP_REG_FAR0].val),
+					0);
+			}
+
+			/* if the fault wasn't handled by someone else: */
+			if (tmp == -ENOSYS) {
+				pr_err("Unexpected IOMMU page fault from secure context bank!\n");
+				pr_err("name = %s\n", drvdata->name);
+				pr_err("context = %s (%d)\n", ctx_drvdata->name,
+					ctx_drvdata->num);
+				pr_err("Interesting registers:\n");
+				print_ctx_regs(ctx_regs);
+			}
+		} else {
+			ret = IRQ_NONE;
+		}
 	}
 free_regs:
 	kfree(regs);
@@ -315,6 +389,8 @@
 			unsigned long va, phys_addr_t pa, size_t len)
 {
 	struct msm_scm_map2_req map;
+	void *flush_va;
+	phys_addr_t flush_pa;
 	int ret = 0;
 
 	map.plist.list = virt_to_phys(&pa);
@@ -325,6 +401,13 @@
 	map.info.va = va;
 	map.info.size = len;
 	map.flags = IOMMU_TLBINVAL_FLAG;
+	flush_va = &pa;
+	flush_pa = virt_to_phys(&pa);
+
+	/*
+	 * Ensure that the buffer is in RAM by the time it gets to TZ
+	 */
+	clean_caches((unsigned long) flush_va, len, flush_pa);
 
 	if (scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2, &map, sizeof(map), &ret,
 								sizeof(ret)))
@@ -332,6 +415,9 @@
 	if (ret)
 		return -EINVAL;
 
+	/* Invalidate cache since TZ touched this address range */
+	invalidate_caches((unsigned long) flush_va, len, flush_pa);
+
 	return 0;
 }
 
@@ -356,6 +442,7 @@
 	struct msm_scm_map2_req map;
 	unsigned int *pa_list = 0;
 	unsigned int pa, cnt;
+	void *flush_va;
 	unsigned int offset = 0, chunk_offset = 0;
 	int ret, scm_ret;
 
@@ -370,6 +457,7 @@
 		map.plist.list = virt_to_phys(&pa);
 		map.plist.list_size = 1;
 		map.plist.size = len;
+		flush_va = &pa;
 	} else {
 		sgiter = sg;
 		cnt = sg->length / SZ_1M;
@@ -400,8 +488,15 @@
 		map.plist.list = virt_to_phys(pa_list);
 		map.plist.list_size = cnt;
 		map.plist.size = SZ_1M;
+		flush_va = pa_list;
 	}
 
+	/*
+	 * Ensure that the buffer is in RAM by the time it gets to TZ
+	 */
+	clean_caches((unsigned long) flush_va,
+		map.plist.size * map.plist.list_size, virt_to_phys(flush_va));
+
 	ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2, &map, sizeof(map),
 			&scm_ret, sizeof(scm_ret));
 	kfree(pa_list);
@@ -704,6 +799,9 @@
 
 	bus_set_iommu(&msm_iommu_sec_bus_type, &msm_iommu_ops);
 	ret = msm_iommu_sec_ptbl_init();
+	if (ret)
+		goto fail;
+	msm_iommu_sec_build_dump_regs_table();
 fail:
 	return ret;
 }
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 4835d62..bac8678 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -109,7 +109,7 @@
 #define FLASH_TMR_WATCHDOG		0x03
 #define FLASH_TMR_SAFETY		0x00
 #define FLASH_FAULT_DETECT_MASK		0X80
-#define FLASH_HW_VREG_OK		0x80
+#define FLASH_HW_VREG_OK		0x40
 #define FLASH_VREG_MASK			0xC0
 #define FLASH_STARTUP_DLY_MASK		0x02
 
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 6734da8..28e8092 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1067,6 +1067,41 @@
 	wake_up_all(&cmdbuf->queue);
 }
 
+static int dvb_dvr_external_input_only(struct dmxdev *dmxdev)
+{
+	struct dmx_caps caps;
+	int is_external_only;
+	int flags;
+	size_t tsp_size;
+
+	if (dmxdev->demux->get_tsp_size)
+		tsp_size = dmxdev->demux->get_tsp_size(dmxdev->demux);
+	else
+		tsp_size = 188;
+
+	/*
+	 * For backward compatibility, default assumes that
+	 * external only buffers are not supported.
+	 */
+	flags = 0;
+	if (dmxdev->demux->get_caps) {
+		dmxdev->demux->get_caps(dmxdev->demux, &caps);
+
+		if (tsp_size == 188)
+			flags = caps.playback_188_tsp.flags;
+		else
+			flags = caps.playback_192_tsp.flags;
+	}
+
+	if (!(flags & DMX_BUFFER_INTERNAL_SUPPORT) &&
+		(flags & DMX_BUFFER_EXTERNAL_SUPPORT))
+		is_external_only = 1;
+	else
+		is_external_only = 0;
+
+	return is_external_only;
+}
+
 static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
 			     size_t count, loff_t *ppos)
 {
@@ -1082,7 +1117,9 @@
 		return -EOPNOTSUPP;
 
 	if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
-		(!src->data) || (!cmdbuf->data))
+		!src->data || !cmdbuf->data ||
+		(dvb_dvr_external_input_only(dmxdev) &&
+		 (dmxdev->dvr_input_buffer_mode == DMX_BUFFER_MODE_INTERNAL)))
 		return -EINVAL;
 
 	if ((file->f_flags & O_NONBLOCK) &&
@@ -1238,7 +1275,7 @@
 
 	if (buf->size == size)
 		return 0;
-	if ((!size) || (buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
+	if (!size || (buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
 		return -EINVAL;
 
 	newmem = vmalloc_user(size);
@@ -1282,10 +1319,6 @@
 		(mode != DMX_BUFFER_MODE_EXTERNAL))
 		return -EINVAL;
 
-	if ((mode == DMX_BUFFER_MODE_INTERNAL) &&
-		(dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
-		return -EINVAL;
-
 	if ((mode == DMX_BUFFER_MODE_EXTERNAL) &&
 		(!dmxdev->demux->map_buffer || !dmxdev->demux->unmap_buffer))
 		return -EINVAL;
@@ -1543,7 +1576,8 @@
 
 	if (buf->size == size)
 		return 0;
-	if ((!size) || (dmxdevfilter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
+	if (!size ||
+		(dmxdevfilter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
 		return -EINVAL;
 	if (dmxdevfilter->state >= DMXDEV_STATE_GO)
 		return -EBUSY;
@@ -1580,10 +1614,6 @@
 		(mode != DMX_BUFFER_MODE_EXTERNAL))
 		return -EINVAL;
 
-	if ((mode == DMX_BUFFER_MODE_INTERNAL) &&
-		(dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
-		return -EINVAL;
-
 	if ((mode == DMX_BUFFER_MODE_EXTERNAL) &&
 		(!dmxdev->demux->map_buffer || !dmxdev->demux->unmap_buffer))
 		return -EINVAL;
@@ -1765,8 +1795,15 @@
 	int found_pid;
 	struct dmxdev_feed *feed;
 	struct dmxdev_feed *ts_feed = NULL;
+	struct dmx_caps caps;
+
+	if (!dmxdevfilter->dev->demux->get_caps)
+		return -EINVAL;
+
+	dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
 
 	if (!idx_params ||
+		!(caps.caps & DMX_CAP_VIDEO_INDEXING) ||
 		(dmxdevfilter->state < DMXDEV_STATE_SET) ||
 		(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
 		((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -1907,10 +1944,16 @@
 	int first_buffer;
 	struct dmxdev_feed *feed;
 	struct ts_insertion_buffer *ts_buffer;
+	struct dmx_caps caps;
+
+	if (!dmxdevfilter->dev->demux->get_caps)
+		return -EINVAL;
+
+	dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
 
 	if (!params ||
 		!params->size ||
-		!(dmxdevfilter->dev->capabilities & DMXDEV_CAP_TS_INSERTION) ||
+		!(caps.caps & DMX_CAP_TS_INSERTION) ||
 		(dmxdevfilter->state < DMXDEV_STATE_SET) ||
 		(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
 		((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -1974,9 +2017,15 @@
 	int found_buffer;
 	struct dmxdev_feed *feed;
 	struct ts_insertion_buffer *ts_buffer, *tmp;
+	struct dmx_caps caps;
+
+	if (!dmxdevfilter->dev->demux->get_caps)
+			return -EINVAL;
+
+	dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
 
 	if (!params ||
-		!(dmxdevfilter->dev->capabilities & DMXDEV_CAP_TS_INSERTION) ||
+		!(caps.caps & DMX_CAP_TS_INSERTION) ||
 		(dmxdevfilter->state < DMXDEV_STATE_SET) ||
 		(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
 		((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -2122,15 +2171,21 @@
 					enum dmx_playback_mode_t playback_mode)
 {
 	struct dmxdev *dmxdev = dmxdevfilter->dev;
+	struct dmx_caps caps;
+
+	if (dmxdev->demux->get_caps)
+		dmxdev->demux->get_caps(dmxdev->demux, &caps);
+	else
+		caps.caps = 0;
 
 	if ((playback_mode != DMX_PB_MODE_PUSH) &&
 		(playback_mode != DMX_PB_MODE_PULL))
 		return -EINVAL;
 
 	if (((dmxdev->source < DMX_SOURCE_DVR0) ||
-		!dmxdev->demux->set_playback_mode ||
-		!(dmxdev->capabilities & DMXDEV_CAP_PULL_MODE)) &&
-		(playback_mode == DMX_PB_MODE_PULL))
+		 !dmxdev->demux->set_playback_mode ||
+		 !(caps.caps & DMX_CAP_PULL_MODE)) &&
+		 (playback_mode == DMX_PB_MODE_PULL))
 		return -EPERM;
 
 	if (dmxdevfilter->state == DMXDEV_STATE_GO)
@@ -3083,6 +3138,43 @@
 	return 0;
 }
 
+static int dvb_filter_external_buffer_only(struct dmxdev *dmxdev,
+	struct dmxdev_filter *filter)
+{
+	struct dmx_caps caps;
+	int is_external_only;
+	int flags;
+
+	/*
+	 * For backward compatibility, default assumes that
+	 * external only buffers are not supported.
+	 */
+	flags = 0;
+	if (dmxdev->demux->get_caps) {
+		dmxdev->demux->get_caps(dmxdev->demux, &caps);
+
+		if (filter->type == DMXDEV_TYPE_SEC)
+			flags = caps.section.flags;
+		else if (filter->params.pes.output == DMX_OUT_DECODER)
+			/* For decoder filters dmxdev buffer is not required */
+			flags = 0;
+		else if (filter->params.pes.output == DMX_OUT_TAP)
+			flags = caps.pes.flags;
+		else if (filter->dmx_tsp_format == DMX_TSP_FORMAT_188)
+			flags = caps.recording_188_tsp.flags;
+		else
+			flags = caps.recording_192_tsp.flags;
+	}
+
+	if (!(flags & DMX_BUFFER_INTERNAL_SUPPORT) &&
+		(flags & DMX_BUFFER_EXTERNAL_SUPPORT))
+		is_external_only = 1;
+	else
+		is_external_only = 0;
+
+	return is_external_only;
+}
+
 static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
 {
 	struct dmxdev *dmxdev = filter->dev;
@@ -3098,14 +3190,18 @@
 
 	if (!filter->buffer.data) {
 		if ((filter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL) ||
-			(dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
+			dvb_filter_external_buffer_only(dmxdev, filter))
 			return -ENOMEM;
+
 		mem = vmalloc_user(filter->buffer.size);
 		if (!mem)
 			return -ENOMEM;
 		spin_lock_irq(&filter->dev->lock);
 		filter->buffer.data = mem;
 		spin_unlock_irq(&filter->dev->lock);
+	} else if ((filter->buffer_mode == DMX_BUFFER_MODE_INTERNAL) &&
+			dvb_filter_external_buffer_only(dmxdev, filter)) {
+		return -ENOMEM;
 	}
 
 	filter->eos_state = 0;
@@ -3577,10 +3673,13 @@
 	struct dmx_decoder_buffers *dec_buffs;
 	struct dmx_caps caps;
 
-	if (NULL == dmxdev || NULL == filter || NULL == buffs)
+	if (!dmxdev || !filter || !buffs)
 		return -EINVAL;
 
 	dec_buffs = &filter->decoder_buffers;
+	if (!dmxdev->demux->get_caps)
+		return -EINVAL;
+
 	dmxdev->demux->get_caps(dmxdev->demux, &caps);
 
 	if ((buffs->buffers_size == 0) ||
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 49e5e1b..4e306e8 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -196,11 +196,6 @@
 	int filternum;
 	int capabilities;
 #define DMXDEV_CAP_DUPLEX	0x01
-#define DMXDEV_CAP_PULL_MODE	0x02
-#define DMXDEV_CAP_INDEXING	0x04
-#define DMXDEV_CAP_EXTERNAL_BUFFS_ONLY	0x08
-#define DMXDEV_CAP_TS_INSERTION	0x10
-
 
 	enum dmx_playback_mode_t playback_mode;
 	dmx_source_t source;
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index 525a545..3a30970 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -137,6 +137,15 @@
 		hfr video at 60, 90 and 120 fps. This sensor driver does
 		not support auto focus.
 
+config HI256
+        bool "Hynix hi256 (YUV 2MP)"
+        depends on MSMB_CAMERA
+        ---help---
+                OmniVision 8 MP Bayer Sensor with auto focus.uses
+                2 mipi lanes, preview config = 1632*1224 30 fps,
+                snapshot config = 3264 * 2448 at 18 fps.
+                2 lanes max fps is 18, 4 lanes max fps is 24.
+
 config MT9M114
 	bool "Sensor MT9M114 (YUV 1.26MP)"
 	depends on MSMB_CAMERA
@@ -146,6 +155,15 @@
 		1280 * 270. It does not support auto focus. It supports
 		few special effects like saturation.
 
+config SP1628
+	bool "Sensor SP1628 (YUV 720P)"
+	depends on MSMB_CAMERA
+	---help---
+		SP1628 is SuperPix YUV sensor. It supports 720P preview
+		and snapshot. The preview and snapshot resolution shall be
+		1280 * 270. It does not support auto focus. It supports
+		few special effects like mono.
+
 config OV8825
 	bool "OmniVision OV8825 (BAYER 8MP)"
 	depends on MSMB_CAMERA
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 84ba4d1..2ff70d3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -32,6 +32,7 @@
 
 #define VFE40_8974V1_VERSION 0x10000018
 #define VFE40_8974V2_VERSION 0x1001001A
+#define VFE40_8974V3_VERSION 0x1001001B
 #define VFE40_8x26_VERSION 0x20000013
 
 #define VFE40_BURST_LEN 3
@@ -102,7 +103,8 @@
 		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_5);
 		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_6);
 		msm_camera_io_w(0x0002AAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_7);
-	} else if (vfe_dev->vfe_hw_version == VFE40_8974V2_VERSION) {
+	} else if (vfe_dev->vfe_hw_version == VFE40_8974V2_VERSION ||
+		vfe_dev->vfe_hw_version == VFE40_8974V3_VERSION) {
 		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_0);
 		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_1);
 		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_2);
@@ -231,6 +233,7 @@
 		msm_vfe40_init_vbif_parms_8974_v1(vfe_dev);
 		break;
 	case VFE40_8974V2_VERSION:
+	case VFE40_8974V3_VERSION:
 		msm_vfe40_init_vbif_parms_8974_v2(vfe_dev);
 		break;
 	case VFE40_8x26_VERSION:
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index e74f1082..df72328 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -698,11 +698,9 @@
 	iounmap(cpp_dev->cpp_hw_base);
 	msm_cam_clk_enable(&cpp_dev->pdev->dev, cpp_clk_info,
 		cpp_dev->cpp_clk, ARRAY_SIZE(cpp_clk_info), 0);
-	if (0) {
-		regulator_disable(cpp_dev->fs_cpp);
-		regulator_put(cpp_dev->fs_cpp);
-		cpp_dev->fs_cpp = NULL;
-	}
+	regulator_disable(cpp_dev->fs_cpp);
+	regulator_put(cpp_dev->fs_cpp);
+	cpp_dev->fs_cpp = NULL;
 	msm_isp_update_bandwidth(ISP_CPP, 0, 0);
 	msm_isp_deinit_bandwidth_mgr(ISP_CPP);
 }
@@ -819,6 +817,7 @@
 	cpp_dev->cpp_open_cnt++;
 	if (cpp_dev->cpp_open_cnt == 1) {
 		cpp_init_hardware(cpp_dev);
+		iommu_attach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
 		cpp_init_mem(cpp_dev);
 		cpp_dev->state = CPP_STATE_IDLE;
 	}
@@ -855,6 +854,7 @@
 	if (cpp_dev->cpp_open_cnt == 0) {
 		msm_camera_io_w(0x0, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL);
 		cpp_deinit_mem(cpp_dev);
+		iommu_detach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
 		cpp_release_hardware(cpp_dev);
 		cpp_dev->state = CPP_STATE_OFF;
 	}
@@ -1467,6 +1467,7 @@
 	return msm_register_domain(&cpp_fw_layout);
 }
 
+
 static int __devinit cpp_probe(struct platform_device *pdev)
 {
 	struct cpp_device *cpp_dev;
@@ -1581,7 +1582,6 @@
 	cpp_dev->msm_sd.sd.entity.revision = cpp_dev->msm_sd.sd.devnode->num;
 	cpp_dev->state = CPP_STATE_BOOT;
 	cpp_init_hardware(cpp_dev);
-	iommu_attach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
 
 	msm_camera_io_w(0x0, cpp_dev->base +
 					   MSM_CPP_MICRO_IRQGEN_MASK);
@@ -1599,7 +1599,6 @@
 	cpp_dev->cpp_open_cnt = 0;
 	cpp_dev->is_firmware_loaded = 0;
 	return rc;
-
 ERROR3:
 	release_mem_region(cpp_dev->mem->start, resource_size(cpp_dev->mem));
 ERROR2:
@@ -1629,7 +1628,6 @@
 		return 0;
 	}
 
-	iommu_detach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
 	msm_sd_unregister(&cpp_dev->msm_sd);
 	release_mem_region(cpp_dev->mem->start, resource_size(cpp_dev->mem));
 	release_mem_region(cpp_dev->vbif_mem->start,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index 300daca..c188105 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -30,6 +30,7 @@
 static struct msm_actuator msm_vcm_actuator_table;
 static struct msm_actuator msm_piezo_actuator_table;
 
+static struct i2c_driver msm_actuator_i2c_driver;
 static struct msm_actuator *actuators[] = {
 	&msm_vcm_actuator_table,
 	&msm_piezo_actuator_table,
@@ -549,7 +550,11 @@
 		pr_err("failed\n");
 		return -EINVAL;
 	}
-	*subdev_id = a_ctrl->pdev->id;
+	if (a_ctrl->act_device_type == MSM_CAMERA_PLATFORM_DEVICE)
+		*subdev_id = a_ctrl->pdev->id;
+	else
+		*subdev_id = a_ctrl->subdev_id;
+
 	CDBG("subdev_id %d\n", *subdev_id);
 	CDBG("Exit\n");
 	return 0;
@@ -684,6 +689,11 @@
 	.core = &msm_actuator_subdev_core_ops,
 };
 
+static const struct i2c_device_id msm_actuator_i2c_id[] = {
+	{"qcom,actuator", (kernel_ulong_t)NULL},
+	{ }
+};
+
 static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
@@ -691,19 +701,46 @@
 	struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
 	CDBG("Enter\n");
 
+	if (client == NULL) {
+		pr_err("msm_actuator_i2c_probe: client is null\n");
+		rc = -EINVAL;
+		goto probe_failure;
+	}
+
+	act_ctrl_t = kzalloc(sizeof(struct msm_actuator_ctrl_t),
+		GFP_KERNEL);
+	if (!act_ctrl_t) {
+		pr_err("%s:%d failed no memory\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		pr_err("i2c_check_functionality failed\n");
 		goto probe_failure;
 	}
 
-	act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
 	CDBG("client = %x\n", (unsigned int) client);
+
+	rc = of_property_read_u32(client->dev.of_node, "cell-index",
+		&act_ctrl_t->subdev_id);
+	CDBG("cell-index %d, rc %d\n", act_ctrl_t->subdev_id, rc);
+	if (rc < 0) {
+		pr_err("failed rc %d\n", rc);
+		return rc;
+	}
+
+	act_ctrl_t->i2c_driver = &msm_actuator_i2c_driver;
 	act_ctrl_t->i2c_client.client = client;
+	act_ctrl_t->curr_step_pos = 0,
+	act_ctrl_t->curr_region_index = 0,
 	/* Set device type as I2C */
 	act_ctrl_t->act_device_type = MSM_CAMERA_I2C_DEVICE;
 	act_ctrl_t->i2c_client.i2c_func_tbl = &msm_sensor_qup_func_tbl;
 	act_ctrl_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
 	act_ctrl_t->actuator_mutex = &msm_actuator_mutex;
+
+	act_ctrl_t->cam_name = act_ctrl_t->subdev_id;
+	CDBG("act_ctrl_t->cam_name: %d", act_ctrl_t->cam_name);
 	/* Assign name for sub device */
 	snprintf(act_ctrl_t->msm_sd.sd.name, sizeof(act_ctrl_t->msm_sd.sd.name),
 		"%s", act_ctrl_t->i2c_driver->driver.name);
@@ -720,7 +757,7 @@
 	act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
 	act_ctrl_t->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x2;
 	msm_sd_register(&act_ctrl_t->msm_sd);
-	CDBG("succeeded\n");
+	pr_info("msm_actuator_i2c_probe: succeeded\n");
 	CDBG("Exit\n");
 
 probe_failure:
@@ -795,17 +832,21 @@
 	return rc;
 }
 
-static const struct i2c_device_id msm_actuator_i2c_id[] = {
-	{"msm_actuator", (kernel_ulong_t)NULL},
-	{ }
+static const struct of_device_id msm_actuator_i2c_dt_match[] = {
+	{.compatible = "qcom,actuator"},
+	{}
 };
 
+MODULE_DEVICE_TABLE(of, msm_actuator_i2c_dt_match);
+
 static struct i2c_driver msm_actuator_i2c_driver = {
 	.id_table = msm_actuator_i2c_id,
 	.probe  = msm_actuator_i2c_probe,
 	.remove = __exit_p(msm_actuator_i2c_remove),
 	.driver = {
-		.name = "msm_actuator",
+		.name = "qcom,actuator",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_actuator_i2c_dt_match,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
index c616307..c4a4137 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
@@ -80,6 +80,7 @@
 	struct msm_camera_i2c_reg_tbl *i2c_reg_tbl;
 	uint16_t i2c_tbl_index;
 	enum cci_i2c_master_t cci_master;
+	uint32_t subdev_id;
 };
 
 #endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
index 7af0c14..9aca234 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
@@ -201,9 +201,21 @@
 	{"csi_ahb_clk", -1},
 	{"csi_src_clk", 200000000},
 	{"csi_clk", -1},
-	{"csi_phy_clk", -1},
-	{"csi_pix_clk", -1},
-	{"csi_rdi_clk", -1},
+	{"csi0phy_mux_clk", -1},
+	{"csi1phy_mux_clk", -1},
+	{"csi0pix_mux_clk", -1},
+	{"csi0rdi_mux_clk", -1},
+	{"csi1rdi_mux_clk", -1},
+	{"csi2rdi_mux_clk", -1},
+};
+
+static struct msm_cam_clk_info csid_8610_clk_src_info[] = {
+	{"csi_phy_src_clk", 0},
+	{"csi_phy_src_clk", 0},
+	{"csi_pix_src_clk", 0},
+	{"csi_rdi_src_clk", 0},
+	{"csi_rdi_src_clk", 0},
+	{"csi_rdi_src_clk", 0},
 };
 
 static struct camera_vreg_t csid_8960_vreg_info[] = {
@@ -271,6 +283,9 @@
 				goto clk_enable_failed;
 			}
 		} else {
+			msm_cam_clk_sel_src(&csid_dev->pdev->dev,
+				&csid_8610_clk_info[3], csid_8610_clk_src_info,
+				ARRAY_SIZE(csid_8610_clk_src_info));
 			rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
 				csid_8610_clk_info, csid_dev->csid_clk,
 				ARRAY_SIZE(csid_8610_clk_info), 1);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
index e30e798..c2a5cad 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
@@ -107,6 +107,34 @@
 	msm_camera_io_dump(dest_addr, len);
 }
 
+int msm_cam_clk_sel_src(struct device *dev, struct msm_cam_clk_info *clk_info,
+		struct msm_cam_clk_info *clk_src_info, int num_clk)
+{
+	int i;
+	int rc = 0;
+	struct clk *mux_clk = NULL;
+	struct clk *src_clk = NULL;
+
+	for (i = 0; i < num_clk; i++) {
+		if (clk_src_info[i].clk_name) {
+			mux_clk = clk_get(dev, clk_info[i].clk_name);
+			if (IS_ERR(mux_clk)) {
+				pr_err("%s get failed\n",
+					 clk_info[i].clk_name);
+				continue;
+			}
+			src_clk = clk_get(dev, clk_src_info[i].clk_name);
+			if (IS_ERR(src_clk)) {
+				pr_err("%s get failed\n",
+					clk_src_info[i].clk_name);
+				continue;
+			}
+			clk_set_parent(mux_clk, src_clk);
+		}
+	}
+	return rc;
+}
+
 int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
 		struct clk **clk_ptr, int num_clk, int enable)
 {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h
index 499a045..73376e2 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h
@@ -25,7 +25,8 @@
 void msm_camera_io_dump(void __iomem *addr, int size);
 void msm_camera_io_memcpy(void __iomem *dest_addr,
 		void __iomem *src_addr, u32 len);
-
+int msm_cam_clk_sel_src(struct device *dev, struct msm_cam_clk_info *clk_info,
+		struct msm_cam_clk_info *clk_src_info, int num_clk);
 int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
 		struct clk **clk_ptr, int num_clk, int enable);
 
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
index 29369de..ef3f57f 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
@@ -548,7 +548,8 @@
 		return -EINVAL;
 	}
 
-	caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA;
+	caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA |
+		DMX_CAP_TS_INSERTION | DMX_CAP_VIDEO_INDEXING;
 	caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
 	caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
 	caps->num_pid_filters = dvb_demux->feednum;
@@ -599,7 +600,6 @@
 	caps->playback_192_tsp.max_size = 0xFFFFFFFF;
 	caps->playback_192_tsp.size_alignment = 0;
 	caps->decoder.flags =
-		DMX_BUFFER_CONTIGUOUS_MEM	|
 		DMX_BUFFER_SECURED_IF_DECRYPTED	|
 		DMX_BUFFER_EXTERNAL_SUPPORT	|
 		DMX_BUFFER_INTERNAL_SUPPORT	|
@@ -700,11 +700,7 @@
 	/* Now initailize the dmx-dev object */
 	mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
 	mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
-	mpq_demux->dmxdev.capabilities =
-		DMXDEV_CAP_DUPLEX |
-		DMXDEV_CAP_PULL_MODE |
-		DMXDEV_CAP_INDEXING |
-		DMXDEV_CAP_TS_INSERTION;
+	mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
 
 	mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
 	mpq_demux->dmxdev.demux->get_stc = mpq_tsif_dmx_get_stc;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index a2ce428..8e628f6 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -1614,7 +1614,8 @@
 		return -EINVAL;
 	}
 
-	caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA;
+	caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA |
+		DMX_CAP_TS_INSERTION | DMX_CAP_VIDEO_INDEXING;
 	caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
 	caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
 	caps->num_pid_filters = TSPP_MAX_PID_FILTER_NUM;
@@ -1623,9 +1624,9 @@
 	caps->section_filter_length = DMX_FILTER_SIZE;
 	caps->num_demod_inputs = TSIF_COUNT;
 	caps->num_memory_inputs = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
-	caps->max_bitrate = 144;
-	caps->demod_input_max_bitrate = 72;
-	caps->memory_input_max_bitrate = 72;
+	caps->max_bitrate = 192;
+	caps->demod_input_max_bitrate = 96;
+	caps->memory_input_max_bitrate = 96;
 
 	/* Buffer requirements */
 	caps->section.flags =
@@ -1665,7 +1666,6 @@
 	caps->playback_192_tsp.max_size = 0xFFFFFFFF;
 	caps->playback_192_tsp.size_alignment = 0;
 	caps->decoder.flags =
-		DMX_BUFFER_CONTIGUOUS_MEM	|
 		DMX_BUFFER_SECURED_IF_DECRYPTED	|
 		DMX_BUFFER_EXTERNAL_SUPPORT	|
 		DMX_BUFFER_INTERNAL_SUPPORT	|
@@ -1758,11 +1758,7 @@
 	/* Now initailize the dmx-dev object */
 	mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
 	mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
-	mpq_demux->dmxdev.capabilities =
-		DMXDEV_CAP_DUPLEX |
-		DMXDEV_CAP_PULL_MODE |
-		DMXDEV_CAP_INDEXING |
-		DMXDEV_CAP_TS_INSERTION;
+	mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
 
 	mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
 	mpq_demux->dmxdev.demux->get_stc = mpq_tspp_dmx_get_stc;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
index 60e3cb4..1ab9da1 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
@@ -73,7 +73,7 @@
 	}
 
 	caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_INDEXING |
-		DMX_CAP_VIDEO_DECODER_DATA;
+		DMX_CAP_VIDEO_DECODER_DATA | DMX_CAP_TS_INSERTION;
 	caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
 	caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
 	caps->num_pid_filters = TSPP_MAX_PID_FILTER_NUM;
@@ -140,11 +140,7 @@
 	/* Now initailize the dmx-dev object */
 	mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
 	mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
-	mpq_demux->dmxdev.capabilities =
-		DMXDEV_CAP_DUPLEX |
-		DMXDEV_CAP_PULL_MODE |
-		DMXDEV_CAP_INDEXING |
-		DMXDEV_CAP_TS_INSERTION;
+	mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
 
 	mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
 	mpq_demux->dmxdev.demux->get_caps = mpq_tspp_dmx_get_caps;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 8453b81..15ac493 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -2322,13 +2322,15 @@
 	bus_info = &device->resources.bus_info;
 
 	bus_info->ddr_handle[MSM_VIDC_ENCODER] =
-		msm_bus_scale_register_client(&device->res->bus_pdata[2]);
+		msm_bus_scale_register_client(
+			&device->res->bus_pdata[BUS_IDX_ENC_DDR]);
 	if (!bus_info->ddr_handle[MSM_VIDC_ENCODER]) {
 		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
 		goto err_init_bus;
 	}
 	bus_info->ddr_handle[MSM_VIDC_DECODER] =
-		msm_bus_scale_register_client(&device->res->bus_pdata[3]);
+		msm_bus_scale_register_client(
+			&device->res->bus_pdata[BUS_IDX_DEC_DDR]);
 	if (!bus_info->ddr_handle[MSM_VIDC_DECODER]) {
 		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
 		goto err_init_bus;
@@ -2337,7 +2339,7 @@
 	if (device->res->has_ocmem) {
 		bus_info->ocmem_handle[MSM_VIDC_ENCODER] =
 			msm_bus_scale_register_client(
-						&device->res->bus_pdata[0]);
+				&device->res->bus_pdata[BUS_IDX_ENC_OCMEM]);
 		if (!bus_info->ocmem_handle[MSM_VIDC_ENCODER]) {
 			dprintk(VIDC_ERR,
 				"Failed to register bus scale client\n");
@@ -2346,7 +2348,7 @@
 
 		bus_info->ocmem_handle[MSM_VIDC_DECODER] =
 			msm_bus_scale_register_client(
-						&device->res->bus_pdata[1]);
+				&device->res->bus_pdata[BUS_IDX_DEC_OCMEM]);
 		if (!bus_info->ocmem_handle[MSM_VIDC_DECODER]) {
 			dprintk(VIDC_ERR,
 				"Failed to register bus scale client\n");
@@ -2370,15 +2372,35 @@
 	979200,
 };
 
-static int venus_hfi_get_bus_vector(int load)
+static int venus_hfi_get_bus_vector(struct venus_hfi_device *device, int load,
+			enum session_type type, enum mem_type mtype)
 {
 	int num_rows = sizeof(venus_hfi_bus_table)/(sizeof(u32));
 	int i, j;
+	int idx = 0;
+
+	if (!device || (mtype != DDR_MEM && mtype != OCMEM_MEM) ||
+		(type != MSM_VIDC_ENCODER && type != MSM_VIDC_DECODER)) {
+		dprintk(VIDC_ERR, "%s invalid params", __func__);
+		return -EINVAL;
+	}
+
 	for (i = 0; i < num_rows; i++) {
 		if (load <= venus_hfi_bus_table[i])
 			break;
 	}
+
+	if (type == MSM_VIDC_ENCODER)
+		idx = (mtype == DDR_MEM) ? BUS_IDX_ENC_DDR : BUS_IDX_ENC_OCMEM;
+	else
+		idx = (mtype == DDR_MEM) ? BUS_IDX_DEC_DDR : BUS_IDX_DEC_OCMEM;
+
 	j = clamp(i, 0, num_rows-1) + 1;
+
+	/* Ensure bus index remains within the supported range,
+	* as specified in the device dtsi file */
+	j = clamp(j, 0, device->res->bus_pdata[idx].num_usecases - 1);
+
 	dprintk(VIDC_DBG, "Required bus = %d\n", j);
 	return j;
 }
@@ -2389,6 +2411,7 @@
 	int rc = 0;
 	u32 handle = 0;
 	struct venus_hfi_device *device = dev;
+	int bus_vector = 0;
 
 	if (!device) {
 		dprintk(VIDC_ERR, "%s invalid device handle %p",
@@ -2402,8 +2425,13 @@
 		handle = device->resources.bus_info.ocmem_handle[type];
 
 	if (handle) {
-		rc = msm_bus_scale_client_update_request(
-				handle, venus_hfi_get_bus_vector(load));
+		bus_vector = venus_hfi_get_bus_vector(device, load,
+				type, mtype);
+		if (bus_vector < 0) {
+			dprintk(VIDC_ERR, "Failed to get bus vector\n");
+			return -EINVAL;
+		}
+		rc = msm_bus_scale_client_update_request(handle, bus_vector);
 		if (rc)
 			dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
 	} else {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index 197c754..a59a053 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -116,6 +116,14 @@
 	VIDC_HWREG_HVI_SOFTINTEN =  0xA,
 };
 
+enum bus_index {
+	BUS_IDX_ENC_OCMEM,
+	BUS_IDX_DEC_OCMEM,
+	BUS_IDX_ENC_DDR,
+	BUS_IDX_DEC_DDR,
+	BUS_IDX_MAX
+};
+
 struct vidc_mem_addr {
 	u8 *align_device_addr;
 	u8 *align_virtual_addr;
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index 0388484..eb8320f 100644
--- a/drivers/mfd/pm8xxx-pwm.c
+++ b/drivers/mfd/pm8xxx-pwm.c
@@ -262,6 +262,9 @@
 
 	chip = pwm->chip;
 
+	if (!pwm->banks)
+		pwm->banks = (PM_PWM_BANK_LO | PM_PWM_BANK_HI);
+
 	if (pwm->banks & PM_PWM_BANK_LO) {
 		if (enable)
 			reg = chip->lo_bank_mask | (1 << pwm->pwm_id);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 3986cdd..e285bfa 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -3747,6 +3747,7 @@
 {
 	struct msmsdcc_host *host = mmc_priv(mmc);
 	unsigned long flags;
+	bool prev_pwrsave, curr_pwrsave;
 	int rc = 0;
 
 	switch (ios->signal_voltage) {
@@ -3779,7 +3780,9 @@
 	 * low voltage is required
 	 */
 	spin_lock_irqsave(&host->lock, flags);
-
+	prev_pwrsave = !!(readl_relaxed(host->base + MMCICLOCK) &
+			MCI_CLK_PWRSAVE);
+	curr_pwrsave = prev_pwrsave;
 	/*
 	 * Poll on MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT
 	 * register until they become all zeros.
@@ -3792,9 +3795,12 @@
 	}
 
 	/* Stop SD CLK output. */
-	writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
-			MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
-	msmsdcc_sync_reg_wr(host);
+	if (!prev_pwrsave) {
+		writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
+				MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+		msmsdcc_sync_reg_wr(host);
+		curr_pwrsave = true;
+	}
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	/*
@@ -3815,6 +3821,7 @@
 	writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
 			& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
 	msmsdcc_sync_reg_wr(host);
+	curr_pwrsave = false;
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	/*
@@ -3835,10 +3842,9 @@
 	}
 
 out_unlock:
-	/* Enable PWRSAVE */
-	writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
-			MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
-	msmsdcc_sync_reg_wr(host);
+	/* Restore the correct PWRSAVE state */
+	if (prev_pwrsave ^ curr_pwrsave)
+		msmsdcc_set_pwrsave(mmc, prev_pwrsave);
 	spin_unlock_irqrestore(&host->lock, flags);
 out:
 	return rc;
@@ -3877,17 +3883,24 @@
 	int rc = 0;
 	unsigned long flags;
 	u32 wait_cnt;
+	bool prev_pwrsave, curr_pwrsave;
 
 	spin_lock_irqsave(&host->lock, flags);
+	prev_pwrsave = !!(readl_relaxed(host->base + MMCICLOCK) &
+			MCI_CLK_PWRSAVE);
+	curr_pwrsave = prev_pwrsave;
 	/*
 	 * Make sure that clock is always enabled when DLL
 	 * tuning is in progress. Keeping PWRSAVE ON may
 	 * turn off the clock. So let's disable the PWRSAVE
 	 * here and re-enable it once tuning is completed.
 	 */
-	writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
-			& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
-	msmsdcc_sync_reg_wr(host);
+	if (prev_pwrsave) {
+		writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
+				& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+		msmsdcc_sync_reg_wr(host);
+		curr_pwrsave = false;
+	}
 
 	/* Write 1 to DLL_RST bit of MCI_DLL_CONFIG register */
 	writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
@@ -3930,10 +3943,9 @@
 	}
 
 out:
-	/* re-enable PWRSAVE */
-	writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
-			MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
-	msmsdcc_sync_reg_wr(host);
+	/* Restore the correct PWRSAVE state */
+	if (prev_pwrsave ^ curr_pwrsave)
+		msmsdcc_set_pwrsave(host->mmc, prev_pwrsave);
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	return rc;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index c73bf01..c86eef8 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -512,19 +512,25 @@
 	int rc = 0;
 	unsigned long flags;
 	u32 wait_cnt;
+	bool prev_pwrsave, curr_pwrsave;
 
 	pr_debug("%s: Enter %s\n", mmc_hostname(mmc), __func__);
 	spin_lock_irqsave(&host->lock, flags);
-
+	prev_pwrsave = !!(readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) &
+			  CORE_CLK_PWRSAVE);
+	curr_pwrsave = prev_pwrsave;
 	/*
 	 * Make sure that clock is always enabled when DLL
 	 * tuning is in progress. Keeping PWRSAVE ON may
 	 * turn off the clock. So let's disable the PWRSAVE
 	 * here and re-enable it once tuning is completed.
 	 */
-	writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
-			& ~CORE_CLK_PWRSAVE),
-			host->ioaddr + CORE_VENDOR_SPEC);
+	if (prev_pwrsave) {
+		writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
+				& ~CORE_CLK_PWRSAVE),
+				host->ioaddr + CORE_VENDOR_SPEC);
+		curr_pwrsave = false;
+	}
 
 	/* Write 1 to DLL_RST bit of DLL_CONFIG register */
 	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
@@ -567,10 +573,18 @@
 	}
 
 out:
-	/* re-enable PWRSAVE */
-	writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) |
-			CORE_CLK_PWRSAVE),
-			host->ioaddr + CORE_VENDOR_SPEC);
+	/* Restore the correct PWRSAVE state */
+	if (prev_pwrsave ^ curr_pwrsave) {
+		u32 reg = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+
+		if (prev_pwrsave)
+			reg |= CORE_CLK_PWRSAVE;
+		else
+			reg &= ~CORE_CLK_PWRSAVE;
+
+		writel_relaxed(reg, host->ioaddr + CORE_VENDOR_SPEC);
+	}
+
 	spin_unlock_irqrestore(&host->lock, flags);
 	pr_debug("%s: Exit %s\n", mmc_hostname(mmc), __func__);
 	return rc;
@@ -2405,6 +2419,7 @@
 	msm_host->mmc->caps2 |= MMC_CAP2_POWEROFF_NOTIFY;
 	msm_host->mmc->caps2 |= MMC_CAP2_CLK_SCALE;
 	msm_host->mmc->caps2 |= MMC_CAP2_STOP_REQUEST;
+	msm_host->mmc->caps2 |= MMC_CAP2_ASYNC_SDIO_IRQ_4BIT_MODE;
 
 	if (msm_host->pdata->nonremovable)
 		msm_host->mmc->caps |= MMC_CAP_NONREMOVABLE;
diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c
index c02daa4..2251f2f 100644
--- a/drivers/net/wireless/wcnss/wcnss_vreg.c
+++ b/drivers/net/wireless/wcnss/wcnss_vreg.c
@@ -100,7 +100,7 @@
 	{"qcom,iris-vddpa",  VREG_NULL_CONFIG, 2900000, 0,
 		3000000, 515000, NULL},
 	{"qcom,iris-vdddig", VREG_NULL_CONFIG, 1225000, 0,
-		1300000, 10000,  NULL},
+		1800000, 10000,  NULL},
 };
 
 /* WCNSS regulators for Pronto hardware */
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index ba81e5d..38a1a9c 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -400,8 +400,8 @@
 			tx_pkt->mult.base = transfer.iovec;
 			tx_pkt->mult.size = size;
 			tx_pkt->cnt = num_desc;
-			INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
 		}
+		INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
 
 		iovec = &transfer.iovec[i];
 		iovec->flags = 0;
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index d378838..087cfa8 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -43,9 +43,14 @@
 #define QPNP_PON_RESIN_S2_TIMER(base)		(base + 0x45)
 #define QPNP_PON_RESIN_S2_CNTL(base)		(base + 0x46)
 #define QPNP_PON_RESIN_S2_CNTL2(base)		(base + 0x47)
+#define QPNP_PON_KPDPWR_RESIN_S1_TIMER(base)	(base + 0x48)
+#define QPNP_PON_KPDPWR_RESIN_S2_TIMER(base)	(base + 0x49)
+#define QPNP_PON_KPDPWR_RESIN_S2_CNTL(base)	(base + 0x4A)
+#define QPNP_PON_KPDPWR_RESIN_S2_CNTL2(base)	(base + 0x4B)
 #define QPNP_PON_PS_HOLD_RST_CTL(base)		(base + 0x5A)
 #define QPNP_PON_PS_HOLD_RST_CTL2(base)		(base + 0x5B)
 #define QPNP_PON_TRIGGER_EN(base)		(base + 0x80)
+#define QPNP_PON_S3_DBC_CTL(base)		(base + 0x75)
 
 #define QPNP_PON_WARM_RESET_TFT			BIT(4)
 
@@ -65,6 +70,7 @@
 #define QPNP_PON_RESIN_N_SET			BIT(1)
 #define QPNP_PON_CBLPWR_N_SET			BIT(2)
 #define QPNP_PON_RESIN_BARK_N_SET		BIT(4)
+#define QPNP_PON_KPDPWR_RESIN_BARK_N_SET	BIT(5)
 
 #define QPNP_PON_RESET_EN			BIT(7)
 #define QPNP_PON_WARM_RESET			BIT(0)
@@ -73,6 +79,8 @@
 /* Ranges */
 #define QPNP_PON_S1_TIMER_MAX			10256
 #define QPNP_PON_S2_TIMER_MAX			2000
+#define QPNP_PON_S3_TIMER_SECS_MAX		128
+#define QPNP_PON_S3_DBC_DELAY_MASK		0x07
 #define QPNP_PON_RESET_TYPE_MAX			0xF
 #define PON_S1_COUNT_MAX			0xF
 
@@ -83,6 +91,7 @@
 	PON_KPDPWR,
 	PON_RESIN,
 	PON_CBLPWR,
+	PON_KPDPWR_RESIN,
 };
 
 struct qpnp_pon_config {
@@ -325,6 +334,9 @@
 	case PON_CBLPWR:
 		pon_rt_bit = QPNP_PON_CBLPWR_N_SET;
 		break;
+	case PON_KPDPWR_RESIN:
+		pon_rt_bit = QPNP_PON_KPDPWR_RESIN_BARK_N_SET;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -364,6 +376,11 @@
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t qpnp_kpdpwr_resin_bark_irq(int irq, void *_pon)
+{
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t qpnp_cblpwr_irq(int irq, void *_pon)
 {
 	int rc;
@@ -477,6 +494,9 @@
 	case PON_CBLPWR:
 		pull_bit = QPNP_PON_CBLPWR_PULL_UP;
 		break;
+	case PON_KPDPWR_RESIN:
+		pull_bit = QPNP_PON_KPDPWR_PULL_UP | QPNP_PON_RESIN_PULL_UP;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -505,6 +525,10 @@
 		s1_timer_addr = QPNP_PON_RESIN_S1_TIMER(pon->base);
 		s2_timer_addr = QPNP_PON_RESIN_S2_TIMER(pon->base);
 		break;
+	case PON_KPDPWR_RESIN:
+		s1_timer_addr = QPNP_PON_KPDPWR_RESIN_S1_TIMER(pon->base);
+		s2_timer_addr = QPNP_PON_KPDPWR_RESIN_S2_TIMER(pon->base);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -624,6 +648,20 @@
 			return rc;
 		}
 		break;
+	case PON_KPDPWR_RESIN:
+		if (cfg->support_reset) {
+			rc = devm_request_irq(&pon->spmi->dev, cfg->bark_irq,
+					qpnp_kpdpwr_resin_bark_irq,
+					IRQF_TRIGGER_RISING,
+					"qpnp_kpdpwr_resin_bark", pon);
+			if (rc < 0) {
+				dev_err(&pon->spmi->dev,
+					"Can't request %d IRQ\n",
+						cfg->bark_irq);
+				return rc;
+			}
+		}
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -663,11 +701,11 @@
 	int rc = 0, i = 0;
 	struct device_node *pp = NULL;
 	struct qpnp_pon_config *cfg;
-	u8 reg;
+	u8 pon_ver;
 
 	/* Check if it is rev B */
 	rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
-			QPNP_PON_REVISION2(pon->base), &reg, 1);
+			QPNP_PON_REVISION2(pon->base), &pon_ver, 1);
 	if (rc) {
 		dev_err(&pon->spmi->dev,
 			"Unable to read addr=%x, rc(%d)\n",
@@ -714,7 +752,7 @@
 				}
 			}
 
-			if (reg == QPNP_PON_REV_B) {
+			if (pon_ver == QPNP_PON_REV_B) {
 				cfg->s2_cntl_addr =
 					QPNP_PON_KPDPWR_S2_CNTL(pon->base);
 				cfg->s2_cntl2_addr =
@@ -752,7 +790,7 @@
 				}
 			}
 
-			if (reg == QPNP_PON_REV_B) {
+			if (pon_ver == QPNP_PON_REV_B) {
 				cfg->s2_cntl_addr =
 					QPNP_PON_RESIN_S2_CNTL(pon->base);
 				cfg->s2_cntl2_addr =
@@ -772,6 +810,36 @@
 				return rc;
 			}
 			break;
+		case PON_KPDPWR_RESIN:
+			rc = of_property_read_u32(pp, "qcom,support-reset",
+							&cfg->support_reset);
+			if (rc && rc != -EINVAL) {
+				dev_err(&pon->spmi->dev,
+					"Unable to read 'support-reset'\n");
+				return rc;
+			}
+
+			if (cfg->support_reset) {
+				cfg->bark_irq = spmi_get_irq_byname(pon->spmi,
+						NULL, "kpdpwr-resin-bark");
+				if (cfg->bark_irq < 0) {
+					dev_err(&pon->spmi->dev,
+					"Unable to get kpdpwr-resin-bark irq\n");
+					return cfg->bark_irq;
+				}
+			}
+
+			if (pon_ver == QPNP_PON_REV_B) {
+				cfg->s2_cntl_addr =
+				QPNP_PON_KPDPWR_RESIN_S2_CNTL(pon->base);
+				cfg->s2_cntl2_addr =
+				QPNP_PON_KPDPWR_RESIN_S2_CNTL2(pon->base);
+			} else {
+				cfg->s2_cntl_addr = cfg->s2_cntl2_addr =
+				QPNP_PON_KPDPWR_RESIN_S2_CNTL(pon->base);
+			}
+
+			break;
 		default:
 			dev_err(&pon->spmi->dev, "PON RESET %d not supported",
 								cfg->pon_type);
@@ -819,13 +887,14 @@
 					"Incorrect reset type specified\n");
 				return -EINVAL;
 			}
+
 		}
 		/*
 		 * Get the standard-key parameters. This might not be
 		 * specified if there is no key mapping on the reset line.
 		 */
 		rc = of_property_read_u32(pp, "linux,code", &cfg->key_code);
-		if (rc && rc == -EINVAL) {
+		if (rc && rc != -EINVAL) {
 			dev_err(&pon->spmi->dev,
 				"Unable to read key-code\n");
 			return rc;
@@ -896,7 +965,7 @@
 	struct qpnp_pon *pon;
 	struct resource *pon_resource;
 	struct device_node *itr = NULL;
-	u32 delay = 0;
+	u32 delay = 0, s3_debounce = 0;
 	int rc, sys_reset;
 
 	pon = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_pon),
@@ -956,6 +1025,32 @@
 		}
 	}
 
+	/* program s3 debounce */
+	rc = of_property_read_u32(pon->spmi->dev.of_node,
+				"qcom,s3-debounce", &s3_debounce);
+	if (rc) {
+		if (rc != -EINVAL) {
+			dev_err(&pon->spmi->dev, "Unable to read s3 timer\n");
+			return rc;
+		}
+	} else {
+		if (s3_debounce > QPNP_PON_S3_TIMER_SECS_MAX) {
+			dev_info(&pon->spmi->dev,
+				"Exceeded S3 max value, set it to max\n");
+			s3_debounce = QPNP_PON_S3_TIMER_SECS_MAX;
+		}
+
+		/* 0 is a special value to indicate instant s3 reset */
+		if (s3_debounce != 0)
+			s3_debounce = ilog2(s3_debounce);
+		rc = qpnp_pon_masked_write(pon, QPNP_PON_S3_DBC_CTL(pon->base),
+				QPNP_PON_S3_DBC_DELAY_MASK, s3_debounce);
+		if (rc) {
+			dev_err(&spmi->dev, "Unable to set S3 debounce\n");
+			return rc;
+		}
+	}
+
 	dev_set_drvdata(&spmi->dev, pon);
 
 	INIT_DELAYED_WORK(&pon->bark_work, bark_work_func);
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index c39de83..1069dd5 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -172,7 +172,6 @@
 static struct usb_bam_ctx_type ctx;
 
 static struct device *hsic_host_dev;
-static bool hsic_host_dev_resumed_from_cons_request;
 
 static int __usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
 	void *param, bool trigger_cb_per_pipe);
@@ -899,7 +898,6 @@
 
 		break;
 	case HSIC_BAM:
-			hsic_host_dev_resumed_from_cons_request = true;
 
 			usb_bam_resume_hsic_host();
 
@@ -969,8 +967,6 @@
 			(int)hsic_host_dev);
 			pm_runtime_put(hsic_host_dev);
 			info.in_lpm[HSIC_BAM] = true;
-			/* In case consumer release before resume happned */
-			hsic_host_dev_resumed_from_cons_request = false;
 		}
 	}
 
@@ -1336,9 +1332,6 @@
 
 void msm_bam_wait_for_hsic_prod_granted(void)
 {
-	if (hsic_host_dev_resumed_from_cons_request)
-		return;
-
 	ctx.is_bam_inactivity[HSIC_BAM] = false;
 
 	/* Get back to resume state including wakeup ipa */
@@ -1356,11 +1349,8 @@
 	 * and clocked on. Therefore we can now set the inactivity
 	 * timer to the hsic bam hw.
 	 */
-	if (ctx.inactivity_timer_ms[HSIC_BAM] &&
-	    !hsic_host_dev_resumed_from_cons_request)
+	if (ctx.inactivity_timer_ms[HSIC_BAM])
 		usb_bam_set_inactivity_timer(HSIC_BAM);
-
-	hsic_host_dev_resumed_from_cons_request = false;
 }
 
 bool msm_bam_hsic_lpm_ok(void)
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index e244df4..1fd4434 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -156,7 +156,7 @@
 	int			enable_fcc_learning;
 	int			min_fcc_learning_soc;
 	int			min_fcc_ocv_pc;
-	int			max_fcc_learning_samples;
+	int			min_fcc_learning_samples;
 	struct			fcc_data *fcc_table;
 	int			fcc_new;
 	int			start_real_soc;
@@ -223,7 +223,7 @@
 static int last_chargecycles = DEFAULT_CHARGE_CYCLES;
 static int last_charge_increase;
 static int last_fcc_update_count;
-static int max_fcc_cycles = -EINVAL;
+static int min_fcc_cycles = -EINVAL;
 module_param(last_chargecycles, int, 0644);
 module_param(last_charge_increase, int, 0644);
 module_param(last_fcc_update_count, int, 0644);
@@ -253,8 +253,7 @@
 /* Make last_soc as read only as it is already calculated from shutdown_soc */
 module_param_cb(last_soc, &bms_param_ops, &last_soc, 0644);
 module_param_cb(battery_removed, &bms_param_ops, &battery_removed, 0644);
-module_param_cb(max_fcc_cycles, &bms_param_ops,
-				&max_fcc_cycles, 0644);
+module_param_cb(min_fcc_cycles, &bms_param_ops, &min_fcc_cycles, 0644);
 
 /*
  * bms_fake_battery is set in setups where a battery emulator is used instead
@@ -2790,7 +2789,7 @@
 
 static void invalidate_fcc(struct pm8921_bms_chip *chip)
 {
-	memset(chip->fcc_table, 0, chip->max_fcc_learning_samples *
+	memset(chip->fcc_table, 0, chip->min_fcc_learning_samples *
 					sizeof(*(chip->fcc_table)));
 	last_fcc_update_count = 0;
 	chip->adjusted_fcc_temp_lut = NULL;
@@ -2807,7 +2806,7 @@
 	struct fcc_data *ft;
 
 	/* Interpolate all the FCC entries to the same temperature */
-	for (i = 0; i < chip->max_fcc_learning_samples; i++) {
+	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
 		ft = &chip->fcc_table[i];
 		if (ft->batt_temp == batt_temp_final)
 			continue;
@@ -2825,7 +2824,7 @@
 	int i, temp_fcc_avg = 0, new_fcc_avg = 0, temp_fcc_delta = 0, count;
 	struct fcc_data *ft;
 
-	count = last_fcc_update_count % chip->max_fcc_learning_samples;
+	count = last_fcc_update_count % chip->min_fcc_learning_samples;
 	ft = &chip->fcc_table[count];
 	ft->fcc_new = ft->fcc_real = new_fcc_uah;
 	ft->batt_temp = ft->temp_real = batt_temp;
@@ -2838,14 +2837,14 @@
 	pr_debug("Updated fcc table. new_fcc=%d, chargecycle=%d, temp=%d fcc_update_count=%d\n",
 		new_fcc_uah, chargecycles, batt_temp, last_fcc_update_count);
 
-	if (last_fcc_update_count < chip->max_fcc_learning_samples) {
+	if (last_fcc_update_count < chip->min_fcc_learning_samples) {
 		pr_debug("Not enough FCC samples. Current count = %d\n",
 						last_fcc_update_count);
 		return; /* Not enough samples to update fcc */
 	}
 
 	/* reject entries if they are > 50 chargecycles apart */
-	for (i = 0; i < chip->max_fcc_learning_samples; i++) {
+	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
 		if ((chip->fcc_table[i].chargecycles + VALID_FCC_CHGCYL_RANGE)
 							< chargecycles) {
 			pr_debug("Charge cycle too old (> %d cycles apart)\n",
@@ -2857,20 +2856,20 @@
 	update_fcc_table_for_temp(chip, batt_temp);
 
 	/* Calculate the avg. and SD for all the fcc entries */
-	for (i = 0; i < chip->max_fcc_learning_samples; i++)
+	for (i = 0; i < chip->min_fcc_learning_samples; i++)
 		temp_fcc_avg += chip->fcc_table[i].fcc_new;
 
-	temp_fcc_avg /= chip->max_fcc_learning_samples;
+	temp_fcc_avg /= chip->min_fcc_learning_samples;
 	temp_fcc_delta = div_u64(temp_fcc_avg * DELTA_FCC_PERCENT, 100);
 
 	/* fix the fcc if its an outlier i.e. > 5% of the average */
-	for (i = 0; i < chip->max_fcc_learning_samples; i++) {
+	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
 		ft = &chip->fcc_table[i];
 		if (abs(ft->fcc_new - temp_fcc_avg) > temp_fcc_delta)
 			ft->fcc_new = temp_fcc_avg;
 		new_fcc_avg += ft->fcc_new;
 	}
-	new_fcc_avg /= chip->max_fcc_learning_samples;
+	new_fcc_avg /= chip->min_fcc_learning_samples;
 
 	last_real_fcc_mah = new_fcc_avg/1000;
 	last_real_fcc_batt_temp = batt_temp;
@@ -2878,6 +2877,7 @@
 	pr_debug("FCC update: last_real_fcc_mah=%d, last_real_fcc_batt_temp=%d\n",
 						new_fcc_avg, batt_temp);
 	readjust_fcc_table();
+	sysfs_notify(&chip->dev->kobj, NULL, "fcc_data");
 }
 
 static bool is_new_fcc_valid(int new_fcc_uah, int fcc_uah)
@@ -3496,7 +3496,7 @@
 		return count;
 	}
 
-	i %= chip->max_fcc_learning_samples;
+	i %= chip->min_fcc_learning_samples;
 	rc = sscanf(buf, "%d", &fcc_new);
 	if (rc != 1)
 		return -EINVAL;
@@ -3535,7 +3535,7 @@
 	int batt_temp = 0, rc;
 	struct pm8921_bms_chip *chip = dev_get_drvdata(dev);
 
-	i %= chip->max_fcc_learning_samples;
+	i %= chip->min_fcc_learning_samples;
 	rc = sscanf(buf, "%d", &batt_temp);
 	if (rc != 1)
 		return -EINVAL;
@@ -3554,7 +3554,7 @@
 	int chargecycle = 0, rc;
 	struct pm8921_bms_chip *chip = dev_get_drvdata(dev);
 
-	i %= chip->max_fcc_learning_samples;
+	i %= chip->min_fcc_learning_samples;
 	rc = sscanf(buf, "%d", &chargecycle);
 	if (rc != 1)
 		return -EINVAL;
@@ -3572,10 +3572,10 @@
 	struct fcc_data *ft;
 	int i = 0, j, count = 0;
 
-	if (last_fcc_update_count < chip->max_fcc_learning_samples)
+	if (last_fcc_update_count < chip->min_fcc_learning_samples)
 		i = last_fcc_update_count;
 	else
-		i = chip->max_fcc_learning_samples;
+		i = chip->min_fcc_learning_samples;
 
 	for (j = 0; j < i; j++) {
 		ft = &chip->fcc_table[j];
@@ -3733,7 +3733,7 @@
 	chip->enable_fcc_learning = pdata->enable_fcc_learning;
 	chip->min_fcc_learning_soc = pdata->min_fcc_learning_soc;
 	chip->min_fcc_ocv_pc = pdata->min_fcc_ocv_pc;
-	chip->max_fcc_learning_samples = pdata->max_fcc_learning_samples;
+	chip->min_fcc_learning_samples = pdata->min_fcc_learning_samples;
 	if (chip->enable_fcc_learning) {
 		if (!chip->min_fcc_learning_soc)
 			chip->min_fcc_learning_soc =
@@ -3741,13 +3741,13 @@
 		if (!chip->min_fcc_ocv_pc)
 			chip->min_fcc_ocv_pc =
 					MIN_START_OCV_PERCENT_FOR_LEARNING;
-		if (!chip->max_fcc_learning_samples ||
-			chip->max_fcc_learning_samples > MAX_FCC_LEARNING_COUNT)
-			chip->max_fcc_learning_samples = MAX_FCC_LEARNING_COUNT;
+		if (!chip->min_fcc_learning_samples ||
+			chip->min_fcc_learning_samples > MAX_FCC_LEARNING_COUNT)
+			chip->min_fcc_learning_samples = MAX_FCC_LEARNING_COUNT;
 
-		max_fcc_cycles = chip->max_fcc_learning_samples;
+		min_fcc_cycles = chip->min_fcc_learning_samples;
 		chip->fcc_table = kzalloc(sizeof(struct fcc_data) *
-				chip->max_fcc_learning_samples, GFP_KERNEL);
+				chip->min_fcc_learning_samples, GFP_KERNEL);
 		if (!chip->fcc_table) {
 			pr_err("Unable to allocate table for fcc learning\n");
 			rc = -ENOMEM;
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 5cdb666..11e6cc1 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -159,6 +159,7 @@
 	POWER_SUPPLY_ATTR(charge_now),
 	POWER_SUPPLY_ATTR(charge_avg),
 	POWER_SUPPLY_ATTR(charge_counter),
+	POWER_SUPPLY_ATTR(charge_counter_shadow),
 	POWER_SUPPLY_ATTR(energy_full_design),
 	POWER_SUPPLY_ATTR(energy_empty_design),
 	POWER_SUPPLY_ATTR(energy_full),
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index d9a216d..c7450fd 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -247,6 +247,7 @@
 	uint16_t			charge_cycles;
 	u8				charge_increase;
 	int				fcc_new_sysfs;
+	int				fcc_update_complete;
 };
 
 static struct of_device_id qpnp_bms_match_table[] = {
@@ -277,13 +278,35 @@
 {
 	return -EINVAL;
 }
+
+static int
+bms_last_fcc_count_set(const char *val, const struct kernel_param *kp)
+{
+	int rc;
+
+	if (battery_removed) {
+		last_fcc_update_count = 0;
+		return 0;
+	}
+	rc = param_set_int(val, kp);
+	if (rc)
+		pr_err("Failed to set last_fcc_update_count rc=%d\n", rc);
+
+	return rc;
+}
+
 static struct kernel_param_ops bms_ro_param_ops = {
 	.set = bms_ro_ops_set,
 	.get = param_get_int,
 };
+static struct kernel_param_ops bms_last_fcc_count_param_ops = {
+	.set = bms_last_fcc_count_set,
+	.get = param_get_int,
+};
 module_param_cb(min_fcc_cycles, &bms_ro_param_ops, &min_fcc_cycles, 0644);
 module_param_cb(battery_removed, &bms_ro_param_ops, &battery_removed, 0644);
-module_param(last_fcc_update_count, int, 0644);
+module_param_cb(last_fcc_update_count, &bms_last_fcc_count_param_ops,
+						&last_fcc_update_count, 0644);
 
 static int qpnp_read_wrapper(struct qpnp_bms_chip *chip, u8 *val,
 			u16 base, int count)
@@ -1480,7 +1503,7 @@
 #define SOC_CATCHUP_SEC_MAX		600
 #define SOC_CATCHUP_SEC_PER_PERCENT	60
 #define MAX_CATCHUP_SOC	(SOC_CATCHUP_SEC_MAX / SOC_CATCHUP_SEC_PER_PERCENT)
-#define SOC_CHANGE_PER_SEC	20
+#define SOC_CHANGE_PER_SEC		5
 static int report_cc_based_soc(struct qpnp_bms_chip *chip)
 {
 	int soc, soc_change;
@@ -1884,7 +1907,7 @@
 					struct raw_soc_params *raw,
 					int batt_temp)
 {
-	int soc, new_ocv_uv;
+	int soc, new_ocv_uv, previous_soc;
 	int shutdown_soc, new_calculated_soc, remaining_usable_charge_uah;
 	struct soc_params params;
 
@@ -1984,6 +2007,7 @@
 
 done_calculating:
 	mutex_lock(&chip->last_soc_mutex);
+	previous_soc = chip->calculated_soc;
 	chip->calculated_soc = new_calculated_soc;
 	pr_debug("CC based calculated SOC = %d\n", chip->calculated_soc);
 	if (chip->last_soc_invalid) {
@@ -2007,7 +2031,7 @@
 	}
 	mutex_unlock(&chip->last_soc_mutex);
 
-	if (new_calculated_soc != chip->calculated_soc
+	if (new_calculated_soc != previous_soc
 			&& chip->bms_psy.name != NULL) {
 		power_supply_changed(&chip->bms_psy);
 		pr_debug("power supply changed\n");
@@ -2250,7 +2274,8 @@
 	} else {
 		pr_debug("unknown voltage notification state: %d\n", state);
 	}
-	power_supply_changed(&chip->bms_psy);
+	if (chip->bms_psy.name != NULL)
+		power_supply_changed(&chip->bms_psy);
 }
 
 static int reset_vbat_monitoring(struct qpnp_bms_chip *chip)
@@ -2263,7 +2288,6 @@
 		pr_err("tm measure failed: %d\n", rc);
 		return rc;
 	}
-	mutex_lock(&chip->vbat_monitor_mutex);
 	if (wake_lock_active(&chip->low_voltage_wake_lock)) {
 		pr_debug("battery removed, releasing wakelock\n");
 		wake_unlock(&chip->low_voltage_wake_lock);
@@ -2272,7 +2296,6 @@
 		pr_debug("battery removed, removing in_cv_range state\n");
 		chip->in_cv_range = false;
 	}
-	mutex_unlock(&chip->vbat_monitor_mutex);
 	return 0;
 }
 
@@ -2762,6 +2785,11 @@
 	static int i;
 	int fcc_new = 0, rc;
 
+	if (chip->fcc_update_complete) {
+		pr_debug("Invalid FCC update\n");
+		return count;
+	}
+
 	i %= chip->min_fcc_learning_samples;
 	rc = sscanf(buf, "%d", &fcc_new);
 	if (rc != 1)
@@ -2781,6 +2809,7 @@
 
 	count = snprintf(buf, PAGE_SIZE, "%d", chip->fcc_new_sysfs);
 	pr_debug("Sent: fcc_new=%d\n", chip->fcc_new_sysfs);
+	chip->fcc_update_complete = 1;
 
 	return count;
 }
@@ -2792,6 +2821,9 @@
 	int batt_temp = 0, rc;
 	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
 
+	if (chip->fcc_update_complete)
+		return count;
+
 	i %= chip->min_fcc_learning_samples;
 	rc = sscanf(buf, "%d", &batt_temp);
 	if (rc != 1)
@@ -2810,6 +2842,9 @@
 	int chargecycle = 0, rc;
 	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
 
+	if (chip->fcc_update_complete)
+		return count;
+
 	i %= chip->min_fcc_learning_samples;
 	rc = sscanf(buf, "%d", &chargecycle);
 	if (rc != 1)
@@ -3477,6 +3512,9 @@
 		goto error_setup;
 	}
 
+	battery_insertion_check(chip);
+	battery_status_check(chip);
+
 	calculate_soc_work(&(chip->calculate_soc_delayed_work.work));
 
 	/* setup & register the battery power supply */
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 4d464c1..7f669d8 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -245,6 +245,48 @@
 #define UARTDM_TO_MSM(uart_port) \
 	container_of((uart_port), struct msm_hs_port, uport)
 
+
+static int msm_hs_ioctl(struct uart_port *uport, unsigned int cmd,
+						unsigned long arg)
+{
+	int ret = 0, state = 1;
+	enum msm_hs_clk_states_e clk_state;
+	unsigned long flags;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	switch (cmd) {
+	case MSM_ENABLE_UART_CLOCK: {
+		pr_debug("%s():ENABLE UART CLOCK: cmd=%d\n", __func__, cmd);
+		msm_hs_request_clock_on(&msm_uport->uport);
+		break;
+	}
+	case MSM_DISABLE_UART_CLOCK: {
+		pr_debug("%s():DISABLE UART CLOCK: cmd=%d\n", __func__, cmd);
+		msm_hs_request_clock_off(&msm_uport->uport);
+		break;
+	}
+	case MSM_GET_UART_CLOCK_STATUS: {
+		/* Return value 0 - UART CLOCK is OFF
+		 * Return value 1 - UART CLOCK is ON */
+		pr_debug("%s():GET UART CLOCK STATUS: cmd=%d\n", __func__, cmd);
+		spin_lock_irqsave(&msm_uport->uport.lock, flags);
+		clk_state = msm_uport->clk_state;
+		spin_unlock_irqrestore(&msm_uport->uport.lock, flags);
+		if (clk_state <= MSM_HS_CLK_OFF)
+			state = 0;
+		ret = state;
+		break;
+	}
+	default: {
+		pr_debug("%s():Unknown cmd specified: cmd=%d\n", __func__, cmd);
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+	}
+
+	return ret;
+}
+
 static ssize_t show_clock(struct device *dev, struct device_attribute *attr,
 			  char *buf)
 {
@@ -3307,6 +3349,7 @@
 	.release_port = msm_hs_release_port,
 	.request_port = msm_hs_request_port,
 	.flush_buffer = msm_hs_flush_buffer,
+	.ioctl = msm_hs_ioctl,
 };
 
 module_init(msm_serial_hs_init);
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index cdd0450..cd24f23 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -32,6 +32,10 @@
 #define ADM1_CRCI_GSBI6_RX_SEL         0x800
 #define ADM1_CRCI_GSBI6_TX_SEL         0x400
 
+#define MSM_ENABLE_UART_CLOCK 13
+#define MSM_DISABLE_UART_CLOCK 14
+#define MSM_GET_UART_CLOCK_STATUS 15
+
 enum msm_hsl_regs {
 	UARTDM_MR1,
 	UARTDM_MR2,
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 6aeb26e..a5f586b 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -381,15 +381,29 @@
  */
 static u32 dwc3_msm_ssusb_read_phycreg(void *base, u32 addr)
 {
+	bool first_read = true;
+
 	iowrite32(addr, base + SS_CR_PROTOCOL_DATA_IN_REG);
 	iowrite32(0x1, base + SS_CR_PROTOCOL_CAP_ADDR_REG);
 	while (ioread32(base + SS_CR_PROTOCOL_CAP_ADDR_REG))
 		cpu_relax();
 
+	/*
+	 * Due to hardware bug, first read of SSPHY register might be
+	 * incorrect. Hence as workaround, SW should perform SSPHY register
+	 * read twice, but use only second read and ignore first read.
+	 */
+retry:
 	iowrite32(0x1, base + SS_CR_PROTOCOL_READ_REG);
 	while (ioread32(base + SS_CR_PROTOCOL_READ_REG))
 		cpu_relax();
 
+	if (first_read) {
+		ioread32(base + SS_CR_PROTOCOL_DATA_OUT_REG);
+		first_read = false;
+		goto retry;
+	}
+
 	return ioread32(base + SS_CR_PROTOCOL_DATA_OUT_REG);
 }
 
@@ -1511,7 +1525,8 @@
 	case DWC3_DCP_CHARGER:		return "USB_DCP_CHARGER";
 	case DWC3_CDP_CHARGER:		return "USB_CDP_CHARGER";
 	case DWC3_PROPRIETARY_CHARGER:	return "USB_PROPRIETARY_CHARGER";
-	default:			return "INVALID_CHARGER";
+	case DWC3_UNSUPPORTED_CHARGER:	return "INVALID_CHARGER";
+	default:			return "UNKNOWN_CHARGER";
 	}
 }
 
@@ -1541,9 +1556,17 @@
 		if (is_dcd || tmout) {
 			dwc3_chg_disable_dcd(mdwc);
 			if (dwc3_chg_det_check_linestate(mdwc)) {
-				dev_dbg(mdwc->dev, "proprietary charger\n");
-				mdwc->charger.chg_type =
+				dwc3_chg_enable_primary_det(mdwc);
+				usleep_range(1000, 1200);
+				vout = dwc3_chg_det_check_output(mdwc);
+				if (!vout)
+					mdwc->charger.chg_type =
+						DWC3_UNSUPPORTED_CHARGER;
+				else
+					mdwc->charger.chg_type =
 						DWC3_PROPRIETARY_CHARGER;
+				dwc3_msm_write_reg(mdwc->base,
+						CHARGING_DET_CTRL_REG, 0x0);
 				mdwc->chg_state = USB_CHG_STATE_DETECTED;
 				delay = 0;
 				break;
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index be9a4b5..98c9b4c 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -13,6 +13,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 #include <linux/platform_device.h>
@@ -23,6 +24,10 @@
 #include "io.h"
 #include "xhci.h"
 
+#define MAX_INVALID_CHRGR_RETRY 3
+static int max_chgr_retry_count = MAX_INVALID_CHRGR_RETRY;
+module_param(max_chgr_retry_count, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_chgr_retry_count, "Max invalid charger retry count");
 static void dwc3_otg_reset(struct dwc3_otg *dotg);
 
 static void dwc3_otg_notify_host_mode(struct usb_otg *otg, int host_mode);
@@ -686,6 +691,7 @@
 			dev_dbg(phy->dev, "!id\n");
 			phy->state = OTG_STATE_A_IDLE;
 			work = 1;
+			dotg->charger_retry_count = 0;
 			if (charger) {
 				if (charger->chg_type == DWC3_INVALID_CHARGER)
 					charger->start_detection(dotg->charger,
@@ -720,6 +726,17 @@
 					phy->state = OTG_STATE_B_PERIPHERAL;
 					work = 1;
 					break;
+				case DWC3_UNSUPPORTED_CHARGER:
+					dotg->charger_retry_count++;
+					if (dotg->charger_retry_count ==
+						max_chgr_retry_count) {
+						dwc3_otg_set_power(phy, 0);
+						pm_runtime_put_sync(phy->dev);
+						break;
+					}
+					charger->start_detection(dotg->charger,
+									false);
+
 				default:
 					dev_dbg(phy->dev, "chg_det started\n");
 					charger->start_detection(charger, true);
@@ -744,6 +761,7 @@
 			if (charger)
 				charger->start_detection(dotg->charger, false);
 
+			dotg->charger_retry_count = 0;
 			dwc3_otg_set_power(phy, 0);
 			dev_dbg(phy->dev, "No device, trying to suspend\n");
 			pm_runtime_put_sync(phy->dev);
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index 90e26cf..b00468e 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -50,6 +50,7 @@
 	struct power_supply	*psy;
 	struct completion	dwc3_xcvr_vbus_init;
 	int			host_bus_suspend;
+	int			charger_retry_count;
 };
 
 /**
@@ -70,6 +71,7 @@
 	DWC3_DCP_CHARGER,
 	DWC3_CDP_CHARGER,
 	DWC3_PROPRIETARY_CHARGER,
+	DWC3_UNSUPPORTED_CHARGER,
 };
 
 struct dwc3_charger {
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index bb0b2fb..0cfd515 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -393,6 +393,7 @@
 	u32			recip;
 	u32			wValue;
 	u32			wIndex;
+	u32			reg;
 	int			ret;
 
 	wValue = le16_to_cpu(ctrl->wValue);
@@ -413,6 +414,13 @@
 				return -EINVAL;
 			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 				return -EINVAL;
+
+			reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+			if (set)
+				reg |= DWC3_DCTL_INITU1ENA;
+			else
+				reg &= ~DWC3_DCTL_INITU1ENA;
+			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 			break;
 
 		case USB_DEVICE_U2_ENABLE:
@@ -420,6 +428,13 @@
 				return -EINVAL;
 			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 				return -EINVAL;
+
+			reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+			if (set)
+				reg |= DWC3_DCTL_INITU2ENA;
+			else
+				reg &= ~DWC3_DCTL_INITU2ENA;
+			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 			break;
 
 		case USB_DEVICE_LTM_ENABLE:
@@ -524,6 +539,7 @@
 {
 	u32 cfg;
 	int ret;
+	u32 reg;
 
 	dwc->start_config_issued = false;
 	cfg = le16_to_cpu(ctrl->wValue);
@@ -538,6 +554,14 @@
 		/* if the cfg matches and the cfg is non zero */
 		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
 			dwc->dev_state = DWC3_CONFIGURED_STATE;
+			/*
+			 * Enable transition to U1/U2 state when
+			 * nothing is pending from application.
+			 */
+			reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+			reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA);
+			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
 			dwc->resize_fifos = true;
 			dev_dbg(dwc->dev, "resize fifos flag SET\n");
 		}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 1059a4d..63698de 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -36,6 +36,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -56,6 +57,11 @@
 #include "debug.h"
 #include "io.h"
 
+static bool tx_fifo_resize_enable;
+module_param(tx_fifo_resize_enable, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(tx_fifo_resize_enable,
+			"Enable allocating Tx fifo for endpoints");
+
 /**
  * dwc3_gadget_set_test_mode - Enables USB2 Test Modes
  * @dwc: pointer to our context structure
@@ -178,7 +184,7 @@
 	int		mdwidth;
 	int		num;
 
-	if (!dwc->needs_fifo_resize)
+	if (!dwc->needs_fifo_resize && !tx_fifo_resize_enable)
 		return 0;
 
 	ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c
index ff2287e..55f5b80 100644
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -662,7 +662,7 @@
 {
 	struct adb_dev *dev = _adb_dev;
 
-	printk(KERN_INFO "adb_bind_config\n");
+	pr_debug("adb_bind_config\n");
 
 	dev->cdev = c->cdev;
 	dev->function.name = "adb";
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c
index 4586d80..a4192ca 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -558,17 +558,15 @@
 	struct mtp_dev *dev = fp->private_data;
 	struct usb_composite_dev *cdev = dev->cdev;
 	struct usb_request *req;
-	int r = count, xfer;
+	int r = count, xfer, len;
 	int ret = 0;
 
 	DBG(cdev, "mtp_read(%d)\n", count);
 
-	if (count > mtp_rx_req_len)
-		return -EINVAL;
+	len = ALIGN(count, dev->ep_out->maxpacket);
 
-	if (!IS_ALIGNED(count, dev->ep_out->maxpacket))
-		DBG(cdev, "%s - count(%d) not multiple of mtu(%d)\n", __func__,
-						count, dev->ep_out->maxpacket);
+	if (len > mtp_rx_req_len)
+		return -EINVAL;
 
 	/* we will block until we're online */
 	DBG(cdev, "mtp_read: waiting for online state\n");
@@ -591,7 +589,7 @@
 requeue_req:
 	/* queue a request */
 	req = dev->rx_req[0];
-	req->length = mtp_rx_req_len;
+	req->length = len;
 	dev->rx_done = 0;
 	ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL);
 	if (ret < 0) {
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index f095efb..6dcc3b4 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -1121,7 +1121,7 @@
 			goto fail;
 	}
 
-	pr_info("%s: RmNet(%d) %s Speed, IN:%s OUT:%s\n",
+	pr_debug("%s: RmNet(%d) %s Speed, IN:%s OUT:%s\n",
 			__func__, dev->port_num,
 			gadget_is_dualspeed(cdev->gadget) ? "dual" : "full",
 			dev->port.in->name, dev->port.out->name);
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index edcafcc..022e641 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -215,6 +215,9 @@
 			req->no_interrupt = 1;
 		}
 
+		/* Send ZLP in case packet length is multiple of maxpacksize */
+		req->zero = 1;
+
 		list_del(&req->list);
 
 		spin_unlock(&port->port_lock_dl);
@@ -639,6 +642,7 @@
 			gbam_epout_complete, GFP_ATOMIC);
 	if (ret) {
 		pr_err("%s: rx req allocation failed\n", __func__);
+		spin_unlock_irqrestore(&port->port_lock_ul, flags);
 		return;
 	}
 
@@ -655,6 +659,7 @@
 	if (ret) {
 		pr_err("%s: tx req allocation failed\n", __func__);
 		gbam_free_requests(ep, &d->rx_idle);
+		spin_unlock_irqrestore(&port->port_lock_dl, flags);
 		return;
 	}
 
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index c2e8943..0b89dd0 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -28,6 +28,7 @@
 #include <linux/pm_runtime.h>
 
 #include <linux/usb/otg.h>
+#include <linux/usb/msm_hsusb.h>
 #include <linux/usb/msm_hsusb_hw.h>
 
 #define MSM_USB_BASE (hcd->regs)
@@ -51,7 +52,13 @@
 	/* Use the AHB transactor */
 	writel_relaxed(0x08, USB_AHBMODE);
 	/* Disable streaming mode and select host mode */
-	writel(0x13, USB_USBMODE);
+	writel_relaxed(0x13, USB_USBMODE);
+
+	if (ehci->transceiver->flags & ENABLE_SECONDARY_PHY) {
+		ehci_dbg(ehci, "using secondary hsphy\n");
+		writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
+							USB_PHY_CTRL2);
+	}
 
 	ehci_port_power(ehci, 1);
 	return 0;
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
index bb5d3ca..5c164e4 100644
--- a/drivers/video/msm/mdss/dsi_panel_v2.c
+++ b/drivers/video/msm/mdss/dsi_panel_v2.c
@@ -34,6 +34,7 @@
 	int rst_gpio;
 	int disp_en_gpio;
 	int video_mode_gpio;
+	int te_gpio;
 	char bl_ctrl;
 
 	struct regulator *vddio_vreg;
@@ -190,6 +191,8 @@
 				gpio_set_value(panel_private->video_mode_gpio,
 						0);
 		}
+		if (gpio_is_valid(panel_private->te_gpio))
+			gpio_request(panel_private->te_gpio, "panel_te");
 	} else {
 		gpio_set_value(panel_private->rst_gpio, 0);
 		gpio_free(panel_private->rst_gpio);
@@ -202,6 +205,8 @@
 		if (gpio_is_valid(panel_private->video_mode_gpio))
 			gpio_free(panel_private->video_mode_gpio);
 
+		if (gpio_is_valid(panel_private->te_gpio))
+			gpio_free(panel_private->te_gpio);
 		dsi_panel_power(0);
 	}
 }
@@ -233,16 +238,10 @@
 	pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
 		 mipi->mode);
 
-	if (mipi->mode == DSI_VIDEO_MODE) {
-		dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
-				panel_private->on_cmds_list->buf,
-				panel_private->on_cmds_list->size);
-	} else {
-		pr_err("%s:%d, CMD MODE NOT SUPPORTED", __func__, __LINE__);
-		return -EINVAL;
-	}
 
-	return 0;
+	return dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
+					panel_private->on_cmds_list->buf,
+					panel_private->on_cmds_list->size);
 }
 
 static int dsi_panel_off(struct mdss_panel_data *pdata)
@@ -252,16 +251,10 @@
 
 	pr_debug("%s:%d, debug info\n", __func__, __LINE__);
 
-	if (mipi->mode == DSI_VIDEO_MODE) {
-		dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
-				panel_private->off_cmds_list->buf,
-				panel_private->off_cmds_list->size);
-	} else {
-		pr_debug("%s:%d, CMD mode not supported", __func__, __LINE__);
-		return -EINVAL;
-	}
 
-	return 0;
+	return dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
+					panel_private->off_cmds_list->buf,
+					panel_private->off_cmds_list->size);
 }
 
 static int dsi_panel_parse_gpio(struct platform_device *pdev)
@@ -272,6 +265,8 @@
 	panel_private->rst_gpio = of_get_named_gpio(np, "qcom,rst-gpio", 0);
 	panel_private->video_mode_gpio = of_get_named_gpio(np,
 						"qcom,mode-selection-gpio", 0);
+	panel_private->te_gpio = of_get_named_gpio(np,
+						"qcom,te-gpio", 0);
 	return 0;
 }
 
@@ -364,86 +359,9 @@
 				struct dsi_panel_common_pdata *panel_data)
 {
 	struct device_node *np = pdev->dev.of_node;
-	u32 res[6], tmp;
-	int i, len, rc;
+	int i, len;
 	const char *data;
 
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mode", &tmp);
-	panel_data->panel_info.mipi.mode = (!rc ? tmp : DSI_VIDEO_MODE);
-
-	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
-	panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
-
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-dsi-h-power-stop", res, 3);
-	panel_data->panel_info.mipi.hbp_power_stop = (!rc ? res[0] : false);
-	panel_data->panel_info.mipi.hsa_power_stop = (!rc ? res[1] : false);
-	panel_data->panel_info.mipi.hfp_power_stop = (!rc ? res[2] : false);
-
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-dsi-bllp-power-stop", res, 2);
-	panel_data->panel_info.mipi.bllp_power_stop =
-					(!rc ? res[0] : false);
-	panel_data->panel_info.mipi.eof_bllp_power_stop =
-					(!rc ? res[1] : false);
-
-	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-dsi-traffic-mode", &tmp);
-	panel_data->panel_info.mipi.traffic_mode =
-			(!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
-
-	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-dsi-dst-format", &tmp);
-	panel_data->panel_info.mipi.dst_format =
-			(!rc ? tmp : DSI_VIDEO_DST_FORMAT_RGB888);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-vc", &tmp);
-	panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-rgb-swap", &tmp);
-	panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
-
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-dsi-data-lanes", res, 4);
-	panel_data->panel_info.mipi.data_lane0 = (!rc ? res[0] : true);
-	panel_data->panel_info.mipi.data_lane1 = (!rc ? res[1] : false);
-	panel_data->panel_info.mipi.data_lane2 = (!rc ? res[2] : false);
-	panel_data->panel_info.mipi.data_lane3 = (!rc ? res[3] : false);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dlane-swap", &tmp);
-	panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
-
-	rc = of_property_read_u32_array(np, "qcom,mdss-pan-dsi-t-clk", res, 2);
-	panel_data->panel_info.mipi.t_clk_pre = (!rc ? res[0] : 0x24);
-	panel_data->panel_info.mipi.t_clk_post = (!rc ? res[1] : 0x03);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-stream", &tmp);
-	panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mdp-tr", &tmp);
-	panel_data->panel_info.mipi.mdp_trigger =
-			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
-	if (panel_data->panel_info.mipi.mdp_trigger > 6) {
-		pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
-						 __func__, __LINE__);
-		panel_data->panel_info.mipi.mdp_trigger =
-					DSI_CMD_TRIGGER_SW;
-	}
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dma-tr", &tmp);
-	panel_data->panel_info.mipi.dma_trigger =
-			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
-	if (panel_data->panel_info.mipi.dma_trigger > 6) {
-		pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
-						 __func__, __LINE__);
-		panel_data->panel_info.mipi.dma_trigger =
-					DSI_CMD_TRIGGER_SW;
-	}
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
-	panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
-
 	data = of_get_property(np, "qcom,panel-phy-regulatorSettings", &len);
 	if ((!data) || (len != 6)) {
 		pr_err("%s:%d, Unable to read Phy regulator settings",
@@ -713,6 +631,102 @@
 	return rc;
 }
 
+static int dsi_panel_parse_host_cfg(struct platform_device *pdev,
+				struct dsi_panel_common_pdata *panel_data)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 res[6], tmp;
+	int rc;
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mode", &tmp);
+	panel_data->panel_info.mipi.mode = (!rc ? tmp : DSI_VIDEO_MODE);
+
+	rc = of_property_read_u32(np,
+		"qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
+	panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
+
+	rc = of_property_read_u32_array(np,
+		"qcom,mdss-pan-dsi-h-power-stop", res, 3);
+	panel_data->panel_info.mipi.hbp_power_stop = (!rc ? res[0] : false);
+	panel_data->panel_info.mipi.hsa_power_stop = (!rc ? res[1] : false);
+	panel_data->panel_info.mipi.hfp_power_stop = (!rc ? res[2] : false);
+
+	rc = of_property_read_u32_array(np,
+		"qcom,mdss-pan-dsi-bllp-power-stop", res, 2);
+	panel_data->panel_info.mipi.bllp_power_stop =
+					(!rc ? res[0] : false);
+	panel_data->panel_info.mipi.eof_bllp_power_stop =
+					(!rc ? res[1] : false);
+
+	rc = of_property_read_u32(np,
+		"qcom,mdss-pan-dsi-traffic-mode", &tmp);
+	panel_data->panel_info.mipi.traffic_mode =
+			(!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
+
+	rc = of_property_read_u32(np,
+		"qcom,mdss-pan-dsi-dst-format", &tmp);
+	panel_data->panel_info.mipi.dst_format =
+			(!rc ? tmp : DSI_VIDEO_DST_FORMAT_RGB888);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-vc", &tmp);
+	panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-rgb-swap", &tmp);
+	panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
+
+	rc = of_property_read_u32_array(np,
+		"qcom,mdss-pan-dsi-data-lanes", res, 4);
+	panel_data->panel_info.mipi.data_lane0 = (!rc ? res[0] : true);
+	panel_data->panel_info.mipi.data_lane1 = (!rc ? res[1] : false);
+	panel_data->panel_info.mipi.data_lane2 = (!rc ? res[2] : false);
+	panel_data->panel_info.mipi.data_lane3 = (!rc ? res[3] : false);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dlane-swap", &tmp);
+	panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
+
+	rc = of_property_read_u32_array(np, "qcom,mdss-pan-dsi-t-clk", res, 2);
+	panel_data->panel_info.mipi.t_clk_pre = (!rc ? res[0] : 0x24);
+	panel_data->panel_info.mipi.t_clk_post = (!rc ? res[1] : 0x03);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-stream", &tmp);
+	panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-te-sel", &tmp);
+	panel_data->panel_info.mipi.te_sel = (!rc ? tmp : 1);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-insert-dcs-cmd", &tmp);
+	panel_data->panel_info.mipi.insert_dcs_cmd = (!rc ? tmp : 1);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-wr-mem-continue", &tmp);
+	panel_data->panel_info.mipi.wr_mem_continue = (!rc ? tmp : 0x3c);
+	rc = of_property_read_u32(np, "qcom,mdss-pan-wr-mem-start", &tmp);
+	panel_data->panel_info.mipi.wr_mem_start = (!rc ? tmp : 0x2c);
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mdp-tr", &tmp);
+	panel_data->panel_info.mipi.mdp_trigger =
+			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
+	if (panel_data->panel_info.mipi.mdp_trigger > 6) {
+		pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
+						 __func__, __LINE__);
+		panel_data->panel_info.mipi.mdp_trigger =
+					DSI_CMD_TRIGGER_SW;
+	}
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dma-tr", &tmp);
+	panel_data->panel_info.mipi.dma_trigger =
+			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
+	if (panel_data->panel_info.mipi.dma_trigger > 6) {
+		pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
+						 __func__, __LINE__);
+		panel_data->panel_info.mipi.dma_trigger =
+					DSI_CMD_TRIGGER_SW;
+	}
+
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
+	panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
+	return rc;
+}
+
 static int dsi_panel_parse_dt(struct platform_device *pdev,
 				struct dsi_panel_common_pdata *panel_data,
 				char *bl_ctrl)
@@ -755,6 +769,12 @@
 		return rc;
 	}
 
+	rc = dsi_panel_parse_host_cfg(pdev, panel_data);
+	if (rc) {
+		pr_err("fail to parse DSI host configs\n");
+		return rc;
+	}
+
 	rc = dsi_panel_parse_init_cmds(pdev, panel_data);
 	if (rc) {
 		pr_err("fail to parse DSI init commands\n");
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 98e7e29..67004d5 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -19,6 +19,7 @@
 #include <linux/major.h>
 #include <linux/module.h>
 #include <linux/uaccess.h>
+#include <linux/delay.h>
 
 #include "mdp3_ctrl.h"
 #include "mdp3.h"
@@ -26,7 +27,6 @@
 
 #define MDP_CORE_CLK_RATE	100000000
 #define MDP_VSYNC_CLK_RATE	19200000
-#define VSYNC_PERIOD 16
 
 static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd);
 static int mdp3_overlay_unset(struct msm_fb_data_type *mfd, int ndx);
@@ -120,16 +120,30 @@
 
 	mutex_lock(&mdp3_session->lock);
 	mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
+	if (enable && mdp3_session->status == 1 && !mdp3_session->intf->active)
+		mod_timer(&mdp3_session->vsync_timer,
+			jiffies + msecs_to_jiffies(mdp3_session->vsync_period));
+	 else if (!enable)
+		del_timer(&mdp3_session->vsync_timer);
+
 	mutex_unlock(&mdp3_session->lock);
 	spin_lock_irqsave(&mdp3_session->vsync_lock, flag);
-	if (enable)
-		INIT_COMPLETION(mdp3_session->vsync_comp);
-	else
-		complete(&mdp3_session->vsync_comp);
+	INIT_COMPLETION(mdp3_session->vsync_comp);
 	spin_unlock_irqrestore(&mdp3_session->vsync_lock, flag);
 	return 0;
 }
 
+void mdp3_vsync_timer_func(unsigned long arg)
+{
+	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
+	if (session->status == 1 && !session->intf->active) {
+		pr_debug("mdp3_vsync_timer_func trigger\n");
+		vsync_notify_handler(session);
+		mod_timer(&session->vsync_timer,
+			jiffies + msecs_to_jiffies(session->vsync_period));
+	}
+}
+
 static int mdp3_ctrl_async_blit_req(struct msm_fb_data_type *mfd,
 	void __user *p)
 {
@@ -183,14 +197,15 @@
 	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
 
 	rc = wait_for_completion_interruptible(&mdp3_session->vsync_comp);
-	if (rc < 0)
+	if (rc < 0) {
+		pr_debug("mdp3_vsync_show_event interrupted\n");
 		return rc;
-
+	}
 	spin_lock_irqsave(&mdp3_session->vsync_lock, flag);
 	vsync_ticks = ktime_to_ns(mdp3_session->vsync_time);
 	spin_unlock_irqrestore(&mdp3_session->vsync_lock, flag);
 
-	pr_debug("fb%d vsync=%llu", mfd->index, vsync_ticks);
+	pr_debug("fb%d vsync=%llu\n", mfd->index, vsync_ticks);
 	rc = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_ticks);
 	return rc;
 }
@@ -442,10 +457,13 @@
 		goto on_error;
 	}
 
-	rc = mdp3_session->dma->start(mdp3_session->dma, mdp3_session->intf);
-	if (rc) {
-		pr_err("fail to start the MDP display interface\n");
-		goto on_error;
+	if (mfd->fbi->screen_base) {
+		rc = mdp3_session->dma->start(mdp3_session->dma,
+						mdp3_session->intf);
+		if (rc) {
+			pr_err("fail to start the MDP display interface\n");
+			goto on_error;
+		}
 	}
 
 on_error:
@@ -640,7 +658,8 @@
 	data = mdp3_bufq_pop(&mdp3_session->bufq_in);
 	if (data) {
 		mdp3_session->dma->update(mdp3_session->dma,
-			(void *)data->addr);
+			(void *)data->addr,
+			mdp3_session->intf);
 		mdp3_bufq_push(&mdp3_session->bufq_out, data);
 	}
 
@@ -686,8 +705,14 @@
 		goto pan_error;
 	}
 
-	mdp3_session->dma->update(mdp3_session->dma,
-				(void *)mfd->iova + offset);
+	if (mfd->fbi->screen_base) {
+		mdp3_session->dma->update(mdp3_session->dma,
+				(void *)mfd->iova + offset,
+				mdp3_session->intf);
+	} else {
+		pr_debug("mdp3_ctrl_pan_display no memory, stop interface");
+		mdp3_session->intf->stop(mdp3_session->intf);
+	}
 pan_error:
 	mutex_unlock(&mdp3_session->lock);
 }
@@ -725,8 +750,6 @@
 	struct msmfb_overlay_data ov_data;
 	int val;
 
-	pr_debug("mdp3_ctrl_ioctl_handler\n");
-
 	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
 	if (!mdp3_session)
 		return -ENODEV;
@@ -844,6 +867,10 @@
 	mdp3_bufq_init(&mdp3_session->bufq_in);
 	mdp3_bufq_init(&mdp3_session->bufq_out);
 
+	init_timer(&mdp3_session->vsync_timer);
+	mdp3_session->vsync_timer.function = mdp3_vsync_timer_func;
+	mdp3_session->vsync_timer.data = (u32)mdp3_session;
+	mdp3_session->vsync_period = 1000 / mfd->panel_info->mipi.frame_rate;
 	mfd->mdp.private1 = mdp3_session;
 
 	rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index fb3bd36..8d2a235 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -17,6 +17,7 @@
 #include <linux/types.h>
 #include <linux/mutex.h>
 #include <linux/completion.h>
+#include <linux/timer.h>
 
 #include "mdp3.h"
 #include "mdp3_dma.h"
@@ -41,7 +42,9 @@
 	struct msm_fb_data_type *mfd;
 	ktime_t vsync_time;
 	spinlock_t vsync_lock;
+	struct timer_list vsync_timer;
 	struct completion vsync_comp;
+	int vsync_period;
 	struct mdp_overlay overlay;
 	struct mdp3_buffer_queue bufq_in;
 	struct mdp3_buffer_queue bufq_out;
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 94ad9be..ea8d47d 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -415,7 +415,8 @@
 	return 0;
 }
 
-static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf)
+static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf,
+				struct mdp3_intf *intf)
 {
 	unsigned long flag;
 	int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
@@ -424,15 +425,20 @@
 
 	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
 		cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
-		wait_for_completion_killable(&dma->dma_comp);
+		if (intf->active)
+			wait_for_completion_killable(&dma->dma_comp);
 	}
-
 	spin_lock_irqsave(&dma->dma_lock, flag);
 	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
 	dma->source_config.buf = buf;
 	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD)
 		MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
 
+	if (!intf->active) {
+		pr_debug("mdp3_dmap_update start interface\n");
+		intf->start(intf);
+	}
+
 	wmb();
 	init_completion(&dma->vsync_comp);
 	spin_unlock_irqrestore(&dma->dma_lock, flag);
@@ -444,14 +450,16 @@
 	return 0;
 }
 
-static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf)
+static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf,
+				struct mdp3_intf *intf)
 {
 	unsigned long flag;
 	int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
 
 	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
 		cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
-		wait_for_completion_killable(&dma->dma_comp);
+		if (intf->active)
+			wait_for_completion_killable(&dma->dma_comp);
 	}
 
 	spin_lock_irqsave(&dma->dma_lock, flag);
@@ -459,6 +467,12 @@
 	dma->source_config.buf = buf;
 	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD)
 		MDP3_REG_WRITE(MDP3_REG_DMA_S_START, 1);
+
+	if (!intf->active) {
+		pr_debug("mdp3_dmap_update start interface\n");
+		intf->start(intf);
+	}
+
 	wmb();
 	init_completion(&dma->vsync_comp);
 	spin_unlock_irqrestore(&dma->dma_lock, flag);
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index f86bea9..faaeee2 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -251,7 +251,7 @@
 			struct mdp3_dma_ccs *ccs,
 			struct mdp3_dma_lut *lut);
 
-	int (*update)(struct mdp3_dma *dma, void *buf);
+	int (*update)(struct mdp3_dma *dma, void *buf, struct mdp3_intf *intf);
 
 	int (*update_cursor)(struct mdp3_dma *dma, int x, int y);
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 539ed22..b29b0eb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -527,6 +527,9 @@
 			ret = ion_map_iommu(iclient, data->srcp_ihdl,
 					    mdss_get_iommu_domain(domain),
 					    0, SZ_4K, 0, start, len, 0, 0);
+			if (ret && (domain == MDSS_IOMMU_DOMAIN_SECURE))
+				msm_ion_unsecure_buffer(iclient,
+						data->srcp_ihdl);
 		} else {
 			ret = ion_phys(iclient, data->srcp_ihdl, start,
 				       (size_t *) len);
@@ -541,6 +544,7 @@
 
 	if (!*start) {
 		pr_err("start address is zero!\n");
+		mdss_mdp_put_img(data);
 		return -ENOMEM;
 	}
 
@@ -551,7 +555,8 @@
 		pr_debug("mem=%d ihdl=%p buf=0x%x len=0x%x\n", img->memory_id,
 			 data->srcp_ihdl, data->addr, data->len);
 	} else {
-		return -EINVAL;
+		mdss_mdp_put_img(data);
+		return ret ? : -EOVERFLOW;
 	}
 
 	return ret;
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index 235248c..9c74fbb 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -53,6 +53,20 @@
 #define DEVFREQ_FLAG_LEAST_UPPER_BOUND		0x1
 
 /**
+ * struct devfreq_governor_data - mapping to per device governor data
+ * @name:		The name of the governor.
+ * @data:		Private data for the governor.
+ *
+ * Devices may pass in an array of this structure to allow governors
+ * to get the correct data pointer when they are enabled after
+ * the devfreq_add_device() call.
+ */
+struct devfreq_governor_data {
+	const char *name;
+	void *data;
+};
+
+/**
  * struct devfreq_dev_profile - Devfreq's user device profile
  * @initial_freq:	The operating frequency when devfreq_add_device() is
  *			called.
@@ -75,6 +89,11 @@
  *			this is the time to unregister it.
  * @freq_table:	Optional list of frequencies to support statistics.
  * @max_state:	The size of freq_table.
+ * @governor_data:	Optional array of private data for governors.
+ *			This is used to set devfreq->data correctly
+ *			when a governor is enabled via sysfs or other
+ *			mechanisms after the devfreq_add_device() call.
+ * @num_governor_data:  Number of elements in governor_data.
  */
 struct devfreq_dev_profile {
 	unsigned long initial_freq;
@@ -88,6 +107,8 @@
 
 	unsigned int *freq_table;
 	unsigned int max_state;
+	const struct devfreq_governor_data *governor_data;
+	unsigned int num_governor_data;
 };
 
 /**
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index ce9e5b9..bd954ee 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -528,6 +528,9 @@
 /* Indicates whether demux support sending data directly to subtitle decoder */
 #define DMX_CAP_SUBTITLE_DECODER_DATA	0x10
 
+/* Indicates whether TS insertion is supported */
+#define DMX_CAP_TS_INSERTION	0x20
+
 	/* Number of decoders demux can output data to */
 	int num_decoders;
 
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 7562166..cd70726 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -41,7 +41,7 @@
  *				learning can start
  * @min_fcc_ocv_pc:		minimum PC (lookup(OCV)) at which CC counting
  *				for FCC learning can start
- * @max_fcc_learning_samples:	Maximum number of FCC measurement cycles to be
+ * @min_fcc_learning_samples:	Minimum number of FCC measurement cycles to be
  *				used for FCC update
  * @normal_voltage_calc_ms:	The period of soc calculation in ms when battery
  *				voltage higher than cutoff voltage
@@ -74,7 +74,7 @@
 	int				enable_fcc_learning;
 	int				min_fcc_learning_soc;
 	int				min_fcc_ocv_pc;
-	int				max_fcc_learning_samples;
+	int				min_fcc_learning_samples;
 	int				shutdown_soc_valid_limit;
 	int				ignore_shutdown_soc;
 	int				adjust_soc_low_threshold;
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 6d7d178..6a68b72 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -608,6 +608,13 @@
  *	with the relevant Information Elements. This event is used to report
  *	received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
  *
+ * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running
+ *	a critical protocol that needs more reliability in the connection to
+ *	complete.
+ *
+ * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
+ *	return back to normal.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -768,6 +775,9 @@
 	NL80211_CMD_UPDATE_FT_IES,
 	NL80211_CMD_FT_EVENT,
 
+	NL80211_CMD_CRIT_PROTOCOL_START,
+	NL80211_CMD_CRIT_PROTOCOL_STOP,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1360,6 +1370,16 @@
  * @NL80211_ATTR_IE_RIC: Resource Information Container Information
  *	Element
  *
+ * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased
+ *	reliability, see &enum nl80211_crit_proto_id (u16).
+ * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
+ *      the connection should have increased reliability (u16).
+ *
+ * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16).
+ *	This is similar to @NL80211_ATTR_STA_AID but with a difference of being
+ *	allowed to be used with the first @NL80211_CMD_SET_STATION command to
+ *	update a TDLS peer STA entry.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1655,6 +1675,11 @@
 	NL80211_ATTR_MDID,
 	NL80211_ATTR_IE_RIC,
 
+	NL80211_ATTR_CRIT_PROT_ID,
+	NL80211_ATTR_MAX_CRIT_PROT_DURATION,
+
+	NL80211_ATTR_PEER_AID,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -3097,4 +3122,25 @@
 	NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED,
 	NL80211_ACL_POLICY_DENY_UNLESS_LISTED,
 };
+/**
+ * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers
+ *
+ * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified.
+ * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol.
+ * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol.
+ * @NL80211_CRIT_PROTO_APIPA: APIPA protocol.
+ * @NUM_NL80211_CRIT_PROTO: must be kept last.
+ */
+enum nl80211_crit_proto_id {
+	NL80211_CRIT_PROTO_UNSPEC,
+	NL80211_CRIT_PROTO_DHCP,
+	NL80211_CRIT_PROTO_EAPOL,
+	NL80211_CRIT_PROTO_APIPA,
+	/* add other protocols before this one */
+	NUM_NL80211_CRIT_PROTO
+};
+
+/* maximum duration for critical protocol measures */
+#define NL80211_CRIT_PROTO_MAX_DURATION		5000 /* msec */
+
 #endif /* __LINUX_NL80211_H */
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 1de9aaa..3d7b1c9 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -110,6 +110,7 @@
 	POWER_SUPPLY_PROP_CHARGE_NOW,
 	POWER_SUPPLY_PROP_CHARGE_AVG,
 	POWER_SUPPLY_PROP_CHARGE_COUNTER,
+	POWER_SUPPLY_PROP_CHARGE_COUNTER_SHADOW,
 	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
 	POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
 	POWER_SUPPLY_PROP_ENERGY_FULL,
@@ -280,6 +281,7 @@
 	case POWER_SUPPLY_PROP_CHARGE_NOW:
 	case POWER_SUPPLY_PROP_CHARGE_AVG:
 	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+	case POWER_SUPPLY_PROP_CHARGE_COUNTER_SHADOW:
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
 	case POWER_SUPPLY_PROP_CURRENT_AVG:
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 111f26b..c168907 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1881,8 +1881,6 @@
 {
 	int delta = 0;
 
-	if (headroom < NET_SKB_PAD)
-		headroom = NET_SKB_PAD;
 	if (headroom > skb_headroom(skb))
 		delta = headroom - skb_headroom(skb);
 
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index 6cd4995..8e9aedf 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -69,6 +69,7 @@
 	int bytes_per_pixel;
 	unsigned int source_address;
 	unsigned int destination_address;
+	unsigned int compl_destination_address;
 	unsigned int src_stride;
 	unsigned int dst_stride;
 	int rotate_270;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 1a07d2e..3513fef 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5890,6 +5890,7 @@
 {
 	struct rq *rq = cpu_rq(cpu);
 	struct sched_domain *tmp;
+	unsigned long next_balance = rq->next_balance;
 
 	/* Remove the sched domains which do not contribute to scheduling. */
 	for (tmp = sd; tmp; ) {
@@ -5914,6 +5915,17 @@
 			sd->child = NULL;
 	}
 
+	for (tmp = sd; tmp; ) {
+		unsigned long interval;
+
+		interval = msecs_to_jiffies(tmp->balance_interval);
+		if (time_after(next_balance, tmp->last_balance + interval))
+			next_balance = tmp->last_balance + interval;
+
+		tmp = tmp->parent;
+	}
+	rq->next_balance = next_balance;
+
 	sched_domain_debug(sd, cpu);
 
 	rq_attach_root(rq, rd);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 6ed6d3e..68fd9d7 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -222,6 +222,7 @@
 	[NL80211_ATTR_MDID] = { .type = NLA_U16 },
 	[NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
 				  .len = IEEE80211_MAX_DATA_LEN },
+	[NL80211_ATTR_PEER_AID] = { .type = NLA_U16 },
 };
 
 /* policy for the key attributes */
@@ -2787,6 +2788,8 @@
 	int err;
 
 	/* Dummy STA entry gets updated once the peer capabilities are known */
+	if (info->attrs[NL80211_ATTR_PEER_AID])
+		params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
 	if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
 		params->ht_capa =
 			nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
@@ -3016,7 +3019,8 @@
 	if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
 		return -EINVAL;
 
-	if (!info->attrs[NL80211_ATTR_STA_AID])
+	if (!info->attrs[NL80211_ATTR_STA_AID] &&
+	    !info->attrs[NL80211_ATTR_PEER_AID])
 		return -EINVAL;
 
 	mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
@@ -3027,7 +3031,10 @@
 	params.listen_interval =
 		nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
 
-	params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
+	if (info->attrs[NL80211_ATTR_STA_AID])
+		params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
+	else
+		params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
 	if (!params.aid || params.aid > IEEE80211_MAX_AID)
 		return -EINVAL;
 
diff --git a/scripts/build-all.py b/scripts/build-all.py
index 4789af7..c585e4a 100755
--- a/scripts/build-all.py
+++ b/scripts/build-all.py
@@ -88,6 +88,7 @@
         r'[fm]sm[0-9]*_defconfig',
         r'apq*_defconfig',
         r'qsd*_defconfig',
+	r'msmkrypton*_defconfig',
         )
     for p in arch_pats:
         for n in glob.glob('arch/arm/configs/' + p):
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index 6d1c6bb..2a48022 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -27,3 +27,5 @@
 # dependencies on generated files need to be listed explicitly
 $(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h
 
+# generated files need to be cleaned explicitly
+clean-files	:= dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h
diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc
index 6ddf9ec..bece49b 100644
--- a/scripts/dtc/Makefile.dtc
+++ b/scripts/dtc/Makefile.dtc
@@ -3,7 +3,16 @@
 # This is not a complete Makefile of itself.  Instead, it is designed to
 # be easily embeddable into other systems of Makefiles.
 #
-DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
-	checks.c
+DTC_SRCS = \
+	checks.c \
+	data.c \
+	dtc.c \
+	flattree.c \
+	fstree.c \
+	livetree.c \
+	srcpos.c \
+	treesource.c \
+	util.c
+
 DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
 DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index a662a00..ee96a25 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -31,12 +31,6 @@
 #define TRACE(c, fmt, ...)	do { } while (0)
 #endif
 
-enum checklevel {
-	IGNORE = 0,
-	WARN = 1,
-	ERROR = 2,
-};
-
 enum checkstatus {
 	UNCHECKED = 0,
 	PREREQ,
@@ -57,14 +51,14 @@
 	node_check_fn node_fn;
 	prop_check_fn prop_fn;
 	void *data;
-	enum checklevel level;
+	bool warn, error;
 	enum checkstatus status;
 	int inprogress;
 	int num_prereqs;
 	struct check **prereq;
 };
 
-#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
+#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...)	       \
 	static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
 	static struct check nm = { \
 		.name = #nm, \
@@ -72,20 +66,37 @@
 		.node_fn = (nfn), \
 		.prop_fn = (pfn), \
 		.data = (d), \
-		.level = (lvl), \
+		.warn = (w), \
+		.error = (e), \
 		.status = UNCHECKED, \
 		.num_prereqs = ARRAY_SIZE(nm##_prereqs), \
 		.prereq = nm##_prereqs, \
 	};
+#define WARNING(nm, tfn, nfn, pfn, d, ...) \
+	CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
+#define ERROR(nm, tfn, nfn, pfn, d, ...) \
+	CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
+#define CHECK(nm, tfn, nfn, pfn, d, ...) \
+	CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__)
 
-#define TREE_CHECK(nm, d, lvl, ...) \
-	CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
-#define NODE_CHECK(nm, d, lvl, ...) \
-	CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
-#define PROP_CHECK(nm, d, lvl, ...) \
-	CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
-#define BATCH_CHECK(nm, lvl, ...) \
-	CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
+#define TREE_WARNING(nm, d, ...) \
+	WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
+#define TREE_ERROR(nm, d, ...) \
+	ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
+#define TREE_CHECK(nm, d, ...) \
+	CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
+#define NODE_WARNING(nm, d, ...) \
+	WARNING(nm, NULL, check_##nm, NULL, d,  __VA_ARGS__)
+#define NODE_ERROR(nm, d, ...) \
+	ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
+#define NODE_CHECK(nm, d, ...) \
+	CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
+#define PROP_WARNING(nm, d, ...) \
+	WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
+#define PROP_ERROR(nm, d, ...) \
+	ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
+#define PROP_CHECK(nm, d, ...) \
+	CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
 
 #ifdef __GNUC__
 static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
@@ -95,13 +106,13 @@
 	va_list ap;
 	va_start(ap, fmt);
 
-	if ((c->level < WARN) || (c->level <= quiet))
-		return; /* Suppress message */
-
-	fprintf(stderr, "%s (%s): ",
-		(c->level == ERROR) ? "ERROR" : "Warning", c->name);
-	vfprintf(stderr, fmt, ap);
-	fprintf(stderr, "\n");
+	if ((c->warn && (quiet < 1))
+	    || (c->error && (quiet < 2))) {
+		fprintf(stderr, "%s (%s): ",
+			(c->error) ? "ERROR" : "Warning", c->name);
+		vfprintf(stderr, fmt, ap);
+		fprintf(stderr, "\n");
+	}
 }
 
 #define FAIL(c, ...) \
@@ -167,7 +178,7 @@
 
 out:
 	c->inprogress = 0;
-	if ((c->status != PASSED) && (c->level == ERROR))
+	if ((c->status != PASSED) && (c->error))
 		error = 1;
 	return error;
 }
@@ -176,6 +187,13 @@
  * Utility check functions
  */
 
+/* A check which always fails, for testing purposes only */
+static inline void check_always_fail(struct check *c, struct node *dt)
+{
+	FAIL(c, "always_fail check");
+}
+TREE_CHECK(always_fail, NULL);
+
 static void check_is_string(struct check *c, struct node *root,
 			    struct node *node)
 {
@@ -190,8 +208,10 @@
 		FAIL(c, "\"%s\" property in %s is not a string",
 		     propname, node->fullpath);
 }
-#define CHECK_IS_STRING(nm, propname, lvl) \
-	CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
+#define WARNING_IF_NOT_STRING(nm, propname) \
+	WARNING(nm, NULL, check_is_string, NULL, (propname))
+#define ERROR_IF_NOT_STRING(nm, propname) \
+	ERROR(nm, NULL, check_is_string, NULL, (propname))
 
 static void check_is_cell(struct check *c, struct node *root,
 			  struct node *node)
@@ -207,8 +227,10 @@
 		FAIL(c, "\"%s\" property in %s is not a single cell",
 		     propname, node->fullpath);
 }
-#define CHECK_IS_CELL(nm, propname, lvl) \
-	CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
+#define WARNING_IF_NOT_CELL(nm, propname) \
+	WARNING(nm, NULL, check_is_cell, NULL, (propname))
+#define ERROR_IF_NOT_CELL(nm, propname) \
+	ERROR(nm, NULL, check_is_cell, NULL, (propname))
 
 /*
  * Structural check functions
@@ -227,20 +249,24 @@
 				FAIL(c, "Duplicate node name %s",
 				     child->fullpath);
 }
-NODE_CHECK(duplicate_node_names, NULL, ERROR);
+NODE_ERROR(duplicate_node_names, NULL);
 
 static void check_duplicate_property_names(struct check *c, struct node *dt,
 					   struct node *node)
 {
 	struct property *prop, *prop2;
 
-	for_each_property(node, prop)
-		for (prop2 = prop->next; prop2; prop2 = prop2->next)
+	for_each_property(node, prop) {
+		for (prop2 = prop->next; prop2; prop2 = prop2->next) {
+			if (prop2->deleted)
+				continue;
 			if (streq(prop->name, prop2->name))
 				FAIL(c, "Duplicate property name %s in %s",
 				     prop->name, node->fullpath);
+		}
+	}
 }
-NODE_CHECK(duplicate_property_names, NULL, ERROR);
+NODE_ERROR(duplicate_property_names, NULL);
 
 #define LOWERCASE	"abcdefghijklmnopqrstuvwxyz"
 #define UPPERCASE	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -256,7 +282,7 @@
 		FAIL(c, "Bad character '%c' in node %s",
 		     node->name[n], node->fullpath);
 }
-NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
+NODE_ERROR(node_name_chars, PROPNODECHARS "@");
 
 static void check_node_name_format(struct check *c, struct node *dt,
 				   struct node *node)
@@ -265,7 +291,7 @@
 		FAIL(c, "Node %s has multiple '@' characters in name",
 		     node->fullpath);
 }
-NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
+NODE_ERROR(node_name_format, NULL, &node_name_chars);
 
 static void check_property_name_chars(struct check *c, struct node *dt,
 				      struct node *node, struct property *prop)
@@ -276,7 +302,7 @@
 		FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
 		     prop->name[n], prop->name, node->fullpath);
 }
-PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
+PROP_ERROR(property_name_chars, PROPNODECHARS);
 
 #define DESCLABEL_FMT	"%s%s%s%s%s"
 #define DESCLABEL_ARGS(node,prop,mark)		\
@@ -331,8 +357,8 @@
 	for_each_marker_of_type(m, LABEL)
 		check_duplicate_label(c, dt, m->ref, node, prop, m);
 }
-CHECK(duplicate_label, NULL, check_duplicate_label_node,
-      check_duplicate_label_prop, NULL, ERROR);
+ERROR(duplicate_label, NULL, check_duplicate_label_node,
+      check_duplicate_label_prop, NULL);
 
 static void check_explicit_phandles(struct check *c, struct node *root,
 				    struct node *node, struct property *prop)
@@ -391,7 +417,7 @@
 
 	node->phandle = phandle;
 }
-PROP_CHECK(explicit_phandles, NULL, ERROR);
+PROP_ERROR(explicit_phandles, NULL);
 
 static void check_name_properties(struct check *c, struct node *root,
 				  struct node *node)
@@ -420,8 +446,8 @@
 		free(prop);
 	}
 }
-CHECK_IS_STRING(name_is_string, "name", ERROR);
-NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
+ERROR_IF_NOT_STRING(name_is_string, "name");
+NODE_ERROR(name_properties, NULL, &name_is_string);
 
 /*
  * Reference fixup functions
@@ -448,7 +474,7 @@
 		*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
 	}
 }
-CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
+ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
       &duplicate_node_names, &explicit_phandles);
 
 static void fixup_path_references(struct check *c, struct node *dt,
@@ -473,19 +499,19 @@
 						  strlen(path) + 1);
 	}
 }
-CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
+ERROR(path_references, NULL, NULL, fixup_path_references, NULL,
       &duplicate_node_names);
 
 /*
  * Semantic checks
  */
-CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
-CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
-CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
+WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
+WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
+WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
 
-CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
-CHECK_IS_STRING(model_is_string, "model", WARN);
-CHECK_IS_STRING(status_is_string, "status", WARN);
+WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
+WARNING_IF_NOT_STRING(model_is_string, "model");
+WARNING_IF_NOT_STRING(status_is_string, "status");
 
 static void fixup_addr_size_cells(struct check *c, struct node *dt,
 				  struct node *node)
@@ -503,8 +529,8 @@
 	if (prop)
 		node->size_cells = propval_cell(prop);
 }
-CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
-      &address_cells_is_cell, &size_cells_is_cell);
+WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
+	&address_cells_is_cell, &size_cells_is_cell);
 
 #define node_addr_cells(n) \
 	(((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
@@ -538,7 +564,7 @@
 		     "(#address-cells == %d, #size-cells == %d)",
 		     node->fullpath, prop->val.len, addr_cells, size_cells);
 }
-NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
+NODE_WARNING(reg_format, NULL, &addr_size_cells);
 
 static void check_ranges_format(struct check *c, struct node *dt,
 				struct node *node)
@@ -579,7 +605,7 @@
 		     p_addr_cells, c_addr_cells, c_size_cells);
 	}
 }
-NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
+NODE_WARNING(ranges_format, NULL, &addr_size_cells);
 
 /*
  * Style checks
@@ -606,7 +632,7 @@
 		FAIL(c, "Relying on default #size-cells value for %s",
 		     node->fullpath);
 }
-NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
+NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);
 
 static void check_obsolete_chosen_interrupt_controller(struct check *c,
 						       struct node *dt)
@@ -623,7 +649,7 @@
 		FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
 		     "property");
 }
-TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
+TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
 
 static struct check *check_table[] = {
 	&duplicate_node_names, &duplicate_property_names,
@@ -642,8 +668,71 @@
 
 	&avoid_default_addr_size,
 	&obsolete_chosen_interrupt_controller,
+
+	&always_fail,
 };
 
+static void enable_warning_error(struct check *c, bool warn, bool error)
+{
+	int i;
+
+	/* Raising level, also raise it for prereqs */
+	if ((warn && !c->warn) || (error && !c->error))
+		for (i = 0; i < c->num_prereqs; i++)
+			enable_warning_error(c->prereq[i], warn, error);
+
+	c->warn = c->warn || warn;
+	c->error = c->error || error;
+}
+
+static void disable_warning_error(struct check *c, bool warn, bool error)
+{
+	int i;
+
+	/* Lowering level, also lower it for things this is the prereq
+	 * for */
+	if ((warn && c->warn) || (error && c->error)) {
+		for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+			struct check *cc = check_table[i];
+			int j;
+
+			for (j = 0; j < cc->num_prereqs; j++)
+				if (cc->prereq[j] == c)
+					disable_warning_error(cc, warn, error);
+		}
+	}
+
+	c->warn = c->warn && !warn;
+	c->error = c->error && !error;
+}
+
+void parse_checks_option(bool warn, bool error, const char *optarg)
+{
+	int i;
+	const char *name = optarg;
+	bool enable = true;
+
+	if ((strncmp(optarg, "no-", 3) == 0)
+	    || (strncmp(optarg, "no_", 3) == 0)) {
+		name = optarg + 3;
+		enable = false;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+		struct check *c = check_table[i];
+
+		if (streq(c->name, name)) {
+			if (enable)
+				enable_warning_error(c, warn, error);
+			else
+				disable_warning_error(c, warn, error);
+			return;
+		}
+	}
+
+	die("Unrecognized check name \"%s\"\n", name);
+}
+
 void process_checks(int force, struct boot_info *bi)
 {
 	struct node *dt = bi->dt;
@@ -653,7 +742,7 @@
 	for (i = 0; i < ARRAY_SIZE(check_table); i++) {
 		struct check *c = check_table[i];
 
-		if (c->level != IGNORE)
+		if (c->warn || c->error)
 			error = error || run_check(c, dt);
 	}
 
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
index fe555e8..4a40c5b 100644
--- a/scripts/dtc/data.c
+++ b/scripts/dtc/data.c
@@ -68,40 +68,6 @@
 	return d;
 }
 
-static char get_oct_char(const char *s, int *i)
-{
-	char x[4];
-	char *endx;
-	long val;
-
-	x[3] = '\0';
-	strncpy(x, s + *i, 3);
-
-	val = strtol(x, &endx, 8);
-
-	assert(endx > x);
-
-	(*i) += endx - x;
-	return val;
-}
-
-static char get_hex_char(const char *s, int *i)
-{
-	char x[3];
-	char *endx;
-	long val;
-
-	x[2] = '\0';
-	strncpy(x, s + *i, 2);
-
-	val = strtol(x, &endx, 16);
-	if (!(endx  > x))
-		die("\\x used with no following hex digits\n");
-
-	(*i) += endx - x;
-	return val;
-}
-
 struct data data_copy_escape_string(const char *s, int len)
 {
 	int i = 0;
@@ -114,53 +80,10 @@
 	while (i < len) {
 		char c = s[i++];
 
-		if (c != '\\') {
-			q[d.len++] = c;
-			continue;
-		}
+		if (c == '\\')
+			c = get_escape_char(s, &i);
 
-		c = s[i++];
-		assert(c);
-		switch (c) {
-		case 'a':
-			q[d.len++] = '\a';
-			break;
-		case 'b':
-			q[d.len++] = '\b';
-			break;
-		case 't':
-			q[d.len++] = '\t';
-			break;
-		case 'n':
-			q[d.len++] = '\n';
-			break;
-		case 'v':
-			q[d.len++] = '\v';
-			break;
-		case 'f':
-			q[d.len++] = '\f';
-			break;
-		case 'r':
-			q[d.len++] = '\r';
-			break;
-		case '0':
-		case '1':
-		case '2':
-		case '3':
-		case '4':
-		case '5':
-		case '6':
-		case '7':
-			i--; /* need to re-read the first digit as
-			      * part of the octal value */
-			q[d.len++] = get_oct_char(s, &i);
-			break;
-		case 'x':
-			q[d.len++] = get_hex_char(s, &i);
-			break;
-		default:
-			q[d.len++] = c;
-		}
+		q[d.len++] = c;
 	}
 
 	q[d.len++] = '\0';
@@ -245,11 +168,33 @@
 	return d;
 }
 
-struct data data_append_cell(struct data d, cell_t word)
+struct data data_append_integer(struct data d, uint64_t value, int bits)
 {
-	cell_t beword = cpu_to_fdt32(word);
+	uint8_t value_8;
+	uint16_t value_16;
+	uint32_t value_32;
+	uint64_t value_64;
 
-	return data_append_data(d, &beword, sizeof(beword));
+	switch (bits) {
+	case 8:
+		value_8 = value;
+		return data_append_data(d, &value_8, 1);
+
+	case 16:
+		value_16 = cpu_to_fdt16(value);
+		return data_append_data(d, &value_16, 2);
+
+	case 32:
+		value_32 = cpu_to_fdt32(value);
+		return data_append_data(d, &value_32, 4);
+
+	case 64:
+		value_64 = cpu_to_fdt64(value);
+		return data_append_data(d, &value_64, 8);
+
+	default:
+		die("Invalid literal size (%d)\n", bits);
+	}
 }
 
 struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
@@ -262,11 +207,14 @@
 	return data_append_data(d, &bere, sizeof(bere));
 }
 
+struct data data_append_cell(struct data d, cell_t word)
+{
+	return data_append_integer(d, word, sizeof(word) * 8);
+}
+
 struct data data_append_addr(struct data d, uint64_t addr)
 {
-	uint64_t beaddr = cpu_to_fdt64(addr);
-
-	return data_append_data(d, &beaddr, sizeof(beaddr));
+	return data_append_integer(d, addr, sizeof(addr) * 8);
 }
 
 struct data data_append_byte(struct data d, uint8_t byte)
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index e866ea5..254d5af 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -29,6 +29,7 @@
 PATHCHAR	({PROPNODECHAR}|[/])
 LABEL		[a-zA-Z_][a-zA-Z0-9_]*
 STRING		\"([^\\"]|\\.)*\"
+CHAR_LITERAL	'([^']|\\')*'
 WS		[[:space:]]
 COMMENT		"/*"([^*]|\*+[^*/])*\*+"/"
 LINECOMMENT	"//".*\n
@@ -70,6 +71,27 @@
 			push_input_file(name);
 		}
 
+<*>^"#"(line)?{WS}+[0-9]+{WS}+{STRING}({WS}+[0-9]+)? {
+			char *line, *tmp, *fn;
+			/* skip text before line # */
+			line = yytext;
+			while (!isdigit(*line))
+				line++;
+			/* skip digits in line # */
+			tmp = line;
+			while (!isspace(*tmp))
+				tmp++;
+			/* "NULL"-terminate line # */
+			*tmp = '\0';
+			/* start of filename */
+			fn = strchr(tmp + 1, '"') + 1;
+			/* strip trailing " from filename */
+			tmp = strchr(fn, '"');
+			*tmp = 0;
+			/* -1 since #line is the number of the next line */
+			srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+		}
+
 <*><<EOF>>		{
 			if (!pop_input_file()) {
 				yyterminate();
@@ -96,6 +118,26 @@
 			return DT_MEMRESERVE;
 		}
 
+<*>"/bits/"	{
+			DPRINT("Keyword: /bits/\n");
+			BEGIN_DEFAULT();
+			return DT_BITS;
+		}
+
+<*>"/delete-property/"	{
+			DPRINT("Keyword: /delete-property/\n");
+			DPRINT("<PROPNODENAME>\n");
+			BEGIN(PROPNODENAME);
+			return DT_DEL_PROP;
+		}
+
+<*>"/delete-node/"	{
+			DPRINT("Keyword: /delete-node/\n");
+			DPRINT("<PROPNODENAME>\n");
+			BEGIN(PROPNODENAME);
+			return DT_DEL_NODE;
+		}
+
 <*>{LABEL}:	{
 			DPRINT("Label: %s\n", yytext);
 			yylval.labelref = xstrdup(yytext);
@@ -103,12 +145,19 @@
 			return DT_LABEL;
 		}
 
-<V1>[0-9]+|0[xX][0-9a-fA-F]+      {
+<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
 			yylval.literal = xstrdup(yytext);
 			DPRINT("Literal: '%s'\n", yylval.literal);
 			return DT_LITERAL;
 		}
 
+<*>{CHAR_LITERAL}	{
+			yytext[yyleng-1] = '\0';
+			yylval.literal = xstrdup(yytext+1);
+			DPRINT("Character literal: %s\n", yylval.literal);
+			return DT_CHAR_LITERAL;
+		}
+
 <*>\&{LABEL}	{	/* label reference */
 			DPRINT("Ref: %s\n", yytext+1);
 			yylval.labelref = xstrdup(yytext+1);
@@ -134,9 +183,10 @@
 			return ']';
 		}
 
-<PROPNODENAME>{PROPNODECHAR}+ {
+<PROPNODENAME>\\?{PROPNODECHAR}+ {
 			DPRINT("PropNodeName: %s\n", yytext);
-			yylval.propnodename = xstrdup(yytext);
+			yylval.propnodename = xstrdup((yytext[0] == '\\') ?
+							yytext + 1 : yytext);
 			BEGIN_DEFAULT();
 			return DT_PROPNODENAME;
 		}
@@ -150,6 +200,15 @@
 <*>{COMMENT}+	/* eat C-style comments */
 <*>{LINECOMMENT}+ /* eat C++-style comments */
 
+<*>"<<"		{ return DT_LSHIFT; };
+<*>">>"		{ return DT_RSHIFT; };
+<*>"<="		{ return DT_LE; };
+<*>">="		{ return DT_GE; };
+<*>"=="		{ return DT_EQ; };
+<*>"!="		{ return DT_NE; };
+<*>"&&"		{ return DT_AND; };
+<*>"||"		{ return DT_OR; };
+
 <*>.		{
 			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
 				(unsigned)yytext[0]);
diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
index 8bbe128..a6c5fcd 100644
--- a/scripts/dtc/dtc-lexer.lex.c_shipped
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
@@ -1,5 +1,6 @@
+#line 2 "dtc-lexer.lex.c"
 
-#line 3 "scripts/dtc/dtc-lexer.lex.c_shipped"
+#line 4 "dtc-lexer.lex.c"
 
 #define  YY_INT_ALIGNED short int
 
@@ -53,7 +54,6 @@
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -84,6 +84,8 @@
 #define UINT32_MAX             (4294967295U)
 #endif
 
+#endif /* ! C99 */
+
 #endif /* ! FLEXINT_H */
 
 #ifdef __cplusplus
@@ -140,7 +142,15 @@
 
 /* Size of default input buffer. */
 #ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
 #define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
 #endif
 
 /* The state buf must be large enough to hold one state per character in the main buffer.
@@ -362,8 +372,8 @@
 	*yy_cp = '\0'; \
 	(yy_c_buf_p) = yy_cp;
 
-#define YY_NUM_RULES 17
-#define YY_END_OF_BUFFER 18
+#define YY_NUM_RULES 30
+#define YY_END_OF_BUFFER 31
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -371,19 +381,25 @@
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[94] =
+static yyconst flex_int16_t yy_accept[161] =
     {   0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       18,   16,   13,   13,   16,   16,   16,   16,   16,   16,
-       16,   10,   11,   11,    6,    6,   13,    0,    2,    0,
-        7,    0,    0,    0,    0,    0,    0,    0,    5,    0,
-        9,    9,   11,   11,    6,    0,    7,    0,    0,    0,
-        0,   15,    0,    0,    0,    0,    6,    0,   14,    0,
-        0,    0,    0,    0,    8,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    3,   12,
-        0,    0,    0,    0,    0,    0,    0,    0,    1,    0,
-        0,    4,    0
+       31,   29,   18,   18,   29,   29,   29,   29,   29,   29,
+       29,   29,   29,   29,   29,   29,   29,   29,   15,   16,
+       16,   29,   16,   10,   10,   18,   26,    0,    3,    0,
+       27,   12,    0,    0,   11,    0,    0,    0,    0,    0,
+        0,    0,   21,   23,   25,   24,   22,    0,    9,   28,
+        0,    0,    0,   14,   14,   16,   16,   16,   10,   10,
+       10,    0,   12,    0,   11,    0,    0,    0,   20,    0,
+        0,    0,    0,    0,    0,    0,    0,   16,   10,   10,
+       10,    0,   19,    0,    0,    0,    0,    0,    0,    0,
 
+        0,    0,   16,   13,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   16,    6,    0,    0,    0,    0,    0,
+        0,    2,    0,    0,    0,    0,    0,    0,    0,    0,
+        4,   17,    0,    0,    2,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    1,    0,    0,
+        0,    0,    5,    8,    0,    0,    0,    0,    7,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -391,17 +407,17 @@
         1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
         2,    2,    2,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    1,    4,    5,    1,    1,    6,    1,    1,
-        1,    7,    5,    5,    8,    5,    9,   10,   11,   12,
-       12,   12,   12,   12,   12,   12,   12,   13,    1,    1,
-        1,    1,    5,    5,   14,   14,   14,   14,   14,   14,
-       15,   15,   15,   15,   15,   15,   15,   15,   15,   15,
-       15,   15,   15,   15,   15,   15,   15,   16,   15,   15,
-        1,   17,   18,    1,   15,    1,   14,   19,   20,   21,
+        1,    2,    4,    5,    6,    1,    1,    7,    8,    1,
+        1,    9,   10,   10,   11,   10,   12,   13,   14,   15,
+       15,   15,   15,   15,   15,   15,   15,   16,    1,   17,
+       18,   19,   10,   10,   20,   20,   20,   20,   20,   20,
+       21,   21,   21,   21,   21,   22,   21,   21,   21,   21,
+       21,   21,   21,   21,   23,   21,   21,   24,   21,   21,
+        1,   25,   26,    1,   21,    1,   20,   27,   28,   29,
 
-       22,   14,   15,   15,   23,   15,   15,   24,   25,   26,
-       15,   15,   15,   27,   28,   29,   30,   31,   15,   16,
-       15,   15,   32,    1,   33,    1,    1,    1,    1,    1,
+       30,   20,   21,   21,   31,   21,   21,   32,   33,   34,
+       35,   36,   21,   37,   38,   39,   40,   41,   21,   24,
+       42,   21,   43,   44,   45,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -418,112 +434,163 @@
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[34] =
+static yyconst flex_int32_t yy_meta[46] =
     {   0,
-        1,    1,    1,    1,    2,    1,    2,    2,    3,    4,
-        4,    4,    5,    6,    7,    7,    1,    1,    6,    6,
-        6,    6,    7,    7,    7,    7,    7,    7,    7,    7,
-        7,    8,    1
+        1,    1,    1,    1,    1,    2,    3,    1,    2,    2,
+        2,    4,    5,    5,    5,    6,    1,    1,    1,    7,
+        8,    8,    8,    8,    1,    1,    7,    7,    7,    7,
+        8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
+        8,    8,    3,    1,    1
     } ;
 
-static yyconst flex_int16_t yy_base[106] =
+static yyconst flex_int16_t yy_base[175] =
     {   0,
-        0,    0,  237,  236,   25,    0,   47,    0,   30,   71,
-      244,  247,   82,   84,   84,  211,   95,  229,  218,    0,
-      111,  247,    0,   84,   83,   95,  106,   86,  247,  237,
-        0,  230,  231,  234,  207,  209,  212,  220,  247,  206,
-      247,  218,    0,  106,  116,    0,    0,    0,  223,   89,
-      226,  219,  199,  206,  200,  204,    0,  190,  213,  212,
-      202,   91,  178,  161,  247,  172,  144,  150,  140,  130,
-      140,  124,  128,  120,  138,  137,  123,  122,  247,  247,
-      134,  114,  132,   86,  135,  125,   90,  136,  247,   97,
-       29,  247,  247,  153,  156,  161,  165,  170,  176,  180,
+        0,  388,  381,   40,   41,  386,   71,  385,   34,   44,
+      390,  395,   60,   62,  371,  112,  111,  111,  111,  104,
+      370,  106,  371,  342,  124,  119,    0,  144,  395,    0,
+      123,    0,  159,  153,  165,  167,  395,  130,  395,  382,
+      395,    0,  372,  122,  395,  157,  374,  379,  350,   21,
+      346,  349,  395,  395,  395,  395,  395,  362,  395,  395,
+      181,  346,  342,  395,  359,    0,  191,  343,  190,  351,
+      350,    0,    0,    0,  173,  362,  177,  367,  357,  329,
+      335,  328,  337,  331,  206,  329,  334,  327,  395,  338,
+      170,  314,  346,  345,  318,  325,  343,  158,  316,  212,
 
-      187,  195,  200,  205,  212
+      322,  319,  320,  395,  340,  336,  308,  305,  314,  304,
+      295,  138,  208,  220,  395,  292,  305,  265,  264,  254,
+      201,  222,  285,  275,  273,  270,  236,  235,  225,  115,
+      395,  395,  252,  216,  216,  217,  214,  230,  209,  220,
+      213,  239,  211,  217,  216,  209,  229,  395,  240,  225,
+      206,  169,  395,  395,  116,  106,   99,   54,  395,  395,
+      254,  260,  268,  272,  276,  282,  289,  293,  301,  309,
+      313,  319,  327,  335
     } ;
 
-static yyconst flex_int16_t yy_def[106] =
+static yyconst flex_int16_t yy_def[175] =
     {   0,
-       93,    1,    1,    1,    1,    5,   93,    7,    1,    1,
-       93,   93,   93,   93,   94,   95,   93,   96,   17,   97,
-       96,   93,   98,   99,   93,   93,   93,   94,   93,   94,
-      100,   93,  101,  102,   93,   93,   93,   96,   93,   93,
-       93,   96,   98,   99,   93,  103,  100,  104,  101,  101,
-      102,   93,   93,   93,   93,   93,  103,  104,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,  105,   93,  105,   93,  105,
-       93,   93,    0,   93,   93,   93,   93,   93,   93,   93,
+      160,    1,    1,    1,    1,    5,  160,    7,    1,    1,
+      160,  160,  160,  160,  160,  161,  162,  163,  160,  160,
+      160,  160,  164,  160,  160,  160,  165,  164,  160,  166,
+      167,  166,  166,  160,  160,  160,  160,  161,  160,  161,
+      160,  168,  160,  163,  160,  163,  169,  170,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  164,  160,  160,
+      160,  160,  160,  160,  164,  166,  167,  166,  160,  160,
+      160,  171,  168,  172,  163,  169,  169,  170,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  166,  160,  160,
+      171,  172,  160,  160,  160,  160,  160,  160,  160,  160,
 
-       93,   93,   93,   93,   93
+      160,  160,  166,  160,  160,  160,  160,  160,  160,  160,
+      160,  173,  160,  166,  160,  160,  160,  160,  160,  160,
+      173,  160,  173,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  174,  160,  160,  160,  174,  160,  174,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,    0,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160
     } ;
 
-static yyconst flex_int16_t yy_nxt[281] =
+static yyconst flex_int16_t yy_nxt[441] =
     {   0,
-       12,   13,   14,   15,   12,   16,   12,   12,   17,   12,
-       12,   12,   12,   18,   18,   18,   12,   12,   18,   18,
-       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-       18,   12,   12,   19,   20,   20,   20,   92,   21,   25,
-       26,   26,   22,   21,   21,   21,   21,   12,   13,   14,
-       15,   23,   16,   23,   23,   19,   23,   23,   23,   12,
-       24,   24,   24,   12,   12,   24,   24,   24,   24,   24,
-       24,   24,   24,   24,   24,   24,   24,   24,   12,   12,
-       25,   26,   26,   27,   27,   27,   27,   29,   43,   29,
-       43,   43,   45,   45,   45,   50,   39,   59,   46,   93,
+       12,   13,   14,   15,   16,   12,   17,   18,   12,   12,
+       12,   19,   12,   12,   12,   12,   20,   21,   22,   23,
+       23,   23,   23,   23,   12,   12,   23,   23,   23,   23,
+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   12,   24,   12,   25,   34,   35,   35,   25,
+       81,   26,   26,   27,   27,   27,   34,   35,   35,   82,
+       28,   36,   36,   36,   36,  159,   29,   28,   28,   28,
+       28,   12,   13,   14,   15,   16,   30,   17,   18,   30,
+       30,   30,   26,   30,   30,   30,   12,   20,   21,   22,
+       31,   31,   31,   31,   31,   32,   12,   31,   31,   31,
 
-       30,   33,   30,   34,   45,   45,   45,   27,   27,   68,
-       43,   91,   43,   43,   69,   35,   87,   36,   39,   37,
-       42,   42,   42,   39,   42,   45,   45,   45,   89,   42,
-       42,   42,   42,   85,   85,   86,   85,   85,   86,   89,
-       84,   90,   83,   82,   81,   80,   79,   78,   77,   76,
-       75,   74,   90,   28,   28,   28,   28,   28,   28,   28,
-       28,   31,   31,   31,   38,   38,   38,   38,   41,   73,
-       41,   43,   72,   43,   71,   43,   43,   44,   33,   44,
-       44,   44,   44,   47,   69,   47,   47,   49,   49,   49,
-       49,   49,   49,   49,   49,   51,   51,   51,   51,   51,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   12,   24,   12,   39,   41,   45,   47,
+       53,   54,   48,   56,   57,   61,   61,   47,   66,   45,
+       48,   66,   66,   66,   39,   46,   40,   49,   59,   50,
+      158,   51,  122,   52,  157,   49,   46,   50,  136,   63,
+      137,   52,  156,   43,   40,   62,   65,   65,   65,   59,
+       61,   61,  123,   65,   75,   69,   69,   69,   36,   36,
+       65,   65,   65,   65,   70,   71,   72,   69,   69,   69,
+       45,   46,   61,   61,  109,   77,   70,   71,   93,  110,
+       68,   70,   71,   85,   85,   85,   66,   46,  155,   66,
 
-       51,   51,   51,   57,   70,   57,   58,   58,   58,   67,
-       58,   58,   88,   88,   88,   88,   88,   88,   88,   88,
-       34,   66,   65,   64,   63,   62,   61,   60,   52,   50,
-       39,   56,   39,   55,   54,   53,   52,   50,   48,   93,
-       40,   39,   32,   93,   19,   19,   11,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93
+       66,   66,   69,   69,   69,  122,   59,  100,  100,   61,
+       61,   70,   71,  100,  100,  148,  112,  154,   85,   85,
+       85,   61,   61,  129,  129,  123,  129,  129,  135,  135,
+      135,  142,  142,  148,  143,  149,  153,  135,  135,  135,
+      142,  142,  160,  143,  152,  151,  150,  146,  145,  144,
+      141,  140,  139,  149,   38,   38,   38,   38,   38,   38,
+       38,   38,   42,  138,  134,  133,   42,   42,   44,   44,
+       44,   44,   44,   44,   44,   44,   58,   58,   58,   58,
+       64,  132,   64,   66,  131,  130,   66,  160,   66,   66,
+       67,  128,  127,   67,   67,   67,   67,   73,  126,   73,
+
+       73,   76,   76,   76,   76,   76,   76,   76,   76,   78,
+       78,   78,   78,   78,   78,   78,   78,   91,  125,   91,
+       92,  124,   92,   92,  120,   92,   92,  121,  121,  121,
+      121,  121,  121,  121,  121,  147,  147,  147,  147,  147,
+      147,  147,  147,  119,  118,  117,  116,  115,   47,  114,
+      110,  113,  111,  108,  107,  106,   48,  105,  104,   89,
+      103,  102,  101,   99,   98,   97,   96,   95,   94,   79,
+       77,   90,   89,   88,   59,   87,   86,   59,   84,   83,
+       80,   79,   77,   74,  160,   60,   59,   55,   37,  160,
+       33,   25,   26,   25,   11,  160,  160,  160,  160,  160,
+
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160
     } ;
 
-static yyconst flex_int16_t yy_chk[281] =
+static yyconst flex_int16_t yy_chk[441] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    5,    5,    5,    5,   91,    5,    9,
-        9,    9,    5,    5,    5,    5,    5,    7,    7,    7,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    4,    9,    9,    9,   10,
+       50,    4,    5,    5,    5,    5,   10,   10,   10,   50,
+        5,   13,   13,   14,   14,  158,    5,    5,    5,    5,
+        5,    7,    7,    7,    7,    7,    7,    7,    7,    7,
         7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
         7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
-        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
-       10,   10,   10,   13,   13,   14,   14,   15,   24,   28,
-       24,   24,   25,   25,   25,   50,   24,   50,   25,   90,
 
-       15,   17,   28,   17,   26,   26,   26,   27,   27,   62,
-       44,   87,   44,   44,   62,   17,   84,   17,   44,   17,
-       21,   21,   21,   21,   21,   45,   45,   45,   86,   21,
-       21,   21,   21,   83,   83,   83,   85,   85,   85,   88,
-       82,   86,   81,   78,   77,   76,   75,   74,   73,   72,
-       71,   70,   88,   94,   94,   94,   94,   94,   94,   94,
-       94,   95,   95,   95,   96,   96,   96,   96,   97,   69,
-       97,   98,   68,   98,   67,   98,   98,   99,   66,   99,
-       99,   99,   99,  100,   64,  100,  100,  101,  101,  101,
-      101,  101,  101,  101,  101,  102,  102,  102,  102,  102,
+        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,   16,   17,   18,   19,
+       20,   20,   19,   22,   22,   25,   25,   26,   31,   44,
+       26,   31,   31,   31,   38,   18,   16,   19,   31,   19,
+      157,   19,  112,   19,  156,   26,   44,   26,  130,   26,
+      130,   26,  155,   17,   38,   25,   28,   28,   28,   28,
+       33,   33,  112,   28,   46,   34,   34,   34,   36,   36,
+       28,   28,   28,   28,   34,   34,   34,   35,   35,   35,
+       75,   46,   61,   61,   98,   77,   35,   35,   77,   98,
+       33,   91,   91,   61,   61,   61,   67,   75,  152,   67,
 
-      102,  102,  102,  103,   63,  103,  104,  104,  104,   61,
-      104,  104,  105,  105,  105,  105,  105,  105,  105,  105,
-       60,   59,   58,   56,   55,   54,   53,   52,   51,   49,
-       42,   40,   38,   37,   36,   35,   34,   33,   32,   30,
-       19,   18,   16,   11,    4,    3,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93
+       67,   67,   69,   69,   69,  121,   67,   85,   85,  113,
+      113,   69,   69,  100,  100,  143,  100,  151,   85,   85,
+       85,  114,  114,  122,  122,  121,  129,  129,  135,  135,
+      135,  138,  138,  147,  138,  143,  150,  129,  129,  129,
+      142,  142,  149,  142,  146,  145,  144,  141,  140,  139,
+      137,  136,  134,  147,  161,  161,  161,  161,  161,  161,
+      161,  161,  162,  133,  128,  127,  162,  162,  163,  163,
+      163,  163,  163,  163,  163,  163,  164,  164,  164,  164,
+      165,  126,  165,  166,  125,  124,  166,  123,  166,  166,
+      167,  120,  119,  167,  167,  167,  167,  168,  118,  168,
+
+      168,  169,  169,  169,  169,  169,  169,  169,  169,  170,
+      170,  170,  170,  170,  170,  170,  170,  171,  117,  171,
+      172,  116,  172,  172,  111,  172,  172,  173,  173,  173,
+      173,  173,  173,  173,  173,  174,  174,  174,  174,  174,
+      174,  174,  174,  110,  109,  108,  107,  106,  105,  103,
+      102,  101,   99,   97,   96,   95,   94,   93,   92,   90,
+       88,   87,   86,   84,   83,   82,   81,   80,   79,   78,
+       76,   71,   70,   68,   65,   63,   62,   58,   52,   51,
+       49,   48,   47,   43,   40,   24,   23,   21,   15,   11,
+        8,    6,    3,    2,  160,  160,  160,  160,  160,  160,
+
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160
     } ;
 
 static yy_state_type yy_last_accepting_state;
@@ -540,6 +607,7 @@
 #define YY_MORE_ADJ 0
 #define YY_RESTORE_YY_MORE_OFFSET
 char *yytext;
+#line 1 "dtc-lexer.l"
 /*
  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
  *
@@ -561,6 +629,10 @@
  */
 #define YY_NO_INPUT 1
 
+
+
+
+#line 38 "dtc-lexer.l"
 #include "dtc.h"
 #include "srcpos.h"
 #include "dtc-parser.tab.h"
@@ -588,6 +660,7 @@
 
 static void push_input_file(const char *filename);
 static int pop_input_file(void);
+#line 664 "dtc-lexer.lex.c"
 
 #define INITIAL 0
 #define INCLUDE 1
@@ -670,7 +743,12 @@
 
 /* Amount of stuff to slurp up with each read. */
 #ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
 #define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
 #endif
 
 /* Copy whatever the last rule matched to the standard output. */
@@ -689,7 +767,7 @@
 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
 		{ \
 		int c = '*'; \
-		unsigned n; \
+		size_t n; \
 		for ( n = 0; n < max_size && \
 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
 			buf[n] = (char) c; \
@@ -761,6 +839,9 @@
 #endif
 
 #define YY_RULE_SETUP \
+	if ( yyleng > 0 ) \
+		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+				(yytext[yyleng - 1] == '\n'); \
 	YY_USER_ACTION
 
 /** The main scanner function which does all the work.
@@ -771,6 +852,10 @@
 	register char *yy_cp, *yy_bp;
 	register int yy_act;
     
+#line 67 "dtc-lexer.l"
+
+#line 858 "dtc-lexer.lex.c"
+
 	if ( !(yy_init) )
 		{
 		(yy_init) = 1;
@@ -810,6 +895,7 @@
 		yy_bp = yy_cp;
 
 		yy_current_state = (yy_start);
+		yy_current_state += YY_AT_BOL();
 yy_match:
 		do
 			{
@@ -822,13 +908,13 @@
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 94 )
+				if ( yy_current_state >= 161 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			++yy_cp;
 			}
-		while ( yy_current_state != 93 );
+		while ( yy_current_state != 160 );
 		yy_cp = (yy_last_accepting_cpos);
 		yy_current_state = (yy_last_accepting_state);
 
@@ -851,26 +937,54 @@
 case 1:
 /* rule 1 can match eol */
 YY_RULE_SETUP
+#line 68 "dtc-lexer.l"
 {
 			char *name = strchr(yytext, '\"') + 1;
 			yytext[yyleng-1] = '\0';
 			push_input_file(name);
 		}
 	YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 74 "dtc-lexer.l"
+{
+			char *line, *tmp, *fn;
+			/* skip text before line # */
+			line = yytext;
+			while (!isdigit(*line))
+				line++;
+			/* skip digits in line # */
+			tmp = line;
+			while (!isspace(*tmp))
+				tmp++;
+			/* "NULL"-terminate line # */
+			*tmp = '\0';
+			/* start of filename */
+			fn = strchr(tmp + 1, '"') + 1;
+			/* strip trailing " from filename */
+			tmp = strchr(fn, '"');
+			*tmp = 0;
+			/* -1 since #line is the number of the next line */
+			srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+		}
+	YY_BREAK
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(INCLUDE):
 case YY_STATE_EOF(BYTESTRING):
 case YY_STATE_EOF(PROPNODENAME):
 case YY_STATE_EOF(V1):
+#line 95 "dtc-lexer.l"
 {
 			if (!pop_input_file()) {
 				yyterminate();
 			}
 		}
 	YY_BREAK
-case 2:
-/* rule 2 can match eol */
+case 3:
+/* rule 3 can match eol */
 YY_RULE_SETUP
+#line 101 "dtc-lexer.l"
 {
 			DPRINT("String: %s\n", yytext);
 			yylval.data = data_copy_escape_string(yytext+1,
@@ -878,8 +992,9 @@
 			return DT_STRING;
 		}
 	YY_BREAK
-case 3:
+case 4:
 YY_RULE_SETUP
+#line 108 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /dts-v1/\n");
 			dts_version = 1;
@@ -887,16 +1002,47 @@
 			return DT_V1;
 		}
 	YY_BREAK
-case 4:
+case 5:
 YY_RULE_SETUP
+#line 115 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /memreserve/\n");
 			BEGIN_DEFAULT();
 			return DT_MEMRESERVE;
 		}
 	YY_BREAK
-case 5:
+case 6:
 YY_RULE_SETUP
+#line 121 "dtc-lexer.l"
+{
+			DPRINT("Keyword: /bits/\n");
+			BEGIN_DEFAULT();
+			return DT_BITS;
+		}
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 127 "dtc-lexer.l"
+{
+			DPRINT("Keyword: /delete-property/\n");
+			DPRINT("<PROPNODENAME>\n");
+			BEGIN(PROPNODENAME);
+			return DT_DEL_PROP;
+		}
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 134 "dtc-lexer.l"
+{
+			DPRINT("Keyword: /delete-node/\n");
+			DPRINT("<PROPNODENAME>\n");
+			BEGIN(PROPNODENAME);
+			return DT_DEL_NODE;
+		}
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 141 "dtc-lexer.l"
 {
 			DPRINT("Label: %s\n", yytext);
 			yylval.labelref = xstrdup(yytext);
@@ -904,24 +1050,38 @@
 			return DT_LABEL;
 		}
 	YY_BREAK
-case 6:
+case 10:
 YY_RULE_SETUP
+#line 148 "dtc-lexer.l"
 {
 			yylval.literal = xstrdup(yytext);
 			DPRINT("Literal: '%s'\n", yylval.literal);
 			return DT_LITERAL;
 		}
 	YY_BREAK
-case 7:
+case 11:
+/* rule 11 can match eol */
 YY_RULE_SETUP
+#line 154 "dtc-lexer.l"
+{
+			yytext[yyleng-1] = '\0';
+			yylval.literal = xstrdup(yytext+1);
+			DPRINT("Character literal: %s\n", yylval.literal);
+			return DT_CHAR_LITERAL;
+		}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 161 "dtc-lexer.l"
 {	/* label reference */
 			DPRINT("Ref: %s\n", yytext+1);
 			yylval.labelref = xstrdup(yytext+1);
 			return DT_REF;
 		}
 	YY_BREAK
-case 8:
+case 13:
 YY_RULE_SETUP
+#line 167 "dtc-lexer.l"
 {	/* new-style path reference */
 			yytext[yyleng-1] = '\0';
 			DPRINT("Ref: %s\n", yytext+2);
@@ -929,55 +1089,104 @@
 			return DT_REF;
 		}
 	YY_BREAK
-case 9:
+case 14:
 YY_RULE_SETUP
+#line 174 "dtc-lexer.l"
 {
 			yylval.byte = strtol(yytext, NULL, 16);
 			DPRINT("Byte: %02x\n", (int)yylval.byte);
 			return DT_BYTE;
 		}
 	YY_BREAK
-case 10:
+case 15:
 YY_RULE_SETUP
+#line 180 "dtc-lexer.l"
 {
 			DPRINT("/BYTESTRING\n");
 			BEGIN_DEFAULT();
 			return ']';
 		}
 	YY_BREAK
-case 11:
+case 16:
 YY_RULE_SETUP
+#line 186 "dtc-lexer.l"
 {
 			DPRINT("PropNodeName: %s\n", yytext);
-			yylval.propnodename = xstrdup(yytext);
+			yylval.propnodename = xstrdup((yytext[0] == '\\') ?
+							yytext + 1 : yytext);
 			BEGIN_DEFAULT();
 			return DT_PROPNODENAME;
 		}
 	YY_BREAK
-case 12:
+case 17:
 YY_RULE_SETUP
+#line 194 "dtc-lexer.l"
 {
 			DPRINT("Binary Include\n");
 			return DT_INCBIN;
 		}
 	YY_BREAK
-case 13:
-/* rule 13 can match eol */
+case 18:
+/* rule 18 can match eol */
 YY_RULE_SETUP
+#line 199 "dtc-lexer.l"
 /* eat whitespace */
 	YY_BREAK
-case 14:
-/* rule 14 can match eol */
+case 19:
+/* rule 19 can match eol */
 YY_RULE_SETUP
+#line 200 "dtc-lexer.l"
 /* eat C-style comments */
 	YY_BREAK
-case 15:
-/* rule 15 can match eol */
+case 20:
+/* rule 20 can match eol */
 YY_RULE_SETUP
+#line 201 "dtc-lexer.l"
 /* eat C++-style comments */
 	YY_BREAK
-case 16:
+case 21:
 YY_RULE_SETUP
+#line 203 "dtc-lexer.l"
+{ return DT_LSHIFT; };
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 204 "dtc-lexer.l"
+{ return DT_RSHIFT; };
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 205 "dtc-lexer.l"
+{ return DT_LE; };
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 206 "dtc-lexer.l"
+{ return DT_GE; };
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 207 "dtc-lexer.l"
+{ return DT_EQ; };
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 208 "dtc-lexer.l"
+{ return DT_NE; };
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 209 "dtc-lexer.l"
+{ return DT_AND; };
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 210 "dtc-lexer.l"
+{ return DT_OR; };
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 212 "dtc-lexer.l"
 {
 			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
 				(unsigned)yytext[0]);
@@ -993,10 +1202,12 @@
 			return yytext[0];
 		}
 	YY_BREAK
-case 17:
+case 30:
 YY_RULE_SETUP
+#line 227 "dtc-lexer.l"
 ECHO;
 	YY_BREAK
+#line 1211 "dtc-lexer.lex.c"
 
 	case YY_END_OF_BUFFER:
 		{
@@ -1275,6 +1486,7 @@
 	register char *yy_cp;
     
 	yy_current_state = (yy_start);
+	yy_current_state += YY_AT_BOL();
 
 	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
 		{
@@ -1287,7 +1499,7 @@
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 94 )
+			if ( yy_current_state >= 161 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1315,11 +1527,11 @@
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 94 )
+		if ( yy_current_state >= 161 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 93);
+	yy_is_jam = (yy_current_state == 160);
 
 	return yy_is_jam ? 0 : yy_current_state;
 }
@@ -1394,6 +1606,8 @@
 	*(yy_c_buf_p) = '\0';	/* preserve yytext */
 	(yy_hold_char) = *++(yy_c_buf_p);
 
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
 	return c;
 }
 #endif	/* ifndef YY_NO_INPUT */
@@ -1712,8 +1926,8 @@
 
 /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
  * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
  * 
  * @return the newly allocated buffer state object.
  */
@@ -1952,6 +2166,10 @@
 
 #define YYTABLES_NAME "yytables"
 
+#line 227 "dtc-lexer.l"
+
+
+
 static void push_input_file(const char *filename)
 {
 	assert(filename);
@@ -1963,6 +2181,7 @@
 	yypush_buffer_state(yy_create_buffer(yyin,YY_BUF_SIZE));
 }
 
+
 static int pop_input_file(void)
 {
 	if (srcfile_pop() == 0)
diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
index b05921e..4af5590 100644
--- a/scripts/dtc/dtc-parser.tab.c_shipped
+++ b/scripts/dtc/dtc-parser.tab.c_shipped
@@ -1,9 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.4.3.  */
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
 
 /* Skeleton implementation for Bison's Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-   2009, 2010 Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
    
    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
@@ -45,7 +46,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.4.3"
+#define YYBISON_VERSION "2.4.1"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -66,6 +67,8 @@
 
 /* Copy the first part of user declarations.  */
 
+/* Line 189 of yacc.c  */
+#line 21 "dtc-parser.y"
 
 #include <stdio.h>
 
@@ -82,12 +85,15 @@
 extern int treesource_error;
 
 static unsigned long long eval_literal(const char *s, int base, int bits);
+static unsigned char eval_char_literal(const char *s);
 
 
+/* Line 189 of yacc.c  */
+#line 93 "dtc-parser.tab.c"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
-# define YYDEBUG 1
+# define YYDEBUG 0
 #endif
 
 /* Enabling verbose error messages.  */
@@ -112,14 +118,26 @@
    enum yytokentype {
      DT_V1 = 258,
      DT_MEMRESERVE = 259,
-     DT_PROPNODENAME = 260,
-     DT_LITERAL = 261,
-     DT_BASE = 262,
-     DT_BYTE = 263,
-     DT_STRING = 264,
-     DT_LABEL = 265,
-     DT_REF = 266,
-     DT_INCBIN = 267
+     DT_LSHIFT = 260,
+     DT_RSHIFT = 261,
+     DT_LE = 262,
+     DT_GE = 263,
+     DT_EQ = 264,
+     DT_NE = 265,
+     DT_AND = 266,
+     DT_OR = 267,
+     DT_BITS = 268,
+     DT_DEL_PROP = 269,
+     DT_DEL_NODE = 270,
+     DT_PROPNODENAME = 271,
+     DT_LITERAL = 272,
+     DT_CHAR_LITERAL = 273,
+     DT_BASE = 274,
+     DT_BYTE = 275,
+     DT_STRING = 276,
+     DT_LABEL = 277,
+     DT_REF = 278,
+     DT_INCBIN = 279
    };
 #endif
 
@@ -129,6 +147,8 @@
 typedef union YYSTYPE
 {
 
+/* Line 214 of yacc.c  */
+#line 40 "dtc-parser.y"
 
 	char *propnodename;
 	char *literal;
@@ -137,16 +157,22 @@
 	uint8_t byte;
 	struct data data;
 
-	uint64_t addr;
-	cell_t cell;
+	struct {
+		struct data	data;
+		int		bits;
+	} array;
+
 	struct property *prop;
 	struct property *proplist;
 	struct node *node;
 	struct node *nodelist;
 	struct reserve_info *re;
+	uint64_t integer;
 
 
 
+/* Line 214 of yacc.c  */
+#line 176 "dtc-parser.tab.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -157,6 +183,8 @@
 /* Copy the second part of user declarations.  */
 
 
+/* Line 264 of yacc.c  */
+#line 188 "dtc-parser.tab.c"
 
 #ifdef short
 # undef short
@@ -206,7 +234,7 @@
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
+# if YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -371,20 +399,20 @@
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  4
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   56
+#define YYLAST   133
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  25
+#define YYNTOKENS  48
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  16
+#define YYNNTS  28
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  39
+#define YYNRULES  79
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  67
+#define YYNSTATES  141
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   267
+#define YYMAXUTOK   279
 
 #define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -395,16 +423,16 @@
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      22,    24,     2,     2,    23,     2,     2,    14,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,    13,
-      18,    17,    19,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    47,     2,     2,     2,    45,    41,     2,
+      33,    35,    44,    42,    34,    43,     2,    26,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    38,    25,
+      36,    29,    30,    37,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    20,     2,    21,     2,     2,     2,     2,     2,     2,
+       2,    31,     2,    32,    40,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    15,     2,    16,     2,     2,     2,     2,
+       2,     2,     2,    27,    39,    28,    46,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -418,45 +446,68 @@
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24
 };
 
 #if YYDEBUG
 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
    YYRHS.  */
-static const yytype_uint8 yyprhs[] =
+static const yytype_uint16 yyprhs[] =
 {
-       0,     0,     3,     8,     9,    12,    17,    20,    22,    25,
-      29,    33,    39,    40,    43,    48,    51,    54,    57,    62,
-      67,    70,    80,    86,    89,    90,    93,    96,    97,   100,
-     103,   106,   108,   109,   112,   115,   116,   119,   122,   125
+       0,     0,     3,     8,     9,    12,    17,    20,    23,    27,
+      31,    36,    42,    43,    46,    51,    54,    58,    61,    64,
+      68,    73,    76,    86,    92,    95,    96,    99,   102,   106,
+     108,   111,   114,   117,   119,   121,   125,   127,   129,   135,
+     137,   141,   143,   147,   149,   153,   155,   159,   161,   165,
+     167,   171,   175,   177,   181,   185,   189,   193,   197,   201,
+     203,   207,   211,   213,   217,   221,   225,   227,   229,   232,
+     235,   238,   239,   242,   245,   246,   249,   252,   255,   259
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      26,     0,    -1,     3,    13,    27,    30,    -1,    -1,    28,
-      27,    -1,     4,    29,    29,    13,    -1,    10,    28,    -1,
-       6,    -1,    14,    31,    -1,    30,    14,    31,    -1,    30,
-      11,    31,    -1,    15,    32,    39,    16,    13,    -1,    -1,
-      32,    33,    -1,     5,    17,    34,    13,    -1,     5,    13,
-      -1,    10,    33,    -1,    35,     9,    -1,    35,    18,    36,
-      19,    -1,    35,    20,    38,    21,    -1,    35,    11,    -1,
-      35,    12,    22,     9,    23,    29,    23,    29,    24,    -1,
-      35,    12,    22,     9,    24,    -1,    34,    10,    -1,    -1,
-      34,    23,    -1,    35,    10,    -1,    -1,    36,    37,    -1,
-      36,    11,    -1,    36,    10,    -1,     6,    -1,    -1,    38,
-       8,    -1,    38,    10,    -1,    -1,    40,    39,    -1,    40,
-      33,    -1,     5,    31,    -1,    10,    40,    -1
+      49,     0,    -1,     3,    25,    50,    52,    -1,    -1,    51,
+      50,    -1,     4,    59,    59,    25,    -1,    22,    51,    -1,
+      26,    53,    -1,    52,    26,    53,    -1,    52,    23,    53,
+      -1,    52,    15,    23,    25,    -1,    27,    54,    74,    28,
+      25,    -1,    -1,    54,    55,    -1,    16,    29,    56,    25,
+      -1,    16,    25,    -1,    14,    16,    25,    -1,    22,    55,
+      -1,    57,    21,    -1,    57,    58,    30,    -1,    57,    31,
+      73,    32,    -1,    57,    23,    -1,    57,    24,    33,    21,
+      34,    59,    34,    59,    35,    -1,    57,    24,    33,    21,
+      35,    -1,    56,    22,    -1,    -1,    56,    34,    -1,    57,
+      22,    -1,    13,    17,    36,    -1,    36,    -1,    58,    59,
+      -1,    58,    23,    -1,    58,    22,    -1,    17,    -1,    18,
+      -1,    33,    60,    35,    -1,    61,    -1,    62,    -1,    62,
+      37,    60,    38,    61,    -1,    63,    -1,    62,    12,    63,
+      -1,    64,    -1,    63,    11,    64,    -1,    65,    -1,    64,
+      39,    65,    -1,    66,    -1,    65,    40,    66,    -1,    67,
+      -1,    66,    41,    67,    -1,    68,    -1,    67,     9,    68,
+      -1,    67,    10,    68,    -1,    69,    -1,    68,    36,    69,
+      -1,    68,    30,    69,    -1,    68,     7,    69,    -1,    68,
+       8,    69,    -1,    69,     5,    70,    -1,    69,     6,    70,
+      -1,    70,    -1,    70,    42,    71,    -1,    70,    43,    71,
+      -1,    71,    -1,    71,    44,    72,    -1,    71,    26,    72,
+      -1,    71,    45,    72,    -1,    72,    -1,    59,    -1,    43,
+      72,    -1,    46,    72,    -1,    47,    72,    -1,    -1,    73,
+      20,    -1,    73,    22,    -1,    -1,    75,    74,    -1,    75,
+      55,    -1,    16,    53,    -1,    15,    16,    25,    -1,    22,
+      75,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    86,    86,    95,    98,   105,   109,   117,   124,   128,
-     132,   145,   153,   156,   163,   167,   171,   179,   183,   187,
-     191,   195,   212,   222,   230,   233,   237,   245,   248,   252,
-     257,   264,   272,   275,   279,   287,   290,   294,   302,   306
+       0,   109,   109,   118,   121,   128,   132,   140,   144,   148,
+     158,   172,   180,   183,   190,   194,   198,   202,   210,   214,
+     218,   222,   226,   243,   253,   261,   264,   268,   275,   290,
+     295,   315,   329,   336,   340,   344,   351,   355,   356,   360,
+     361,   365,   366,   370,   371,   375,   376,   380,   381,   385,
+     386,   387,   391,   392,   393,   394,   395,   399,   400,   401,
+     405,   406,   407,   411,   412,   413,   414,   418,   419,   420,
+     421,   426,   429,   433,   441,   444,   448,   456,   460,   464
 };
 #endif
 
@@ -465,13 +516,19 @@
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
-  "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE",
-  "DT_PROPNODENAME", "DT_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING",
-  "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='",
-  "'<'", "'>'", "'['", "']'", "'('", "','", "')'", "$accept", "sourcefile",
-  "memreserves", "memreserve", "addr", "devicetree", "nodedef", "proplist",
-  "propdef", "propdata", "propdataprefix", "celllist", "cellval",
-  "bytestring", "subnodes", "subnode", 0
+  "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT",
+  "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR",
+  "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL",
+  "DT_CHAR_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING", "DT_LABEL",
+  "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['",
+  "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'",
+  "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
+  "memreserves", "memreserve", "devicetree", "nodedef", "proplist",
+  "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim",
+  "integer_expr", "integer_trinary", "integer_or", "integer_and",
+  "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq",
+  "integer_rela", "integer_shift", "integer_add", "integer_mul",
+  "integer_unary", "bytestring", "subnodes", "subnode", 0
 };
 #endif
 
@@ -481,27 +538,37 @@
 static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,    59,    47,   123,   125,    61,    60,    62,
-      91,    93,    40,    44,    41
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,    59,    47,   123,   125,    61,
+      62,    91,    93,    40,    44,    41,    60,    63,    58,   124,
+      94,    38,    43,    45,    42,    37,   126,    33
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    25,    26,    27,    27,    28,    28,    29,    30,    30,
-      30,    31,    32,    32,    33,    33,    33,    34,    34,    34,
-      34,    34,    34,    34,    35,    35,    35,    36,    36,    36,
-      36,    37,    38,    38,    38,    39,    39,    39,    40,    40
+       0,    48,    49,    50,    50,    51,    51,    52,    52,    52,
+      52,    53,    54,    54,    55,    55,    55,    55,    56,    56,
+      56,    56,    56,    56,    56,    57,    57,    57,    58,    58,
+      58,    58,    58,    59,    59,    59,    60,    61,    61,    62,
+      62,    63,    63,    64,    64,    65,    65,    66,    66,    67,
+      67,    67,    68,    68,    68,    68,    68,    69,    69,    69,
+      70,    70,    70,    71,    71,    71,    71,    72,    72,    72,
+      72,    73,    73,    73,    74,    74,    74,    75,    75,    75
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     4,     0,     2,     4,     2,     1,     2,     3,
-       3,     5,     0,     2,     4,     2,     2,     2,     4,     4,
-       2,     9,     5,     2,     0,     2,     2,     0,     2,     2,
-       2,     1,     0,     2,     2,     0,     2,     2,     2,     2
+       0,     2,     4,     0,     2,     4,     2,     2,     3,     3,
+       4,     5,     0,     2,     4,     2,     3,     2,     2,     3,
+       4,     2,     9,     5,     2,     0,     2,     2,     3,     1,
+       2,     2,     2,     1,     1,     3,     1,     1,     5,     1,
+       3,     1,     3,     1,     3,     1,     3,     1,     3,     1,
+       3,     3,     1,     3,     3,     3,     3,     3,     3,     1,
+       3,     3,     1,     3,     3,     3,     1,     1,     2,     2,
+       2,     0,     2,     2,     0,     2,     2,     2,     3,     2
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -509,41 +576,59 @@
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,     0,     0,     3,     1,     0,     0,     0,     3,     7,
-       0,     6,     0,     2,     4,     0,    12,     8,     0,     0,
-       5,    35,    10,     9,     0,     0,    13,     0,    35,    15,
-      24,    38,    16,    39,     0,    37,    36,     0,     0,    11,
-      23,    14,    25,    17,    26,    20,     0,    27,    32,     0,
-       0,     0,     0,    31,    30,    29,    18,    28,    33,    34,
-      19,     0,    22,     0,     0,     0,    21
+       0,     0,     0,     3,     1,     0,     0,     0,     3,    33,
+      34,     0,     0,     6,     0,     2,     4,     0,     0,     0,
+      67,     0,    36,    37,    39,    41,    43,    45,    47,    49,
+      52,    59,    62,    66,     0,    12,     7,     0,     0,     0,
+      68,    69,    70,    35,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     5,    74,     0,     9,     8,    40,     0,
+      42,    44,    46,    48,    50,    51,    55,    56,    54,    53,
+      57,    58,    60,    61,    64,    63,    65,     0,     0,     0,
+       0,    13,     0,    74,    10,     0,     0,     0,    15,    25,
+      77,    17,    79,     0,    76,    75,    38,    16,    78,     0,
+       0,    11,    24,    14,    26,     0,    18,    27,    21,     0,
+      71,    29,     0,     0,     0,     0,    32,    31,    19,    30,
+      28,     0,    72,    73,    20,     0,    23,     0,     0,     0,
+      22
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     2,     7,     8,    10,    13,    17,    21,    26,    37,
-      38,    50,    57,    51,    27,    28
+      -1,     2,     7,     8,    15,    36,    64,    91,   109,   110,
+     122,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,   125,    92,    93
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -12
+#define YYPACT_NINF -78
 static const yytype_int8 yypact[] =
 {
-      10,   -11,    18,    -1,   -12,    22,    -1,    15,    -1,   -12,
-      22,   -12,    20,     1,   -12,    17,   -12,   -12,    20,    20,
-     -12,     6,   -12,   -12,    21,     6,   -12,    23,     6,   -12,
-     -12,   -12,   -12,   -12,    28,   -12,   -12,    -6,    13,   -12,
-     -12,   -12,   -12,   -12,   -12,   -12,    24,   -12,   -12,    33,
-      -5,     0,    -4,   -12,   -12,   -12,   -12,   -12,   -12,   -12,
-     -12,    22,   -12,    25,    22,    19,   -12
+      22,    11,    51,    10,   -78,    23,    10,     2,    10,   -78,
+     -78,    -9,    23,   -78,    30,    38,   -78,    -9,    -9,    -9,
+     -78,    35,   -78,    -6,    52,    29,    48,    49,    33,     3,
+      71,    36,     0,   -78,    64,   -78,   -78,    68,    30,    30,
+     -78,   -78,   -78,   -78,    -9,    -9,    -9,    -9,    -9,    -9,
+      -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,
+      -9,    -9,    -9,   -78,    44,    67,   -78,   -78,    52,    55,
+      29,    48,    49,    33,     3,     3,    71,    71,    71,    71,
+      36,    36,     0,     0,   -78,   -78,   -78,    78,    79,    42,
+      44,   -78,    69,    44,   -78,    -9,    73,    74,   -78,   -78,
+     -78,   -78,   -78,    75,   -78,   -78,   -78,   -78,   -78,    -7,
+      -1,   -78,   -78,   -78,   -78,    84,   -78,   -78,   -78,    63,
+     -78,   -78,    32,    66,    82,    -3,   -78,   -78,   -78,   -78,
+     -78,    46,   -78,   -78,   -78,    23,   -78,    70,    23,    72,
+     -78
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -12,   -12,    36,    39,   -10,   -12,     8,   -12,    12,   -12,
-     -12,   -12,   -12,   -12,    27,    31
+     -78,   -78,    97,   100,   -78,   -37,   -78,   -77,   -78,   -78,
+     -78,    -5,    65,    13,   -78,    76,    77,    62,    80,    83,
+      34,    20,    26,    28,   -14,   -78,    18,    24
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -553,35 +638,59 @@
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-      15,    53,     3,     5,    40,    54,    55,    41,    58,     6,
-      59,    24,    18,     1,    56,    19,    25,    42,     4,    61,
-      62,    60,    43,    44,    45,    46,    22,    23,     9,    12,
-      20,    47,    31,    48,    29,    16,    16,    32,    30,    34,
-      35,    39,    52,    66,    14,    11,    49,     0,    64,     0,
-       0,    63,     0,     0,    65,    36,    33
+      12,    66,    67,    40,    41,    42,    44,    34,     9,    10,
+      52,    53,   115,   101,     5,   112,   104,   132,   113,   133,
+     116,   117,   118,   119,    11,     1,    60,   114,    14,   134,
+     120,    45,     6,    54,    17,   121,     3,    18,    19,    55,
+       9,    10,    50,    51,    61,    62,    84,    85,    86,     9,
+      10,     4,   100,    37,   126,   127,    11,    35,    87,    88,
+      89,    38,   128,    46,    39,    11,    90,    98,    47,    35,
+      43,    99,    76,    77,    78,    79,    56,    57,    58,    59,
+     135,   136,    80,    81,    74,    75,    82,    83,    48,    63,
+      49,    65,    94,    95,    96,    97,   124,   103,   107,   108,
+     111,   123,   130,   131,   138,    16,    13,   140,   106,    71,
+      69,   105,     0,     0,   102,     0,     0,   129,     0,     0,
+      68,     0,     0,    70,     0,     0,     0,     0,    72,     0,
+     137,     0,    73,   139
 };
 
-static const yytype_int8 yycheck[] =
+static const yytype_int16 yycheck[] =
 {
-      10,     6,    13,     4,    10,    10,    11,    13,     8,    10,
-      10,     5,    11,     3,    19,    14,    10,    23,     0,    23,
-      24,    21,     9,    10,    11,    12,    18,    19,     6,    14,
-      13,    18,    24,    20,    13,    15,    15,    25,    17,    16,
-      28,    13,     9,    24,     8,     6,    22,    -1,    23,    -1,
-      -1,    61,    -1,    -1,    64,    28,    25
+       5,    38,    39,    17,    18,    19,    12,    12,    17,    18,
+       7,     8,    13,    90,     4,    22,    93,    20,    25,    22,
+      21,    22,    23,    24,    33,     3,    26,    34,    26,    32,
+      31,    37,    22,    30,    43,    36,    25,    46,    47,    36,
+      17,    18,     9,    10,    44,    45,    60,    61,    62,    17,
+      18,     0,    89,    15,    22,    23,    33,    27,    14,    15,
+      16,    23,    30,    11,    26,    33,    22,    25,    39,    27,
+      35,    29,    52,    53,    54,    55,     5,     6,    42,    43,
+      34,    35,    56,    57,    50,    51,    58,    59,    40,    25,
+      41,    23,    25,    38,    16,    16,    33,    28,    25,    25,
+      25,    17,    36,    21,    34,     8,     6,    35,    95,    47,
+      45,    93,    -1,    -1,    90,    -1,    -1,   122,    -1,    -1,
+      44,    -1,    -1,    46,    -1,    -1,    -1,    -1,    48,    -1,
+     135,    -1,    49,   138
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,    26,    13,     0,     4,    10,    27,    28,     6,
-      29,    28,    14,    30,    27,    29,    15,    31,    11,    14,
-      13,    32,    31,    31,     5,    10,    33,    39,    40,    13,
-      17,    31,    33,    40,    16,    33,    39,    34,    35,    13,
-      10,    13,    23,     9,    10,    11,    12,    18,    20,    22,
-      36,    38,     9,     6,    10,    11,    19,    37,     8,    10,
-      21,    23,    24,    29,    23,    29,    24
+       0,     3,    49,    25,     0,     4,    22,    50,    51,    17,
+      18,    33,    59,    51,    26,    52,    50,    43,    46,    47,
+      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
+      69,    70,    71,    72,    59,    27,    53,    15,    23,    26,
+      72,    72,    72,    35,    12,    37,    11,    39,    40,    41,
+       9,    10,     7,     8,    30,    36,     5,     6,    42,    43,
+      26,    44,    45,    25,    54,    23,    53,    53,    63,    60,
+      64,    65,    66,    67,    68,    68,    69,    69,    69,    69,
+      70,    70,    71,    71,    72,    72,    72,    14,    15,    16,
+      22,    55,    74,    75,    25,    38,    16,    16,    25,    29,
+      53,    55,    75,    28,    55,    74,    61,    25,    25,    56,
+      57,    25,    22,    25,    34,    13,    21,    22,    23,    24,
+      31,    36,    58,    17,    33,    73,    22,    23,    30,    59,
+      36,    21,    20,    22,    32,    34,    35,    59,    34,    59,
+      35
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -596,18 +705,9 @@
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  However,
-   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
-   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
-   discussed.  */
+   Once GCC version 2 has supplanted version 1, this can go.  */
 
 #define YYFAIL		goto yyerrlab
-#if defined YYFAIL
-  /* This is here to suppress warnings from the GCC cpp's
-     -Wunused-macros.  Normally we don't worry about that warning, but
-     some users do, and we want to make it easy for users to remove
-     YYFAIL uses, which will produce warnings from Bison 2.5.  */
-#endif
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -664,7 +764,7 @@
    we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# if YYLTYPE_IS_TRIVIAL
 #  define YY_LOCATION_PRINT(File, Loc)			\
      fprintf (File, "%d.%d-%d.%d",			\
 	      (Loc).first_line, (Loc).first_column,	\
@@ -1403,6 +1503,8 @@
     {
         case 2:
 
+/* Line 1455 of yacc.c  */
+#line 110 "dtc-parser.y"
     {
 			the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node),
 							guess_boot_cpuid((yyvsp[(4) - (4)].node)));
@@ -1411,6 +1513,8 @@
 
   case 3:
 
+/* Line 1455 of yacc.c  */
+#line 118 "dtc-parser.y"
     {
 			(yyval.re) = NULL;
 		;}
@@ -1418,6 +1522,8 @@
 
   case 4:
 
+/* Line 1455 of yacc.c  */
+#line 122 "dtc-parser.y"
     {
 			(yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
 		;}
@@ -1425,13 +1531,17 @@
 
   case 5:
 
+/* Line 1455 of yacc.c  */
+#line 129 "dtc-parser.y"
     {
-			(yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].addr), (yyvsp[(3) - (4)].addr));
+			(yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer));
 		;}
     break;
 
   case 6:
 
+/* Line 1455 of yacc.c  */
+#line 133 "dtc-parser.y"
     {
 			add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref));
 			(yyval.re) = (yyvsp[(2) - (2)].re);
@@ -1440,27 +1550,26 @@
 
   case 7:
 
-    {
-			(yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
-		;}
-    break;
-
-  case 8:
-
+/* Line 1455 of yacc.c  */
+#line 141 "dtc-parser.y"
     {
 			(yyval.node) = name_node((yyvsp[(2) - (2)].node), "");
 		;}
     break;
 
-  case 9:
+  case 8:
 
+/* Line 1455 of yacc.c  */
+#line 145 "dtc-parser.y"
     {
 			(yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 		;}
     break;
 
-  case 10:
+  case 9:
 
+/* Line 1455 of yacc.c  */
+#line 149 "dtc-parser.y"
     {
 			struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref));
 
@@ -1472,8 +1581,26 @@
 		;}
     break;
 
+  case 10:
+
+/* Line 1455 of yacc.c  */
+#line 159 "dtc-parser.y"
+    {
+			struct node *target = get_node_by_ref((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].labelref));
+
+			if (!target)
+				print_error("label or path, '%s', not found", (yyvsp[(3) - (4)].labelref));
+			else
+				delete_node(target);
+
+			(yyval.node) = (yyvsp[(1) - (4)].node);
+		;}
+    break;
+
   case 11:
 
+/* Line 1455 of yacc.c  */
+#line 173 "dtc-parser.y"
     {
 			(yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
 		;}
@@ -1481,6 +1608,8 @@
 
   case 12:
 
+/* Line 1455 of yacc.c  */
+#line 180 "dtc-parser.y"
     {
 			(yyval.proplist) = NULL;
 		;}
@@ -1488,6 +1617,8 @@
 
   case 13:
 
+/* Line 1455 of yacc.c  */
+#line 184 "dtc-parser.y"
     {
 			(yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
 		;}
@@ -1495,6 +1626,8 @@
 
   case 14:
 
+/* Line 1455 of yacc.c  */
+#line 191 "dtc-parser.y"
     {
 			(yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data));
 		;}
@@ -1502,6 +1635,8 @@
 
   case 15:
 
+/* Line 1455 of yacc.c  */
+#line 195 "dtc-parser.y"
     {
 			(yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data);
 		;}
@@ -1509,62 +1644,85 @@
 
   case 16:
 
+/* Line 1455 of yacc.c  */
+#line 199 "dtc-parser.y"
+    {
+			(yyval.prop) = build_property_delete((yyvsp[(2) - (3)].propnodename));
+		;}
+    break;
+
+  case 17:
+
+/* Line 1455 of yacc.c  */
+#line 203 "dtc-parser.y"
     {
 			add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref));
 			(yyval.prop) = (yyvsp[(2) - (2)].prop);
 		;}
     break;
 
-  case 17:
+  case 18:
 
+/* Line 1455 of yacc.c  */
+#line 211 "dtc-parser.y"
     {
 			(yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
 		;}
     break;
 
-  case 18:
-
-    {
-			(yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
-		;}
-    break;
-
   case 19:
 
+/* Line 1455 of yacc.c  */
+#line 215 "dtc-parser.y"
     {
-			(yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+			(yyval.data) = data_merge((yyvsp[(1) - (3)].data), (yyvsp[(2) - (3)].array).data);
 		;}
     break;
 
   case 20:
 
+/* Line 1455 of yacc.c  */
+#line 219 "dtc-parser.y"
     {
-			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+			(yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
 		;}
     break;
 
   case 21:
 
+/* Line 1455 of yacc.c  */
+#line 223 "dtc-parser.y"
+    {
+			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+		;}
+    break;
+
+  case 22:
+
+/* Line 1455 of yacc.c  */
+#line 227 "dtc-parser.y"
     {
 			FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL);
 			struct data d;
 
-			if ((yyvsp[(6) - (9)].addr) != 0)
-				if (fseek(f, (yyvsp[(6) - (9)].addr), SEEK_SET) != 0)
+			if ((yyvsp[(6) - (9)].integer) != 0)
+				if (fseek(f, (yyvsp[(6) - (9)].integer), SEEK_SET) != 0)
 					print_error("Couldn't seek to offset %llu in \"%s\": %s",
-						     (unsigned long long)(yyvsp[(6) - (9)].addr),
+						     (unsigned long long)(yyvsp[(6) - (9)].integer),
 						     (yyvsp[(4) - (9)].data).val,
 						     strerror(errno));
 
-			d = data_copy_file(f, (yyvsp[(8) - (9)].addr));
+			d = data_copy_file(f, (yyvsp[(8) - (9)].integer));
 
 			(yyval.data) = data_merge((yyvsp[(1) - (9)].data), d);
 			fclose(f);
 		;}
     break;
 
-  case 22:
+  case 23:
 
+/* Line 1455 of yacc.c  */
+#line 244 "dtc-parser.y"
     {
 			FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL);
 			struct data d = empty_data;
@@ -1576,122 +1734,383 @@
 		;}
     break;
 
-  case 23:
-
-    {
-			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
-		;}
-    break;
-
   case 24:
 
+/* Line 1455 of yacc.c  */
+#line 254 "dtc-parser.y"
     {
-			(yyval.data) = empty_data;
+			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
 		;}
     break;
 
   case 25:
 
+/* Line 1455 of yacc.c  */
+#line 261 "dtc-parser.y"
     {
-			(yyval.data) = (yyvsp[(1) - (2)].data);
+			(yyval.data) = empty_data;
 		;}
     break;
 
   case 26:
 
+/* Line 1455 of yacc.c  */
+#line 265 "dtc-parser.y"
     {
-			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+			(yyval.data) = (yyvsp[(1) - (2)].data);
 		;}
     break;
 
   case 27:
 
+/* Line 1455 of yacc.c  */
+#line 269 "dtc-parser.y"
     {
-			(yyval.data) = empty_data;
+			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
 		;}
     break;
 
   case 28:
 
+/* Line 1455 of yacc.c  */
+#line 276 "dtc-parser.y"
     {
-			(yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
+			(yyval.array).data = empty_data;
+			(yyval.array).bits = eval_literal((yyvsp[(2) - (3)].literal), 0, 7);
+
+			if (((yyval.array).bits !=  8) &&
+			    ((yyval.array).bits != 16) &&
+			    ((yyval.array).bits != 32) &&
+			    ((yyval.array).bits != 64))
+			{
+				print_error("Only 8, 16, 32 and 64-bit elements"
+					    " are currently supported");
+				(yyval.array).bits = 32;
+			}
 		;}
     break;
 
   case 29:
 
+/* Line 1455 of yacc.c  */
+#line 291 "dtc-parser.y"
     {
-			(yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE,
-							      (yyvsp[(2) - (2)].labelref)), -1);
+			(yyval.array).data = empty_data;
+			(yyval.array).bits = 32;
 		;}
     break;
 
   case 30:
 
+/* Line 1455 of yacc.c  */
+#line 296 "dtc-parser.y"
     {
-			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+			if ((yyvsp[(1) - (2)].array).bits < 64) {
+				uint64_t mask = (1ULL << (yyvsp[(1) - (2)].array).bits) - 1;
+				/*
+				 * Bits above mask must either be all zero
+				 * (positive within range of mask) or all one
+				 * (negative and sign-extended). The second
+				 * condition is true if when we set all bits
+				 * within the mask to one (i.e. | in the
+				 * mask), all bits are one.
+				 */
+				if (((yyvsp[(2) - (2)].integer) > mask) && (((yyvsp[(2) - (2)].integer) | mask) != -1ULL))
+					print_error(
+						"integer value out of range "
+						"%016lx (%d bits)", (yyvsp[(1) - (2)].array).bits);
+			}
+
+			(yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, (yyvsp[(2) - (2)].integer), (yyvsp[(1) - (2)].array).bits);
 		;}
     break;
 
   case 31:
 
+/* Line 1455 of yacc.c  */
+#line 316 "dtc-parser.y"
     {
-			(yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32);
+			uint64_t val = ~0ULL >> (64 - (yyvsp[(1) - (2)].array).bits);
+
+			if ((yyvsp[(1) - (2)].array).bits == 32)
+				(yyvsp[(1) - (2)].array).data = data_add_marker((yyvsp[(1) - (2)].array).data,
+							  REF_PHANDLE,
+							  (yyvsp[(2) - (2)].labelref));
+			else
+				print_error("References are only allowed in "
+					    "arrays with 32-bit elements.");
+
+			(yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, val, (yyvsp[(1) - (2)].array).bits);
 		;}
     break;
 
   case 32:
 
+/* Line 1455 of yacc.c  */
+#line 330 "dtc-parser.y"
     {
-			(yyval.data) = empty_data;
+			(yyval.array).data = data_add_marker((yyvsp[(1) - (2)].array).data, LABEL, (yyvsp[(2) - (2)].labelref));
 		;}
     break;
 
   case 33:
 
+/* Line 1455 of yacc.c  */
+#line 337 "dtc-parser.y"
     {
-			(yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+			(yyval.integer) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
 		;}
     break;
 
   case 34:
 
+/* Line 1455 of yacc.c  */
+#line 341 "dtc-parser.y"
     {
-			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+			(yyval.integer) = eval_char_literal((yyvsp[(1) - (1)].literal));
 		;}
     break;
 
   case 35:
 
+/* Line 1455 of yacc.c  */
+#line 345 "dtc-parser.y"
+    {
+			(yyval.integer) = (yyvsp[(2) - (3)].integer);
+		;}
+    break;
+
+  case 38:
+
+/* Line 1455 of yacc.c  */
+#line 356 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (5)].integer) ? (yyvsp[(3) - (5)].integer) : (yyvsp[(5) - (5)].integer); ;}
+    break;
+
+  case 40:
+
+/* Line 1455 of yacc.c  */
+#line 361 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) || (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 42:
+
+/* Line 1455 of yacc.c  */
+#line 366 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) && (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 44:
+
+/* Line 1455 of yacc.c  */
+#line 371 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) | (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 46:
+
+/* Line 1455 of yacc.c  */
+#line 376 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) ^ (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 48:
+
+/* Line 1455 of yacc.c  */
+#line 381 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) & (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 50:
+
+/* Line 1455 of yacc.c  */
+#line 386 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) == (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 51:
+
+/* Line 1455 of yacc.c  */
+#line 387 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) != (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 53:
+
+/* Line 1455 of yacc.c  */
+#line 392 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) < (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 54:
+
+/* Line 1455 of yacc.c  */
+#line 393 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) > (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 55:
+
+/* Line 1455 of yacc.c  */
+#line 394 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) <= (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 56:
+
+/* Line 1455 of yacc.c  */
+#line 395 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) >= (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 57:
+
+/* Line 1455 of yacc.c  */
+#line 399 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) << (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 58:
+
+/* Line 1455 of yacc.c  */
+#line 400 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) >> (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 60:
+
+/* Line 1455 of yacc.c  */
+#line 405 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) + (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 61:
+
+/* Line 1455 of yacc.c  */
+#line 406 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) - (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 63:
+
+/* Line 1455 of yacc.c  */
+#line 411 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) * (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 64:
+
+/* Line 1455 of yacc.c  */
+#line 412 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) / (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 65:
+
+/* Line 1455 of yacc.c  */
+#line 413 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) % (yyvsp[(3) - (3)].integer); ;}
+    break;
+
+  case 68:
+
+/* Line 1455 of yacc.c  */
+#line 419 "dtc-parser.y"
+    { (yyval.integer) = -(yyvsp[(2) - (2)].integer); ;}
+    break;
+
+  case 69:
+
+/* Line 1455 of yacc.c  */
+#line 420 "dtc-parser.y"
+    { (yyval.integer) = ~(yyvsp[(2) - (2)].integer); ;}
+    break;
+
+  case 70:
+
+/* Line 1455 of yacc.c  */
+#line 421 "dtc-parser.y"
+    { (yyval.integer) = !(yyvsp[(2) - (2)].integer); ;}
+    break;
+
+  case 71:
+
+/* Line 1455 of yacc.c  */
+#line 426 "dtc-parser.y"
+    {
+			(yyval.data) = empty_data;
+		;}
+    break;
+
+  case 72:
+
+/* Line 1455 of yacc.c  */
+#line 430 "dtc-parser.y"
+    {
+			(yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+		;}
+    break;
+
+  case 73:
+
+/* Line 1455 of yacc.c  */
+#line 434 "dtc-parser.y"
+    {
+			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+		;}
+    break;
+
+  case 74:
+
+/* Line 1455 of yacc.c  */
+#line 441 "dtc-parser.y"
     {
 			(yyval.nodelist) = NULL;
 		;}
     break;
 
-  case 36:
+  case 75:
 
+/* Line 1455 of yacc.c  */
+#line 445 "dtc-parser.y"
     {
 			(yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
 		;}
     break;
 
-  case 37:
+  case 76:
 
+/* Line 1455 of yacc.c  */
+#line 449 "dtc-parser.y"
     {
 			print_error("syntax error: properties must precede subnodes");
 			YYERROR;
 		;}
     break;
 
-  case 38:
+  case 77:
 
+/* Line 1455 of yacc.c  */
+#line 457 "dtc-parser.y"
     {
 			(yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename));
 		;}
     break;
 
-  case 39:
+  case 78:
 
+/* Line 1455 of yacc.c  */
+#line 461 "dtc-parser.y"
+    {
+			(yyval.node) = name_node(build_node_delete(), (yyvsp[(2) - (3)].propnodename));
+		;}
+    break;
+
+  case 79:
+
+/* Line 1455 of yacc.c  */
+#line 465 "dtc-parser.y"
     {
 			add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref));
 			(yyval.node) = (yyvsp[(2) - (2)].node);
@@ -1700,6 +2119,8 @@
 
 
 
+/* Line 1455 of yacc.c  */
+#line 2124 "dtc-parser.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -1910,6 +2331,8 @@
 
 
 
+/* Line 1675 of yacc.c  */
+#line 471 "dtc-parser.y"
 
 
 void print_error(char const *fmt, ...)
@@ -1934,9 +2357,12 @@
 
 	errno = 0;
 	val = strtoull(s, &e, base);
-	if (*e)
-		print_error("bad characters in literal");
-	else if ((errno == ERANGE)
+	if (*e) {
+		size_t uls = strspn(e, "UL");
+		if (e[uls])
+			print_error("bad characters in literal");
+	}
+	if ((errno == ERANGE)
 		 || ((bits < 64) && (val >= (1ULL << bits))))
 		print_error("literal out of range");
 	else if (errno != 0)
@@ -1944,3 +2370,29 @@
 	return val;
 }
 
+static unsigned char eval_char_literal(const char *s)
+{
+	int i = 1;
+	char c = s[0];
+
+	if (c == '\0')
+	{
+		print_error("empty character literal");
+		return 0;
+	}
+
+	/*
+	 * If the first character in the character literal is a \ then process
+	 * the remaining characters as an escape encoding. If the first
+	 * character is neither an escape or a terminator it should be the only
+	 * character in the literal and will be returned.
+	 */
+	if (c == '\\')
+		c = get_escape_char(s, &i);
+
+	if (s[i] != '\0')
+		print_error("malformed character literal");
+
+	return c;
+}
+
diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
index 4ee682b..9d2dce4 100644
--- a/scripts/dtc/dtc-parser.tab.h_shipped
+++ b/scripts/dtc/dtc-parser.tab.h_shipped
@@ -1,9 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.4.3.  */
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
 
 /* Skeleton interface for Bison's Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-   2009, 2010 Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
    
    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
@@ -40,14 +41,26 @@
    enum yytokentype {
      DT_V1 = 258,
      DT_MEMRESERVE = 259,
-     DT_PROPNODENAME = 260,
-     DT_LITERAL = 261,
-     DT_BASE = 262,
-     DT_BYTE = 263,
-     DT_STRING = 264,
-     DT_LABEL = 265,
-     DT_REF = 266,
-     DT_INCBIN = 267
+     DT_LSHIFT = 260,
+     DT_RSHIFT = 261,
+     DT_LE = 262,
+     DT_GE = 263,
+     DT_EQ = 264,
+     DT_NE = 265,
+     DT_AND = 266,
+     DT_OR = 267,
+     DT_BITS = 268,
+     DT_DEL_PROP = 269,
+     DT_DEL_NODE = 270,
+     DT_PROPNODENAME = 271,
+     DT_LITERAL = 272,
+     DT_CHAR_LITERAL = 273,
+     DT_BASE = 274,
+     DT_BYTE = 275,
+     DT_STRING = 276,
+     DT_LABEL = 277,
+     DT_REF = 278,
+     DT_INCBIN = 279
    };
 #endif
 
@@ -57,6 +70,8 @@
 typedef union YYSTYPE
 {
 
+/* Line 1676 of yacc.c  */
+#line 40 "dtc-parser.y"
 
 	char *propnodename;
 	char *literal;
@@ -65,16 +80,22 @@
 	uint8_t byte;
 	struct data data;
 
-	uint64_t addr;
-	cell_t cell;
+	struct {
+		struct data	data;
+		int		bits;
+	} array;
+
 	struct property *prop;
 	struct property *proplist;
 	struct node *node;
 	struct node *nodelist;
 	struct reserve_info *re;
+	uint64_t integer;
 
 
 
+/* Line 1676 of yacc.c  */
+#line 99 "dtc-parser.tab.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index 5e84a67..f412460 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -34,6 +34,7 @@
 extern int treesource_error;
 
 static unsigned long long eval_literal(const char *s, int base, int bits);
+static unsigned char eval_char_literal(const char *s);
 %}
 
 %union {
@@ -44,19 +45,28 @@
 	uint8_t byte;
 	struct data data;
 
-	uint64_t addr;
-	cell_t cell;
+	struct {
+		struct data	data;
+		int		bits;
+	} array;
+
 	struct property *prop;
 	struct property *proplist;
 	struct node *node;
 	struct node *nodelist;
 	struct reserve_info *re;
+	uint64_t integer;
 }
 
 %token DT_V1
 %token DT_MEMRESERVE
+%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
+%token DT_BITS
+%token DT_DEL_PROP
+%token DT_DEL_NODE
 %token <propnodename> DT_PROPNODENAME
 %token <literal> DT_LITERAL
+%token <literal> DT_CHAR_LITERAL
 %token <cbase> DT_BASE
 %token <byte> DT_BYTE
 %token <data> DT_STRING
@@ -68,9 +78,7 @@
 %type <data> propdataprefix
 %type <re> memreserve
 %type <re> memreserves
-%type <addr> addr
-%type <data> celllist
-%type <cell> cellval
+%type <array> arrayprefix
 %type <data> bytestring
 %type <prop> propdef
 %type <proplist> proplist
@@ -80,6 +88,21 @@
 %type <node> subnode
 %type <nodelist> subnodes
 
+%type <integer> integer_prim
+%type <integer> integer_unary
+%type <integer> integer_mul
+%type <integer> integer_add
+%type <integer> integer_shift
+%type <integer> integer_rela
+%type <integer> integer_eq
+%type <integer> integer_bitand
+%type <integer> integer_bitxor
+%type <integer> integer_bitor
+%type <integer> integer_and
+%type <integer> integer_or
+%type <integer> integer_trinary
+%type <integer> integer_expr
+
 %%
 
 sourcefile:
@@ -102,7 +125,7 @@
 	;
 
 memreserve:
-	  DT_MEMRESERVE addr addr ';'
+	  DT_MEMRESERVE integer_prim integer_prim ';'
 		{
 			$$ = build_reserve_entry($2, $3);
 		}
@@ -113,13 +136,6 @@
 		}
 	;
 
-addr:
-	  DT_LITERAL
-		{
-			$$ = eval_literal($1, 0, 64);
-		}
-	  ;
-
 devicetree:
 	  '/' nodedef
 		{
@@ -139,6 +155,17 @@
 				print_error("label or path, '%s', not found", $2);
 			$$ = $1;
 		}
+	| devicetree DT_DEL_NODE DT_REF ';'
+		{
+			struct node *target = get_node_by_ref($1, $3);
+
+			if (!target)
+				print_error("label or path, '%s', not found", $3);
+			else
+				delete_node(target);
+
+			$$ = $1;
+		}
 	;
 
 nodedef:
@@ -168,6 +195,10 @@
 		{
 			$$ = build_property($1, empty_data);
 		}
+	| DT_DEL_PROP DT_PROPNODENAME ';'
+		{
+			$$ = build_property_delete($2);
+		}
 	| DT_LABEL propdef
 		{
 			add_label(&$2->labels, $1);
@@ -180,9 +211,9 @@
 		{
 			$$ = data_merge($1, $2);
 		}
-	| propdataprefix '<' celllist '>'
+	| propdataprefix arrayprefix '>'
 		{
-			$$ = data_merge($1, $3);
+			$$ = data_merge($1, $2.data);
 		}
 	| propdataprefix '[' bytestring ']'
 		{
@@ -192,7 +223,7 @@
 		{
 			$$ = data_add_marker($1, REF_PATH, $2);
 		}
-	| propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
+	| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
 		{
 			FILE *f = srcfile_relative_open($4.val, NULL);
 			struct data d;
@@ -240,31 +271,154 @@
 		}
 	;
 
-celllist:
-	  /* empty */
+arrayprefix:
+	DT_BITS DT_LITERAL '<'
 		{
-			$$ = empty_data;
+			$$.data = empty_data;
+			$$.bits = eval_literal($2, 0, 7);
+
+			if (($$.bits !=  8) &&
+			    ($$.bits != 16) &&
+			    ($$.bits != 32) &&
+			    ($$.bits != 64))
+			{
+				print_error("Only 8, 16, 32 and 64-bit elements"
+					    " are currently supported");
+				$$.bits = 32;
+			}
 		}
-	| celllist cellval
+	| '<'
 		{
-			$$ = data_append_cell($1, $2);
+			$$.data = empty_data;
+			$$.bits = 32;
 		}
-	| celllist DT_REF
+	| arrayprefix integer_prim
 		{
-			$$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
-							      $2), -1);
+			if ($1.bits < 64) {
+				uint64_t mask = (1ULL << $1.bits) - 1;
+				/*
+				 * Bits above mask must either be all zero
+				 * (positive within range of mask) or all one
+				 * (negative and sign-extended). The second
+				 * condition is true if when we set all bits
+				 * within the mask to one (i.e. | in the
+				 * mask), all bits are one.
+				 */
+				if (($2 > mask) && (($2 | mask) != -1ULL))
+					print_error(
+						"integer value out of range "
+						"%016lx (%d bits)", $1.bits);
+			}
+
+			$$.data = data_append_integer($1.data, $2, $1.bits);
 		}
-	| celllist DT_LABEL
+	| arrayprefix DT_REF
 		{
-			$$ = data_add_marker($1, LABEL, $2);
+			uint64_t val = ~0ULL >> (64 - $1.bits);
+
+			if ($1.bits == 32)
+				$1.data = data_add_marker($1.data,
+							  REF_PHANDLE,
+							  $2);
+			else
+				print_error("References are only allowed in "
+					    "arrays with 32-bit elements.");
+
+			$$.data = data_append_integer($1.data, val, $1.bits);
+		}
+	| arrayprefix DT_LABEL
+		{
+			$$.data = data_add_marker($1.data, LABEL, $2);
 		}
 	;
 
-cellval:
+integer_prim:
 	  DT_LITERAL
 		{
-			$$ = eval_literal($1, 0, 32);
+			$$ = eval_literal($1, 0, 64);
 		}
+	| DT_CHAR_LITERAL
+		{
+			$$ = eval_char_literal($1);
+		}
+	| '(' integer_expr ')'
+		{
+			$$ = $2;
+		}
+	;
+
+integer_expr:
+	integer_trinary
+	;
+
+integer_trinary:
+	  integer_or
+	| integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
+	;
+
+integer_or:
+	  integer_and
+	| integer_or DT_OR integer_and { $$ = $1 || $3; }
+	;
+
+integer_and:
+	  integer_bitor
+	| integer_and DT_AND integer_bitor { $$ = $1 && $3; }
+	;
+
+integer_bitor:
+	  integer_bitxor
+	| integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
+	;
+
+integer_bitxor:
+	  integer_bitand
+	| integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
+	;
+
+integer_bitand:
+	  integer_eq
+	| integer_bitand '&' integer_eq { $$ = $1 & $3; }
+	;
+
+integer_eq:
+	  integer_rela
+	| integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
+	| integer_eq DT_NE integer_rela { $$ = $1 != $3; }
+	;
+
+integer_rela:
+	  integer_shift
+	| integer_rela '<' integer_shift { $$ = $1 < $3; }
+	| integer_rela '>' integer_shift { $$ = $1 > $3; }
+	| integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
+	| integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
+	;
+
+integer_shift:
+	  integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
+	| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
+	| integer_add
+	;
+
+integer_add:
+	  integer_add '+' integer_mul { $$ = $1 + $3; }
+	| integer_add '-' integer_mul { $$ = $1 - $3; }
+	| integer_mul
+	;
+
+integer_mul:
+	  integer_mul '*' integer_unary { $$ = $1 * $3; }
+	| integer_mul '/' integer_unary { $$ = $1 / $3; }
+	| integer_mul '%' integer_unary { $$ = $1 % $3; }
+	| integer_unary
+	;
+
+integer_unary:
+	  integer_prim
+	| '-' integer_unary { $$ = -$2; }
+	| '~' integer_unary { $$ = ~$2; }
+	| '!' integer_unary { $$ = !$2; }
 	;
 
 bytestring:
@@ -303,6 +457,10 @@
 		{
 			$$ = name_node($2, $1);
 		}
+	| DT_DEL_NODE DT_PROPNODENAME ';'
+		{
+			$$ = name_node(build_node_delete(), $2);
+		}
 	| DT_LABEL subnode
 		{
 			add_label(&$2->labels, $1);
@@ -334,12 +492,41 @@
 
 	errno = 0;
 	val = strtoull(s, &e, base);
-	if (*e)
-		print_error("bad characters in literal");
-	else if ((errno == ERANGE)
+	if (*e) {
+		size_t uls = strspn(e, "UL");
+		if (e[uls])
+			print_error("bad characters in literal");
+	}
+	if ((errno == ERANGE)
 		 || ((bits < 64) && (val >= (1ULL << bits))))
 		print_error("literal out of range");
 	else if (errno != 0)
 		print_error("bad literal");
 	return val;
 }
+
+static unsigned char eval_char_literal(const char *s)
+{
+	int i = 1;
+	char c = s[0];
+
+	if (c == '\0')
+	{
+		print_error("empty character literal");
+		return 0;
+	}
+
+	/*
+	 * If the first character in the character literal is a \ then process
+	 * the remaining characters as an escape encoding. If the first
+	 * character is neither an escape or a terminator it should be the only
+	 * character in the literal and will be returned.
+	 */
+	if (c == '\\')
+		c = get_escape_char(s, &i);
+
+	if (s[i] != '\0')
+		print_error("malformed character literal");
+
+	return c;
+}
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index 2ef5e2e..a375683 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -82,6 +82,8 @@
 	fprintf(stderr, "\t\tSet the physical boot cpu\n");
 	fprintf(stderr, "\t-f\n");
 	fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
+	fprintf(stderr, "\t-i\n");
+	fprintf(stderr, "\t\tAdd a path to search for include files\n");
 	fprintf(stderr, "\t-s\n");
 	fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n");
 	fprintf(stderr, "\t-v\n");
@@ -91,6 +93,9 @@
 	fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n");
 	fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n");
 	fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n");
+	fprintf(stderr, "\t-W [no-]<checkname>\n");
+	fprintf(stderr, "\t-E [no-]<checkname>\n");
+	fprintf(stderr, "\t\t\tenable or disable warnings and errors\n");
 	exit(3);
 }
 
@@ -113,7 +118,7 @@
 	minsize    = 0;
 	padsize    = 0;
 
-	while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fcqb:vH:s"))
+	while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
 			!= EOF) {
 		switch (opt) {
 		case 'I':
@@ -149,6 +154,9 @@
 		case 'b':
 			cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
 			break;
+		case 'i':
+			srcfile_add_search_path(optarg);
+			break;
 		case 'v':
 			printf("Version: %s\n", DTC_VERSION);
 			exit(0);
@@ -168,6 +176,14 @@
 			sort = 1;
 			break;
 
+		case 'W':
+			parse_checks_option(true, false, optarg);
+			break;
+
+		case 'E':
+			parse_checks_option(false, true, optarg);
+			break;
+
 		case 'h':
 		default:
 			usage();
@@ -188,9 +204,6 @@
 	if (minsize)
 		fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n");
 
-	fprintf(stderr, "DTC: %s->%s  on file \"%s\"\n",
-		inform, outform, arg);
-
 	if (depname) {
 		depfile = fopen(depname, "w");
 		if (!depfile)
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index f37c97e..3e42a07 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <stdarg.h>
 #include <assert.h>
 #include <ctype.h>
@@ -109,6 +110,7 @@
 				  const void *p, int len);
 struct data data_merge(struct data d1, struct data d2);
 struct data data_append_cell(struct data d, cell_t word);
+struct data data_append_integer(struct data d, uint64_t word, int bits);
 struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
 struct data data_append_addr(struct data d, uint64_t addr);
 struct data data_append_byte(struct data d, uint8_t byte);
@@ -126,11 +128,13 @@
 
 /* Live trees */
 struct label {
+	int deleted;
 	char *label;
 	struct label *next;
 };
 
 struct property {
+	int deleted;
 	char *name;
 	struct data val;
 
@@ -140,6 +144,7 @@
 };
 
 struct node {
+	int deleted;
 	char *name;
 	struct property *proplist;
 	struct node *children;
@@ -156,28 +161,47 @@
 	struct label *labels;
 };
 
-#define for_each_label(l0, l) \
+#define for_each_label_withdel(l0, l) \
 	for ((l) = (l0); (l); (l) = (l)->next)
 
-#define for_each_property(n, p) \
+#define for_each_label(l0, l) \
+	for_each_label_withdel(l0, l) \
+		if (!(l)->deleted)
+
+#define for_each_property_withdel(n, p) \
 	for ((p) = (n)->proplist; (p); (p) = (p)->next)
 
-#define for_each_child(n, c)	\
+#define for_each_property(n, p) \
+	for_each_property_withdel(n, p) \
+		if (!(p)->deleted)
+
+#define for_each_child_withdel(n, c) \
 	for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
 
+#define for_each_child(n, c) \
+	for_each_child_withdel(n, c) \
+		if (!(c)->deleted)
+
 void add_label(struct label **labels, char *label);
+void delete_labels(struct label **labels);
 
 struct property *build_property(char *name, struct data val);
+struct property *build_property_delete(char *name);
 struct property *chain_property(struct property *first, struct property *list);
 struct property *reverse_properties(struct property *first);
 
 struct node *build_node(struct property *proplist, struct node *children);
+struct node *build_node_delete(void);
 struct node *name_node(struct node *node, char *name);
 struct node *chain_node(struct node *first, struct node *list);
 struct node *merge_nodes(struct node *old_node, struct node *new_node);
 
 void add_property(struct node *node, struct property *prop);
+void delete_property_by_name(struct node *node, char *name);
+void delete_property(struct property *prop);
 void add_child(struct node *parent, struct node *child);
+void delete_node_by_name(struct node *parent, char *name);
+void delete_node(struct node *node);
 
 const char *get_unitname(struct node *node);
 struct property *get_property(struct node *node, const char *propname);
@@ -224,6 +248,7 @@
 
 /* Checks */
 
+void parse_checks_option(bool warn, bool error, const char *optarg);
 void process_checks(int force, struct boot_info *bi);
 
 /* Flattened trees */
diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c
new file mode 100644
index 0000000..207a46d
--- /dev/null
+++ b/scripts/dtc/fdtdump.c
@@ -0,0 +1,162 @@
+/*
+ * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <fdt.h>
+#include <libfdt_env.h>
+
+#include "util.h"
+
+#define ALIGN(x, a)	(((x) + ((a) - 1)) & ~((a) - 1))
+#define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a))))
+#define GET_CELL(p)	(p += 4, *((const uint32_t *)(p-4)))
+
+static void print_data(const char *data, int len)
+{
+	int i;
+	const char *p = data;
+
+	/* no data, don't print */
+	if (len == 0)
+		return;
+
+	if (util_is_printable_string(data, len)) {
+		printf(" = \"%s\"", (const char *)data);
+	} else if ((len % 4) == 0) {
+		printf(" = <");
+		for (i = 0; i < len; i += 4)
+			printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)),
+			       i < (len - 4) ? " " : "");
+		printf(">");
+	} else {
+		printf(" = [");
+		for (i = 0; i < len; i++)
+			printf("%02x%s", *p++, i < len - 1 ? " " : "");
+		printf("]");
+	}
+}
+
+static void dump_blob(void *blob)
+{
+	struct fdt_header *bph = blob;
+	uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
+	uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
+	uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
+	struct fdt_reserve_entry *p_rsvmap =
+		(struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
+	const char *p_struct = (const char *)blob + off_dt;
+	const char *p_strings = (const char *)blob + off_str;
+	uint32_t version = fdt32_to_cpu(bph->version);
+	uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
+	uint32_t tag;
+	const char *p, *s, *t;
+	int depth, sz, shift;
+	int i;
+	uint64_t addr, size;
+
+	depth = 0;
+	shift = 4;
+
+	printf("/dts-v1/;\n");
+	printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
+	printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
+	printf("// off_dt_struct:\t0x%x\n", off_dt);
+	printf("// off_dt_strings:\t0x%x\n", off_str);
+	printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
+	printf("// version:\t\t%d\n", version);
+	printf("// last_comp_version:\t%d\n",
+	       fdt32_to_cpu(bph->last_comp_version));
+	if (version >= 2)
+		printf("// boot_cpuid_phys:\t0x%x\n",
+		       fdt32_to_cpu(bph->boot_cpuid_phys));
+
+	if (version >= 3)
+		printf("// size_dt_strings:\t0x%x\n",
+		       fdt32_to_cpu(bph->size_dt_strings));
+	if (version >= 17)
+		printf("// size_dt_struct:\t0x%x\n",
+		       fdt32_to_cpu(bph->size_dt_struct));
+	printf("\n");
+
+	for (i = 0; ; i++) {
+		addr = fdt64_to_cpu(p_rsvmap[i].address);
+		size = fdt64_to_cpu(p_rsvmap[i].size);
+		if (addr == 0 && size == 0)
+			break;
+
+		printf("/memreserve/ %llx %llx;\n",
+		       (unsigned long long)addr, (unsigned long long)size);
+	}
+
+	p = p_struct;
+	while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
+
+		/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
+
+		if (tag == FDT_BEGIN_NODE) {
+			s = p;
+			p = PALIGN(p + strlen(s) + 1, 4);
+
+			if (*s == '\0')
+				s = "/";
+
+			printf("%*s%s {\n", depth * shift, "", s);
+
+			depth++;
+			continue;
+		}
+
+		if (tag == FDT_END_NODE) {
+			depth--;
+
+			printf("%*s};\n", depth * shift, "");
+			continue;
+		}
+
+		if (tag == FDT_NOP) {
+			printf("%*s// [NOP]\n", depth * shift, "");
+			continue;
+		}
+
+		if (tag != FDT_PROP) {
+			fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
+			break;
+		}
+		sz = fdt32_to_cpu(GET_CELL(p));
+		s = p_strings + fdt32_to_cpu(GET_CELL(p));
+		if (version < 16 && sz >= 8)
+			p = PALIGN(p, 8);
+		t = p;
+
+		p = PALIGN(p + sz, 4);
+
+		printf("%*s%s", depth * shift, "", s);
+		print_data(t, sz);
+		printf(";\n");
+	}
+}
+
+
+int main(int argc, char *argv[])
+{
+	char *buf;
+
+	if (argc < 2) {
+		fprintf(stderr, "supply input filename\n");
+		return 5;
+	}
+
+	buf = utilfdt_read(argv[1]);
+	if (buf)
+		dump_blob(buf);
+	else
+		return 10;
+
+	return 0;
+}
diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c
new file mode 100644
index 0000000..c2fbab2
--- /dev/null
+++ b/scripts/dtc/fdtget.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * Portions from U-Boot cmd_fdt.c (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
+ * Based on code written by:
+ *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and
+ *   Matthew McClintock <msm@freescale.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.
+ *
+ * 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.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+enum display_mode {
+	MODE_SHOW_VALUE,	/* show values for node properties */
+	MODE_LIST_PROPS,	/* list the properties for a node */
+	MODE_LIST_SUBNODES,	/* list the subnodes of a node */
+};
+
+/* Holds information which controls our output and options */
+struct display_info {
+	int type;		/* data type (s/i/u/x or 0 for default) */
+	int size;		/* data size (1/2/4) */
+	enum display_mode mode;	/* display mode that we are using */
+	const char *default_val; /* default value if node/property not found */
+};
+
+static void report_error(const char *where, int err)
+{
+	fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
+}
+
+/**
+ * Displays data of a given length according to selected options
+ *
+ * If a specific data type is provided in disp, then this is used. Otherwise
+ * we try to guess the data type / size from the contents.
+ *
+ * @param disp		Display information / options
+ * @param data		Data to display
+ * @param len		Maximum length of buffer
+ * @return 0 if ok, -1 if data does not match format
+ */
+static int show_data(struct display_info *disp, const char *data, int len)
+{
+	int i, size;
+	const uint8_t *p = (const uint8_t *)data;
+	const char *s;
+	int value;
+	int is_string;
+	char fmt[3];
+
+	/* no data, don't print */
+	if (len == 0)
+		return 0;
+
+	is_string = (disp->type) == 's' ||
+		(!disp->type && util_is_printable_string(data, len));
+	if (is_string) {
+		if (data[len - 1] != '\0') {
+			fprintf(stderr, "Unterminated string\n");
+			return -1;
+		}
+		for (s = data; s - data < len; s += strlen(s) + 1) {
+			if (s != data)
+				printf(" ");
+			printf("%s", (const char *)s);
+		}
+		return 0;
+	}
+	size = disp->size;
+	if (size == -1) {
+		size = (len % 4) == 0 ? 4 : 1;
+	} else if (len % size) {
+		fprintf(stderr, "Property length must be a multiple of "
+				"selected data size\n");
+		return -1;
+	}
+	fmt[0] = '%';
+	fmt[1] = disp->type ? disp->type : 'd';
+	fmt[2] = '\0';
+	for (i = 0; i < len; i += size, p += size) {
+		if (i)
+			printf(" ");
+		value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) :
+			size == 2 ? (*p << 8) | p[1] : *p;
+		printf(fmt, value);
+	}
+	return 0;
+}
+
+/**
+ * List all properties in a node, one per line.
+ *
+ * @param blob		FDT blob
+ * @param node		Node to display
+ * @return 0 if ok, or FDT_ERR... if not.
+ */
+static int list_properties(const void *blob, int node)
+{
+	const struct fdt_property *data;
+	const char *name;
+	int prop;
+
+	prop = fdt_first_property_offset(blob, node);
+	do {
+		/* Stop silently when there are no more properties */
+		if (prop < 0)
+			return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
+		data = fdt_get_property_by_offset(blob, prop, NULL);
+		name = fdt_string(blob, fdt32_to_cpu(data->nameoff));
+		if (name)
+			puts(name);
+		prop = fdt_next_property_offset(blob, prop);
+	} while (1);
+}
+
+#define MAX_LEVEL	32		/* how deeply nested we will go */
+
+/**
+ * List all subnodes in a node, one per line
+ *
+ * @param blob		FDT blob
+ * @param node		Node to display
+ * @return 0 if ok, or FDT_ERR... if not.
+ */
+static int list_subnodes(const void *blob, int node)
+{
+	int nextoffset;		/* next node offset from libfdt */
+	uint32_t tag;		/* current tag */
+	int level = 0;		/* keep track of nesting level */
+	const char *pathp;
+	int depth = 1;		/* the assumed depth of this node */
+
+	while (level >= 0) {
+		tag = fdt_next_tag(blob, node, &nextoffset);
+		switch (tag) {
+		case FDT_BEGIN_NODE:
+			pathp = fdt_get_name(blob, node, NULL);
+			if (level <= depth) {
+				if (pathp == NULL)
+					pathp = "/* NULL pointer error */";
+				if (*pathp == '\0')
+					pathp = "/";	/* root is nameless */
+				if (level == 1)
+					puts(pathp);
+			}
+			level++;
+			if (level >= MAX_LEVEL) {
+				printf("Nested too deep, aborting.\n");
+				return 1;
+			}
+			break;
+		case FDT_END_NODE:
+			level--;
+			if (level == 0)
+				level = -1;		/* exit the loop */
+			break;
+		case FDT_END:
+			return 1;
+		case FDT_PROP:
+			break;
+		default:
+			if (level <= depth)
+				printf("Unknown tag 0x%08X\n", tag);
+			return 1;
+		}
+		node = nextoffset;
+	}
+	return 0;
+}
+
+/**
+ * Show the data for a given node (and perhaps property) according to the
+ * display option provided.
+ *
+ * @param blob		FDT blob
+ * @param disp		Display information / options
+ * @param node		Node to display
+ * @param property	Name of property to display, or NULL if none
+ * @return 0 if ok, -ve on error
+ */
+static int show_data_for_item(const void *blob, struct display_info *disp,
+		int node, const char *property)
+{
+	const void *value = NULL;
+	int len, err = 0;
+
+	switch (disp->mode) {
+	case MODE_LIST_PROPS:
+		err = list_properties(blob, node);
+		break;
+
+	case MODE_LIST_SUBNODES:
+		err = list_subnodes(blob, node);
+		break;
+
+	default:
+		assert(property);
+		value = fdt_getprop(blob, node, property, &len);
+		if (value) {
+			if (show_data(disp, value, len))
+				err = -1;
+			else
+				printf("\n");
+		} else if (disp->default_val) {
+			puts(disp->default_val);
+		} else {
+			report_error(property, len);
+			err = -1;
+		}
+		break;
+	}
+
+	return err;
+}
+
+/**
+ * Run the main fdtget operation, given a filename and valid arguments
+ *
+ * @param disp		Display information / options
+ * @param filename	Filename of blob file
+ * @param arg		List of arguments to process
+ * @param arg_count	Number of arguments
+ * @param return 0 if ok, -ve on error
+ */
+static int do_fdtget(struct display_info *disp, const char *filename,
+		     char **arg, int arg_count, int args_per_step)
+{
+	char *blob;
+	const char *prop;
+	int i, node;
+
+	blob = utilfdt_read(filename);
+	if (!blob)
+		return -1;
+
+	for (i = 0; i + args_per_step <= arg_count; i += args_per_step) {
+		node = fdt_path_offset(blob, arg[i]);
+		if (node < 0) {
+			if (disp->default_val) {
+				puts(disp->default_val);
+				continue;
+			} else {
+				report_error(arg[i], node);
+				return -1;
+			}
+		}
+		prop = args_per_step == 1 ? NULL : arg[i + 1];
+
+		if (show_data_for_item(blob, disp, node, prop))
+			return -1;
+	}
+	return 0;
+}
+
+static const char *usage_msg =
+	"fdtget - read values from device tree\n"
+	"\n"
+	"Each value is printed on a new line.\n\n"
+	"Usage:\n"
+	"	fdtget <options> <dt file> [<node> <property>]...\n"
+	"	fdtget -p <options> <dt file> [<node> ]...\n"
+	"Options:\n"
+	"\t-t <type>\tType of data\n"
+	"\t-p\t\tList properties for each node\n"
+	"\t-l\t\tList subnodes for each node\n"
+	"\t-d\t\tDefault value to display when the property is "
+			"missing\n"
+	"\t-h\t\tPrint this help\n\n"
+	USAGE_TYPE_MSG;
+
+static void usage(const char *msg)
+{
+	if (msg)
+		fprintf(stderr, "Error: %s\n\n", msg);
+
+	fprintf(stderr, "%s", usage_msg);
+	exit(2);
+}
+
+int main(int argc, char *argv[])
+{
+	char *filename = NULL;
+	struct display_info disp;
+	int args_per_step = 2;
+
+	/* set defaults */
+	memset(&disp, '\0', sizeof(disp));
+	disp.size = -1;
+	disp.mode = MODE_SHOW_VALUE;
+	for (;;) {
+		int c = getopt(argc, argv, "d:hlpt:");
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'h':
+		case '?':
+			usage(NULL);
+
+		case 't':
+			if (utilfdt_decode_type(optarg, &disp.type,
+					&disp.size))
+				usage("Invalid type string");
+			break;
+
+		case 'p':
+			disp.mode = MODE_LIST_PROPS;
+			args_per_step = 1;
+			break;
+
+		case 'l':
+			disp.mode = MODE_LIST_SUBNODES;
+			args_per_step = 1;
+			break;
+
+		case 'd':
+			disp.default_val = optarg;
+			break;
+		}
+	}
+
+	if (optind < argc)
+		filename = argv[optind++];
+	if (!filename)
+		usage("Missing filename");
+
+	argv += optind;
+	argc -= optind;
+
+	/* Allow no arguments, and silently succeed */
+	if (!argc)
+		return 0;
+
+	/* Check for node, property arguments */
+	if (args_per_step == 2 && (argc % 2))
+		usage("Must have an even number of arguments");
+
+	if (do_fdtget(&disp, filename, argv, argc, args_per_step))
+		return 1;
+	return 0;
+}
diff --git a/scripts/dtc/fdtput.c b/scripts/dtc/fdtput.c
new file mode 100644
index 0000000..f2197f5
--- /dev/null
+++ b/scripts/dtc/fdtput.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. 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 as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+/* These are the operations we support */
+enum oper_type {
+	OPER_WRITE_PROP,		/* Write a property in a node */
+	OPER_CREATE_NODE,		/* Create a new node */
+};
+
+struct display_info {
+	enum oper_type oper;	/* operation to perform */
+	int type;		/* data type (s/i/u/x or 0 for default) */
+	int size;		/* data size (1/2/4) */
+	int verbose;		/* verbose output */
+	int auto_path;		/* automatically create all path components */
+};
+
+
+/**
+ * Report an error with a particular node.
+ *
+ * @param name		Node name to report error on
+ * @param namelen	Length of node name, or -1 to use entire string
+ * @param err		Error number to report (-FDT_ERR_...)
+ */
+static void report_error(const char *name, int namelen, int err)
+{
+	if (namelen == -1)
+		namelen = strlen(name);
+	fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name,
+		fdt_strerror(err));
+}
+
+/**
+ * Encode a series of arguments in a property value.
+ *
+ * @param disp		Display information / options
+ * @param arg		List of arguments from command line
+ * @param arg_count	Number of arguments (may be 0)
+ * @param valuep	Returns buffer containing value
+ * @param *value_len	Returns length of value encoded
+ */
+static int encode_value(struct display_info *disp, char **arg, int arg_count,
+			char **valuep, int *value_len)
+{
+	char *value = NULL;	/* holding area for value */
+	int value_size = 0;	/* size of holding area */
+	char *ptr;		/* pointer to current value position */
+	int len;		/* length of this cell/string/byte */
+	int ival;
+	int upto;	/* the number of bytes we have written to buf */
+	char fmt[3];
+
+	upto = 0;
+
+	if (disp->verbose)
+		fprintf(stderr, "Decoding value:\n");
+
+	fmt[0] = '%';
+	fmt[1] = disp->type ? disp->type : 'd';
+	fmt[2] = '\0';
+	for (; arg_count > 0; arg++, arg_count--, upto += len) {
+		/* assume integer unless told otherwise */
+		if (disp->type == 's')
+			len = strlen(*arg) + 1;
+		else
+			len = disp->size == -1 ? 4 : disp->size;
+
+		/* enlarge our value buffer by a suitable margin if needed */
+		if (upto + len > value_size) {
+			value_size = (upto + len) + 500;
+			value = realloc(value, value_size);
+			if (!value) {
+				fprintf(stderr, "Out of mmory: cannot alloc "
+					"%d bytes\n", value_size);
+				return -1;
+			}
+		}
+
+		ptr = value + upto;
+		if (disp->type == 's') {
+			memcpy(ptr, *arg, len);
+			if (disp->verbose)
+				fprintf(stderr, "\tstring: '%s'\n", ptr);
+		} else {
+			int *iptr = (int *)ptr;
+			sscanf(*arg, fmt, &ival);
+			if (len == 4)
+				*iptr = cpu_to_fdt32(ival);
+			else
+				*ptr = (uint8_t)ival;
+			if (disp->verbose) {
+				fprintf(stderr, "\t%s: %d\n",
+					disp->size == 1 ? "byte" :
+					disp->size == 2 ? "short" : "int",
+					ival);
+			}
+		}
+	}
+	*value_len = upto;
+	*valuep = value;
+	if (disp->verbose)
+		fprintf(stderr, "Value size %d\n", upto);
+	return 0;
+}
+
+static int store_key_value(void *blob, const char *node_name,
+		const char *property, const char *buf, int len)
+{
+	int node;
+	int err;
+
+	node = fdt_path_offset(blob, node_name);
+	if (node < 0) {
+		report_error(node_name, -1, node);
+		return -1;
+	}
+
+	err = fdt_setprop(blob, node, property, buf, len);
+	if (err) {
+		report_error(property, -1, err);
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * Create paths as needed for all components of a path
+ *
+ * Any components of the path that do not exist are created. Errors are
+ * reported.
+ *
+ * @param blob		FDT blob to write into
+ * @param in_path	Path to process
+ * @return 0 if ok, -1 on error
+ */
+static int create_paths(void *blob, const char *in_path)
+{
+	const char *path = in_path;
+	const char *sep;
+	int node, offset = 0;
+
+	/* skip leading '/' */
+	while (*path == '/')
+		path++;
+
+	for (sep = path; *sep; path = sep + 1, offset = node) {
+		/* equivalent to strchrnul(), but it requires _GNU_SOURCE */
+		sep = strchr(path, '/');
+		if (!sep)
+			sep = path + strlen(path);
+
+		node = fdt_subnode_offset_namelen(blob, offset, path,
+				sep - path);
+		if (node == -FDT_ERR_NOTFOUND) {
+			node = fdt_add_subnode_namelen(blob, offset, path,
+						       sep - path);
+		}
+		if (node < 0) {
+			report_error(path, sep - path, node);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Create a new node in the fdt.
+ *
+ * This will overwrite the node_name string. Any error is reported.
+ *
+ * TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this.
+ *
+ * @param blob		FDT blob to write into
+ * @param node_name	Name of node to create
+ * @return new node offset if found, or -1 on failure
+ */
+static int create_node(void *blob, const char *node_name)
+{
+	int node = 0;
+	char *p;
+
+	p = strrchr(node_name, '/');
+	if (!p) {
+		report_error(node_name, -1, -FDT_ERR_BADPATH);
+		return -1;
+	}
+	*p = '\0';
+
+	if (p > node_name) {
+		node = fdt_path_offset(blob, node_name);
+		if (node < 0) {
+			report_error(node_name, -1, node);
+			return -1;
+		}
+	}
+
+	node = fdt_add_subnode(blob, node, p + 1);
+	if (node < 0) {
+		report_error(p + 1, -1, node);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int do_fdtput(struct display_info *disp, const char *filename,
+		    char **arg, int arg_count)
+{
+	char *value;
+	char *blob;
+	int len, ret = 0;
+
+	blob = utilfdt_read(filename);
+	if (!blob)
+		return -1;
+
+	switch (disp->oper) {
+	case OPER_WRITE_PROP:
+		/*
+		 * Convert the arguments into a single binary value, then
+		 * store them into the property.
+		 */
+		assert(arg_count >= 2);
+		if (disp->auto_path && create_paths(blob, *arg))
+			return -1;
+		if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
+			store_key_value(blob, *arg, arg[1], value, len))
+			ret = -1;
+		break;
+	case OPER_CREATE_NODE:
+		for (; ret >= 0 && arg_count--; arg++) {
+			if (disp->auto_path)
+				ret = create_paths(blob, *arg);
+			else
+				ret = create_node(blob, *arg);
+		}
+		break;
+	}
+	if (ret >= 0)
+		ret = utilfdt_write(filename, blob);
+
+	free(blob);
+	return ret;
+}
+
+static const char *usage_msg =
+	"fdtput - write a property value to a device tree\n"
+	"\n"
+	"The command line arguments are joined together into a single value.\n"
+	"\n"
+	"Usage:\n"
+	"	fdtput <options> <dt file> <node> <property> [<value>...]\n"
+	"	fdtput -c <options> <dt file> [<node>...]\n"
+	"Options:\n"
+	"\t-c\t\tCreate nodes if they don't already exist\n"
+	"\t-p\t\tAutomatically create nodes as needed for the node path\n"
+	"\t-t <type>\tType of data\n"
+	"\t-v\t\tVerbose: display each value decoded from command line\n"
+	"\t-h\t\tPrint this help\n\n"
+	USAGE_TYPE_MSG;
+
+static void usage(const char *msg)
+{
+	if (msg)
+		fprintf(stderr, "Error: %s\n\n", msg);
+
+	fprintf(stderr, "%s", usage_msg);
+	exit(2);
+}
+
+int main(int argc, char *argv[])
+{
+	struct display_info disp;
+	char *filename = NULL;
+
+	memset(&disp, '\0', sizeof(disp));
+	disp.size = -1;
+	disp.oper = OPER_WRITE_PROP;
+	for (;;) {
+		int c = getopt(argc, argv, "chpt:v");
+		if (c == -1)
+			break;
+
+		/*
+		 * TODO: add options to:
+		 * - delete property
+		 * - delete node (optionally recursively)
+		 * - rename node
+		 * - pack fdt before writing
+		 * - set amount of free space when writing
+		 * - expand fdt if value doesn't fit
+		 */
+		switch (c) {
+		case 'c':
+			disp.oper = OPER_CREATE_NODE;
+			break;
+		case 'h':
+		case '?':
+			usage(NULL);
+		case 'p':
+			disp.auto_path = 1;
+			break;
+		case 't':
+			if (utilfdt_decode_type(optarg, &disp.type,
+					&disp.size))
+				usage("Invalid type string");
+			break;
+
+		case 'v':
+			disp.verbose = 1;
+			break;
+		}
+	}
+
+	if (optind < argc)
+		filename = argv[optind++];
+	if (!filename)
+		usage("Missing filename");
+
+	argv += optind;
+	argc -= optind;
+
+	if (disp.oper == OPER_WRITE_PROP) {
+		if (argc < 1)
+			usage("Missing node");
+		if (argc < 2)
+			usage("Missing property");
+	}
+
+	if (do_fdtput(&disp, filename, argv, argc))
+		return 1;
+	return 0;
+}
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
index 28d0b23..665dad7 100644
--- a/scripts/dtc/flattree.c
+++ b/scripts/dtc/flattree.c
@@ -263,6 +263,9 @@
 	struct node *child;
 	int seen_name_prop = 0;
 
+	if (tree->deleted)
+		return;
+
 	emit->beginnode(etarget, tree->labels);
 
 	if (vi->flags & FTF_FULLPATH)
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
index 6c42acf..91126c0 100644
--- a/scripts/dtc/libfdt/Makefile.libfdt
+++ b/scripts/dtc/libfdt/Makefile.libfdt
@@ -3,6 +3,8 @@
 # This is not a complete Makefile of itself.  Instead, it is designed to
 # be easily embeddable into other systems of Makefiles.
 #
-LIBFDT_INCLUDES = fdt.h libfdt.h
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
+LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
+LIBFDT_VERSION = version.lds
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 2acaec5..e56833a 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -74,7 +74,7 @@
 	return 0;
 }
 
-const void *fdt_offset_ptr(const void *fdt, int offset, int len)
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
 {
 	const char *p;
 
@@ -90,42 +90,53 @@
 	return p;
 }
 
-uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
+uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
 {
 	const uint32_t *tagp, *lenp;
 	uint32_t tag;
+	int offset = startoffset;
 	const char *p;
 
-	if (offset % FDT_TAGSIZE)
-		return -1;
-
+	*nextoffset = -FDT_ERR_TRUNCATED;
 	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
-	if (! tagp)
+	if (!tagp)
 		return FDT_END; /* premature end */
 	tag = fdt32_to_cpu(*tagp);
 	offset += FDT_TAGSIZE;
 
+	*nextoffset = -FDT_ERR_BADSTRUCTURE;
 	switch (tag) {
 	case FDT_BEGIN_NODE:
 		/* skip name */
 		do {
 			p = fdt_offset_ptr(fdt, offset++, 1);
 		} while (p && (*p != '\0'));
-		if (! p)
-			return FDT_END;
+		if (!p)
+			return FDT_END; /* premature end */
 		break;
+
 	case FDT_PROP:
 		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
-		if (! lenp)
-			return FDT_END;
-		/* skip name offset, length and value */
-		offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
+		if (!lenp)
+			return FDT_END; /* premature end */
+		/* skip-name offset, length and value */
+		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+			+ fdt32_to_cpu(*lenp);
 		break;
+
+	case FDT_END:
+	case FDT_END_NODE:
+	case FDT_NOP:
+		break;
+
+	default:
+		return FDT_END;
 	}
 
-	if (nextoffset)
-		*nextoffset = FDT_TAGALIGN(offset);
+	if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+		return FDT_END; /* premature end */
 
+	*nextoffset = FDT_TAGALIGN(offset);
 	return tag;
 }
 
@@ -138,6 +149,15 @@
 	return offset;
 }
 
+int _fdt_check_prop_offset(const void *fdt, int offset)
+{
+	if ((offset < 0) || (offset % FDT_TAGSIZE)
+	    || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
+		return -FDT_ERR_BADOFFSET;
+
+	return offset;
+}
+
 int fdt_next_node(const void *fdt, int offset, int *depth)
 {
 	int nextoffset = 0;
@@ -162,15 +182,16 @@
 			break;
 
 		case FDT_END_NODE:
-			if (depth)
-				(*depth)--;
+			if (depth && ((--(*depth)) < 0))
+				return nextoffset;
 			break;
 
 		case FDT_END:
-			return -FDT_ERR_NOTFOUND;
-
-		default:
-			return -FDT_ERR_BADSTRUCTURE;
+			if ((nextoffset >= 0)
+			    || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
+				return -FDT_ERR_NOTFOUND;
+			else
+				return nextoffset;
 		}
 	} while (tag != FDT_BEGIN_NODE);
 
diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c
new file mode 100644
index 0000000..f72d13b
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_empty_tree.c
@@ -0,0 +1,84 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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.
+ *
+ *     This library 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.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     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 OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_create_empty_tree(void *buf, int bufsize)
+{
+	int err;
+
+	err = fdt_create(buf, bufsize);
+	if (err)
+		return err;
+
+	err = fdt_finish_reservemap(buf);
+	if (err)
+		return err;
+
+	err = fdt_begin_node(buf, "");
+	if (err)
+		return err;
+
+	err =  fdt_end_node(buf);
+	if (err)
+		return err;
+
+	err = fdt_finish(buf);
+	if (err)
+		return err;
+
+	return fdt_open_into(buf, buf, bufsize);
+}
+
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index 22e6929..02b6d68 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -80,6 +80,14 @@
 	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
 }
 
+static int _fdt_string_eq(const void *fdt, int stroffset,
+			  const char *s, int len)
+{
+	const char *p = fdt_string(fdt, stroffset);
+
+	return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
 	FDT_CHECK_HEADER(fdt);
@@ -97,6 +105,30 @@
 	return i;
 }
 
+static int _nextprop(const void *fdt, int offset)
+{
+	uint32_t tag;
+	int nextoffset;
+
+	do {
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		switch (tag) {
+		case FDT_END:
+			if (nextoffset >= 0)
+				return -FDT_ERR_BADSTRUCTURE;
+			else
+				return nextoffset;
+
+		case FDT_PROP:
+			return offset;
+		}
+		offset = nextoffset;
+	} while (tag == FDT_NOP);
+
+	return -FDT_ERR_NOTFOUND;
+}
+
 int fdt_subnode_offset_namelen(const void *fdt, int offset,
 			       const char *name, int namelen)
 {
@@ -104,20 +136,16 @@
 
 	FDT_CHECK_HEADER(fdt);
 
-	for (depth = 0, offset = fdt_next_node(fdt, offset, &depth);
-	     (offset >= 0) && (depth > 0);
-	     offset = fdt_next_node(fdt, offset, &depth)) {
-		if (depth < 0)
-			return -FDT_ERR_NOTFOUND;
-		else if ((depth == 1)
-			 && _fdt_nodename_eq(fdt, offset, name, namelen))
+	for (depth = 0;
+	     (offset >= 0) && (depth >= 0);
+	     offset = fdt_next_node(fdt, offset, &depth))
+		if ((depth == 1)
+		    && _fdt_nodename_eq(fdt, offset, name, namelen))
 			return offset;
-	}
 
-	if (offset < 0)
-		return offset; /* error */
-	else
+	if (depth < 0)
 		return -FDT_ERR_NOTFOUND;
+	return offset; /* error */
 }
 
 int fdt_subnode_offset(const void *fdt, int parentoffset,
@@ -134,8 +162,20 @@
 
 	FDT_CHECK_HEADER(fdt);
 
-	if (*path != '/')
-		return -FDT_ERR_BADPATH;
+	/* see if we have an alias */
+	if (*path != '/') {
+		const char *q = strchr(path, '/');
+
+		if (!q)
+			q = end;
+
+		p = fdt_get_alias_namelen(fdt, p, q - p);
+		if (!p)
+			return -FDT_ERR_BADPATH;
+		offset = fdt_path_offset(fdt, p);
+
+		p = q;
+	}
 
 	while (*p) {
 		const char *q;
@@ -178,93 +218,142 @@
 	return NULL;
 }
 
+int fdt_first_property_offset(const void *fdt, int nodeoffset)
+{
+	int offset;
+
+	if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+		return offset;
+
+	return _nextprop(fdt, offset);
+}
+
+int fdt_next_property_offset(const void *fdt, int offset)
+{
+	if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
+		return offset;
+
+	return _nextprop(fdt, offset);
+}
+
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+						      int offset,
+						      int *lenp)
+{
+	int err;
+	const struct fdt_property *prop;
+
+	if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+		if (lenp)
+			*lenp = err;
+		return NULL;
+	}
+
+	prop = _fdt_offset_ptr(fdt, offset);
+
+	if (lenp)
+		*lenp = fdt32_to_cpu(prop->len);
+
+	return prop;
+}
+
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+						    int offset,
+						    const char *name,
+						    int namelen, int *lenp)
+{
+	for (offset = fdt_first_property_offset(fdt, offset);
+	     (offset >= 0);
+	     (offset = fdt_next_property_offset(fdt, offset))) {
+		const struct fdt_property *prop;
+
+		if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
+			offset = -FDT_ERR_INTERNAL;
+			break;
+		}
+		if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+				   name, namelen))
+			return prop;
+	}
+
+	if (lenp)
+		*lenp = offset;
+	return NULL;
+}
+
 const struct fdt_property *fdt_get_property(const void *fdt,
 					    int nodeoffset,
 					    const char *name, int *lenp)
 {
-	uint32_t tag;
-	const struct fdt_property *prop;
-	int namestroff;
-	int offset, nextoffset;
-	int err;
-
-	if (((err = fdt_check_header(fdt)) != 0)
-	    || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
-			goto fail;
-
-	nextoffset = err;
-	do {
-		offset = nextoffset;
-
-		tag = fdt_next_tag(fdt, offset, &nextoffset);
-		switch (tag) {
-		case FDT_END:
-			err = -FDT_ERR_TRUNCATED;
-			goto fail;
-
-		case FDT_BEGIN_NODE:
-		case FDT_END_NODE:
-		case FDT_NOP:
-			break;
-
-		case FDT_PROP:
-			err = -FDT_ERR_BADSTRUCTURE;
-			prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
-			if (! prop)
-				goto fail;
-			namestroff = fdt32_to_cpu(prop->nameoff);
-			if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
-				/* Found it! */
-				int len = fdt32_to_cpu(prop->len);
-				prop = fdt_offset_ptr(fdt, offset,
-						      sizeof(*prop)+len);
-				if (! prop)
-					goto fail;
-
-				if (lenp)
-					*lenp = len;
-
-				return prop;
-			}
-			break;
-
-		default:
-			err = -FDT_ERR_BADSTRUCTURE;
-			goto fail;
-		}
-	} while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
-
-	err = -FDT_ERR_NOTFOUND;
- fail:
-	if (lenp)
-		*lenp = err;
-	return NULL;
+	return fdt_get_property_namelen(fdt, nodeoffset, name,
+					strlen(name), lenp);
 }
 
-const void *fdt_getprop(const void *fdt, int nodeoffset,
-		  const char *name, int *lenp)
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+				const char *name, int namelen, int *lenp)
 {
 	const struct fdt_property *prop;
 
-	prop = fdt_get_property(fdt, nodeoffset, name, lenp);
+	prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
 	if (! prop)
 		return NULL;
 
 	return prop->data;
 }
 
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+				  const char **namep, int *lenp)
+{
+	const struct fdt_property *prop;
+
+	prop = fdt_get_property_by_offset(fdt, offset, lenp);
+	if (!prop)
+		return NULL;
+	if (namep)
+		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+	return prop->data;
+}
+
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+			const char *name, int *lenp)
+{
+	return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
+}
+
 uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
 {
 	const uint32_t *php;
 	int len;
 
-	php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
-	if (!php || (len != sizeof(*php)))
-		return 0;
+	/* FIXME: This is a bit sub-optimal, since we potentially scan
+	 * over all the properties twice. */
+	php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
+	if (!php || (len != sizeof(*php))) {
+		php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+		if (!php || (len != sizeof(*php)))
+			return 0;
+	}
 
 	return fdt32_to_cpu(*php);
 }
 
+const char *fdt_get_alias_namelen(const void *fdt,
+				  const char *name, int namelen)
+{
+	int aliasoffset;
+
+	aliasoffset = fdt_path_offset(fdt, "/aliases");
+	if (aliasoffset < 0)
+		return NULL;
+
+	return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+}
+
+const char *fdt_get_alias(const void *fdt, const char *name)
+{
+	return fdt_get_alias_namelen(fdt, name, strlen(name));
+}
+
 int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
 {
 	int pdepth = 0, p = 0;
@@ -279,9 +368,6 @@
 	for (offset = 0, depth = 0;
 	     (offset >= 0) && (offset <= nodeoffset);
 	     offset = fdt_next_node(fdt, offset, &depth)) {
-		if (pdepth < depth)
-			continue; /* overflowed buffer */
-
 		while (pdepth > depth) {
 			do {
 				p--;
@@ -289,14 +375,16 @@
 			pdepth--;
 		}
 
-		name = fdt_get_name(fdt, offset, &namelen);
-		if (!name)
-			return namelen;
-		if ((p + namelen + 1) <= buflen) {
-			memcpy(buf + p, name, namelen);
-			p += namelen;
-			buf[p++] = '/';
-			pdepth++;
+		if (pdepth >= depth) {
+			name = fdt_get_name(fdt, offset, &namelen);
+			if (!name)
+				return namelen;
+			if ((p + namelen + 1) <= buflen) {
+				memcpy(buf + p, name, namelen);
+				p += namelen;
+				buf[p++] = '/';
+				pdepth++;
+			}
 		}
 
 		if (offset == nodeoffset) {
@@ -306,7 +394,7 @@
 			if (p > 1) /* special case so that root path is "/", not "" */
 				p--;
 			buf[p] = '\0';
-			return p;
+			return 0;
 		}
 	}
 
@@ -404,14 +492,31 @@
 
 int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
 {
+	int offset;
+
 	if ((phandle == 0) || (phandle == -1))
 		return -FDT_ERR_BADPHANDLE;
-	phandle = cpu_to_fdt32(phandle);
-	return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
-					     &phandle, sizeof(phandle));
+
+	FDT_CHECK_HEADER(fdt);
+
+	/* FIXME: The algorithm here is pretty horrible: we
+	 * potentially scan each property of a node in
+	 * fdt_get_phandle(), then if that didn't find what
+	 * we want, we scan over them again making our way to the next
+	 * node.  Still it's the easiest to implement approach;
+	 * performance can come later. */
+	for (offset = fdt_next_node(fdt, -1, NULL);
+	     offset >= 0;
+	     offset = fdt_next_node(fdt, offset, NULL)) {
+		if (fdt_get_phandle(fdt, offset) == phandle)
+			return offset;
+	}
+
+	return offset; /* error from fdt_next_node() */
 }
 
-static int _stringlist_contains(const char *strlist, int listlen, const char *str)
+static int _fdt_stringlist_contains(const char *strlist, int listlen,
+				    const char *str)
 {
 	int len = strlen(str);
 	const char *p;
@@ -437,7 +542,7 @@
 	prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
 	if (!prop)
 		return len;
-	if (_stringlist_contains(prop, len, compatible))
+	if (_fdt_stringlist_contains(prop, len, compatible))
 		return 0;
 	else
 		return 1;
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 8e7ec4c..24437df 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -289,6 +289,33 @@
 	return 0;
 }
 
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+		   const void *val, int len)
+{
+	struct fdt_property *prop;
+	int err, oldlen, newlen;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+	if (prop) {
+		newlen = len + oldlen;
+		err = _fdt_splice_struct(fdt, prop->data,
+					 FDT_TAGALIGN(oldlen),
+					 FDT_TAGALIGN(newlen));
+		if (err)
+			return err;
+		prop->len = cpu_to_fdt32(newlen);
+		memcpy(prop->data + oldlen, val, len);
+	} else {
+		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+		if (err)
+			return err;
+		memcpy(prop->data, val, len);
+	}
+	return 0;
+}
+
 int fdt_delprop(void *fdt, int nodeoffset, const char *name)
 {
 	struct fdt_property *prop;
@@ -406,6 +433,8 @@
 		struct_size = 0;
 		while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
 			;
+		if (struct_size < 0)
+			return struct_size;
 	}
 
 	if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
index 698329e..55ebebf 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -70,7 +70,7 @@
 			return err; \
 	}
 
-static void *_fdt_grab_space(void *fdt, int len)
+static void *_fdt_grab_space(void *fdt, size_t len)
 {
 	int offset = fdt_size_dt_struct(fdt);
 	int spaceleft;
@@ -82,7 +82,7 @@
 		return NULL;
 
 	fdt_set_size_dt_struct(fdt, offset + len);
-	return fdt_offset_ptr_w(fdt, offset, len);
+	return _fdt_offset_ptr_w(fdt, offset);
 }
 
 int fdt_create(void *buf, int bufsize)
@@ -237,18 +237,17 @@
 	while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
 		if (tag == FDT_PROP) {
 			struct fdt_property *prop =
-				fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
+				_fdt_offset_ptr_w(fdt, offset);
 			int nameoff;
 
-			if (! prop)
-				return -FDT_ERR_BADSTRUCTURE;
-
 			nameoff = fdt32_to_cpu(prop->nameoff);
 			nameoff += fdt_size_dt_strings(fdt);
 			prop->nameoff = cpu_to_fdt32(nameoff);
 		}
 		offset = nextoffset;
 	}
+	if (nextoffset < 0)
+		return nextoffset;
 
 	/* Finally, adjust the header */
 	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
index a4652c6..6025fa1 100644
--- a/scripts/dtc/libfdt/fdt_wip.c
+++ b/scripts/dtc/libfdt/fdt_wip.c
@@ -94,41 +94,14 @@
 	return 0;
 }
 
-int _fdt_node_end_offset(void *fdt, int nodeoffset)
+int _fdt_node_end_offset(void *fdt, int offset)
 {
-	int level = 0;
-	uint32_t tag;
-	int offset, nextoffset;
+	int depth = 0;
 
-	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
-	if (tag != FDT_BEGIN_NODE)
-		return -FDT_ERR_BADOFFSET;
-	do {
-		offset = nextoffset;
-		tag = fdt_next_tag(fdt, offset, &nextoffset);
+	while ((offset >= 0) && (depth >= 0))
+		offset = fdt_next_node(fdt, offset, &depth);
 
-		switch (tag) {
-		case FDT_END:
-			return offset;
-
-		case FDT_BEGIN_NODE:
-			level++;
-			break;
-
-		case FDT_END_NODE:
-			level--;
-			break;
-
-		case FDT_PROP:
-		case FDT_NOP:
-			break;
-
-		default:
-			return -FDT_ERR_BADSTRUCTURE;
-		}
-	} while (level >= 0);
-
-	return nextoffset;
+	return offset;
 }
 
 int fdt_nop_node(void *fdt, int nodeoffset)
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index ff6246f..73f4975 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -61,7 +61,7 @@
 #define FDT_ERR_NOTFOUND	1
 	/* FDT_ERR_NOTFOUND: The requested node or property does not exist */
 #define FDT_ERR_EXISTS		2
-	/* FDT_ERR_EXISTS: Attempted to create a node or property which
+	/* FDT_ERR_EXISTS: Attemped to create a node or property which
 	 * already exists */
 #define FDT_ERR_NOSPACE		3
 	/* FDT_ERR_NOSPACE: Operation needed to expand the device
@@ -122,7 +122,7 @@
 /* Low-level functions (you probably don't need these)                */
 /**********************************************************************/
 
-const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
 static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
 {
 	return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
@@ -156,7 +156,7 @@
 #define __fdt_set_hdr(name) \
 	static inline void fdt_set_##name(void *fdt, uint32_t val) \
 	{ \
-		struct fdt_header *fdth = fdt; \
+		struct fdt_header *fdth = (struct fdt_header*)fdt; \
 		fdth->name = cpu_to_fdt32(val); \
 	}
 __fdt_set_hdr(magic);
@@ -343,6 +343,91 @@
 const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
 
 /**
+ * fdt_first_property_offset - find the offset of a node's first property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ *
+ * fdt_first_property_offset() finds the first property of the node at
+ * the given structure block offset.
+ *
+ * returns:
+ *	structure block offset of the property (>=0), on success
+ *	-FDT_ERR_NOTFOUND, if the requested node has no properties
+ *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_first_property_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_next_property_offset - step through a node's properties
+ * @fdt: pointer to the device tree blob
+ * @offset: structure block offset of a property
+ *
+ * fdt_next_property_offset() finds the property immediately after the
+ * one at the given structure block offset.  This will be a property
+ * of the same node as the given property.
+ *
+ * returns:
+ *	structure block offset of the next property (>=0), on success
+ *	-FDT_ERR_NOTFOUND, if the given property is the last in its node
+ *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_next_property_offset(const void *fdt, int offset);
+
+/**
+ * fdt_get_property_by_offset - retrieve the property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @offset: offset of the property to retrieve
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property_by_offset() retrieves a pointer to the
+ * fdt_property structure within the device tree blob at the given
+ * offset.  If lenp is non-NULL, the length of the property value is
+ * also returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the structure representing the property
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+						      int offset,
+						      int *lenp);
+
+/**
+ * fdt_get_property_namelen - find a property based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_get_property_namelen(), but only examine the first
+ * namelen characters of name for matching the property name.
+ */
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+						    int nodeoffset,
+						    const char *name,
+						    int namelen, int *lenp);
+
+/**
  * fdt_get_property - find a given property in a given node
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to find
@@ -380,6 +465,54 @@
 }
 
 /**
+ * fdt_getprop_by_offset - retrieve the value of a property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @ffset: offset of the property to read
+ * @namep: pointer to a string variable (will be overwritten) or NULL
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop_by_offset() retrieves a pointer to the value of the
+ * property at structure block offset 'offset' (this will be a pointer
+ * to within the device blob itself, not a copy of the value).  If
+ * lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp.  If namep is non-NULL,
+ * the property's namne will also be returned in the char * pointed to
+ * by namep (this will be a pointer to within the device tree's string
+ * block, not a new copy of the name).
+ *
+ * returns:
+ *	pointer to the property's value
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *		if namep is non-NULL *namep contiains a pointer to the property
+ *		name.
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+				  const char **namep, int *lenp);
+
+/**
+ * fdt_getprop_namelen - get property value based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_getprop(), but only examine the first namelen
+ * characters of name for matching the property name.
+ */
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+				const char *name, int namelen, int *lenp);
+
+/**
  * fdt_getprop - retrieve the value of a given property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to find
@@ -429,6 +562,32 @@
 uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
 
 /**
+ * fdt_get_alias_namelen - get alias based on substring
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_get_alias(), but only examine the first namelen
+ * characters of name for matching the alias name.
+ */
+const char *fdt_get_alias_namelen(const void *fdt,
+				  const char *name, int namelen);
+
+/**
+ * fdt_get_alias - retreive the path referenced by a given alias
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ *
+ * fdt_get_alias() retrieves the value of a given alias.  That is, the
+ * value of the property named 'name' in the node /aliases.
+ *
+ * returns:
+ *	a pointer to the expansion of the alias named 'name', of it exists
+ *	NULL, if the given alias or the /aliases node does not exist
+ */
+const char *fdt_get_alias(const void *fdt, const char *name);
+
+/**
  * fdt_get_path - determine the full path of a node
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose path to find
@@ -693,17 +852,17 @@
 			const void *val, int len);
 
 /**
- * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
  * @name: name of the property to change
- * @val: cell (32-bit integer) value to replace the property with
+ * @val: 32-bit integer value to replace the property with
  *
- * fdt_setprop_inplace_cell() replaces the value of a given property
- * with the 32-bit integer cell value in val, converting val to
- * big-endian if necessary.  This function cannot change the size of a
- * property, and so will only work if the property already exists and
- * has length 4.
+ * fdt_setprop_inplace_u32() replaces the value of a given property
+ * with the 32-bit integer value in val, converting val to big-endian
+ * if necessary.  This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 4.
  *
  * This function will alter only the bytes in the blob which contain
  * the given property value, and will not alter or move any other part
@@ -712,7 +871,7 @@
  * returns:
  *	0, on success
  *	-FDT_ERR_NOSPACE, if the property's length is not equal to 4
-  *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
  *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
  *	-FDT_ERR_BADMAGIC,
  *	-FDT_ERR_BADVERSION,
@@ -720,14 +879,60 @@
  *	-FDT_ERR_BADSTRUCTURE,
  *	-FDT_ERR_TRUNCATED, standard meanings
  */
-static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
-					   const char *name, uint32_t val)
+static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
+					  const char *name, uint32_t val)
 {
 	val = cpu_to_fdt32(val);
 	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
 }
 
 /**
+ * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to replace the property with
+ *
+ * fdt_setprop_inplace_u64() replaces the value of a given property
+ * with the 64-bit integer value in val, converting val to big-endian
+ * if necessary.  This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 8.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, if the property's length is not equal to 8
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
+					  const char *name, uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ *
+ * This is an alternative name for fdt_setprop_inplace_u32()
+ */
+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
+					   const char *name, uint32_t val)
+{
+	return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val);
+}
+
+/**
  * fdt_nop_property - replace a property with nop tags
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to nop
@@ -786,11 +991,20 @@
 int fdt_finish_reservemap(void *fdt);
 int fdt_begin_node(void *fdt, const char *name);
 int fdt_property(void *fdt, const char *name, const void *val, int len);
-static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
 {
 	val = cpu_to_fdt32(val);
 	return fdt_property(fdt, name, &val, sizeof(val));
 }
+static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_property(fdt, name, &val, sizeof(val));
+}
+static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+{
+	return fdt_property_u32(fdt, name, val);
+}
 #define fdt_property_string(fdt, name, str) \
 	fdt_property(fdt, name, str, strlen(str)+1)
 int fdt_end_node(void *fdt);
@@ -800,6 +1014,7 @@
 /* Read-write functions                                               */
 /**********************************************************************/
 
+int fdt_create_empty_tree(void *buf, int bufsize);
 int fdt_open_into(const void *fdt, void *buf, int bufsize);
 int fdt_pack(void *fdt);
 
@@ -909,14 +1124,14 @@
 		const void *val, int len);
 
 /**
- * fdt_setprop_cell - set a property to a single cell value
+ * fdt_setprop_u32 - set a property to a 32-bit integer
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
  * @name: name of the property to change
  * @val: 32-bit integer value for the property (native endian)
  *
- * fdt_setprop_cell() sets the value of the named property in the
- * given node to the given cell value (converting to big-endian if
+ * fdt_setprop_u32() sets the value of the named property in the given
+ * node to the given 32-bit integer value (converting to big-endian if
  * necessary), or creates a new property with that value if it does
  * not already exist.
  *
@@ -936,14 +1151,60 @@
  *	-FDT_ERR_BADLAYOUT,
  *	-FDT_ERR_TRUNCATED, standard meanings
  */
-static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
-				   uint32_t val)
+static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
+				  uint32_t val)
 {
 	val = cpu_to_fdt32(val);
 	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
 }
 
 /**
+ * fdt_setprop_u64 - set a property to a 64-bit integer
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_u64() sets the value of the named property in the given
+ * node to the given 64-bit integer value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
+				  uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ *
+ * This is an alternative name for fdt_setprop_u32()
+ */
+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
+				   uint32_t val)
+{
+	return fdt_setprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
  * fdt_setprop_string - set a property to a string value
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
@@ -975,6 +1236,147 @@
 	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
 
 /**
+ * fdt_appendprop - append to or create a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to append to
+ * @val: pointer to data to append to the property value
+ * @len: length of the data to append to the property value
+ *
+ * fdt_appendprop() appends the value to the named property in the
+ * given node, creating the property if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+		   const void *val, int len);
+
+/**
+ * fdt_appendprop_u32 - append a 32-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u32() appends the given 32-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
+				     const char *name, uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_appendprop_u64 - append a 64-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u64() appends the given 64-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
+				     const char *name, uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_appendprop_cell - append a single cell value to a property
+ *
+ * This is an alternative name for fdt_appendprop_u32()
+ */
+static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
+				      const char *name, uint32_t val)
+{
+	return fdt_appendprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
+ * fdt_appendprop_string - append a string to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value to append to the property
+ *
+ * fdt_appendprop_string() appends the given string to the value of
+ * the named property in the given node, or creates a new property
+ * with that value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_appendprop_string(fdt, nodeoffset, name, str) \
+	fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
  * fdt_delprop - delete a property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to nop
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
index 449bf60..213d7fb 100644
--- a/scripts/dtc/libfdt/libfdt_env.h
+++ b/scripts/dtc/libfdt/libfdt_env.h
@@ -5,19 +5,25 @@
 #include <stdint.h>
 #include <string.h>
 
-#define _B(n)	((unsigned long long)((uint8_t *)&x)[n])
+#define EXTRACT_BYTE(n)	((unsigned long long)((uint8_t *)&x)[n])
+static inline uint16_t fdt16_to_cpu(uint16_t x)
+{
+	return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1);
+}
+#define cpu_to_fdt16(x) fdt16_to_cpu(x)
+
 static inline uint32_t fdt32_to_cpu(uint32_t x)
 {
-	return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);
+	return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3);
 }
 #define cpu_to_fdt32(x) fdt32_to_cpu(x)
 
 static inline uint64_t fdt64_to_cpu(uint64_t x)
 {
-	return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32)
-		| (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7);
+	return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32)
+		| (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7);
 }
 #define cpu_to_fdt64(x) fdt64_to_cpu(x)
-#undef _B
+#undef EXTRACT_BYTE
 
 #endif /* _LIBFDT_ENV_H */
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
index 46eb93e..381133b 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -62,8 +62,8 @@
 			return err; \
 	}
 
-uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
 int _fdt_check_node_offset(const void *fdt, int offset);
+int _fdt_check_prop_offset(const void *fdt, int offset);
 const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
 int _fdt_node_end_offset(void *fdt, int nodeoffset);
 
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 26d0e1e..b61465f 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -29,16 +29,27 @@
 	struct label *new;
 
 	/* Make sure the label isn't already there */
-	for_each_label(*labels, new)
-		if (streq(new->label, label))
+	for_each_label_withdel(*labels, new)
+		if (streq(new->label, label)) {
+			new->deleted = 0;
 			return;
+		}
 
 	new = xmalloc(sizeof(*new));
+	memset(new, 0, sizeof(*new));
 	new->label = label;
 	new->next = *labels;
 	*labels = new;
 }
 
+void delete_labels(struct label **labels)
+{
+	struct label *label;
+
+	for_each_label(*labels, label)
+		label->deleted = 1;
+}
+
 struct property *build_property(char *name, struct data val)
 {
 	struct property *new = xmalloc(sizeof(*new));
@@ -51,6 +62,18 @@
 	return new;
 }
 
+struct property *build_property_delete(char *name)
+{
+	struct property *new = xmalloc(sizeof(*new));
+
+	memset(new, 0, sizeof(*new));
+
+	new->name = name;
+	new->deleted = 1;
+
+	return new;
+}
+
 struct property *chain_property(struct property *first, struct property *list)
 {
 	assert(first->next == NULL);
@@ -91,6 +114,17 @@
 	return new;
 }
 
+struct node *build_node_delete(void)
+{
+	struct node *new = xmalloc(sizeof(*new));
+
+	memset(new, 0, sizeof(*new));
+
+	new->deleted = 1;
+
+	return new;
+}
+
 struct node *name_node(struct node *node, char *name)
 {
 	assert(node->name == NULL);
@@ -106,8 +140,10 @@
 	struct node *new_child, *old_child;
 	struct label *l;
 
+	old_node->deleted = 0;
+
 	/* Add new node labels to old node */
-	for_each_label(new_node->labels, l)
+	for_each_label_withdel(new_node->labels, l)
 		add_label(&old_node->labels, l->label);
 
 	/* Move properties from the new node to the old node.  If there
@@ -118,14 +154,21 @@
 		new_node->proplist = new_prop->next;
 		new_prop->next = NULL;
 
+		if (new_prop->deleted) {
+			delete_property_by_name(old_node, new_prop->name);
+			free(new_prop);
+			continue;
+		}
+
 		/* Look for a collision, set new value if there is */
-		for_each_property(old_node, old_prop) {
+		for_each_property_withdel(old_node, old_prop) {
 			if (streq(old_prop->name, new_prop->name)) {
 				/* Add new labels to old property */
-				for_each_label(new_prop->labels, l)
+				for_each_label_withdel(new_prop->labels, l)
 					add_label(&old_prop->labels, l->label);
 
 				old_prop->val = new_prop->val;
+				old_prop->deleted = 0;
 				free(new_prop);
 				new_prop = NULL;
 				break;
@@ -146,8 +189,14 @@
 		new_child->parent = NULL;
 		new_child->next_sibling = NULL;
 
+		if (new_child->deleted) {
+			delete_node_by_name(old_node, new_child->name);
+			free(new_child);
+			continue;
+		}
+
 		/* Search for a collision.  Merge if there is */
-		for_each_child(old_node, old_child) {
+		for_each_child_withdel(old_node, old_child) {
 			if (streq(old_child->name, new_child->name)) {
 				merge_nodes(old_child, new_child);
 				new_child = NULL;
@@ -155,7 +204,7 @@
 			}
 		}
 
-		/* if no collision occurred, add child to the old node. */
+		/* if no collision occured, add child to the old node. */
 		if (new_child)
 			add_child(old_node, new_child);
 	}
@@ -188,6 +237,25 @@
 	*p = prop;
 }
 
+void delete_property_by_name(struct node *node, char *name)
+{
+	struct property *prop = node->proplist;
+
+	while (prop) {
+		if (!strcmp(prop->name, name)) {
+			delete_property(prop);
+			return;
+		}
+		prop = prop->next;
+	}
+}
+
+void delete_property(struct property *prop)
+{
+	prop->deleted = 1;
+	delete_labels(&prop->labels);
+}
+
 void add_child(struct node *parent, struct node *child)
 {
 	struct node **p;
@@ -202,6 +270,32 @@
 	*p = child;
 }
 
+void delete_node_by_name(struct node *parent, char *name)
+{
+	struct node *node = parent->children;
+
+	while (node) {
+		if (!strcmp(node->name, name)) {
+			delete_node(node);
+			return;
+		}
+		node = node->next_sibling;
+	}
+}
+
+void delete_node(struct node *node)
+{
+	struct property *prop;
+	struct node *child;
+
+	node->deleted = 1;
+	for_each_child(node, child)
+		delete_node(child);
+	for_each_property(node, prop)
+		delete_property(prop);
+	delete_labels(&node->labels);
+}
+
 struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
 {
 	struct reserve_info *new = xmalloc(sizeof(*new));
@@ -353,8 +447,11 @@
 	const char *p;
 	struct node *child;
 
-	if (!path || ! (*path))
+	if (!path || ! (*path)) {
+		if (tree->deleted)
+			return NULL;
 		return tree;
+	}
 
 	while (path[0] == '/')
 		path++;
@@ -397,8 +494,11 @@
 
 	assert((phandle != 0) && (phandle != -1));
 
-	if (tree->phandle == phandle)
+	if (tree->phandle == phandle) {
+		if (tree->deleted)
+			return NULL;
 		return tree;
+	}
 
 	for_each_child(tree, child) {
 		node = get_node_by_phandle(child, phandle);
@@ -535,7 +635,7 @@
 	int n = 0, i = 0;
 	struct property *prop, **tbl;
 
-	for_each_property(node, prop)
+	for_each_property_withdel(node, prop)
 		n++;
 
 	if (n == 0)
@@ -543,7 +643,7 @@
 
 	tbl = xmalloc(n * sizeof(*tbl));
 
-	for_each_property(node, prop)
+	for_each_property_withdel(node, prop)
 		tbl[i++] = prop;
 
 	qsort(tbl, n, sizeof(*tbl), cmp_prop);
@@ -571,7 +671,7 @@
 	int n = 0, i = 0;
 	struct node *subnode, **tbl;
 
-	for_each_child(node, subnode)
+	for_each_child_withdel(node, subnode)
 		n++;
 
 	if (n == 0)
@@ -579,7 +679,7 @@
 
 	tbl = xmalloc(n * sizeof(*tbl));
 
-	for_each_child(node, subnode)
+	for_each_child_withdel(node, subnode)
 		tbl[i++] = subnode;
 
 	qsort(tbl, n, sizeof(*tbl), cmp_subnode);
@@ -598,7 +698,7 @@
 
 	sort_properties(node);
 	sort_subnodes(node);
-	for_each_child(node, c)
+	for_each_child_withdel(node, c)
 		sort_node(c);
 }
 
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
index 36a38e9..246ab4b 100644
--- a/scripts/dtc/srcpos.c
+++ b/scripts/dtc/srcpos.c
@@ -24,6 +24,15 @@
 #include "dtc.h"
 #include "srcpos.h"
 
+/* A node in our list of directories to search for source/include files */
+struct search_path {
+	struct search_path *next;	/* next node in list, NULL for end */
+	const char *dirname;		/* name of directory to search */
+};
+
+/* This is the list of directories that we search for source files */
+static struct search_path *search_path_head, **search_path_tail;
+
 
 static char *dirname(const char *path)
 {
@@ -47,6 +56,64 @@
 #define MAX_SRCFILE_DEPTH     (100)
 static int srcfile_depth; /* = 0 */
 
+
+/**
+ * Try to open a file in a given directory.
+ *
+ * If the filename is an absolute path, then dirname is ignored. If it is a
+ * relative path, then we look in that directory for the file.
+ *
+ * @param dirname	Directory to look in, or NULL for none
+ * @param fname		Filename to look for
+ * @param fp		Set to NULL if file did not open
+ * @return allocated filename on success (caller must free), NULL on failure
+ */
+static char *try_open(const char *dirname, const char *fname, FILE **fp)
+{
+	char *fullname;
+
+	if (!dirname || fname[0] == '/')
+		fullname = xstrdup(fname);
+	else
+		fullname = join_path(dirname, fname);
+
+	*fp = fopen(fullname, "r");
+	if (!*fp) {
+		free(fullname);
+		fullname = NULL;
+	}
+
+	return fullname;
+}
+
+/**
+ * Open a file for read access
+ *
+ * If it is a relative filename, we search the full search path for it.
+ *
+ * @param fname	Filename to open
+ * @param fp	Returns pointer to opened FILE, or NULL on failure
+ * @return pointer to allocated filename, which caller must free
+ */
+static char *fopen_any_on_path(const char *fname, FILE **fp)
+{
+	const char *cur_dir = NULL;
+	struct search_path *node;
+	char *fullname;
+
+	/* Try current directory first */
+	assert(fp);
+	if (current_srcfile)
+		cur_dir = current_srcfile->dir;
+	fullname = try_open(cur_dir, fname, fp);
+
+	/* Failing that, try each search path in turn */
+	for (node = search_path_head; !*fp && node; node = node->next)
+		fullname = try_open(node->dirname, fname, fp);
+
+	return fullname;
+}
+
 FILE *srcfile_relative_open(const char *fname, char **fullnamep)
 {
 	FILE *f;
@@ -56,13 +123,7 @@
 		f = stdin;
 		fullname = xstrdup("<stdin>");
 	} else {
-		if (!current_srcfile || !current_srcfile->dir
-		    || (fname[0] == '/'))
-			fullname = xstrdup(fname);
-		else
-			fullname = join_path(current_srcfile->dir, fname);
-
-		f = fopen(fullname, "r");
+		fullname = fopen_any_on_path(fname, &f);
 		if (!f)
 			die("Couldn't open \"%s\": %s\n", fname,
 			    strerror(errno));
@@ -119,6 +180,23 @@
 	return current_srcfile ? 1 : 0;
 }
 
+void srcfile_add_search_path(const char *dirname)
+{
+	struct search_path *node;
+
+	/* Create the node */
+	node = xmalloc(sizeof(*node));
+	node->next = NULL;
+	node->dirname = xstrdup(dirname);
+
+	/* Add to the end of our list */
+	if (search_path_tail)
+		*search_path_tail = node;
+	else
+		search_path_head = node;
+	search_path_tail = &node->next;
+}
+
 /*
  * The empty source position.
  */
@@ -250,3 +328,9 @@
 
 	va_end(va);
 }
+
+void srcpos_set_line(char *f, int l)
+{
+	current_srcfile->name = f;
+	current_srcfile->lineno = l;
+}
diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h
index ce980ca..93a2712 100644
--- a/scripts/dtc/srcpos.h
+++ b/scripts/dtc/srcpos.h
@@ -33,10 +33,39 @@
 extern FILE *depfile; /* = NULL */
 extern struct srcfile_state *current_srcfile; /* = NULL */
 
+/**
+ * Open a source file.
+ *
+ * If the source file is a relative pathname, then it is searched for in the
+ * current directory (the directory of the last source file read) and after
+ * that in the search path.
+ *
+ * We work through the search path in order from the first path specified to
+ * the last.
+ *
+ * If the file is not found, then this function does not return, but calls
+ * die().
+ *
+ * @param fname		Filename to search
+ * @param fullnamep	If non-NULL, it is set to the allocated filename of the
+ *			file that was opened. The caller is then responsible
+ *			for freeing the pointer.
+ * @return pointer to opened FILE
+ */
 FILE *srcfile_relative_open(const char *fname, char **fullnamep);
+
 void srcfile_push(const char *fname);
 int srcfile_pop(void);
 
+/**
+ * Add a new directory to the search path for input files
+ *
+ * The new path is added at the end of the list.
+ *
+ * @param dirname	Directory to add
+ */
+void srcfile_add_search_path(const char *dirname);
+
 struct srcpos {
     int first_line;
     int first_column;
@@ -84,4 +113,6 @@
 extern void srcpos_warn(struct srcpos *pos, char const *, ...)
      __attribute__((format(printf, 2, 3)));
 
+extern void srcpos_set_line(char *f, int l);
+
 #endif /* _SRCPOS_H_ */
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
index c09aafa..33eeba5 100644
--- a/scripts/dtc/treesource.c
+++ b/scripts/dtc/treesource.c
@@ -23,6 +23,7 @@
 
 extern FILE *yyin;
 extern int yyparse(void);
+extern YYLTYPE yylloc;
 
 struct boot_info *the_boot_info;
 int treesource_error;
@@ -34,6 +35,7 @@
 
 	srcfile_push(fname);
 	yyin = current_srcfile->f;
+	yylloc.file = current_srcfile;
 
 	if (yyparse() != 0)
 		die("Unable to parse input tree\n");
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
index d7ac27d..2422c34 100644
--- a/scripts/dtc/util.c
+++ b/scripts/dtc/util.c
@@ -1,6 +1,10 @@
 /*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
  *
+ * util_is_printable_string contributed by
+ *	Pantelis Antoniou <pantelis.antoniou AT gmail.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
@@ -17,11 +21,18 @@
  *                                                                   USA
  */
 
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
+#include <assert.h>
 
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "libfdt.h"
 #include "util.h"
 
 char *xstrdup(const char *s)
@@ -57,3 +68,264 @@
 	memcpy(str+lenp, name, lenn+1);
 	return str;
 }
+
+int util_is_printable_string(const void *data, int len)
+{
+	const char *s = data;
+	const char *ss;
+
+	/* zero length is not */
+	if (len == 0)
+		return 0;
+
+	/* must terminate with zero */
+	if (s[len - 1] != '\0')
+		return 0;
+
+	ss = s;
+	while (*s && isprint(*s))
+		s++;
+
+	/* not zero, or not done yet */
+	if (*s != '\0' || (s + 1 - ss) < len)
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Parse a octal encoded character starting at index i in string s.  The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_oct_char(const char *s, int *i)
+{
+	char x[4];
+	char *endx;
+	long val;
+
+	x[3] = '\0';
+	strncpy(x, s + *i, 3);
+
+	val = strtol(x, &endx, 8);
+
+	assert(endx > x);
+
+	(*i) += endx - x;
+	return val;
+}
+
+/*
+ * Parse a hexadecimal encoded character starting at index i in string s.  The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_hex_char(const char *s, int *i)
+{
+	char x[3];
+	char *endx;
+	long val;
+
+	x[2] = '\0';
+	strncpy(x, s + *i, 2);
+
+	val = strtol(x, &endx, 16);
+	if (!(endx  > x))
+		die("\\x used with no following hex digits\n");
+
+	(*i) += endx - x;
+	return val;
+}
+
+char get_escape_char(const char *s, int *i)
+{
+	char	c = s[*i];
+	int	j = *i + 1;
+	char	val;
+
+	assert(c);
+	switch (c) {
+	case 'a':
+		val = '\a';
+		break;
+	case 'b':
+		val = '\b';
+		break;
+	case 't':
+		val = '\t';
+		break;
+	case 'n':
+		val = '\n';
+		break;
+	case 'v':
+		val = '\v';
+		break;
+	case 'f':
+		val = '\f';
+		break;
+	case 'r':
+		val = '\r';
+		break;
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+		j--; /* need to re-read the first digit as
+		      * part of the octal value */
+		val = get_oct_char(s, &j);
+		break;
+	case 'x':
+		val = get_hex_char(s, &j);
+		break;
+	default:
+		val = c;
+	}
+
+	(*i) = j;
+	return val;
+}
+
+int utilfdt_read_err(const char *filename, char **buffp)
+{
+	int fd = 0;	/* assume stdin */
+	char *buf = NULL;
+	off_t bufsize = 1024, offset = 0;
+	int ret = 0;
+
+	*buffp = NULL;
+	if (strcmp(filename, "-") != 0) {
+		fd = open(filename, O_RDONLY);
+		if (fd < 0)
+			return errno;
+	}
+
+	/* Loop until we have read everything */
+	buf = malloc(bufsize);
+	do {
+		/* Expand the buffer to hold the next chunk */
+		if (offset == bufsize) {
+			bufsize *= 2;
+			buf = realloc(buf, bufsize);
+			if (!buf) {
+				ret = ENOMEM;
+				break;
+			}
+		}
+
+		ret = read(fd, &buf[offset], bufsize - offset);
+		if (ret < 0) {
+			ret = errno;
+			break;
+		}
+		offset += ret;
+	} while (ret != 0);
+
+	/* Clean up, including closing stdin; return errno on error */
+	close(fd);
+	if (ret)
+		free(buf);
+	else
+		*buffp = buf;
+	return ret;
+}
+
+char *utilfdt_read(const char *filename)
+{
+	char *buff;
+	int ret = utilfdt_read_err(filename, &buff);
+
+	if (ret) {
+		fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
+			strerror(ret));
+		return NULL;
+	}
+	/* Successful read */
+	return buff;
+}
+
+int utilfdt_write_err(const char *filename, const void *blob)
+{
+	int fd = 1;	/* assume stdout */
+	int totalsize;
+	int offset;
+	int ret = 0;
+	const char *ptr = blob;
+
+	if (strcmp(filename, "-") != 0) {
+		fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+		if (fd < 0)
+			return errno;
+	}
+
+	totalsize = fdt_totalsize(blob);
+	offset = 0;
+
+	while (offset < totalsize) {
+		ret = write(fd, ptr + offset, totalsize - offset);
+		if (ret < 0) {
+			ret = -errno;
+			break;
+		}
+		offset += ret;
+	}
+	/* Close the file/stdin; return errno on error */
+	if (fd != 1)
+		close(fd);
+	return ret < 0 ? -ret : 0;
+}
+
+
+int utilfdt_write(const char *filename, const void *blob)
+{
+	int ret = utilfdt_write_err(filename, blob);
+
+	if (ret) {
+		fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
+			strerror(ret));
+	}
+	return ret ? -1 : 0;
+}
+
+int utilfdt_decode_type(const char *fmt, int *type, int *size)
+{
+	int qualifier = 0;
+
+	if (!*fmt)
+		return -1;
+
+	/* get the conversion qualifier */
+	*size = -1;
+	if (strchr("hlLb", *fmt)) {
+		qualifier = *fmt++;
+		if (qualifier == *fmt) {
+			switch (*fmt++) {
+/* TODO:		case 'l': qualifier = 'L'; break;*/
+			case 'h':
+				qualifier = 'b';
+				break;
+			}
+		}
+	}
+
+	/* we should now have a type */
+	if ((*fmt == '\0') || !strchr("iuxs", *fmt))
+		return -1;
+
+	/* convert qualifier (bhL) to byte size */
+	if (*fmt != 's')
+		*size = qualifier == 'b' ? 1 :
+				qualifier == 'h' ? 2 :
+				qualifier == 'l' ? 4 : -1;
+	*type = *fmt++;
+
+	/* that should be it! */
+	if (*fmt)
+		return -1;
+	return 0;
+}
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
index 9cead84..c8eb45d 100644
--- a/scripts/dtc/util.h
+++ b/scripts/dtc/util.h
@@ -1,7 +1,10 @@
 #ifndef _UTIL_H
 #define _UTIL_H
 
+#include <stdarg.h>
+
 /*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
@@ -53,4 +56,98 @@
 extern char *xstrdup(const char *s);
 extern char *join_path(const char *path, const char *name);
 
+/**
+ * Check a string of a given length to see if it is all printable and
+ * has a valid terminator.
+ *
+ * @param data	The string to check
+ * @param len	The string length including terminator
+ * @return 1 if a valid printable string, 0 if not */
+int util_is_printable_string(const void *data, int len);
+
+/*
+ * Parse an escaped character starting at index i in string s.  The resulting
+ * character will be returned and the index i will be updated to point at the
+ * character directly after the end of the encoding, this may be the '\0'
+ * terminator of the string.
+ */
+char get_escape_char(const char *s, int *i);
+
+/**
+ * Read a device tree file into a buffer. This will report any errors on
+ * stderr.
+ *
+ * @param filename	The filename to read, or - for stdin
+ * @return Pointer to allocated buffer containing fdt, or NULL on error
+ */
+char *utilfdt_read(const char *filename);
+
+/**
+ * Read a device tree file into a buffer. Does not report errors, but only
+ * returns them. The value returned can be passed to strerror() to obtain
+ * an error message for the user.
+ *
+ * @param filename	The filename to read, or - for stdin
+ * @param buffp		Returns pointer to buffer containing fdt
+ * @return 0 if ok, else an errno value representing the error
+ */
+int utilfdt_read_err(const char *filename, char **buffp);
+
+
+/**
+ * Write a device tree buffer to a file. This will report any errors on
+ * stderr.
+ *
+ * @param filename	The filename to write, or - for stdout
+ * @param blob		Poiner to buffer containing fdt
+ * @return 0 if ok, -1 on error
+ */
+int utilfdt_write(const char *filename, const void *blob);
+
+/**
+ * Write a device tree buffer to a file. Does not report errors, but only
+ * returns them. The value returned can be passed to strerror() to obtain
+ * an error message for the user.
+ *
+ * @param filename	The filename to write, or - for stdout
+ * @param blob		Poiner to buffer containing fdt
+ * @return 0 if ok, else an errno value representing the error
+ */
+int utilfdt_write_err(const char *filename, const void *blob);
+
+/**
+ * Decode a data type string. The purpose of this string
+ *
+ * The string consists of an optional character followed by the type:
+ *	Modifier characters:
+ *		hh or b	1 byte
+ *		h	2 byte
+ *		l	4 byte, default
+ *
+ *	Type character:
+ *		s	string
+ *		i	signed integer
+ *		u	unsigned integer
+ *		x	hex
+ *
+ * TODO: Implement ll modifier (8 bytes)
+ * TODO: Implement o type (octal)
+ *
+ * @param fmt		Format string to process
+ * @param type		Returns type found(s/d/u/x), or 0 if none
+ * @param size		Returns size found(1,2,4,8) or 4 if none
+ * @return 0 if ok, -1 on error (no type given, or other invalid format)
+ */
+int utilfdt_decode_type(const char *fmt, int *type, int *size);
+
+/*
+ * This is a usage message fragment for the -t option. It is the format
+ * supported by utilfdt_decode_type.
+ */
+
+#define USAGE_TYPE_MSG \
+	"<type>\ts=string, i=int, u=unsigned, x=hex\n" \
+	"\tOptional modifier prefix:\n" \
+	"\t\thh or b=byte, h=2 byte, l=4 byte (default)\n";
+
 #endif /* _UTIL_H */
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 0ba1ec5..f3c6ef8 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -50,6 +50,11 @@
 
 #define MSM8X10_WCD_I2S_MASTER_MODE_MASK	0x08
 #define MSM8X10_DINO_CODEC_BASE_ADDR		0xFE043000
+#define MSM8x10_TLMM_CDC_PULL_CTL			0xFD512050
+#define HELICON_CORE_0_I2C_ADDR				0x0d
+#define HELICON_CORE_1_I2C_ADDR				0x77
+#define HELICON_CORE_2_I2C_ADDR				0x66
+#define HELICON_CORE_3_I2C_ADDR				0x55
 
 #define MAX_MSM8X10_WCD_DEVICE	4
 #define CODEC_DT_MAX_PROP_SIZE	40
@@ -683,9 +688,9 @@
 					kcontrol->private_value)->shift;
 
 	ucontrol->value.integer.value[0] =
-		snd_soc_read(codec,
+		(snd_soc_read(codec,
 			    (MSM8X10_WCD_A_CDC_IIR1_CTL + 64 * iir_idx)) &
-		(1 << band_idx);
+		(1 << band_idx)) != 0;
 
 	dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
 		iir_idx, band_idx,
@@ -709,22 +714,54 @@
 			    (1 << band_idx), (value << band_idx));
 
 	dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
-		iir_idx, band_idx, value);
+	  iir_idx, band_idx,
+	  ((snd_soc_read(codec, (MSM8X10_WCD_A_CDC_IIR1_CTL + 64 * iir_idx)) &
+	  (1 << band_idx)) != 0));
+
 	return 0;
 }
 static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
 				   int iir_idx, int band_idx,
 				   int coeff_idx)
 {
+	uint32_t value = 0;
+
 	/* Address does not automatically update if reading */
 	snd_soc_write(codec,
 		(MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
-		(band_idx * BAND_MAX + coeff_idx) & 0x1F);
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t)) & 0x7F);
+
+	value |= snd_soc_read(codec,
+		(MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx));
+
+	snd_soc_write(codec,
+		(MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 1) & 0x7F);
+
+	value |= (snd_soc_read(codec,
+		(MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 8);
+
+	snd_soc_write(codec,
+		(MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 2) & 0x7F);
+
+	value |= (snd_soc_read(codec,
+		(MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 16);
+
+	snd_soc_write(codec,
+		(MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 3) & 0x7F);
 
 	/* Mask bits top 2 bits since they are reserved */
-	return ((snd_soc_read(codec,
-		(MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 24)) &
-		0x3FFFFFFF;
+	value |= ((snd_soc_read(codec,
+	  (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) & 0x3f) << 24);
+
+	return value;
+
 }
 
 static int msm8x10_wcd_get_iir_band_audio_mixer(
@@ -768,13 +805,19 @@
 
 static void set_iir_band_coeff(struct snd_soc_codec *codec,
 				int iir_idx, int band_idx,
-				int coeff_idx, uint32_t value)
+				uint32_t value)
 {
-	/* Mask top 3 bits, 6-8 are reserved */
-	/* Update address manually each time */
 	snd_soc_write(codec,
-		(MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
-		(band_idx * BAND_MAX + coeff_idx) & 0x1F);
+		(MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
+		(value & 0xFF));
+
+	snd_soc_write(codec,
+		(MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
+		(value >> 8) & 0xFF);
+
+	snd_soc_write(codec,
+		(MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
+		(value >> 16) & 0xFF);
 
 	/* Mask top 2 bits, 7-8 are reserved */
 	snd_soc_write(codec,
@@ -793,15 +836,22 @@
 	int band_idx = ((struct soc_multi_mixer_control *)
 					kcontrol->private_value)->shift;
 
-	set_iir_band_coeff(codec, iir_idx, band_idx, 0,
+	/* Mask top bit it is reserved */
+	/* Updates addr automatically for each B2 write */
+	snd_soc_write(codec,
+		(MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
+		(band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+
+	set_iir_band_coeff(codec, iir_idx, band_idx,
 			   ucontrol->value.integer.value[0]);
-	set_iir_band_coeff(codec, iir_idx, band_idx, 1,
+	set_iir_band_coeff(codec, iir_idx, band_idx,
 			   ucontrol->value.integer.value[1]);
-	set_iir_band_coeff(codec, iir_idx, band_idx, 2,
+	set_iir_band_coeff(codec, iir_idx, band_idx,
 			   ucontrol->value.integer.value[2]);
-	set_iir_band_coeff(codec, iir_idx, band_idx, 3,
+	set_iir_band_coeff(codec, iir_idx, band_idx,
 			   ucontrol->value.integer.value[3]);
-	set_iir_band_coeff(codec, iir_idx, band_idx, 4,
+	set_iir_band_coeff(codec, iir_idx, band_idx,
 			   ucontrol->value.integer.value[4]);
 
 	dev_dbg(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
@@ -1698,7 +1748,9 @@
 	{"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
 	{"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
 	{"RX1 MIX2", NULL, "RX1 MIX1"},
+	{"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
 	{"RX2 MIX2", NULL, "RX2 MIX1"},
+	{"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
 
 	{"RX1 MIX1 INP1", "RX1", "I2S RX1"},
 	{"RX1 MIX1 INP1", "RX2", "I2S RX2"},
@@ -1730,6 +1782,9 @@
 	{"RX3 MIX1 INP2", "RX3", "I2S RX3"},
 	{"RX3 MIX1 INP2", "IIR1", "IIR1"},
 
+	{"RX1 MIX2 INP1", "IIR1", "IIR1"},
+	{"RX2 MIX2 INP1", "IIR1", "IIR1"},
+
 	/* Decimator Inputs */
 	{"DEC1 MUX", "DMIC1", "DMIC1"},
 	{"DEC1 MUX", "DMIC2", "DMIC2"},
@@ -2350,6 +2405,15 @@
 }
 EXPORT_SYMBOL_GPL(msm8x10_wcd_hs_detect);
 
+static int msm8x10_wcd_bringup(struct snd_soc_codec *codec)
+{
+	snd_soc_write(codec, MSM8X10_WCD_A_CDC_RST_CTL, 0x02);
+	snd_soc_write(codec, MSM8X10_WCD_A_CHIP_CTL, 0x00);
+	usleep_range(5000, 5000);
+	snd_soc_write(codec, MSM8X10_WCD_A_CDC_RST_CTL, 0x03);
+	return 0;
+}
+
 static int msm8x10_wcd_codec_probe(struct snd_soc_codec *codec)
 {
 	struct msm8x10_wcd_priv *msm8x10_wcd;
@@ -2372,6 +2436,7 @@
 	codec->control_data = dev_get_drvdata(codec->dev);
 	snd_soc_codec_set_drvdata(codec, msm8x10_wcd);
 	msm8x10_wcd->codec = codec;
+	msm8x10_wcd_bringup(codec);
 	msm8x10_wcd_codec_init_reg(codec);
 	msm8x10_wcd_update_reg_defaults(codec);
 
@@ -2507,13 +2572,27 @@
 	kfree(msm8x10->supplies);
 }
 
-static int msm8x10_wcd_bringup(struct msm8x10_wcd *msm8x10)
+static int msm8x10_wcd_pads_config(void)
 {
-	msm8x10->read_dev = msm8x10_wcd_reg_read;
-	msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CDC_RST_CTL, 0x02);
-	msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CHIP_CTL, 0x00);
-	usleep_range(5000, 5000);
-	msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CDC_RST_CTL, 0x03);
+	/* Set I2C pads as pull up and rest of pads as no pull */
+	iowrite32(0x03C00000, ioremap(MSM8x10_TLMM_CDC_PULL_CTL, 4));
+	usleep_range(100, 200);
+	return 0;
+}
+
+
+static int msm8x10_wcd_clk_init(void)
+{
+	/* Div-2 */
+	iowrite32(0x3, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_M, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_N, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_D, 4));
+	/* Digital codec clock enable */
+	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
+	/* Set the update bit to make the settings go through */
+	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4));
+	usleep_range(100, 200);
 	return 0;
 }
 
@@ -2523,11 +2602,8 @@
 	mutex_init(&msm8x10->xfer_lock);
 	mutex_init(&msm8x10->pm_lock);
 	msm8x10->wlock_holders = 0;
-
-	iowrite32(0x03C00000, ioremap(0xFD512050, 4));
-	usleep_range(5000, 5000);
-
-	msm8x10_wcd_bringup(msm8x10);
+	msm8x10_wcd_pads_config();
+	msm8x10_wcd_clk_init();
 	return 0;
 }
 
@@ -2539,15 +2615,44 @@
 	struct msm8x10_wcd_pdata *pdata;
 	static int device_id;
 	struct device *dev;
+	enum apr_subsys_state q6_state;
 
-	dev_dbg(&client->dev, "%s:slave addr = 0x%x device_id = %d\n",
-		__func__, client->addr, device_id);
+	dev_dbg(&client->dev, "%s(%d):slave addr = 0x%x device_id = %d\n",
+		__func__, __LINE__,  client->addr, device_id);
 
-	if (device_id > 0) {
-		msm8x10_wcd_modules[device_id++].client = client;
+	switch (client->addr) {
+	case HELICON_CORE_0_I2C_ADDR:
+		msm8x10_wcd_modules[0].client = client;
+		break;
+	case HELICON_CORE_1_I2C_ADDR:
+		msm8x10_wcd_modules[1].client = client;
+		goto rtn;
+	case HELICON_CORE_2_I2C_ADDR:
+		msm8x10_wcd_modules[2].client = client;
+		goto rtn;
+	case HELICON_CORE_3_I2C_ADDR:
+		msm8x10_wcd_modules[3].client = client;
+		goto rtn;
+	default:
+		ret = -EINVAL;
 		goto rtn;
 	}
 
+	q6_state = apr_get_q6_state();
+	if ((q6_state == APR_SUBSYS_DOWN) &&
+	    (client->addr == HELICON_CORE_0_I2C_ADDR)) {
+		dev_info(&client->dev, "defering %s, adsp_state %d\n", __func__,
+			q6_state);
+		return -EPROBE_DEFER;
+	} else
+		dev_info(&client->dev, "adsp is ready\n");
+
+	dev_dbg(&client->dev, "%s(%d):slave addr = 0x%x device_id = %d\n",
+		__func__, __LINE__,  client->addr, device_id);
+
+	if (client->addr != HELICON_CORE_0_I2C_ADDR)
+		goto rtn;
+
 	dev = &client->dev;
 	if (client->dev.of_node) {
 		dev_dbg(&client->dev, "%s:Platform data from device tree\n",
@@ -2569,7 +2674,6 @@
 	}
 
 	msm8x10->dev = &client->dev;
-	msm8x10_wcd_modules[device_id++].client = client;
 	msm8x10->read_dev = msm8x10_wcd_reg_read;
 	msm8x10->write_dev = msm8x10_wcd_reg_write;
 	ret = msm8x10_wcd_enable_supplies(msm8x10, pdata);
diff --git a/sound/soc/codecs/msm8x10-wcd.h b/sound/soc/codecs/msm8x10-wcd.h
index d250e0a..08a2725 100644
--- a/sound/soc/codecs/msm8x10-wcd.h
+++ b/sound/soc/codecs/msm8x10-wcd.h
@@ -23,6 +23,15 @@
 #define MSM8X10_WCD_NUM_IRQ_REGS	3
 #define MAX_REGULATOR				7
 #define MSM8X10_WCD_REG_VAL(reg, val)		{reg, 0, val}
+#define MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL	0xFE03B004
+#define MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR			0xFE02C000
+#define MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR			0xFE02C004
+#define MSM8X10_DINO_LPASS_DIGCODEC_M				0xFE02C008
+#define MSM8X10_DINO_LPASS_DIGCODEC_N				0xFE02C00C
+#define MSM8X10_DINO_LPASS_DIGCODEC_D				0xFE02C010
+#define MSM8X10_DINO_LPASS_DIGCODEC_CBCR			0xFE02C014
+#define MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR			0xFE02C018
+
 
 #define MSM8X10_WCD_IS_DINO_REG(reg) \
 	(((reg >= 0x400) && (reg <= 0x5FF)) ? 1 : 0)
diff --git a/sound/soc/msm/msm-pcm-host-voice.c b/sound/soc/msm/msm-pcm-host-voice.c
index 36826cc..2eafc1d 100644
--- a/sound/soc/msm/msm-pcm-host-voice.c
+++ b/sound/soc/msm/msm-pcm-host-voice.c
@@ -941,7 +941,8 @@
 						struct hpcm_buf_node, list);
 			list_del(&buf_node->list);
 			spin_unlock_irqrestore(&dai_data->dsp_lock, dsp_flags);
-			ret = copy_from_user(&buf_node->frame, buf, count);
+			ret = copy_from_user(&buf_node->frame.voc_pkt,
+					     buf, count);
 			buf_node->frame.len = count;
 			spin_lock_irqsave(&dai_data->dsp_lock, dsp_flags);
 			list_add_tail(&buf_node->list, &dai_data->filled_queue);
@@ -986,7 +987,9 @@
 					struct hpcm_buf_node, list);
 			list_del(&buf_node->list);
 			spin_unlock_irqrestore(&dai_data->dsp_lock, dsp_flags);
-			ret = copy_to_user(buf, &buf_node->frame, count);
+			ret = copy_to_user(buf,
+					   &buf_node->frame.voc_pkt,
+					   count);
 			if (ret) {
 				pr_err("%s: Copy to user retuned %d\n",
 					__func__, ret);
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 22cd61a..9782b2d 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -126,6 +126,7 @@
 static struct clk *codec_clk;
 static int clk_users;
 static int vdd_spkr_gpio = -1;
+static int msm_proxy_rx_ch = 2;
 
 static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
 					bool dapm)
@@ -235,6 +236,8 @@
 
 static const char *const slim0_rx_ch_text[] = {"One", "Two"};
 static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
+static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
+	"Five", "Six", "Seven", "Eight"};
 
 static const struct soc_enum msm_enum[] = {
 	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
@@ -349,6 +352,23 @@
 	return 0;
 }
 
+static int msm_proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
+						msm_proxy_rx_ch);
+	ucontrol->value.integer.value[0] = msm_proxy_rx_ch - 1;
+	return 0;
+}
+
+static int msm_proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	msm_proxy_rx_ch = ucontrol->value.integer.value[0] + 1;
+	pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
+						msm_proxy_rx_ch);
+	return 1;
+}
 static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					struct snd_pcm_hw_params *params)
 {
@@ -364,15 +384,31 @@
 	return 0;
 }
 
-static int msm_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-			struct snd_pcm_hw_params *params)
+static int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
 {
 	struct snd_interval *rate = hw_param_interval(params,
-	SNDRV_PCM_HW_PARAM_RATE);
+					SNDRV_PCM_HW_PARAM_RATE);
 
-	pr_debug("%s()\n", __func__);
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
+
+	if (channels->max < 2)
+		channels->min = channels->max = 2;
+	channels->min = channels->max = msm_proxy_rx_ch;
 	rate->min = rate->max = 48000;
+	return 0;
+}
 
+static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	rate->min = rate->max = 48000;
 	return 0;
 }
 
@@ -535,6 +571,7 @@
 static const struct soc_enum msm_snd_enum[] = {
 	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
 	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
+	SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
 };
 
 static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -546,6 +583,8 @@
 			msm8226_auxpcm_rate_get, msm8226_auxpcm_rate_put),
 	SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
 		     msm_btsco_rate_get, msm_btsco_rate_put),
+	SOC_ENUM_EXT("PROXY_RX Channels", msm_snd_enum[2],
+			msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
 };
 
 static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
@@ -1049,7 +1088,7 @@
 		.codec_dai_name = "msm-stub-rx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
-		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
 		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
 		.ignore_suspend = 1,
@@ -1063,7 +1102,7 @@
 		.codec_dai_name = "msm-stub-tx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
-		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
 		.ignore_suspend = 1,
 	},
 	/* HDMI Hostless */
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index ce6cfea..a076246 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -40,14 +40,6 @@
 static int msm_proxy_rx_ch = 2;
 static struct snd_soc_jack hs_jack;
 
-#define MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL	0xFE03B004
-#define MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR			0xFE02C000
-#define MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR			0xFE02C004
-#define MSM8X10_DINO_LPASS_DIGCODEC_M				0xFE02C008
-#define MSM8X10_DINO_LPASS_DIGCODEC_N				0xFE02C00C
-#define MSM8X10_DINO_LPASS_DIGCODEC_D				0xFE02C010
-#define MSM8X10_DINO_LPASS_DIGCODEC_CBCR			0xFE02C014
-#define MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR			0xFE02C018
 
 /*
  * There is limitation for the clock root selection from
@@ -89,7 +81,8 @@
 	0,
 };
 
-static atomic_t aud_init_rsc_ref;
+static atomic_t mclk_rsc_ref;
+static struct mutex cdc_mclk_mutex;
 
 static int msm8x10_mclk_event(struct snd_soc_dapm_widget *w,
 			      struct snd_kcontrol *kcontrol, int event);
@@ -103,69 +96,9 @@
 
 };
 
-/*
- * This function will be replaced by
- * afe_set_lpass_internal_digital_codec_clock(port_id, cfg)
- * in the future after LPASS API fix
- */
-static int msm_enable_lpass_mclk(void)
-{
-	/* Select the codec root */
-	iowrite32(DIG_CDC_CLK_SEL_DIG_CODEC,
-		  ioremap(MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL,
-		  4));
-	/* Div-2 */
-	iowrite32(0x3, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_M, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_N, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_D, 4));
-	/* Digital codec clock enable */
-	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
-	/* AHB clock enable */
-	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR, 4));
-	/* Set the update bit to make the settings go through */
-	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4));
-
-	return 0;
-}
-
-static int msm_enable_mclk_root(u16 port_id, struct afe_digital_clk_cfg *cfg)
-{
-	int ret = 0;
-	/*
-	  * msm_enable_lpass_mclk() function call will be replaced by
-	  * ret =  afe_set_lpass_internal_digital_codec_clock(port_id, cfg)
-	  * in the future. Currentlt there is a bug in LPASS plan which
-	  * doesn't consider the digital codec clock. It will be fixed soon
-	  * in new Q6 image
-	  */
-	msm_enable_lpass_mclk();
-	pr_debug("%s(): return = %d\n", __func__, ret);
-	return ret;
-}
-
 static int msm_config_mclk(u16 port_id, struct afe_digital_clk_cfg *cfg)
 {
-	/* Select the codec root */
-	iowrite32(DIG_CDC_CLK_SEL_DIG_CODEC,
-		  ioremap(MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL,
-		  4));
-	/* Div-2 */
-	iowrite32(0x3, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_M, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_N, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_D, 4));
-	/* Digital codec clock enable */
-	if (cfg->clk_val == 0) {
-		iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
-		pr_debug("%s(line %d)\n", __func__, __LINE__);
-	} else {
-		iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
-		pr_debug("%s(line %d)\n", __func__, __LINE__);
-	}
 	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
-	/* AHB clock enable */
-	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR, 4));
 	/* Set the update bit to make the settings go through */
 	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4));
 
@@ -173,42 +106,6 @@
 
 }
 
-static int msm_config_mi2s_clk(int enable)
-{
-	int ret = 0;
-	pr_debug("%s(line %d):enable = %x\n", __func__, __LINE__, enable);
-	if (enable) {
-		digital_cdc_clk.clk_val = 9600000;
-		mi2s_rx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
-		mi2s_rx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
-		ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
-					  &mi2s_rx_clk);
-		mi2s_tx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
-		mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
-		ret = afe_set_lpass_clock(AFE_PORT_ID_PRIMARY_MI2S_RX,
-					  &mi2s_tx_clk);
-		if (ret < 0)
-			pr_err("%s:afe_set_lpass_clock failed\n", __func__);
-
-	} else {
-		digital_cdc_clk.clk_val = 0;
-		mi2s_rx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_DISABLE;
-		mi2s_rx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
-		ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
-					  &mi2s_rx_clk);
-		mi2s_tx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_DISABLE;
-		mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
-		ret = afe_set_lpass_clock(AFE_PORT_ID_PRIMARY_MI2S_RX,
-					  &mi2s_tx_clk);
-		if (ret < 0)
-			pr_err("%s:afe_set_lpass_clock failed\n", __func__);
-
-	}
-	ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX, &digital_cdc_clk);
-	return ret;
-}
-
-
 static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 				struct snd_pcm_hw_params *params)
 {
@@ -284,7 +181,6 @@
 			pr_err("%s:afe_set_lpass_clock failed\n", __func__);
 
 	}
-	ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX, &digital_cdc_clk);
 	return ret;
 }
 
@@ -293,20 +189,27 @@
 {
 	int ret = 0;
 
-	pr_debug("%s: enable = %d  codec name %s enable %x\n",
-		   __func__, enable, codec->name, enable);
+	mutex_lock(&cdc_mclk_mutex);
+
+	pr_debug("%s: enable = %d  codec name %s enable %d mclk ref counter %d\n",
+		   __func__, enable, codec->name, enable,
+		   atomic_read(&mclk_rsc_ref));
 	if (enable) {
-		digital_cdc_clk.clk_val = 9600000;
-		msm_config_mi2s_clk(1);
-		ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
-					   &digital_cdc_clk);
-		msm8x10_wcd_mclk_enable(codec, 1, dapm);
+		if (atomic_inc_return(&mclk_rsc_ref) == 1) {
+			digital_cdc_clk.clk_val = 9600000;
+			msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
+					&digital_cdc_clk);
+			msm8x10_wcd_mclk_enable(codec, 1, dapm);
+		}
 	} else {
-		msm8x10_wcd_mclk_enable(codec, 0, dapm);
-		ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
-					   &digital_cdc_clk);
-		msm_config_mi2s_clk(0);
+		if (atomic_dec_return(&mclk_rsc_ref) == 0) {
+			digital_cdc_clk.clk_val = 0;
+			msm8x10_wcd_mclk_enable(codec, 0, dapm);
+			msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
+					&digital_cdc_clk);
+		}
 	}
+	mutex_unlock(&cdc_mclk_mutex);
 	return ret;
 }
 
@@ -363,27 +266,17 @@
 
 	pr_debug("%s(),dev_name%s\n", __func__, dev_name(cpu_dai->dev));
 
-	pr_debug("%s(): aud_init_rsc_ref counter = %d\n",
-		__func__, atomic_read(&aud_init_rsc_ref));
-	if (atomic_inc_return(&aud_init_rsc_ref) != 1)
-		goto exit;
-
 	snd_soc_dapm_new_controls(dapm, msm8x10_dapm_widgets,
 				ARRAY_SIZE(msm8x10_dapm_widgets));
 
 	snd_soc_dapm_sync(dapm);
-	ret =  msm_enable_mclk_root(AFE_PORT_ID_SECONDARY_MI2S_RX,
-				    &digital_cdc_clk);
 
 	ret = snd_soc_jack_new(codec, "Headset Jack",
 			SND_JACK_HEADSET, &hs_jack);
-
 	if (ret) {
 		pr_err("%s: Failed to create headset jack\n", __func__);
-		return ret;
 	}
 
-exit:
 	return ret;
 }
 
@@ -804,9 +697,8 @@
 			ret);
 		goto err;
 	}
-
-	atomic_set(&aud_init_rsc_ref, 0);
-
+	mutex_init(&cdc_mclk_mutex);
+	atomic_set(&mclk_rsc_ref, 0);
 	return 0;
 err:
 	return ret;
@@ -817,7 +709,7 @@
 	struct snd_soc_card *card = platform_get_drvdata(pdev);
 
 	snd_soc_unregister_card(card);
-
+	mutex_destroy(&cdc_mclk_mutex);
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 461fca4..77f3a07 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -48,12 +48,14 @@
 };
 static struct snd_msm_volume pcm_audio = {NULL, 0x2000};
 
-#define PLAYBACK_NUM_PERIODS	8
+#define PLAYBACK_MIN_NUM_PERIODS    2
+#define PLAYBACK_MAX_NUM_PERIODS    8
 #define PLAYBACK_MAX_PERIOD_SIZE    12288
-#define PLAYBACK_MIN_PERIOD_SIZE    1024
-#define CAPTURE_NUM_PERIODS	16
-#define CAPTURE_MAX_PERIOD_SIZE 4096
-#define CAPTURE_MIN_PERIOD_SIZE 512
+#define PLAYBACK_MIN_PERIOD_SIZE    128
+#define CAPTURE_MIN_NUM_PERIODS     2
+#define CAPTURE_MAX_NUM_PERIODS     8
+#define CAPTURE_MAX_PERIOD_SIZE     4096
+#define CAPTURE_MIN_PERIOD_SIZE     320
 
 static struct snd_pcm_hardware msm_pcm_hardware_capture = {
 	.info =                 (SNDRV_PCM_INFO_MMAP |
@@ -67,11 +69,12 @@
 	.rate_max =             48000,
 	.channels_min =         1,
 	.channels_max =         4,
-	.buffer_bytes_max =     CAPTURE_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
+	.buffer_bytes_max =     CAPTURE_MAX_NUM_PERIODS *
+				CAPTURE_MAX_PERIOD_SIZE,
 	.period_bytes_min =	CAPTURE_MIN_PERIOD_SIZE,
 	.period_bytes_max =     CAPTURE_MAX_PERIOD_SIZE,
-	.periods_min =          CAPTURE_NUM_PERIODS,
-	.periods_max =          CAPTURE_NUM_PERIODS,
+	.periods_min =          CAPTURE_MIN_NUM_PERIODS,
+	.periods_max =          CAPTURE_MAX_NUM_PERIODS,
 	.fifo_size =            0,
 };
 
@@ -88,11 +91,12 @@
 	.rate_max =             192000,
 	.channels_min =         1,
 	.channels_max =         8,
-	.buffer_bytes_max =     PLAYBACK_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
+	.buffer_bytes_max =     PLAYBACK_MAX_NUM_PERIODS *
+				PLAYBACK_MAX_PERIOD_SIZE,
 	.period_bytes_min =	PLAYBACK_MIN_PERIOD_SIZE,
 	.period_bytes_max =     PLAYBACK_MAX_PERIOD_SIZE,
-	.periods_min =          PLAYBACK_NUM_PERIODS,
-	.periods_max =          PLAYBACK_NUM_PERIODS,
+	.periods_min =          PLAYBACK_MIN_NUM_PERIODS,
+	.periods_max =          PLAYBACK_MAX_NUM_PERIODS,
 	.fifo_size =            0,
 };
 
@@ -102,7 +106,7 @@
 	96000, 192000
 };
 
-static uint32_t in_frame_info[CAPTURE_NUM_PERIODS][2];
+static uint32_t in_frame_info[CAPTURE_MAX_NUM_PERIODS][2];
 
 static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
 	.count = ARRAY_SIZE(supported_sample_rates),
@@ -364,8 +368,8 @@
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		ret = snd_pcm_hw_constraint_minmax(runtime,
 			SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-			PLAYBACK_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE,
-			PLAYBACK_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE);
+			PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE,
+			PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE);
 		if (ret < 0) {
 			pr_err("constraint for buffer bytes min max ret = %d\n",
 									ret);
@@ -375,8 +379,8 @@
 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 		ret = snd_pcm_hw_constraint_minmax(runtime,
 			SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-			CAPTURE_NUM_PERIODS * CAPTURE_MIN_PERIOD_SIZE,
-			CAPTURE_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE);
+			CAPTURE_MIN_NUM_PERIODS * CAPTURE_MIN_PERIOD_SIZE,
+			CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE);
 		if (ret < 0) {
 			pr_err("constraint for buffer bytes min max ret = %d\n",
 									ret);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 4fd90f9..97803b3 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -2249,6 +2249,9 @@
 	SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
 };
 
 static const struct snd_kcontrol_new sec_auxpcm_rx_port_mixer_controls[] = {
@@ -2258,6 +2261,9 @@
 	SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
 	MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
 };
 
 static const struct snd_kcontrol_new sbus_1_rx_port_mixer_controls[] = {
@@ -3384,8 +3390,10 @@
 
 	{"AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
 	{"AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+	{"AUXPCM_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
 	{"AUX_PCM_RX", NULL, "AUXPCM_RX Port Mixer"},
 
+	{"SEC_AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
 	{"SEC_AUXPCM_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
 	{"SEC_AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"SEC_AUX_PCM_RX", NULL, "SEC_AUXPCM_RX Port Mixer"},
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index bdb0e13..a6ae357 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -1313,7 +1313,6 @@
 {
 	struct  avs_cmd_shared_mem_unmap_regions unmap_regions;
 	int     ret = 0;
-	int     cmd_size = 0;
 	int     index = 0;
 
 	pr_debug("%s\n", __func__);
@@ -1334,14 +1333,14 @@
 	unmap_regions.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
 							APR_PKT_VER);
-	unmap_regions.hdr.pkt_size = cmd_size;
+	unmap_regions.hdr.pkt_size = sizeof(unmap_regions);
 	unmap_regions.hdr.src_port = 0;
 	unmap_regions.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
 	unmap_regions.hdr.token = port_id;
 	unmap_regions.hdr.opcode = ADM_CMD_SHARED_MEM_UNMAP_REGIONS;
 	unmap_regions.mem_map_handle = atomic_read(&this_adm.
 		mem_map_cal_handles[atomic_read(&this_adm.mem_map_cal_index)]);
-	atomic_set(&this_adm.copp_stat[0], 0);
+	atomic_set(&this_adm.copp_stat[index], 0);
 	ret = apr_send_pkt(this_adm.apr, (uint32_t *) &unmap_regions);
 	if (ret < 0) {
 		pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
@@ -1351,11 +1350,16 @@
 	}
 
 	ret = wait_event_timeout(this_adm.wait[index],
-			atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
+				 atomic_read(&this_adm.copp_stat[index]),
+				 5 * HZ);
 	if (!ret) {
-		pr_err("%s: timeout. waited for memory_unmap\n", __func__);
+		pr_err("%s: timeout. waited for memory_unmap index %d\n",
+		       __func__, index);
 		ret = -EINVAL;
 		goto fail_cmd;
+	} else {
+		pr_debug("%s: Unmap handle 0x%x succeeded\n", __func__,
+			 unmap_regions.mem_map_handle);
 	}
 fail_cmd:
 	return ret;
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 46d208b..c65222b 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -30,6 +30,7 @@
 #include <linux/time.h>
 #include <linux/atomic.h>
 #include <linux/msm_audio_ion.h>
+#include <linux/mm.h>
 
 #include <asm/ioctls.h>
 
@@ -761,6 +762,7 @@
 	int rc = 0;
 	struct audio_buffer *buf;
 	int len;
+	int bytes_to_alloc;
 
 	if (!(ac) || ((dir != IN) && (dir != OUT)))
 		return -EINVAL;
@@ -787,8 +789,13 @@
 
 	ac->port[dir].buf = buf;
 
+	bytes_to_alloc = bufsz * bufcnt;
+
+	/* The size to allocate should be multiple of 4K bytes */
+	bytes_to_alloc = PAGE_ALIGN(bytes_to_alloc);
+
 	rc = msm_audio_ion_alloc("audio_client", &buf[0].client, &buf[0].handle,
-		bufsz*bufcnt,
+		bytes_to_alloc,
 		(ion_phys_addr_t *)&buf[0].phys, (size_t *)&len,
 		&buf[0].data);
 	if (rc) {
@@ -2721,6 +2728,11 @@
 	bufcnt_t = (is_contiguous) ? 1 : bufcnt;
 	bufsz_t = (is_contiguous) ? (bufsz * bufcnt) : bufsz;
 
+	if (is_contiguous) {
+		/* The size to memory map should be multiple of 4K bytes */
+		bufsz_t = PAGE_ALIGN(bufsz_t);
+	}
+
 	cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions)
 			+ (sizeof(struct avs_shared_map_region_payload)
 							* bufcnt_t);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 2fabca1..87bee75 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -2761,6 +2761,12 @@
 	/* reset LCH mode */
 	v->lch_mode = 0;
 
+	/* clear mute setting */
+	v->dev_rx.dev_mute =  common.default_mute_val;
+	v->dev_tx.dev_mute =  common.default_mute_val;
+	v->stream_rx.stream_mute = common.default_mute_val;
+	v->stream_tx.stream_mute = common.default_mute_val;
+
 	/* detach VOCPROC and wait for response from mvm */
 	mvm_d_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
@@ -4182,6 +4188,15 @@
 			pr_err("setup voice failed\n");
 			goto fail;
 		}
+
+		ret = voice_send_vol_index_cmd(v);
+		if (ret < 0)
+			pr_err("voice volume failed\n");
+
+		ret = voice_send_stream_mute_cmd(v);
+		if (ret < 0)
+			pr_err("voice mute failed\n");
+
 		ret = voice_send_start_voice_cmd(v);
 		if (ret < 0) {
 			pr_err("start voice failed\n");
@@ -4891,7 +4906,7 @@
 	memset(&common, 0, sizeof(struct common_data));
 
 	/* set default value */
-	common.default_mute_val = 1;  /* default is mute */
+	common.default_mute_val = 0;  /* default is un-mute */
 	common.default_vol_val = 0;
 	common.default_sample_val = 8000;
 
@@ -4907,8 +4922,8 @@
 
 		/* initialize dev_rx and dev_tx */
 		common.voice[i].dev_rx.volume = common.default_vol_val;
-		common.voice[i].dev_rx.dev_mute =  0;
-		common.voice[i].dev_tx.dev_mute =  0;
+		common.voice[i].dev_rx.dev_mute =  common.default_mute_val;
+		common.voice[i].dev_tx.dev_mute =  common.default_mute_val;
 		common.voice[i].stream_rx.stream_mute = common.default_mute_val;
 		common.voice[i].stream_tx.stream_mute = common.default_mute_val;