Merge "ASoC: msm: qdsp6v2: Fix for invalid mem handle after ADSP SSR"
diff --git a/Documentation/arm/msm/msm_ipc_logging.txt b/Documentation/arm/msm/msm_ipc_logging.txt
new file mode 100644
index 0000000..cb330b0
--- /dev/null
+++ b/Documentation/arm/msm/msm_ipc_logging.txt
@@ -0,0 +1,323 @@
+Introduction
+============
+
+This module will be used to log the events by any module/driver which
+enables Inter Processor Communication (IPC). Some of the IPC drivers such
+as Message Routers, Multiplexers etc. which act as a passive pipe need
+some mechanism to log their events. Since all such IPC drivers handle a
+large amount of traffic/events, using kernel logs renders kernel logs
+unusable by other drivers and also degrades the performance of IPC
+drivers. This new module will help in logging such high frequency IPC
+driver events while keeping the standard kernel logging mechanism
+intact.
+
+Hardware description
+====================
+
+This module does not drive any hardware resource and will only use the
+kernel memory-space to log the events.
+
+Software description
+====================
+
+Design Goals
+------------
+This module is designed to
+	* support logging for drivers handling large amount of
+	  traffic/events
+	* define & differentiate events/logs from different drivers
+	* support both id-based and stream-based logging
+	* support extracting the logs from both live target & memory dump
+
+IPC Log Context
+----------------
+
+This module will support logging by multiple drivers. To differentiate
+between the multiple drivers that are using this logging mechanism, each
+driver will be assigned a unique context by this module. Associated with
+each context is the logging space, dynamically allocated from the kernel
+memory-space, specific to that context so that the events logged using that
+context will not interfere with other contexts.
+
+Event Logging
+--------------
+
+Every event will be logged as a <Type: Size: Value> combination. Type
+field identifies the type of the event that is logged. Size field represents
+the size of the log information. Value field represents the actual
+information being logged. This approach will support both id-based logging
+and stream-based logging. This approach will also support logging sub-events
+of an event. This module will provide helper routines to encode/decode the
+logs to/from this format.
+
+Encode Context
+---------------
+
+Encode context is a temporary storage space that will be used by the client
+drivers to log the events in <Type: Size: Value> format. The client drivers
+will perform an encode start operation to initialize the encode context
+data structure. Then the client drivers will log their events into the
+encode context. Upon completion of event logging, the client drivers will
+perform an encode end operation to finalize the encode context data
+structure to be logged. Then this updated encode context data structure
+will be written into the client driver's IPC Log Context. The maximum
+event log size will be defined as 256 bytes.
+
+Log Space
+----------
+
+Each context will have an associated log space, which is dynamically
+allocated from the kernel memory-space. The log space is organized as a
+list of kernel memory pages. Each page contains header information which
+is used to differentiate the log kernel page from the other kernel pages.
+
+	      0 ---------------------------------
+		|     magic_no = 0x52784425     |
+		---------------------------------
+		|    nmagic_no = 0xAD87BBDA     |
+		---------------------------------
+		|            log_id             |
+                ---------------------------------
+		|           page_num            |
+		---------------------------------
+		|  read_offset  | write_offset  |
+		---------------------------------
+		|        next/prev page         |
+		---------------------------------
+		|				|
+		|             Data		|
+		|		.		|
+		|		.		|
+		|		.		|
+		|				|
+		--------------------------------- PAGE_SIZE - 1
+
+This approach will support extracting the logs either from the memory dumps
+or from the live targets using DEBUGFS.
+
+Design
+======
+
+Alternate solutions discussed include using kernel & SMEM logs which are
+limited in size and hence using them render them unusable by other drivers.
+Also kernel logging into serial console is slowing down the performance of
+the drivers by multiple times and sometimes lead to APPs watchdog bite.
+
+Power Management
+================
+
+Not-Applicable
+
+SMP/multi-core
+==============
+
+This module uses spinlocks & mutexes to handle multi-core safety.
+
+Security
+========
+
+Not-Applicable
+
+Performance
+===========
+
+This logging mechanism, based on experimental data, is not expected to
+cause a significant performance degradation. Under worst case, it can
+cause 1 - 2 percent degradation in the throughput of the IPC Drivers.
+
+Interface
+=========
+
+Exported Data Structures
+------------------------
+struct encode_context {
+	struct tsv_header hdr;
+	char buff[MAX_MSG_SIZE];
+	int offset;
+};
+
+struct decode_context {
+	int output_format;
+	char *buff;
+	int size;
+};
+
+Kernel-Space Interface APIs
+----------------------------
+/*
+ * ipc_log_context_create: Create a ipc log context
+ *
+ * @max_num_pages: Number of pages of logging space required (max. 10)
+ * @mod_name     : Name of the directory entry under DEBUGFS
+ *
+ * returns reference to context on success, NULL on failure
+ */
+void * ipc_log_context_create(int max_num_pages,
+			      const char *mod_name);
+
+/*
+ * msg_encode_start: Start encoding a log message
+ *
+ * @ectxt: Temporary storage to hold the encoded message
+ * @type:  Root event type defined by the module which is logging
+ */
+void msg_encode_start(struct encode_context *ectxt, uint32_t type);
+
+/*
+ * msg_encode_end: Complete the message encode process
+ *
+ * @ectxt: Temporary storage which holds the encoded message
+ */
+void msg_encode_end(struct encode_context *ectxt);
+
+/*
+ * tsv_timestamp_write: Writes the current timestamp count
+ *
+ * @ectxt: Context initialized by calling msg_encode_start()
+ *
+ * Returns 0 on success, -ve error code on failure
+ */
+int tsv_timestamp_write(struct encode_context *ectxt);
+
+/*
+ * tsv_pointer_write: Writes a data pointer
+ *
+ * @ectxt:   Context initialized by calling msg_encode_start()
+ * @pointer: Pointer value to write
+ *
+ * Returns 0 on success, -ve error code on failure
+ */
+int tsv_pointer_write(struct encode_context *ectxt, void *pointer);
+
+/*
+ * tsv_int32_write: Writes a 32-bit integer value
+ *
+ * @ectxt: Context initialized by calling msg_encode_start()
+ * @n:     Integer to write
+ *
+ * Returns 0 on success, -ve error code on failure
+ */
+int tsv_int32_write(struct encode_context *ectxt, int32_t n);
+
+/*
+ * tsv_byte_array_write: Writes a byte array
+ *
+ * @ectxt: Context initialized by calling msg_encode_start()
+ * @data:  Location of data
+ * @data_size: Size of data to be written
+ *
+ * Returns 0 on success, -ve error code on failure
+ */
+int tsv_byte_array_write(struct encode_context *ectxt,
+			  void *data, int data_size);
+
+/*
+ * ipc_log_write: Write the encoded message into the log space
+ *
+ * @ctxt: IPC log context where the message has to be logged into
+ * @ectxt: Temporary storage containing the encoded message
+ */
+void ipc_log_write(unsigned long ctxt, struct encode_context *ectxt);
+
+/*
+ * ipc_log_string: Helper function to log a string
+ *
+ * @dlctxt: IPC Log Context created using ipc_log_context_create()
+ * @fmt:    Data specified using format specifiers
+ */
+int ipc_log_string(unsigned long dlctxt, const char *fmt, ...);
+
+/*
+ * tsv_timestamp_read: Reads a timestamp
+ *
+ * @ectxt:  Context retrieved by reading from log space
+ * @dctxt:  Temporary storage to hold the decoded message
+ * @format: Output format while dumping through DEBUGFS
+ */
+void tsv_timestamp_read(struct encode_context *ectxt,
+			struct decode_context *dctxt, const char *format);
+
+/*
+ * tsv_pointer_read: Reads a data pointer
+ *
+ * @ectxt:  Context retrieved by reading from log space
+ * @dctxt:  Temporary storage to hold the decoded message
+ * @format: Output format while dumping through DEBUGFS
+ */
+void tsv_pointer_read(struct encode_context *ectxt,
+		      struct decode_context *dctxt, const char *format);
+
+/*
+ * tsv_int32_read: Reads a 32-bit integer value
+ *
+ * @ectxt:  Context retrieved by reading from log space
+ * @dctxt:  Temporary storage to hold the decoded message
+ * @format: Output format while dumping through DEBUGFS
+ */
+void tsv_int32_read(struct encode_context *ectxt,
+		    struct decode_context *dctxt, const char *format);
+
+/*
+ * tsv_byte_array_read: Reads a byte array/string
+ *
+ * @ectxt:  Context retrieved by reading from log space
+ * @dctxt:  Temporary storage to hold the decoded message
+ * @format: Output format while dumping through DEBUGFS
+ */
+void tsv_byte_array_read(struct encode_context *ectxt,
+			 struct decode_context *dctxt, const char *format);
+
+/*
+ * add_deserialization_func: Register a deserialization function to
+ *                           to unpack the subevents of a main event
+ *
+ * @ctxt: IPC log context to which the deserialization function has
+ *        to be registered
+ * @type: Main/Root event, defined by the module which is logging, to
+ *        which this deserialization function has to be registered.
+ * @dfune: Deserialization function to be registered
+ *
+ * return 0 on success, -ve value on FAILURE
+ */
+int add_deserialization_func(unsigned long ctxt, int type,
+			void (*dfunc)(struct encode_context *,
+				      struct decode_context *));
+
+Driver parameters
+=================
+
+Not-Applicable
+
+Config options
+==============
+
+Not-Applicable
+
+Dependencies
+============
+
+This module will partially depend on CONFIG_DEBUGFS, in order to dump the
+logs through debugfs. If CONFIG_DEBUGFS is disabled, the above mentioned
+helper functions will perform no operation and return appropriate error
+code if the return value is non void. Under such circumstances the logs can
+only be extracted through the memory dump.
+
+User space utilities
+====================
+
+DEBUGFS
+
+Other
+=====
+
+Not-Applicable
+
+Known issues
+============
+
+None
+
+To do
+=====
+
+None
diff --git a/Documentation/devicetree/bindings/arm/msm/board-id.txt b/Documentation/devicetree/bindings/arm/msm/board-id.txt
new file mode 100644
index 0000000..c29a2d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/board-id.txt
@@ -0,0 +1,18 @@
+* BOARD-ID
+
+The qcom,board-id entry specifies the MSM platform and subtype revision.
+It can optionally be an array of these to indicate multiple hardware that use
+the same device tree.  It is expected that the bootloader will use this
+information at boot-up to decide which device tree to use when given multiple
+device trees, some of which may not be compatible with the actual hardware.  It
+is the bootloader's responsibility to pass the correct device tree to the kernel.
+
+Format:
+
+It is expected that the qcom,board-id entry be at the top level of the device
+tree structure.  The format of the entry is:
+
+   qcom,board-id = <platform_id, subtype_id> [, <p2, s2> ...]
+
+Example:
+   qcom,board-id = <15 0>;
diff --git a/Documentation/devicetree/bindings/arm/msm/jtag-fuse.txt b/Documentation/devicetree/bindings/arm/msm/jtag-fuse.txt
new file mode 100644
index 0000000..617d2ba
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/jtag-fuse.txt
@@ -0,0 +1,18 @@
+* JTAG-FUSE
+
+The jtag-fuse entry specifies the memory mapped addresses for the fuse
+registers. The jtag-fuse driver uses these to provide api(s) that can be used
+by jtag save and restore driver(s) to query whether the Hardware they manage
+is functionally disabled or not and take corresponding steps.
+
+Required Properties:
+compatible: component name used for driver matching, should be "qcom,jtag-fuse"
+reg: physical base address and length of the register set
+reg-names: should be "fuse-base"
+
+Example:
+	jtag_fuse: jtagfuse@fc4be024 {
+		compatible = "qcom,jtag-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/msm-id.txt b/Documentation/devicetree/bindings/arm/msm/msm-id.txt
index b8c71d76..b2da59f 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm-id.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm-id.txt
@@ -10,9 +10,16 @@
 Format:
 
 It is expected that the qcom,msm-id entry be at the top level of the device
-tree structure.  The format of the entry is:
+tree structure.  The format can take one of the two forms below:
 
    qcom,msm-id = <chipset_id, platform_id, rev_id> [, <c2, p2, r2> ...]
+   qcom,msm-id = <chipset_id, rev_id> [, <c2, r2> ...]
+
+If the second format is used one must also define the board-id.
 
 Example:
    qcom,msm-id = <126 15 0>;
+
+   qcom,board-id= <15 2>;
+   qcom,msm-id = <126 0>;
+
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
index 8d1d46d..d24e671 100644
--- a/Documentation/devicetree/bindings/coresight/coresight.txt
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -21,6 +21,7 @@
 	"qcom,coresight-csr" for coresight csr device,
 	"arm,coresight-cti" for coresight cti devices,
 	"qcom,coresight-hwevent" for coresight hardware event devices
+	"arm,coresight-fuse" for coresight fuse device,
 - reg : physical base address and length of the register set(s) of the component
 - reg-names : names corresponding to each reg property value. The reg-names that
 	need to be used with corresponding compatible string for a coresight device
@@ -68,6 +69,10 @@
 			"<ss-mux>" - physical base address of hardware event mux
 				control registers where <ss-mux> is subsystem mux it
 				represents
+	- for coresight fuse device:
+		compatible : should be "arm,coresight-fuse"
+		reg-names  : should be:
+			"fuse-base" - physical base address of fuse registers
 - coresight-id : unique integer identifier for the component
 - coresight-name : unique descriptive name of the component
 - coresight-nr-inports : number of input ports on the component
@@ -236,3 +241,13 @@
 
 		qcom,hwevent-clks = "core_mmss_clk";
 	};
+
+	fuse: fuse@fc4be024 {
+		compatible = "arm,coresight-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+
+		coresight-id = <30>;
+		coresight-name = "coresight-fuse";
+		coresight-nr-inports = <0>;
+	};
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 9bc949e..514160e 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -123,7 +123,9 @@
 				offsets as well (i.e. the first mixer offset
 				corresponds to the same pathway as the first
 				AD offset).
-
+- qcom,mdss-has-wfd-blk: Boolean property to indicate the presence of dedicated
+			writeback wfd block in MDSS as opposed to writeback
+			block that is shared between rotator and wfd.
 Optional subnodes:
 Child nodes representing the frame buffer virtual devices.
 
@@ -161,6 +163,7 @@
 		qcom,mdss-rot-block-size = <64>;
 		qcom,mdss-has-bwc;
 		qcom,mdss-has-decimation;
+		qcom,mdss-has-wfd-blk;
 
 		qcom,mdss-ctl-off = <0x00000600 0x00000700 0x00000800
 				     0x00000900 0x0000A00>;
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt b/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt
index 26a119c..9d3ee39 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt
@@ -54,6 +54,10 @@
   qcom,iommu-bfb-regs property. If this property is present, the
   qcom,iommu-bfb-regs property shall also be present, and the lengths of both
   properties shall be the same.
+- qcom,iommu-lpae-bfb-regs : See description for qcom,iommu-bfb-regs. This is
+  the same property except this is for IOMMU with LPAE support.
+- qcom,iommu-lpae-bfb-data : See description for qcom,iommu-bfb-data. This is
+  the same property except this is for IOMMU with LPAE support.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/leds/leds-msm-gpio-flash.txt b/Documentation/devicetree/bindings/leds/leds-msm-gpio-flash.txt
new file mode 100644
index 0000000..ddbfd5a
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-msm-gpio-flash.txt
@@ -0,0 +1,30 @@
+Qualcomm GPIO Flash Leds
+
+Qualcomm GPIO flash LEDs driver is used for
+controlling flash LEDs that are connected with 2 GPIOs.  The 2 GPIOs are name
+flash_en and flash now.
+
+
+The flash LEDs has torch mode and flash mode. The flash mode is used for camera.
+The torch mode is used for torch.
+
+
+Required properties for each node:
+- compatible		: should be "qcom,leds-gpio-flash"
+- qcom,flash-en		: the GPIO pin number of flash-en function
+- qcom,flash-now	: the GPIO pin number of flash-now function
+- linux,name		: name of the led that is used in led framework
+- linux,default-trigger	: name of the led trigger event
+
+No other optional properties for it.
+
+Example:
+
+	flashlight {
+		compatible = "leds-gpio-flash";
+		status = "okay";
+		qcom,flash-en = <&msmgpio 18 0>;
+		qcom,flash-now = <&msmgpio 19 0>;
+		linux,name = "flashlight";
+		linux,default-trigger = "flashlight-trigger";
+	};
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 6e125f2..66949af 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -65,6 +65,15 @@
 					detection, "bpd_thm_id" selects both.
 					If the property is not set, the temperatue pin will
 					be used.
+- qcom,btc-disabled:			If flag is set battery hot and cold monitoring is
+					disabled in hardware. This monitoring is turned on
+					by default.
+- qcom,batt-hot-percent:		Specify a supported hot threshold percentage.
+					Supported thresholds: 25% and 35%. If none is specified
+					hardware defaults will be used.
+- qcom,batt-cold-percent:		Specify a supported cold threshold percentage.
+					Supported thresholds: 70% and 80%. If none is specified
+					hardware defaults will be used.
 - otg-parent-supply			Specify a phandle to a parent supply regulator
 					for the OTG regulator.
 - boost-parent-supply			Specify a phandle to a parent supply regulator
@@ -182,6 +191,9 @@
 		qcom,warm-bat-mv = <4100>;
 		qcom,ibatmax-cool-ma = <350>;
 		qcom,vbatdet-delta-mv = <60>;
+		qcom,batt-hot-percent = <25>;
+		qcom,batt-cold-percent = <85>;
+		qcom,btc-disabled = <0>;
 
 		qcom,chgr@1000 {
 			reg = <0x1000 0x100>;
diff --git a/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt b/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
index 6b090fa..64f2ddd 100644
--- a/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
+++ b/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
@@ -44,6 +44,17 @@
  - qcom,rxreg-access: This boolean indicates that slimbus RX should use direct
 		 register access to receive data. This flag is only needed if
 		 BAM pipe is not available to receive data from slimbus
+ - qcom,apps-ch-pipes: This value represents BAM pipe-mask used by application
+		 processor for data channels. If this property is not defined,
+		 default mask of 0x3F000000 is used indicating apps can use 6
+		 pipes from 24-29.
+ - qcom,ea-pc: This value represents product code (PC) field of enumeration
+		 address (EA) for the Qualcomm slimbus controller hardware.
+		 This value is needed if data-channels originating from apps
+		 are to be used, so that application processor can query
+		 logical address of the ported generic device to be used.
+		 Other than PC, fields of EA are same across platforms.
+
 Example:
 	slim@fe12f000 {
 		cell-index = <1>;
@@ -55,4 +66,6 @@
 		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
 		qcom,min-clk-gear = <10>;
 		qcom,rxreg-access;
+		qcom,apps-ch-pipes = <0x60000000>;
+		qcom,ea-pc = <0x30>;
 	};
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 4c6569e..c799ffb 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -131,15 +131,9 @@
 
 * msm-auxpcm
 
-[First Level Nodes]
-
 Required properties:
 
- - compatible :                           "qcom,msm-auxpcm-resource"
-
- - qcom,msm-cpudai-auxpcm-clk:            clock for auxpcm. The first value is
-                                          for 8khz mode, the second is for
-                                          16khz
+ - compatible :                           "qcom,msm-auxpcm-dev"
 
  - qcom,msm-cpudai-auxpcm-mode:           mode information. The first value is
                                           for 8khz mode, the second is for
@@ -174,16 +168,10 @@
                                           first value is for 8khz mode, the
                                           second is for auxpcm
 
-[Second Level Nodes]
-
-Required Properties:
-
- - qcom,msm-auxpcm-dev-id:                This property specifies the device
-                                          port id.
-                                          For Rx device, the port id is 4106
-                                          and for Tx device, the port id is 4107
-
- - compatible:                            "qcom,msm-auxpcm-dev"
+ - qcom,msm-auxpcm-interface:             name of AUXPCM interface "primary"
+                                          indicates primary AUXPCM interface
+                                          "secondary" indicates secondary
+                                          AUXPCM interface
 
 * msm-pcm-hostless
 
@@ -378,37 +366,17 @@
 		};
 	};
 
-        qcom,msm-auxpcm {
-                compatible = "qcom,msm-auxpcm-resource";
-                qcom,msm-cpudai-auxpcm-clk = "pcm_clk";
-                qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
-                qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
-                qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
-                qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
-                qcom,msm-cpudai-auxpcm-slot = <1>, <1>;
-                qcom,msm-cpudai-auxpcm-data = <0>, <0>;
-                qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
-
-                qcom,msm-prim-auxpcm-rx {
-                        qcom,msm-auxpcm-dev-id = <4106>;
-                        compatible = "qcom,msm-auxpcm-dev";
-                };
-
-                qcom,msm-prim-auxpcm-tx {
-                        qcom,msm-auxpcm-dev-id = <4107>;
-                        compatible = "qcom,msm-auxpcm-dev";
-                };
-
-		qcom,msm-sec-auxpcm-rx {
-			qcom,msm-auxpcm-dev-id = <4108>;
-			compatible = "qcom,msm-auxpcm-dev";
-		};
-
-		qcom,msm-sec-auxpcm-tx {
-			qcom,msm-auxpcm-dev-id = <4109>;
-			compatible = "qcom,msm-auxpcm-dev";
-		};
-        };
+	qcom,msm-pri-auxpcm {
+		qcom,msm-cpudai-auxpcm-mode = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+		qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+		qcom,msm-cpudai-auxpcm-slot = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+		qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+		qcom,msm-auxpcm-interface = "primary";
+		compatible = "qcom,msm-auxpcm-dev";
+	};
 
         qcom,msm-pcm-hostless {
                 compatible = "qcom,msm-pcm-hostless";
diff --git a/Documentation/devicetree/bindings/spi/spi_qsd.txt b/Documentation/devicetree/bindings/spi/spi_qsd.txt
index f16bcbc..1504dc0 100644
--- a/Documentation/devicetree/bindings/spi/spi_qsd.txt
+++ b/Documentation/devicetree/bindings/spi/spi_qsd.txt
@@ -17,9 +17,13 @@
 	'spi{n}' where n is the bus number.
 
 Optional properties:
-- gpios : Specifies the gpio pins to be used for SPI CLK, MISO, MOSI in
-  that order.
-- cs-gpios : Specifies the gpio pins to be used for chipselects.
+- qcom,gpio-mosi : GPIO pin number of the MOSI bus line.
+- qcom,gpio-miso : GPIO pin number of the MISO bus line.
+- qcom,gpio-clk  : GPIO pin number of the CLK  bus line.
+- qcom,gpio-cs0  : GPIO pin number of the chipselect0 bus line.
+- qcom,gpio-cs1  : GPIO pin number of the chipselect1 bus line.
+- qcom,gpio-cs2  : GPIO pin number of the chipselect2 bus line.
+- qcom,gpio-cs3  : GPIO pin number of the chipselect3 bus line.
 - qcom,infinite-mode: When missing or set to zero, QUP uses infinite-mode. When
   value is non-zero, the value is the number of words in maximum transfer
   length.
@@ -77,10 +81,10 @@
 		spi-max-frequency = <19200000>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		gpios = <&msmgpio 3 0>, /* CLK  */
-			<&msmgpio 1 0>, /* MISO */
-			<&msmgpio 0 0>; /* MOSI */
-		cs-gpios = <&msmgpio 9 0>;
+		qcom,gpio-mosi = <&msmgpio 0 0>;
+		qcom,gpio-miso = <&msmgpio 1 0>;
+		qcom,gpio-clk  = <&msmgpio 3 0>;
+		qcom,gpio-cs2  = <&msmgpio 9 0>;
 
 		qcom,infinite-mode = <0>;
 		qcom,use-bam;
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
index 96c9486..762d40f 100644
--- a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
@@ -12,6 +12,11 @@
 - interrupt-names :
 	- "core_irq" to be used as uart irq
 	- "bam irq" to be used as bam irq
+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt
+		source. The type shall be a <u32> and the value shall be 1
+- #address-cells: Specifies the number of cells needed to encode an address.
+		The type shall be <u32> and the value shall be 0
+- interrupt-parent = It is needed for interrupt mapping
 - bam-tx-ep-pipe-index : BAM TX Endpoint Pipe Index for HSUART
 - bam-rx-ep-pipe-index : BAM RX Endpoint Pipe Index for HSUART
 
@@ -35,8 +40,13 @@
 		reg = <0xf995d000 0x1000>,
 		      <0xf9944000 0x5000>;
 		reg-names = "core_mem", "bam_mem";
-		interrupts = <0 113 0>, <0 239 0>;
 		interrupt-names = "core_irq", "bam_irq";
+		#address-cells = <0>;
+		interrupt-parent = <&uart7>;
+		interrupts = <0 1>;
+		#interrupt-cells = <1>;
+		interrupt-map = <0 &intc 0 113 0
+				1 &intc 0 239 0>
 		qcom,bam-tx-ep-pipe-index = <0>;
 		qcom,bam-rx-ep-pipe-index = <1>;
 	};
@@ -50,10 +60,10 @@
 case where there is nothing connected and we want to use internal loopback mode
 for uart.
 - qcom, wakeup_irq : UART RX GPIO IRQ line to be configured as wakeup source.
-- qcom,inject_rx_on_wakeup : inject_rx_on_wakeup enables feature where on
+- qcom,inject-rx-on-wakeup : inject_rx_on_wakeup enables feature where on
 receiving interrupt with UART RX GPIO IRQ line (i.e. above wakeup_irq property),
 HSUART driver injects provided character with property rx_to_inject.
-- qcom, rx_to_inject : The character to be inserted on wakeup.
+- qcom, rx-char-to-inject : The character to be inserted on wakeup.
 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
 below optional properties:
     - qcom,msm_bus,name
@@ -80,13 +90,21 @@
 		reg = <0x19c40000 0x1000">,
 		      <0xf9944000 0x5000>;
 		reg-names = "core_mem", "bam_mem";
-		interrupts = <0 113 0>, <0 239 0>;
-		interrupt-names = "core_irq", "bam_irq";
-
+		interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+		#address-cells = <0>;
+		interrupt-parent = <&uart7>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 113 0
+				1 &intc 0 239 0
+				2 &msmgpio 42 0>;
 		qcom,tx-gpio = <&msmgpio 41 0x00>;
 		qcom,rx-gpio = <&msmgpio 42 0x00>;
 		qcom,cts-gpio = <&msmgpio 43 0x00>;
 		qcom,rfr-gpio = <&msmgpio 44 0x00>;
+		qcom,inject-rx-on-wakeup = <1>;
+		qcom,rx-char-to-inject = <0xFD>;
 
 		qcom,bam-tx-ep-pipe-index = <0>;
 		qcom,bam-rx-ep-pipe-index = <1>;
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 70bf993..e724c62 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -65,6 +65,14 @@
   5 (2^5 = 32)   32 micro frame interrupt threshold aka 4ms interrupt threshold
   6 (2^6 = 64)   64 micro frame interrupt threshold aka 8ms interrupt threshold
 
+- hsic,disable-cerr: CERR is 2bit down error counter that keeps track of number
+  of consecutive errors detected on single usb transaction. When set to non
+  zero value, hw decrements the count and updates qTD when transaction fails.
+  If counter reaches zero, hw marks the qTD inactive and triggers the interrupt.
+  When CERR is programmed to zero, hw ignores transaction failures. ECHI stack
+  programs the CERR  to 3 by default. When this flag is true, CERR is set to
+  zero and transaction errors are ignored.
+
 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
   below optional properties:
     - qcom,msm_bus,name
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index ac314ea..f687e77 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -81,6 +81,7 @@
 	interrupt threshold (ITC), when log2_itc is between 1 to 7.
 - qcom,hsusb-l1-supported: If present, the device supports l1 (Link power
 	management).
+- qcom,no-selective-suspend: If present selective suspend is disabled on hub ports.
 
 Example HSUSB OTG controller device node :
 	usb@f9690000 {
@@ -128,6 +129,9 @@
 
 Optional properties :
 - qcom,usb2-enable-hsphy2: If present, select second PHY for USB operation.
+- qcom,resume-gpio: if present then peripheral connected to usb controller
+  cannot wakeup from XO shutdown using in-band usb bus resume. Use resume
+  gpio to wakeup peripheral.
 
 Example MSM HSUSB EHCI controller device node :
 	ehci: qcom,ehci-host@f9a55000 {
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index 282257c..ff7b03d 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -47,6 +47,8 @@
 		bits 20-25 PARAMETER_OVERRIDE_D
 - qcom,skip-charger-detection: If present then charger detection using BC1.2
   is not supported and attached host should always be assumed as SDP.
+- USB3_GDSC-supply : phandle to the globally distributed switch controller
+  regulator node to the USB controller.
 
 Sub nodes:
 - Sub node for "DWC3- USB3 controller".
@@ -66,6 +68,7 @@
 		HSUSB_1p8-supply = <&pm8941_l6>;
 		HSUSB_3p3-supply = <&pm8941_l24>;
 		vbus_dwc3-supply = <&pm8941_mvs1>;
+		USB3_GDSC-supply = <&gdsc_usb30>;
 		qcom,dwc-usb3-msm-dbm-eps = <4>
 		qcom,vdd-voltage-level = <1 5 7>;
 		qcom,dwc-hsphy-init = <0x00D195A4>;
diff --git a/arch/arm/boot/dts/apq8026-mtp.dts b/arch/arm/boot/dts/apq8026-v1-mtp.dts
similarity index 95%
rename from arch/arm/boot/dts/apq8026-mtp.dts
rename to arch/arm/boot/dts/apq8026-v1-mtp.dts
index e14a6856..b89c676 100644
--- a/arch/arm/boot/dts/apq8026-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v1-mtp.dts
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "apq8026.dtsi"
+/include/ "apq8026-v1.dtsi"
 /include/ "msm8226-mtp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/apq8026-xpm.dts b/arch/arm/boot/dts/apq8026-v1-xpm.dts
similarity index 95%
rename from arch/arm/boot/dts/apq8026-xpm.dts
rename to arch/arm/boot/dts/apq8026-v1-xpm.dts
index 67152af..8c97823 100644
--- a/arch/arm/boot/dts/apq8026-xpm.dts
+++ b/arch/arm/boot/dts/apq8026-v1-xpm.dts
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "apq8026.dtsi"
+/include/ "apq8026-v1.dtsi"
 /include/ "msm8226-cdp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/apq8026.dtsi b/arch/arm/boot/dts/apq8026-v1.dtsi
similarity index 96%
rename from arch/arm/boot/dts/apq8026.dtsi
rename to arch/arm/boot/dts/apq8026-v1.dtsi
index db6576a..f15a96f 100644
--- a/arch/arm/boot/dts/apq8026.dtsi
+++ b/arch/arm/boot/dts/apq8026-v1.dtsi
@@ -16,7 +16,7 @@
  * file.
  */
 
-/include/ "msm8226.dtsi"
+/include/ "msm8226-v1.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026";
diff --git a/arch/arm/boot/dts/apq8026-mtp.dts b/arch/arm/boot/dts/apq8026-v2-mtp.dts
similarity index 86%
copy from arch/arm/boot/dts/apq8026-mtp.dts
copy to arch/arm/boot/dts/apq8026-v2-mtp.dts
index e14a6856..c6b7f2a 100644
--- a/arch/arm/boot/dts/apq8026-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v2-mtp.dts
@@ -12,11 +12,11 @@
 
 
 /dts-v1/;
-/include/ "apq8026.dtsi"
+/include/ "apq8026-v2.dtsi"
 /include/ "msm8226-mtp.dtsi"
 
 / {
-	model = "Qualcomm APQ 8026 MTP";
+	model = "Qualcomm APQ 8026v2 MTP";
 	compatible = "qcom,apq8026-mtp", "qcom,apq8026", "qcom,mtp";
-	qcom,msm-id = <199 8 0>;
+	qcom,msm-id = <199 8 0x20000>;
 };
diff --git a/arch/arm/boot/dts/apq8026-xpm.dts b/arch/arm/boot/dts/apq8026-v2-xpm.dts
similarity index 86%
copy from arch/arm/boot/dts/apq8026-xpm.dts
copy to arch/arm/boot/dts/apq8026-v2-xpm.dts
index 67152af..42acd98 100644
--- a/arch/arm/boot/dts/apq8026-xpm.dts
+++ b/arch/arm/boot/dts/apq8026-v2-xpm.dts
@@ -12,11 +12,11 @@
 
 
 /dts-v1/;
-/include/ "apq8026.dtsi"
+/include/ "apq8026-v2.dtsi"
 /include/ "msm8226-cdp.dtsi"
 
 / {
-	model = "Qualcomm APQ 8026 XPM";
+	model = "Qualcomm APQ 8026v2 XPM";
 	compatible = "qcom,apq8026-xpm", "qcom,apq8026", "qcom,xpm";
-	qcom,msm-id = <199 14 0>;
+	qcom,msm-id = <199 14 0x20000>;
 };
diff --git a/arch/arm/boot/dts/apq8026.dtsi b/arch/arm/boot/dts/apq8026-v2.dtsi
similarity index 96%
copy from arch/arm/boot/dts/apq8026.dtsi
copy to arch/arm/boot/dts/apq8026-v2.dtsi
index db6576a..d87b500 100644
--- a/arch/arm/boot/dts/apq8026.dtsi
+++ b/arch/arm/boot/dts/apq8026-v2.dtsi
@@ -16,7 +16,7 @@
  * file.
  */
 
-/include/ "msm8226.dtsi"
+/include/ "msm8226-v2.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026";
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index 4b20e9f..9557663 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -484,6 +484,7 @@
 &pm8941_mpps {
 
 	mpp@a000 { /* MPP 1 */
+		status = "disabled";
 	};
 
 	mpp@a100 { /* MPP 2 */
@@ -524,22 +525,7 @@
 };
 
 &spi_epm {
-	epm-adc@0 {
-		compatible = "cy,epm-adc-cy8c5568lti-114";
-		reg = <0>;
-		interrupt-parent = <&msmgpio>;
-		spi-max-frequency = <960000>;
-		qcom,channels = <31>;
-		qcom,gain = <50 50 50 50 50 100 50 50 50 50
-				50 50 50 50 100 50 50 50 50 100
-				50 50 50 100 50 50 50 1 1 1
-				1>;
-		qcom,rsense = <40 10 10 25 10 1000 75 25 10 25
-				33 500 200 10 500 100 33 200 25 100
-				75 500 50 200 5 5 3 1 1 1
-				1>;
-		qcom,channel-type = <0xf0000000>;
-	};
+	status = "disabled";
 };
 
 &spmi_bus {
diff --git a/arch/arm/boot/dts/apq8074-v2-liquid.dts b/arch/arm/boot/dts/apq8074-v2-liquid.dts
index 4ec1cdd..a0ecb50 100644
--- a/arch/arm/boot/dts/apq8074-v2-liquid.dts
+++ b/arch/arm/boot/dts/apq8074-v2-liquid.dts
@@ -20,15 +20,3 @@
 	compatible = "qcom,apq8074-liquid", "qcom,apq8074", "qcom,liquid";
 	qcom,msm-id = <184 9 0x20000>;
 };
-
-&usb3 {
-	interrupt-parent = <&usb3>;
-	interrupts = <0 1>;
-	#interrupt-cells = <1>;
-	interrupt-map-mask = <0x0 0xffffffff>;
-	interrupt-map = <0x0 0 &intc 0 133 0
-			0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
-	interrupt-names = "hs_phy_irq", "pmic_id_irq";
-
-	qcom,misc-ref = <&pm8941_misc>;
-};
diff --git a/arch/arm/boot/dts/apq8084-coresight.dtsi b/arch/arm/boot/dts/apq8084-coresight.dtsi
new file mode 100644
index 0000000..610d80b
--- /dev/null
+++ b/arch/arm/boot/dts/apq8084-coresight.dtsi
@@ -0,0 +1,145 @@
+/* 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 {
+	tmc_etr: tmc@fc326000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0xfc326000 0x1000>,
+		      <0xfc37c000 0x3000>;
+		reg-names = "tmc-base", "bam-base";
+
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+
+		coresight-id = <0>;
+		coresight-name = "coresight-tmc-etr";
+		coresight-nr-inports = <1>;
+	};
+
+	replicator: replicator@fc324000 {
+		compatible = "qcom,coresight-replicator";
+		reg = <0xfc324000 0x1000>;
+		reg-names = "replicator-base";
+
+		coresight-id = <2>;
+		coresight-name = "coresight-replicator";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0>;
+		coresight-child-list = <&tmc_etr>;
+		coresight-child-ports = <0>;
+	};
+
+	tmc_etf: tmc@fc325000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0xfc325000 0x1000>;
+		reg-names = "tmc-base";
+
+		coresight-id = <3>;
+		coresight-name = "coresight-tmc-etf";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0>;
+		coresight-child-list = <&replicator>;
+		coresight-child-ports = <0>;
+		coresight-default-sink;
+	};
+
+	funnel_merg: funnel@fc323000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc323000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <4>;
+		coresight-name = "coresight-funnel-merg";
+		coresight-nr-inports = <2>;
+		coresight-outports = <0>;
+		coresight-child-list = <&tmc_etf>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_in0: funnel@fc321000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc321000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <5>;
+		coresight-name = "coresight-funnel-in0";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_merg>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_in1: funnel@fc322000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc322000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <6>;
+		coresight-name = "coresight-funnel-in1";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_merg>;
+		coresight-child-ports = <1>;
+	};
+
+	funnel_kpss: funnel@fc355000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc355000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <7>;
+		coresight-name = "coresight-funnel-kpss";
+		coresight-nr-inports = <4>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <5>;
+	};
+
+	funnel_mmss: funnel@fc36c000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc36c000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <8>;
+		coresight-name = "coresight-funnel-mmss";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <1>;
+	};
+
+	stm: stm@fc302000 {
+		compatible = "arm,coresight-stm";
+		reg = <0xfc302000 0x1000>,
+		      <0xfa280000 0x180000>;
+		reg-names = "stm-base", "stm-data-base";
+
+		coresight-id = <9>;
+		coresight-name = "coresight-stm";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <7>;
+	};
+
+	csr: csr@fc301000 {
+		compatible = "qcom,coresight-csr";
+		reg = <0xfc301000 0x1000>;
+		reg-names = "csr-base";
+
+		coresight-id = <14>;
+		coresight-name = "coresight-csr";
+		coresight-nr-inports = <0>;
+
+		qcom,blk-size = <3>;
+	};
+};
diff --git a/arch/arm/boot/dts/apq8084-iommu.dtsi b/arch/arm/boot/dts/apq8084-iommu.dtsi
new file mode 100644
index 0000000..72d2748
--- /dev/null
+++ b/arch/arm/boot/dts/apq8084-iommu.dtsi
@@ -0,0 +1,477 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "msm-iommu-v1.dtsi"
+
+&venus_iommu {
+	status = "ok";
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2514
+				0x2540
+				0x256c
+				0x20ac
+				0x215c
+				0x220c
+				0x22bc
+				0x2314
+				0x2394
+				0x2414
+				0x2494
+				0x2008
+				0x200c
+				0x2010
+				0x2014
+				0x2018
+				0x201c>;
+
+	qcom,iommu-bfb-data =  <0x7ffffff
+				0x4
+				0x8
+				0x0
+				0x13607
+				0x4201
+				0x14221
+				0x0
+				0x0
+				0x94
+				0x114
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0>;
+
+	qcom,iommu-lpae-bfb-regs = <0x204c
+				    0x2514
+				    0x2540
+				    0x256c
+				    0x20ac
+				    0x215c
+				    0x220c
+				    0x22bc
+				    0x2314
+				    0x2394
+				    0x2414
+				    0x2494
+				    0x2008
+				    0x200c
+				    0x2010
+				    0x2014
+				    0x2018
+				    0x201c>;
+
+	qcom,iommu-lpae-bfb-data = <0x7ffffff
+				    0x0
+				    0x4
+				    0x8
+				    0x13607
+				    0x0
+				    0x4201
+				    0x14221
+				    0x0
+				    0x0
+				    0x94
+				    0x114
+				    0x0
+				    0x0
+				    0x0
+				    0x0
+				    0x0
+				    0x0>;
+
+
+	venus_ns: qcom,iommu-ctx@fdc8c000 {
+		qcom,iommu-ctx-sids = <0 1 2 3 4 5 7>;
+	};
+
+	venus_sec_bitstream: qcom,iommu-ctx@fdc8d000 {
+		qcom,iommu-ctx-sids = <0x80 0x81 0x82 0x83 0x84>;
+		label = "venus_sec_bitstream";
+	};
+
+	venus_sec_pixel: qcom,iommu-ctx@fdc8f000 {
+		compatible = "qcom,msm-smmu-v1-ctx";
+		reg = <0xfdc8f000 0x1000>;
+		interrupts = <0 42 0>;
+		qcom,iommu-ctx-sids = <0x85>;
+		label = "venus_sec_pixel";
+		qcom,secure-context;
+	};
+
+	venus_sec_non_pixel: qcom,iommu-ctx@fdc90000 {
+		compatible = "qcom,msm-smmu-v1-ctx";
+		reg = <0xfdc90000 0x1000>;
+		interrupts = <0 42 0>;
+		qcom,iommu-ctx-sids = <0x87 0xA0>;
+		label = "venus_sec_non_pixel";
+		qcom,secure-context;
+	};
+};
+
+&jpeg_iommu {
+	status = "ok";
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2514
+				0x2540
+				0x256c
+				0x2314
+				0x2394
+				0x2414
+				0x2494
+				0x20ac
+				0x215c
+				0x220c
+				0x22bc
+				0x2008
+				0x200c
+				0x2010>;
+
+	qcom,iommu-bfb-data =  <0x3fff
+				0x4
+				0x4
+				0x0
+				0x0
+				0x10
+				0x50
+				0x0
+				0x2000
+				0x2804
+				0x9614
+				0x0
+				0x0
+				0x0
+				0x0>;
+
+	qcom,iommu-lpae-bfb-regs = <0x204c
+				    0x2514
+				    0x2540
+				    0x256c
+				    0x2314
+				    0x2394
+				    0x2414
+				    0x2494
+				    0x20ac
+				    0x215c
+				    0x220c
+				    0x22bc
+				    0x2008
+				    0x200c
+				    0x2010>;
+
+	qcom,iommu-lpae-bfb-data = <0x3fff
+				    0x0
+				    0x4
+				    0x4
+				    0x0
+				    0x0
+				    0x10
+				    0x50
+				    0x2000
+				    0x964b
+				    0x2804
+				    0x9614
+				    0x0
+				    0x0
+				    0x0>;
+
+};
+
+&mdp_iommu {
+	status = "ok";
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2514
+				0x2540
+				0x256c
+				0x20ac
+				0x215c
+				0x220c
+				0x22bc
+				0x2314
+				0x2394
+				0x2414
+				0x2494
+				0x2008
+				0x200c
+				0x2010
+				0x2014
+				0x2018>;
+
+	qcom,iommu-bfb-data =  <0x7fffff
+				0x4
+				0x10
+				0x0
+				0x5000
+				0x5a1d
+				0x1822d
+				0x0
+				0x0
+				0x28
+				0x68
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0>;
+
+	qcom,iommu-lpae-bfb-regs = <0x204c
+				    0x2514
+				    0x2540
+				    0x256c
+				    0x20ac
+				    0x215c
+				    0x220c
+				    0x22bc
+				    0x2314
+				    0x2394
+				    0x2414
+				    0x2494
+				    0x2008
+				    0x200c
+				    0x2010
+				    0x2014
+				    0x2018>;
+
+	qcom,iommu-lpae-bfb-data = <0x7fffff
+				    0x0
+				    0x4
+				    0x10
+				    0x5000
+				    0x182c1
+				    0x5a1d
+				    0x1822d
+				    0x0
+				    0x0
+				    0x28
+				    0x68
+				    0x0
+				    0x0
+				    0x0
+				    0x0
+				    0x0>;
+
+};
+
+&kgsl_iommu {
+	status = "ok";
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2514
+				0x2540
+				0x256c
+				0x20ac
+				0x215c
+				0x220c
+				0x22bc
+				0x2314
+				0x2394
+				0x2414
+				0x2494
+				0x2008
+				0x2600
+				0x2604
+				0x2608
+				0x260c
+				0x2610
+				0x2614
+				0x2618
+				0x261c
+				0x2620
+				0x2624
+				0x2628
+				0x262c>;
+
+	qcom,iommu-bfb-data =  <0x3
+				0x8
+				0x10
+				0x0
+				0x0
+				0x0
+				0x20
+				0x0
+				0x0
+				0x1
+				0x101
+				0x0
+				0x0
+				0x7
+				0x4
+				0x8
+				0x14
+				0x0
+				0x0
+				0xc
+				0x6c
+				0x0
+				0x8
+				0x10
+				0x0>;
+
+	qcom,iommu-lpae-bfb-regs = <0x204c
+				    0x2514
+				    0x2540
+				    0x256c
+				    0x20ac
+				    0x215c
+				    0x220c
+				    0x22bc
+				    0x2314
+				    0x2394
+				    0x2414
+				    0x2494
+				    0x2008
+				    0x2600
+				    0x2604
+				    0x2608
+				    0x260c
+				    0x2610
+				    0x2614
+				    0x2618
+				    0x261c
+				    0x2620
+				    0x2624
+				    0x2628
+				    0x262c>;
+
+	qcom,iommu-lpae-bfb-data = <0x3
+				    0x0
+				    0x8
+				    0x10
+				    0x0
+				    0x120
+				    0x0
+				    0x20
+				    0x0
+				    0x0
+				    0x1
+				    0x101
+				    0x0
+				    0x7
+				    0x4
+				    0x20
+				    0x8
+				    0x14
+				    0x0
+				    0x0
+				    0xc
+				    0x6c
+				    0x0
+				    0x8
+				    0x10>;
+
+};
+
+&vfe_iommu {
+	status = "ok";
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2514
+				0x2540
+				0x256c
+				0x2314
+				0x2394
+				0x2414
+				0x2494
+				0x20ac
+				0x215c
+				0x220c
+				0x22bc
+				0x2008
+				0x200c
+				0x2010
+				0x2014
+				0x2018
+				0x201c
+				0x2020>;
+
+	qcom,iommu-bfb-data =  <0xffffffff
+				0x4
+				0x8
+				0x0
+				0x0
+				0x20
+				0x78
+				0x0
+				0x4000
+				0x3c08
+				0xb41e
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0>;
+
+	qcom,iommu-lpae-bfb-regs = <0x204c
+				    0x2514
+				    0x2540
+				    0x256c
+				    0x2314
+				    0x2394
+				    0x2414
+				    0x2494
+				    0x20ac
+				    0x215c
+				    0x220c
+				    0x22bc
+				    0x2008
+				    0x200c
+				    0x2010
+				    0x2014
+				    0x2018
+				    0x201c
+				    0x2020>;
+
+	qcom,iommu-lpae-bfb-data = <0xffffffff
+				    0x0
+				    0x4
+				    0x8
+				    0x0
+				    0x0
+				    0x20
+				    0x78
+				    0x4000
+				    0xb45a
+				    0x3c08
+				    0xb41e
+				    0x0
+				    0x0
+				    0x0
+				    0x0
+				    0x0
+				    0x0
+				    0x0>;
+
+};
+
+&copss_iommu {
+	status = "ok";
+};
+
+&vpu_iommu {
+	status = "ok";
+};
+
+&lpass_qdsp_iommu {
+	status = "ok";
+};
+
+&lpass_core_iommu {
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/apq8084-mdss.dtsi b/arch/arm/boot/dts/apq8084-mdss.dtsi
new file mode 100644
index 0000000..b9609cc
--- /dev/null
+++ b/arch/arm/boot/dts/apq8084-mdss.dtsi
@@ -0,0 +1,77 @@
+/* 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 {
+	mdss_mdp: qcom,mdss_mdp@fd900000 {
+		compatible = "qcom,mdss_mdp";
+		reg = <0xfd900000 0x22100>,
+		      <0xfd924000 0x1000>;
+		reg-names = "mdp_phys", "vbif_phys";
+		interrupts = <0 72 0>;
+
+		qcom,max-clk-rate = <320000000>;
+
+		qcom,mdss-pipe-vig-off = <0x00001200 0x00001600
+					  0x00001A00 0x00001E00>;
+		qcom,mdss-pipe-rgb-off = <0x00002200 0x00002600
+					  0x00002A00 0x00002E00>;
+		qcom,mdss-pipe-dma-off = <0x00003200 0x00003600>;
+
+		qcom,mdss-pipe-vig-fetch-id = <1 4 7 19>;
+		qcom,mdss-pipe-rgb-fetch-id = <16 17 18 22>;
+		qcom,mdss-pipe-dma-fetch-id = <10 13>;
+
+		qcom,mdss-smp-data = <44 8192>;
+
+		qcom,mdss-ctl-off = <0x00000600 0x00000700 0x00000800
+				     0x00000900 0x0000A00>;
+		qcom,mdss-mixer-intf-off = <0x00003A00 0x00003E00
+					    0x00004200 0x00004E00>;
+		qcom,mdss-mixer-wb-off = <0x00004600 0x00004A00>;
+		qcom,mdss-dspp-off = <0x00005200 0x00005600 0x00005A00
+				      0x00005E00>;
+		qcom,mdss-wb-off = <0x00011100 0x00011500 0x00011900
+				    0x00011D00 0x00012100>;
+		qcom,mdss-intf-off = <0x00012500 0x00012700
+				      0x00012900 0x00012b00>;
+                qcom,mdss-pingpong-off = <0x00012F00 0x00013000 0x00013100
+					  0x00013200>;
+		qcom,mdss-ad-off = <0x0013500 0x00013700 0x00013900>;
+
+		qcom,mdss-has-bwc;
+		qcom,mdss-has-decimation;
+
+		mdss_fb0: qcom,mdss_fb_primary {
+			cell-index = <0>;
+			compatible = "qcom,mdss-fb";
+			qcom,memory-reservation-type = "EBI1";
+			qcom,memory-reservation-size = <0x1000000>;
+		};
+
+		mdss_fb1: qcom,mdss_fb_external {
+			cell-index = <1>;
+			compatible = "qcom,mdss-fb";
+		};
+
+		mdss_fb2: qcom,mdss_fb_wfd {
+			cell-index = <2>;
+			compatible = "qcom,mdss-fb";
+		};
+	};
+
+	qcom,mdss_wb_panel {
+		compatible = "qcom,mdss_wb";
+		qcom,mdss_pan_res = <1920 1080>;
+		qcom,mdss_pan_bpp = <24>;
+		qcom,mdss-fb-map = <&mdss_fb2>;
+	};
+};
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index e5f083a..39eae2e 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -19,8 +19,12 @@
 	soc: soc { };
 };
 
+/include/ "msm-gdsc.dtsi"
 /include/ "apq8084-ion.dtsi"
+/include/ "apq8084-iommu.dtsi"
 /include/ "apq8084-smp2p.dtsi"
+/include/ "apq8084-coresight.dtsi"
+/include/ "apq8084-mdss.dtsi"
 
 &soc {
 	#address-cells = <1>;
@@ -282,6 +286,16 @@
 			qcom,irq-no-suspend;
 		};
 	};
+
+	qcom,venus@fdce0000 {
+		compatible = "qcom,pil-venus";
+		reg = <0xfdce0000 0x4000>,
+		      <0xfdc80000 0x400>;
+		reg-names = "wrapper_base", "vbif_base";
+		vdd-supply = <&gdsc_venus>;
+
+		qcom,firmware-name = "venus";
+	};
 };
 
 /include/ "msm-pma8084.dtsi"
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
index 7bc748d..d742b30 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -514,7 +514,8 @@
 					29 01 00 00 00 00 02 13 02
 					29 01 00 00 00 00 02 6A 60
 					29 01 00 00 00 00 02 FF 00
-					29 01 00 00 78 00 02 29 00];
+					29 01 00 00 78 00 02 29 00
+					29 01 00 00 78 00 02 53 2C];
 
 		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
 		qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index e8674a0..2eaa32f 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -210,6 +210,41 @@
 		qcom,pet-time = <10000>;
 		qcom,ipi-ping;
 	};
+
+	qcom,ocmem@fdd00000 {
+		compatible = "qcom,msm-ocmem";
+		reg = <0xfdd00000 0x2000>,
+		      <0xfdd02000 0x2000>,
+		      <0xfe070000 0x400>,
+		      <0xfec00000 0x180000>;
+		reg-names = "ocmem_ctrl_physical", "dm_ctrl_physical", "br_ctrl_physical", "ocmem_physical";
+		interrupts = <0 76 0>, <0 77 0>;
+		interrupt-names = "ocmem_irq", "dm_irq";
+		qcom,ocmem-num-regions = <0x3>;
+		qcom,ocmem-num-macros = <0x18>;
+		qcom,resource-type = <0x706d636f>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0xfec00000 0x180000>;
+
+		partition@0 {
+			reg = <0x0 0x100000>;
+			qcom,ocmem-part-name = "graphics";
+			qcom,ocmem-part-min = <0x80000>;
+		};
+
+		partition@80000 {
+			reg = <0x100000 0x80000>;
+			qcom,ocmem-part-name = "lp_audio";
+			qcom,ocmem-part-min = <0x80000>;
+		};
+
+		partition@100000 {
+			reg = <0x100000 0x80000>;
+			qcom,ocmem-part-name = "video";
+			qcom,ocmem-part-min = <0x55000>;
+		};
+	};
 };
 
 &gdsc_venus {
diff --git a/arch/arm/boot/dts/msm-iommu-v1.dtsi b/arch/arm/boot/dts/msm-iommu-v1.dtsi
index 4492077..ef8677d 100644
--- a/arch/arm/boot/dts/msm-iommu-v1.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v1.dtsi
@@ -408,6 +408,15 @@
 			qcom,iommu-ctx-sids = <1>;
 			label = "gfx3d_priv";
 		};
+
+		qcom,iommu-ctx@fdb1a000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xfdb1a000 0x1000>;
+			interrupts = <0 241 0>;
+			qcom,iommu-ctx-sids = <2>;
+			label = "gfx3d_spare";
+		};
+
 	};
 
 	vfe_iommu: qcom,iommu@fda44000 {
@@ -511,4 +520,540 @@
 			label = "cpp";
 		};
 	};
+
+	copss_iommu: qcom,iommu@f9bc4000 {
+		compatible = "qcom,msm-smmu-v1";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xf9bc4000 0x10000>;
+		reg-names = "iommu_base";
+		interrupts = <0 153 0>;
+		label = "copss_iommu";
+		qcom,msm-bus,name = "copss_ebi";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<88 512 0 0>,
+				<88 512 0 1000>;
+		status = "disabled";
+		qcom,iommu-pmu-ngroups = <1>;
+		qcom,iommu-pmu-ncounters = <8>;
+		qcom,iommu-pmu-event-classes = <0x00
+						0x01
+						0x08
+						0x09
+						0x0a
+						0x10
+						0x11
+						0x12
+						0x80
+						0x81
+						0x82
+						0x83
+						0x90
+						0x91
+						0x92
+						0xb0
+						0xb1>;
+
+		qcom,iommu-bfb-regs =  <0x204c
+					0x2514
+					0x2540
+					0x256c
+					0x20ac
+					0x215c
+					0x220c
+					0x22bc
+					0x2314
+					0x2394
+					0x2414
+					0x2494
+					0x2008>;
+
+		qcom,iommu-bfb-data =  <0x3
+					0x4
+					0x4
+					0x0
+					0x0
+					0x0
+					0x1
+					0x0
+					0x0
+					0x40
+					0x44
+					0x0
+					0x0>;
+
+		qcom,iommu-lpae-bfb-regs = <0x204c
+					    0x2514
+					    0x2540
+					    0x256c
+					    0x20ac
+					    0x215c
+					    0x220c
+					    0x22bc
+					    0x2314
+					    0x2394
+					    0x2414
+					    0x2494
+					    0x2008>;
+
+		qcom,iommu-lpae-bfb-data = <0x3
+					    0x0
+					    0x4
+					    0x4
+					    0x0
+					    0x5
+					    0x0
+					    0x1
+					    0x0
+					    0x0
+					    0x40
+					    0x44
+					    0x0>;
+
+
+		copss_cb_0: qcom,iommu-ctx@f9bcc000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xf9bcc000 0x1000>;
+			interrupts = <0 142 0>;
+			qcom,iommu-ctx-sids = <0>;
+			label = "copss_cb_0";
+		};
+
+		copss_cb_1: qcom,iommu-ctx@f9bcd000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xf9bcd000 0x1000>;
+			interrupts = <0 142 0>;
+			qcom,iommu-ctx-sids = <1>;
+			label = "copss_cb_1";
+		};
+
+		copss_cb_2: qcom,iommu-ctx@f9bce000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xf9bce000 0x1000>;
+			interrupts = <0 142 0>;
+			qcom,iommu-ctx-sids = <2>;
+			label = "copss_cb_2";
+		};
+
+		copss_cb_3: qcom,iommu-ctx@f9bcf000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xf9bcf000 0x1000>;
+			interrupts = <0 142 0>;
+			qcom,iommu-ctx-sids = <3>;
+			label = "copss_cb_3";
+		};
+
+		copss_cb_4: qcom,iommu-ctx@f9bd0000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xf9bd0000 0x1000>;
+			interrupts = <0 142 0>;
+			qcom,iommu-ctx-sids = <4>;
+			label = "copss_cb_4";
+		};
+
+		copss_cb_5: qcom,iommu-ctx@f9bd1000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xf9bd1000 0x1000>;
+			interrupts = <0 142 0>;
+			qcom,iommu-ctx-sids = <5>;
+			label = "copss_cb_5";
+		};
+
+		copss_cb_6: qcom,iommu-ctx@f9bd2000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xf9bd2000 0x1000>;
+			interrupts = <0 142 0>;
+			qcom,iommu-ctx-sids = <6>;
+			label = "copss_cb_6";
+		};
+
+		copss_cb_7: qcom,iommu-ctx@f9bd3000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xf9bd3000 0x1000>;
+			interrupts = <0 142 0>;
+			qcom,iommu-ctx-sids = <7>;
+			label = "copss_cb_7";
+		};
+	};
+
+	vpu_iommu: qcom,iommu@fdee4000 {
+		compatible = "qcom,msm-smmu-v1";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xfdee4000 0x10000>;
+		reg-names = "iommu_base";
+		interrupts = <0 147 0>;
+		label = "vpu_iommu";
+		qcom,msm-bus,name = "vpu_ebi";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<93 512 0 0>,
+				<93 512 0 1000>;
+		status = "disabled";
+		qcom,iommu-pmu-ngroups = <1>;
+		qcom,iommu-pmu-ncounters = <8>;
+		qcom,iommu-pmu-event-classes = <0x00
+						0x01
+						0x08
+						0x09
+						0x0a
+						0x10
+						0x11
+						0x12
+						0x80
+						0x81
+						0x82
+						0x83
+						0x90
+						0x91
+						0x92
+						0xb0
+						0xb1>;
+
+		qcom,iommu-bfb-regs =  <0x204c
+					0x2514
+					0x2540
+					0x256c
+					0x2314
+					0x2394
+					0x2414
+					0x2494
+					0x20ac
+					0x215c
+					0x220c
+					0x22bc
+					0x2008
+					0x200c
+					0x2010
+					0x2014>;
+
+		qcom,iommu-bfb-data =  <0xffff
+					0x4
+					0x10
+					0x0
+					0x0
+					0xf
+					0x4b
+					0x0
+					0x1e00
+					0x1e00
+					0x5a0f
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0>;
+
+		qcom,iommu-lpae-bfb-regs = <0x204c
+					    0x2514
+					    0x2540
+					    0x256c
+					    0x2314
+					    0x2394
+					    0x2414
+					    0x2494
+					    0x20ac
+					    0x215c
+					    0x220c
+					    0x22bc
+					    0x2008
+					    0x200c
+					    0x2010
+					    0x2014>;
+
+		qcom,iommu-lpae-bfb-data = <0xffff
+					    0x0
+					    0x4
+					    0x10
+					    0x0
+					    0x0
+					    0xf
+					    0x4b
+					    0x1e00
+					    0x5a2d
+					    0x1e00
+					    0x5a0f
+					    0x0
+					    0x0
+					    0x0
+					    0x0>;
+
+
+		vpu_cb_0: qcom,iommu-ctx@fdeec000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xfdeec000 0x1000>;
+			interrupts = <0 145 0>;
+			qcom,iommu-ctx-sids = <0 1 3>;
+			label = "vpu_cb_0";
+		};
+
+		vpu_cb_1: qcom,iommu-ctx@fdeed000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xfdeed000 0x1000>;
+			interrupts = <0 145 0>;
+			qcom,iommu-ctx-sids = <8 9>;
+			label = "vpu_cb_1";
+		};
+
+		vpu_cb_2: qcom,iommu-ctx@fdeee000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xfdeee000 0x1000>;
+			interrupts = <0 145 0>;
+			qcom,iommu-ctx-sids = <5 7 15>;
+			label = "vpu_cb_2";
+		};
+	};
+
+	lpass_qdsp_iommu: qcom,iommu@fe054000 {
+		compatible = "qcom,msm-smmu-v1";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xfe054000 0x10000>;
+		reg-names = "iommu_base";
+		interrupts = <0 202 0>;
+		label = "lpass_qdsp_iommu";
+		qcom,msm-bus,name = "lpass_qdsp_ebi";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<11 512 0 0>,
+				<11 512 0 1000>;
+		status = "disabled";
+		qcom,iommu-pmu-ngroups = <1>;
+		qcom,iommu-pmu-ncounters = <8>;
+		qcom,iommu-pmu-event-classes = <0x00
+						0x01
+						0x08
+						0x09
+						0x0a
+						0x10
+						0x11
+						0x12
+						0x80
+						0x81
+						0x82
+						0x83
+						0x90
+						0x91
+						0x92
+						0xb0
+						0xb1>;
+
+		qcom,iommu-bfb-regs =  <0x204c
+					0x2514
+					0x2540
+					0x256c
+					0x20ac
+					0x215c
+					0x220c
+					0x22bc
+					0x2314
+					0x2394
+					0x2414
+					0x2494
+					0x2008>;
+
+		qcom,iommu-bfb-data =  <0x3
+					0x4
+					0x4
+					0x0
+					0x0
+					0x0
+					0x10
+					0x0
+					0x0
+					0x15e
+					0x19e
+					0x0
+					0x0>;
+
+		qcom,iommu-lpae-bfb-regs = <0x204c
+					    0x2514
+					    0x2540
+					    0x256c
+					    0x20ac
+					    0x215c
+					    0x220c
+					    0x22bc
+					    0x2314
+					    0x2394
+					    0x2414
+					    0x2494
+					    0x2008>;
+
+		qcom,iommu-lpae-bfb-data = <0x3
+					    0x0
+					    0x4
+					    0x4
+					    0x0
+					    0x20
+					    0x0
+					    0x10
+					    0x0
+					    0x0
+					    0x15e
+					    0x19e
+					    0x0>;
+
+
+		lpass_qdsp_cb_0: qcom,iommu-ctx@fe05c000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xfe05c000 0x1000>;
+			interrupts = <0 265 0>;
+			qcom,iommu-ctx-sids = <0>;
+			label = "lpass_qdsp_cb_0";
+		};
+
+		lpass_qdsp_cb_1: qcom,iommu-ctx@fe05d000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xfe05d000 0x1000>;
+			interrupts = <0 265 0>;
+			qcom,iommu-ctx-sids = <1>;
+			label = "lpass_qdsp_cb_1";
+		};
+
+		lpass_qdsp_cb_2: qcom,iommu-ctx@fe05e000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xfe05e000 0x1000>;
+			interrupts = <0 265 0>;
+			qcom,iommu-ctx-sids = <2>;
+			label = "lpass_qdsp_cb_2";
+		};
+
+		lpass_qdsp_cb_3: qcom,iommu-ctx@fe05f000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xfe05f000 0x1000>;
+			interrupts = <0 265 0>;
+			qcom,iommu-ctx-sids = <3>;
+			label = "lpass_qdsp_cb_3";
+		};
+	};
+
+	lpass_core_iommu: qcom,iommu@fe064000 {
+		compatible = "qcom,msm-smmu-v1";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xfe064000 0x10000>;
+		reg-names = "iommu_base";
+		interrupts = <0 166 0>;
+		label = "lpass_core_iommu";
+		qcom,msm-bus,name = "lpass_core_ebi";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<52 512 0 0>,
+				<52 512 0 1000>;
+		status = "disabled";
+		qcom,iommu-pmu-ngroups = <1>;
+		qcom,iommu-pmu-ncounters = <8>;
+		qcom,iommu-pmu-event-classes = <0x00
+						0x01
+						0x08
+						0x09
+						0x0a
+						0x10
+						0x11
+						0x12
+						0x80
+						0x81
+						0x82
+						0x83
+						0x90
+						0x91
+						0x92
+						0xb0
+						0xb1>;
+
+		qcom,iommu-bfb-regs =  <0x204c
+					0x2514
+					0x2540
+					0x256c
+					0x20ac
+					0x215c
+					0x220c
+					0x22bc
+					0x2314
+					0x2394
+					0x2414
+					0x2494
+					0x2008>;
+
+		qcom,iommu-bfb-data =  <0x3
+					0x4
+					0x4
+					0x0
+					0x0
+					0x0
+					0x4
+					0x0
+					0x0
+					0x40
+					0x50
+					0x0
+					0x0>;
+
+		qcom,iommu-lpae-bfb-regs = <0x204c
+					    0x2514
+					    0x2540
+					    0x256c
+					    0x20ac
+					    0x215c
+					    0x220c
+					    0x22bc
+					    0x2314
+					    0x2394
+					    0x2414
+					    0x2494
+					    0x2008>;
+
+		qcom,iommu-lpae-bfb-data = <0x3
+					    0x0
+					    0x4
+					    0x4
+					    0x0
+					    0xc
+					    0x0
+					    0x4
+					    0x0
+					    0x0
+					    0x40
+					    0x50
+					    0x0>;
+
+
+		lpass_core_cb_0: qcom,iommu-ctx@fe06c000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xfe06c000 0x1000>;
+			interrupts = <0 267 0>;
+			qcom,iommu-ctx-sids = <0>;
+			label = "lpass_core_cb_0";
+		};
+
+		lpass_core_cb_1: qcom,iommu-ctx@fe06d000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xfe06d000 0x1000>;
+			interrupts = <0 267 0>;
+			qcom,iommu-ctx-sids = <1>;
+			label = "lpass_core_cb_1";
+		};
+
+		lpass_core_cb_2: qcom,iommu-ctx@fe06e000 {
+			compatible = "qcom,msm-smmu-v1-ctx";
+			reg = <0xfe06e000 0x1000>;
+			interrupts = <0 267 0>;
+			qcom,iommu-ctx-sids = <2>;
+			label = "lpass_core_cb_2";
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index b801da8..40f9a7c 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -555,7 +555,7 @@
 			};
 		};
 
-		vadc@3100 {
+		pm8941_vadc: vadc@3100 {
 			compatible = "qcom,qpnp-vadc";
 			reg = <0x3100 0x100>;
 			#address-cells = <1>;
@@ -797,7 +797,7 @@
 			};
 		};
 
-		iadc@3600 {
+		pm8941_iadc: iadc@3600 {
 			compatible = "qcom,qpnp-iadc";
 			reg = <0x3600 0x100>;
 			#address-cells = <1>;
@@ -819,7 +819,7 @@
 			};
 		};
 
-		qcom,vadc@3400 {
+		pm8941_adc_tm: qcom,vadc@3400 {
 			compatible = "qcom,qpnp-adc-tm";
 			reg = <0x3400 0x100>;
 			#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
index 41d6b7e..d4b605b 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
@@ -105,4 +105,41 @@
 		qcom,cci-master = <0>;
 		status = "ok";
 	};
+
+	qcom,camera@90 {
+		compatible = "qcom,mt9m114";
+		reg = <0x90 0x0>;
+		qcom,slave-id = <0x90 0x0 0x2481>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "mt9m114";
+		cam_vdig-supply = <&pm8226_l5>;
+		cam_vana-supply = <&pm8226_l19>;
+		cam_vio-supply = <&pm8226_lvs1>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-type = <0 1 0>;
+		qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+		qcom,cam-vreg-op-mode = <200000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 26 0>,
+				<&msmgpio 28 0>,
+				<&msmgpio 35 0>;
+		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 = <0x4320>;
+		qcom,csi-lane-mask = <0x3>;
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index 308a6f5..e5683fb 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -20,6 +20,7 @@
 
 	qcom,mdss_dsi_nt35590_720p_video {
 		status = "ok";
+		qcom,cont-splash-enabled;
 	};
 
 	i2c@f9927000 { /* BLSP1 QUP5 */
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index e11c963..2be7d1f 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -365,8 +365,9 @@
 		compatible = "qcom,coresight-hwevent";
 		reg = <0xfd828018 0x80>,
 		      <0xf9011080 0x80>,
-		      <0xfd4ab160 0x80>;
-		reg-names = "mmss-mux", "apcs-mux", "ppss-mux";
+		      <0xfd4ab160 0x80>,
+		      <0xfc401600 0x80>;
+		reg-names = "mmss-mux", "apcs-mux", "ppss-mux", "gcc-mux";
 
 		coresight-id = <29>;
 		coresight-name = "coresight-hwevent";
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index bd32138..0df3feb 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -20,6 +20,7 @@
 
 	qcom,mdss_dsi_nt35590_720p_video {
 		status = "ok";
+		qcom,cont-splash-enabled;
 	};
 
 	i2c@f9927000 { /* BLSP1 QUP5 */
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 64cbb10..74ecc68 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -10,16 +10,12 @@
  * GNU General Public License for more details.
  */
 
-/include/ "dsi-panel-nt35590-720p-video.dtsi"
 /include/ "msm8226-camera-sensor-qrd.dtsi"
 
 &soc {
 	serial@f991f000 {
 		status = "ok";
-	};
-
-	qcom,mdss_dsi_nt35590_720p_video {
-		status = "ok";
+		qcom,cont-splash-enabled;
 	};
 
 	i2c@f9927000 { /* BLSP1 QUP5 */
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index e1a0f0b..8006da2 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -95,6 +95,15 @@
 			qcom,use-voltage-corner;
 			qcom,consumer-supplies = "vdd_sr2_dig", "";
 		};
+		pm8226_s1_floor_corner: regulator-s1-floor-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s1_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
 	};
 
 	rpm-regulator-smpa3 {
@@ -110,9 +119,9 @@
 	rpm-regulator-smpa4 {
 		status = "okay";
 		pm8226_s4: regulator-s4 {
-			regulator-min-microvolt = <2100000>;
-			regulator-max-microvolt = <2100000>;
-			qcom,init-voltage = <2100000>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2200000>;
+			qcom,init-voltage = <1800000>;
 			status = "okay";
 		};
 	};
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd.dts b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
similarity index 73%
copy from arch/arm/boot/dts/msm8226-v1-qrd.dts
copy to arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
index d2aabac..d36e93e 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
@@ -13,13 +13,19 @@
 /dts-v1/;
 /include/ "msm8226-v1.dtsi"
 /include/ "msm8226-qrd.dtsi"
+/include/ "dsi-panel-hx8394a-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 QRD";
 	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
-	qcom,msm-id = <145 11 0>,
-		      <158 11 0>,
-		      <159 11 0>,
-		      <198 11 0>,
-		      <205 11 0>;
+	qcom,msm-id = <145 0x2000b 0>,
+		      <158 0x2000b 0>,
+		      <159 0x2000b 0>,
+		      <198 0x2000b 0>;
+};
+
+&soc {
+        qcom,mdss_dsi_hx8394a_720p_video {
+                status = "ok";
+        };
 };
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd.dts b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
similarity index 84%
rename from arch/arm/boot/dts/msm8226-v1-qrd.dts
rename to arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
index d2aabac..bf94d04 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
@@ -13,6 +13,7 @@
 /dts-v1/;
 /include/ "msm8226-v1.dtsi"
 /include/ "msm8226-qrd.dtsi"
+/include/ "dsi-panel-nt35590-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 QRD";
@@ -23,3 +24,9 @@
 		      <198 11 0>,
 		      <205 11 0>;
 };
+
+&soc {
+        qcom,mdss_dsi_nt35590_720p_video {
+                status = "ok";
+        };
+};
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
similarity index 73%
copy from arch/arm/boot/dts/msm8226-v1-qrd.dts
copy to arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
index d2aabac..8520ae3 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
@@ -13,13 +13,21 @@
 /dts-v1/;
 /include/ "msm8226-v1.dtsi"
 /include/ "msm8226-qrd.dtsi"
+/include/ "dsi-panel-nt35590-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 QRD";
 	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
-	qcom,msm-id = <145 11 0>,
-		      <158 11 0>,
-		      <159 11 0>,
-		      <198 11 0>,
-		      <205 11 0>;
+	qcom,board-id = <11 2>;
+	qcom,msm-id = <145 0>,
+		      <158 0>,
+		      <159 0>,
+		      <198 0>;
+};
+
+&soc {
+	qcom,mdss_dsi_nt35590_720p_video {
+		status = "ok";
+		qcom,mdss-pan-bl-ctrl = "bl_ctrl_dcs";
+	};
 };
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd.dts b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
similarity index 70%
copy from arch/arm/boot/dts/msm8226-v2-qrd.dts
copy to arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
index ad6d154..f35e2e4 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
@@ -14,13 +14,20 @@
 /include/ "msm8226-v2.dtsi"
 /include/ "msm8226-qrd.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
+/include/ "dsi-panel-hx8394a-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 QRD";
 	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
-	qcom,msm-id = <145 11 0x20000>,
-		      <158 11 0x20000>,
-		      <159 11 0x20000>,
-		      <198 11 0x20000>,
-		      <205 11 0x20000>;
+	qcom,msm-id = <145 0x2000b 0x20000>,
+		      <158 0x2000b 0x20000>,
+		      <159 0x2000b 0x20000>,
+		      <198 0x2000b 0x20000>,
+		      <205 0x2000b 0x20000>;
+};
+
+&soc {
+        qcom,mdss_dsi_hx8394a_720p_video {
+                status = "ok";
+        };
 };
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd.dts b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
similarity index 85%
rename from arch/arm/boot/dts/msm8226-v2-qrd.dts
rename to arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
index ad6d154..3b09d92 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
@@ -14,6 +14,7 @@
 /include/ "msm8226-v2.dtsi"
 /include/ "msm8226-qrd.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
+/include/ "dsi-panel-nt35590-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 QRD";
@@ -24,3 +25,9 @@
 		      <198 11 0x20000>,
 		      <205 11 0x20000>;
 };
+
+&soc {
+        qcom,mdss_dsi_nt35590_720p_video {
+                status = "ok";
+        };
+};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
similarity index 69%
copy from arch/arm/boot/dts/msm8226-v2-qrd.dts
copy to arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
index ad6d154..1c43589 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
@@ -13,14 +13,22 @@
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
 /include/ "msm8226-qrd.dtsi"
-/include/ "msm8226-camera-sensor-cdp.dtsi"
+/include/ "dsi-panel-nt35590-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 QRD";
 	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
-	qcom,msm-id = <145 11 0x20000>,
-		      <158 11 0x20000>,
-		      <159 11 0x20000>,
-		      <198 11 0x20000>,
-		      <205 11 0x20000>;
+	qcom,board-id = <0xb 0x2>;
+	qcom,msm-id = <145 0x20000>,
+		      <158 0x20000>,
+		      <159 0x20000>,
+		      <198 0x20000>,
+		      <205 0x20000>;
+};
+
+&soc {
+	qcom,mdss_dsi_nt35590_720p_video {
+		status = "ok";
+		qcom,mdss-pan-bl-ctrl = "bl_ctrl_dcs";
+	};
 };
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index c151948..527a582 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -266,11 +266,12 @@
 		qcom,dp-manual-pullup;
 
 		qcom,msm-bus,name = "usb";
-		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-cases = <3>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<87 512 0 0>,
-				<87 512 60000 960000>;
+				<87 512 60000 960000>,
+				<87 512 6000  6000>;
 	};
 
 	android_usb@fe8050c8 {
@@ -308,7 +309,7 @@
 			qcom,cdc-reset-gpio = <&msmgpio 72 0>;
 
 			cdc-vdd-buck-supply = <&pm8226_s4>;
-			qcom,cdc-vdd-buck-voltage = <2100000 2100000>;
+			qcom,cdc-vdd-buck-voltage = <1800000 2150000>;
 			qcom,cdc-vdd-buck-current = <650000>;
 
 			cdc-vdd-h-supply = <&pm8226_l6>;
@@ -508,15 +509,19 @@
                         compatible = "qcom,msm-dai-q6-dev";
                         qcom,msm-dai-q6-dev-id = <32773>;
                 };
+
+                qcom,msm-dai-q6-incall-music-2-rx {
+                        compatible = "qcom,msm-dai-q6-dev";
+                        qcom,msm-dai-q6-dev-id = <32770>;
+                };
 	};
 
 	qcom,msm-pcm-hostless {
 		compatible = "qcom,msm-pcm-hostless";
 	};
 
-	qcom,msm-auxpcm {
-		compatible = "qcom,msm-auxpcm-resource";
-		qcom,msm-cpudai-auxpcm-clk = "pcm_clk";
+	qcom,msm-pri-auxpcm {
+		compatible = "qcom,msm-auxpcm-dev";
 		qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
 		qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
 		qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
@@ -524,16 +529,7 @@
 		qcom,msm-cpudai-auxpcm-slot = <1>, <1>;
 		qcom,msm-cpudai-auxpcm-data = <0>, <0>;
 		qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
-
-		qcom,msm-prim-auxpcm-rx {
-			qcom,msm-auxpcm-dev-id = <4106>;
-			compatible = "qcom,msm-auxpcm-dev";
-		};
-
-		qcom,msm-prim-auxpcm-tx {
-			qcom,msm-auxpcm-dev-id = <4107>;
-			compatible = "qcom,msm-auxpcm-dev";
-		};
+		qcom,msm-auxpcm-interface = "primary";
 	};
 
 	qcom,wcnss-wlan@fb000000 {
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 6891b90..6b61317 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -149,12 +149,12 @@
 		compatible = "qcom,msm8x10-wcd-i2c";
 		reg = <0x0d>;
 		cdc-vdda-cp-supply = <&pm8110_s4>;
-		qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
+		qcom,cdc-vdda-cp-voltage = <1800000 2150000>;
 		qcom,cdc-vdda-cp-current = <650000>;
 
 		cdc-vdda-h-supply = <&pm8110_l6>;
 		qcom,cdc-vdda-h-voltage = <1800000 1800000>;
-		qcom,cdc-vdda-h-current = <250000>;
+		qcom,cdc-vdda-h-current = <25000>;
 
 		cdc-vdd-px-supply = <&pm8110_l6>;
 		qcom,cdc-vdd-px-voltage = <1800000 1800000>;
@@ -171,6 +171,13 @@
 		qcom,cdc-micbias-cfilt-sel = <0x0>;
 		qcom,cdc-micbias-cfilt-mv = <1800000>;
 		qcom,cdc-mclk-clk-rate = <12288000>;
+
+		qcom,cdc-static-supplies = "cdc-vdda-h",
+					   "cdc-vdd-px",
+					   "cdc-vdd-1p2v";
+
+		qcom,cdc-on-demand-supplies = "cdc-vdda-cp",
+					      "cdc-vdd-mic-bias";
 	};
 
 	msm8x10_wcd_codec@77{
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 516522e..7cf6c4f 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -345,8 +345,9 @@
 		compatible = "qcom,coresight-hwevent";
 		reg = <0xfd820018 0x80>,
 		      <0xf9011080 0x80>,
-		      <0xfd4ab160 0x80>;
-		reg-names = "mmss-mux", "apcs-mux", "ppss-mux";
+		      <0xfd4ab160 0x80>,
+		      <0xfc401600 0x80>;
+		reg-names = "mmss-mux", "apcs-mux", "ppss-mux", "gcc-mux";
 
 		coresight-id = <27>;
 		coresight-name = "coresight-hwevent";
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index ddbe3a0..27381e2 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -149,7 +149,7 @@
 		compatible = "qcom,msm8x10-wcd-i2c";
 		reg = <0x0d>;
 		cdc-vdda-cp-supply = <&pm8110_s4>;
-		qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
+		qcom,cdc-vdda-cp-voltage = <1800000 2150000>;
 		qcom,cdc-vdda-cp-current = <650000>;
 
 		cdc-vdda-h-supply = <&pm8110_l6>;
@@ -171,6 +171,13 @@
 		qcom,cdc-micbias-cfilt-sel = <0x0>;
 		qcom,cdc-micbias-cfilt-mv = <1800000>;
 		qcom,cdc-mclk-clk-rate = <12288000>;
+
+		qcom,cdc-static-supplies = "cdc-vdda-h",
+					   "cdc-vdd-px",
+					   "cdc-vdd-1p2v";
+
+		qcom,cdc-on-demand-supplies = "cdc-vdda-cp",
+					      "cdc-vdd-mic-bias";
 	};
 
 	msm8x10_wcd_codec@77{
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dts
index 7b45194..86294df 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dts
@@ -12,7 +12,7 @@
 
 /dts-v1/;
 
-/include/ "msm8610.dtsi"
+/include/ "msm8610-qrd.dtsi"
 /include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
 /include/ "msm8610-qrd-camera-sensor.dtsi"
 
@@ -23,308 +23,3 @@
 				  <163 11 0>, <164 11 0>, <166 11 0>;
 };
 
-&soc {
-	i2c@f9923000{
-		focaltech@38{
-			compatible = "focaltech,5x06";
-			reg = <0x38>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <1 0x2>;
-			vdd-supply = <&pm8110_l19>;
-			vcc_i2c-supply = <&pm8110_l14>;
-			focaltech,family-id = <0x06>;
-			focaltech,reset-gpio = <&msmgpio 0 0x00>;
-			focaltech,irq-gpio = <&msmgpio 1 0x00>;
-			focaltech,display-coords = <0 0 480 800>;
-			focaltech,panel-coords = <0 0 480 800>;
-			focaltech,button-map= <139 102 158>;
-			focaltech,no-force-update;
-			focaltech,i2c-pull-up;
-		};
-	};
-
-	gen-vkeys {
-		compatible = "qcom,gen-vkeys";
-		label = "ft5x06_ts";
-		qcom,disp-maxx = <480>;
-		qcom,disp-maxy = <800>;
-		qcom,panel-maxx = <481>;
-		qcom,panel-maxy = <940>;
-		qcom,key-codes = <139 0 102 158 0 0 0>;
-		qcom,y-offset = <0>;
-	};
-	serial@f991e000 {
-		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;
-		};
-	};
-
-	flashlight {
-		compatible = "qcom,leds-gpio-flash";
-		status = "okay";
-		qcom,flash-en = <&msmgpio 18 0>;
-		qcom,flash-now = <&msmgpio 19 0>;
-		linux,name = "flashlight";
-		linux,default-trigger = "flashlight-trigger";
-	};
-
-	gpio_keys {
-                compatible = "gpio-keys";
-                input-name = "gpio-keys";
-
-                camera_snapshot {
-                        label = "camera_snapshot";
-                        gpios = <&msmgpio 73 0x1>;
-                        linux,input-type = <1>;
-                        linux,code = <0x2fe>;
-                        gpio-key,wakeup;
-                        debounce-interval = <15>;
-                };
-
-                camera_focus {
-                        label = "camera_focus";
-                        gpios = <&msmgpio 74 0x1>;
-                        linux,input-type = <1>;
-                        linux,code = <0x210>;
-                        gpio-key,wakeup;
-                        debounce-interval = <15>;
-                };
-
-                vol_up {
-                        label = "volume_up";
-                        gpios = <&msmgpio 72 0x1>;
-                        linux,input-type = <1>;
-                        linux,code = <115>;
-                        gpio-key,wakeup;
-                        debounce-interval = <15>;
-		};
-	};
-
-	i2c@f9927000  {
-                        msm8x10_wcd_codec@0d{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x0d>;
-                        cdc-vdda-cp-supply = <&pm8110_s4>;
-                        qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
-                        qcom,cdc-vdda-cp-current = <650000>;
-
-                        cdc-vdda-h-supply = <&pm8110_l6>;
-                        qcom,cdc-vdda-h-voltage = <1800000 1800000>;
-                        qcom,cdc-vdda-h-current = <250000>;
-
-                        cdc-vdd-px-supply = <&pm8110_l6>;
-                        qcom,cdc-vdd-px-voltage = <1800000 1800000>;
-                        qcom,cdc-vdd-px-current = <10000>;
-
-                        cdc-vdd-1p2v-supply = <&pm8110_l4>;
-                        qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
-                        qcom,cdc-vdd-1p2v-current = <5000>;
-
-                        cdc-vdd-mic-bias-supply = <&pm8110_l20>;
-                        qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
-                        qcom,cdc-vdd-mic-bias-current = <25000>;
-
-                        qcom,cdc-micbias-cfilt-sel = <0x0>;
-                        qcom,cdc-micbias-cfilt-mv = <1800000>;
-                        qcom,cdc-mclk-clk-rate = <12288000>;
-                };
-
-                msm8x10_wcd_codec@77{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x77>;
-                };
-
-                msm8x10_wcd_codec@66{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x66>;
-                };
-
-                msm8x10_wcd_codec@55{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x55>;
-                };
-	};
-
-    sound {
-        qcom,audio-routing =
-            "RX_BIAS", "MCLK",
-            "INT_LDO_H", "MCLK",
-            "MIC BIAS Internal1", "Handset Mic",
-            "MIC BIAS Internal2", "Headset Mic",
-            "AMIC1", "MIC BIAS Internal1",
-            "AMIC2", "MIC BIAS Internal2";
-    };
-};
-
-&spmi_bus {
-	qcom,pm8110@0 {
-		qcom,leds@a100 {
-			status = "okay";
-			qcom,led_mpp_2 {
-				label = "mpp";
-				linux,name = "wled-homerow";
-				linux-default-trigger = "hr-trigger";
-				qcom,default-state = "off";
-				qcom,max-current = <40>;
-				qcom,id = <6>;
-				qcom,source-sel = <1>;
-				qcom,mode-ctrl = <0x61>;
-				qcom,mode = "manual";
-			};
-		};
-
-		qcom,leds@a200 {
-			status = "okay";
-			qcom,led_mpp_3 {
-				label = "mpp";
-				linux,name = "wled-backlight";
-				linux,default-trigger = "bkl-trigger";
-				qcom,default-state = "on";
-				qcom,max-current = <40>;
-				qcom,id = <6>;
-				qcom,source-sel = <1>;
-				qcom,mode-ctrl = <0x10>;
-				qcom,mode = "manual";
-			};
-		};
-	};
-};
-
-&spmi_bus {
-	qcom,pm8110@1 {
-		qcom,vibrator@c000 {
-			status = "okay";
-			qcom,vib-timeout-ms = <15000>;
-			qcom,vib-vtg-level-mV = <3100>;
-		};
-	};
-};
-
-&sdhc_1 {
-	vdd-supply = <&pm8110_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
-	qcom,vdd-voltage-level = <2900000 2900000>;
-	qcom,vdd-current-level = <200 400000>;
-
-	vdd-io-supply = <&pm8110_l6>;
-	qcom,vdd-io-always-on;
-	qcom,vdd-io-voltage-level = <1800000 1800000>;
-	qcom,vdd-io-current-level = <200 60000>;
-
-	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
-	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
-
-	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
-	qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
-	qcom,nonremovable;
-
-	status = "ok";
-};
-
-&sdhc_2 {
-	vdd-supply = <&pm8110_l18>;
-	qcom,vdd-voltage-level = <2950000 2950000>;
-	qcom,vdd-current-level = <15000 400000>;
-
-	vdd-io-supply = <&pm8110_l21>;
-	qcom,vdd-io-always-on;
-	qcom,vdd-io-lpm-sup;
-	qcom,vdd-io-voltage-level = <1800000 2950000>;
-	qcom,vdd-io-current-level = <200 50000>;
-
-	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
-	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
-
-	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
-
-	#address-cells = <0>;
-	interrupt-parent = <&sdhc_2>;
-	interrupts = <0 1 2>;
-	#interrupt-cells = <1>;
-	interrupt-map-mask = <0xffffffff>;
-	interrupt-map = <0 &intc 0 125 0
-			1 &intc 0 221 0
-			2 &msmgpio 42 0x3>;
-	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
-	cd-gpios = <&msmgpio 42 0x1>;
-
-	status = "ok";
-};
-
-&pm8110_chg {
-	status = "ok";
-
-	qcom,chgr@1000 {
-		status = "ok";
-	};
-
-	qcom,buck@1100 {
-		status = "ok";
-	};
-
-	qcom,bat-if@1200 {
-		status = "ok";
-	};
-
-	qcom,usb-chgpth@1300 {
-		status = "ok";
-	};
-
-	qcom,chg-misc@1600 {
-		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-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
new file mode 100644
index 0000000..7a93c49
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -0,0 +1,335 @@
+/* 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.
+ */
+
+/* This is a QRD reference design common file. The common device
+ * tree approach would help OEM during development of their extended
+ * device tree. Each new QRD OEM target can select its own include
+ * files and provide board specific overrides in the top level DTS
+ * file.
+ *
+ * For example:
+ * msm8xxx-qrd.dtsi: QRD reference common node
+ * msm8xxx-qrd-skuxx.dts:
+ * /include/ "msm8610-qrd.dtsi"
+ * / {
+ *      List skuxx specific node which is different with QRD
+ *      reference design.
+ * };
+ */
+
+/include/ "msm8610.dtsi"
+
+&soc {
+	i2c@f9923000{
+		focaltech@38{
+			compatible = "focaltech,5x06";
+			reg = <0x38>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <1 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vcc_i2c-supply = <&pm8110_l14>;
+			focaltech,family-id = <0x06>;
+			focaltech,reset-gpio = <&msmgpio 0 0x00>;
+			focaltech,irq-gpio = <&msmgpio 1 0x00>;
+			focaltech,display-coords = <0 0 480 800>;
+			focaltech,panel-coords = <0 0 480 800>;
+			focaltech,button-map= <139 102 158>;
+			focaltech,no-force-update;
+			focaltech,i2c-pull-up;
+		};
+	};
+
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "ft5x06_ts";
+		qcom,disp-maxx = <480>;
+		qcom,disp-maxy = <800>;
+		qcom,panel-maxx = <481>;
+		qcom,panel-maxy = <940>;
+		qcom,key-codes = <139 0 102 158 0 0 0>;
+		qcom,y-offset = <0>;
+	};
+	serial@f991e000 {
+		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;
+		};
+	};
+
+	flashlight {
+		compatible = "qcom,leds-gpio-flash";
+		status = "okay";
+		qcom,flash-en = <&msmgpio 18 0>;
+		qcom,flash-now = <&msmgpio 19 0>;
+		linux,name = "flashlight";
+		linux,default-trigger = "flashlight-trigger";
+	};
+
+	gpio_keys {
+                compatible = "gpio-keys";
+                input-name = "gpio-keys";
+
+                camera_snapshot {
+                        label = "camera_snapshot";
+                        gpios = <&msmgpio 73 0x1>;
+                        linux,input-type = <1>;
+                        linux,code = <0x2fe>;
+                        gpio-key,wakeup;
+                        debounce-interval = <15>;
+                };
+
+                camera_focus {
+                        label = "camera_focus";
+                        gpios = <&msmgpio 74 0x1>;
+                        linux,input-type = <1>;
+                        linux,code = <0x210>;
+                        gpio-key,wakeup;
+                        debounce-interval = <15>;
+                };
+
+                vol_up {
+                        label = "volume_up";
+                        gpios = <&msmgpio 72 0x1>;
+                        linux,input-type = <1>;
+                        linux,code = <115>;
+                        gpio-key,wakeup;
+                        debounce-interval = <15>;
+		};
+	};
+
+	i2c@f9927000  {
+                        msm8x10_wcd_codec@0d{
+                        compatible = "qcom,msm8x10-wcd-i2c";
+                        reg = <0x0d>;
+                        cdc-vdda-cp-supply = <&pm8110_s4>;
+                        qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
+                        qcom,cdc-vdda-cp-current = <650000>;
+
+                        cdc-vdda-h-supply = <&pm8110_l6>;
+                        qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+                        qcom,cdc-vdda-h-current = <250000>;
+
+                        cdc-vdd-px-supply = <&pm8110_l6>;
+                        qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+                        qcom,cdc-vdd-px-current = <10000>;
+
+                        cdc-vdd-1p2v-supply = <&pm8110_l4>;
+                        qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
+                        qcom,cdc-vdd-1p2v-current = <5000>;
+
+                        cdc-vdd-mic-bias-supply = <&pm8110_l20>;
+                        qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+                        qcom,cdc-vdd-mic-bias-current = <25000>;
+
+                        qcom,cdc-micbias-cfilt-sel = <0x0>;
+                        qcom,cdc-micbias-cfilt-mv = <1800000>;
+                        qcom,cdc-mclk-clk-rate = <12288000>;
+                };
+
+                msm8x10_wcd_codec@77{
+                        compatible = "qcom,msm8x10-wcd-i2c";
+                        reg = <0x77>;
+                };
+
+                msm8x10_wcd_codec@66{
+                        compatible = "qcom,msm8x10-wcd-i2c";
+                        reg = <0x66>;
+                };
+
+                msm8x10_wcd_codec@55{
+                        compatible = "qcom,msm8x10-wcd-i2c";
+                        reg = <0x55>;
+                };
+	};
+
+    sound {
+        qcom,audio-routing =
+            "RX_BIAS", "MCLK",
+            "INT_LDO_H", "MCLK",
+            "MIC BIAS Internal1", "Handset Mic",
+            "MIC BIAS Internal2", "Headset Mic",
+            "AMIC1", "MIC BIAS Internal1",
+            "AMIC2", "MIC BIAS Internal2";
+    };
+};
+
+&spmi_bus {
+	qcom,pm8110@0 {
+		qcom,leds@a100 {
+			status = "okay";
+			qcom,led_mpp_2 {
+				label = "mpp";
+				linux,name = "wled-homerow";
+				linux-default-trigger = "hr-trigger";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,id = <6>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x61>;
+				qcom,mode = "manual";
+			};
+		};
+
+		qcom,leds@a200 {
+			status = "okay";
+			qcom,led_mpp_3 {
+				label = "mpp";
+				linux,name = "wled-backlight";
+				linux,default-trigger = "bkl-trigger";
+				qcom,default-state = "on";
+				qcom,max-current = <40>;
+				qcom,id = <6>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x10>;
+				qcom,mode = "manual";
+			};
+		};
+	};
+};
+
+&spmi_bus {
+	qcom,pm8110@1 {
+		qcom,vibrator@c000 {
+			status = "okay";
+			qcom,vib-timeout-ms = <15000>;
+			qcom,vib-vtg-level-mV = <3100>;
+		};
+	};
+};
+
+&sdhc_1 {
+	vdd-supply = <&pm8110_l17>;
+	qcom,vdd-always-on;
+	qcom,vdd-lpm-sup;
+	qcom,vdd-voltage-level = <2900000 2900000>;
+	qcom,vdd-current-level = <200 400000>;
+
+	vdd-io-supply = <&pm8110_l6>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 60000>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+	qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+	qcom,nonremovable;
+
+	status = "ok";
+};
+
+&sdhc_2 {
+	vdd-supply = <&pm8110_l18>;
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <15000 400000>;
+
+	vdd-io-supply = <&pm8110_l21>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 2950000>;
+	qcom,vdd-io-current-level = <200 50000>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 221 0
+			2 &msmgpio 42 0x3>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&msmgpio 42 0x1>;
+
+	status = "ok";
+};
+
+&pm8110_chg {
+	status = "ok";
+
+	qcom,chgr@1000 {
+		status = "ok";
+	};
+
+	qcom,buck@1100 {
+		status = "ok";
+	};
+
+	qcom,bat-if@1200 {
+		status = "ok";
+	};
+
+	qcom,usb-chgpth@1300 {
+		status = "ok";
+	};
+
+	qcom,chg-misc@1600 {
+		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-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 09520c5..0d47e5d 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -96,6 +96,16 @@
 			qcom,use-voltage-corner;
 			qcom,consumer-supplies = "vdd_sr2_dig", "";
 		};
+
+		pm8110_s1_floor_corner: regulator-s1-floor-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8110_s1_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
 	};
 
 	rpm-regulator-smpa3 {
@@ -111,7 +121,7 @@
 	rpm-regulator-smpa4 {
 		status = "okay";
 		pm8110_s4: regulator-s4 {
-			regulator-min-microvolt = <2150000>;
+			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2150000>;
 			qcom,init-voltage = <2150000>;
 			status = "okay";
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index ad0980c..b99e6f8 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -772,6 +772,21 @@
 		qcom,core-limit-temp = <80>;
 		qcom,core-temp-hysteresis = <10>;
 		qcom,core-control-mask = <0xe>;
+		qcom,vdd-restriction-temp = <5>;
+		qcom,vdd-restriction-temp-hysteresis = <10>;
+		vdd_dig-supply = <&pm8110_s1_floor_corner>;
+
+		qcom,vdd-dig-rstr{
+			qcom,vdd-rstr-reg = "vdd_dig";
+			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
+			qcom,min-level = <1>; /* No Request */
+		};
+
+		qcom,vdd-apps-rstr{
+			qcom,vdd-rstr-reg = "vdd_apps";
+			qcom,levels = <600000 787200 998400>;
+			qcom,freq-req;
+		};
 	};
 
 	qcom,ipc-spinlock@fd484000 {
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 2a60df4..bcdaf1b 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -48,6 +48,7 @@
 			atmel,i2c-pull-up;
 			atmel,no-force-update;
 			atmel,cfg_1 {
+				atmel,fw-name = "atmel_8974_fluid_v1_0_AA.hex";
 				atmel,family-id = <0x82>;
 				atmel,variant-id = <0x19>;
 				atmel,version = <0x10>;
@@ -406,6 +407,8 @@
 	qcom,rx-gpio = <&msmgpio 42 0x00>;
 	qcom,cts-gpio = <&msmgpio 43 0x00>;
 	qcom,rfr-gpio = <&msmgpio 44 0x00>;
+	qcom,inject-rx-on-wakeup = <1>;
+	qcom,rx-char-to-inject = <0xFD>;
 };
 
 &usb3 {
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index 9fee2e5..e41adac 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -379,4 +379,14 @@
 
 		qcom,hwevent-clks = "core_mmss_clk";
 	};
+
+	fuse: fuse@fc4be024 {
+		compatible = "arm,coresight-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+
+		coresight-id = <30>;
+		coresight-name = "coresight-fuse";
+		coresight-nr-inports = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 3d2308d..638e6dd 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -43,6 +43,7 @@
 			atmel,i2c-pull-up;
 			atmel,no-force-update;
 			atmel,cfg_1 {
+				atmel,fw-name = "atmel_8974_fluid_v1_0_AA.hex";
 				atmel,family-id = <0x82>;
 				atmel,variant-id = <0x19>;
 				atmel,version = <0x10>;
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 2dc52b6..ddf5b60 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -813,7 +813,7 @@
 	};
 
 	qcom,dc-chgpth@1400 {
-		status = "ok";
+		status = "disabled";
 	};
 
 	qcom,boost@1500 {
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 6b8d600..46bb71a 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -41,6 +41,7 @@
 		qcom,mdss-intf-off = <0x00021100 0x00021300
 					   0x00021500 0x00021700>;
 
+		qcom,mdss-has-wfd-blk;
 		qcom,vbif-settings = <0x0004 0x00000001>,
 				     <0x00D8 0x00000707>,
 				     <0x00F0 0x00000030>,
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 28111fa..4af48cc 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -43,6 +43,7 @@
 			atmel,i2c-pull-up;
 			atmel,no-force-update;
 			atmel,cfg_1 {
+				atmel,fw-name = "atmel_8974_fluid_v1_0_AA.hex";
 				atmel,family-id = <0x82>;
 				atmel,variant-id = <0x19>;
 				atmel,version = <0x10>;
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 7c191fc..d9d5aaa 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -468,6 +468,7 @@
 		#size-cells = <1>;
 		ranges;
 		qcom,pfm-threshold = <73>;
+		qcom,use-phase-scaling-factor;
 
 		krait0_vreg: regulator@f9088000 {
 			compatible = "qcom,krait-regulator";
diff --git a/arch/arm/boot/dts/msm8974-v2-cdp.dts b/arch/arm/boot/dts/msm8974-v2-cdp.dts
index 85d478b..f4014aa 100644
--- a/arch/arm/boot/dts/msm8974-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-cdp.dts
@@ -22,15 +22,3 @@
 		      <185 1 0x20000>,
 		      <186 1 0x20000>;
 };
-
-&usb3 {
-	interrupt-parent = <&usb3>;
-	interrupts = <0 1>;
-	#interrupt-cells = <1>;
-	interrupt-map-mask = <0x0 0xffffffff>;
-	interrupt-map = <0x0 0 &intc 0 133 0
-			 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
-	interrupt-names = "hs_phy_irq", "pmic_id_irq";
-
-	qcom,misc-ref = <&pm8941_misc>;
-};
diff --git a/arch/arm/boot/dts/msm8974-v2-fluid.dts b/arch/arm/boot/dts/msm8974-v2-fluid.dts
index d83d130..9c9e3c0 100644
--- a/arch/arm/boot/dts/msm8974-v2-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-fluid.dts
@@ -22,15 +22,3 @@
 		      <185 3 0x20000>,
 		      <186 3 0x20000>;
 };
-
-&usb3 {
-	interrupt-parent = <&usb3>;
-	interrupts = <0 1>;
-	#interrupt-cells = <1>;
-	interrupt-map-mask = <0x0 0xffffffff>;
-	interrupt-map = <0x0 0 &intc 0 133 0
-			 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
-	interrupt-names = "hs_phy_irq", "pmic_id_irq";
-
-	qcom,misc-ref = <&pm8941_misc>;
-};
diff --git a/arch/arm/boot/dts/msm8974-v2-liquid.dts b/arch/arm/boot/dts/msm8974-v2-liquid.dts
index 53983dc..ddae6fe 100644
--- a/arch/arm/boot/dts/msm8974-v2-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-liquid.dts
@@ -22,15 +22,3 @@
 		      <185 9 0x20000>,
 		      <186 9 0x20000>;
 };
-
-&usb3 {
-	interrupt-parent = <&usb3>;
-	interrupts = <0 1>;
-	#interrupt-cells = <1>;
-	interrupt-map-mask = <0x0 0xffffffff>;
-	interrupt-map = <0x0 0 &intc 0 133 0
-			 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
-	interrupt-names = "hs_phy_irq", "pmic_id_irq";
-
-	qcom,misc-ref = <&pm8941_misc>;
-};
diff --git a/arch/arm/boot/dts/msm8974-v2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-mtp.dts
index 792a78c..021b626 100644
--- a/arch/arm/boot/dts/msm8974-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-mtp.dts
@@ -23,18 +23,6 @@
 		      <186 8 0x20000>;
 };
 
-&usb3 {
-	interrupt-parent = <&usb3>;
-	interrupts = <0 1>;
-	#interrupt-cells = <1>;
-	interrupt-map-mask = <0x0 0xffffffff>;
-	interrupt-map = <0x0 0 &intc 0 133 0
-			 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
-	interrupt-names = "hs_phy_irq", "pmic_id_irq";
-
-	qcom,misc-ref = <&pm8941_misc>;
-};
-
 &pm8941_chg {
 	qcom,bpd-detection = "bpd_thm";
 };
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 068f581..0e720c7 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -585,11 +585,11 @@
 		spi-max-frequency = <19200000>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		gpios = <&msmgpio 56 0>, /* CLK  */
-			<&msmgpio 54 0>, /* MISO */
-			<&msmgpio 53 0>; /* MOSI */
-		cs-gpios = <&msmgpio 55 0>;
 		qcom,master-id = <84>;
+		qcom,gpio-mosi = <&msmgpio 53 0>;
+		qcom,gpio-miso = <&msmgpio 54 0>;
+		qcom,gpio-clk  = <&msmgpio 56 0>;
+		qcom,gpio-cs0  = <&msmgpio 55 0>;
 	};
 
 	tspp: msm_tspp@f99d8000 {
@@ -648,6 +648,8 @@
 		reg-names = "slimbus_physical", "slimbus_bam_physical";
 		interrupts = <0 163 0 0 164 0>;
 		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+		qcom,apps-ch-pipes = <0x60000000>;
+		qcom,ea-pc = <0x30>;
 
 		taiko_codec {
 			compatible = "qcom,taiko-slim-pgd";
@@ -819,11 +821,11 @@
 		spi-max-frequency = <19200000>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		gpios = <&msmgpio 3 0>, /* CLK  */
-			<&msmgpio 1 0>, /* MISO */
-			<&msmgpio 0 0>; /* MOSI */
-		cs-gpios = <&msmgpio 9 0>;
 		qcom,master-id = <86>;
+		qcom,gpio-mosi = <&msmgpio 0 0>;
+		qcom,gpio-miso = <&msmgpio 1 0>;
+		qcom,gpio-clk  = <&msmgpio 3 0>;
+		qcom,gpio-cs2  = <&msmgpio 9 0>;
 	};
 
 	qcom,acpuclk@f9000000 {
@@ -854,8 +856,15 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
-		interrupts = <0 133 0>;
-		interrupt-names = "hs_phy_irq";
+
+		interrupt-parent = <&usb3>;
+		interrupts = <0 1>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0x0 0xffffffff>;
+		interrupt-map = <0x0 0 &intc 0 133 0
+				 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+		interrupt-names = "hs_phy_irq", "pmic_id_irq";
+
 		ssusb_vdd_dig-supply = <&pm8841_s2_corner>;
 		SSUSB_1p8-supply = <&pm8941_l6>;
 		hsusb_vdd_dig-supply = <&pm8841_s2_corner>;
@@ -865,6 +874,7 @@
 		qcom,dwc-usb3-msm-dbm-eps = <4>;
 		qcom,vdd-voltage-level = <1 5 7>;
 		qcom,dwc-hsphy-init = <0x00D191A4>;
+		qcom,misc-ref = <&pm8941_misc>;
 
 		qcom,msm-bus,name = "usb3";
 		qcom,msm-bus,num-cases = <2>;
@@ -1092,9 +1102,8 @@
 		};
 	};
 
-	qcom,msm-auxpcm {
-		compatible = "qcom,msm-auxpcm-resource";
-		qcom,msm-cpudai-auxpcm-clk = "pcm_clk";
+	qcom,msm-pri-auxpcm {
+		compatible = "qcom,msm-auxpcm-dev";
 		qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
 		qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
 		qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
@@ -1102,26 +1111,19 @@
 		qcom,msm-cpudai-auxpcm-slot = <1>, <1>;
 		qcom,msm-cpudai-auxpcm-data = <0>, <0>;
 		qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+		qcom,msm-auxpcm-interface = "primary";
+	};
 
-		qcom,msm-prim-auxpcm-rx {
-			qcom,msm-auxpcm-dev-id = <4106>;
-			compatible = "qcom,msm-auxpcm-dev";
-		};
-
-		qcom,msm-prim-auxpcm-tx {
-			qcom,msm-auxpcm-dev-id = <4107>;
-			compatible = "qcom,msm-auxpcm-dev";
-		};
-
-		qcom,msm-sec-auxpcm-rx {
-			qcom,msm-auxpcm-dev-id = <4108>;
-			compatible = "qcom,msm-auxpcm-dev";
-		};
-
-		qcom,msm-sec-auxpcm-tx {
-			qcom,msm-auxpcm-dev-id = <4109>;
-			compatible = "qcom,msm-auxpcm-dev";
-		};
+	qcom,msm-sec-auxpcm {
+		compatible = "qcom,msm-auxpcm-dev";
+		qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+		qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+		qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+		qcom,msm-cpudai-auxpcm-slot = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+		qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+		qcom,msm-auxpcm-interface = "secondary";
 	};
 
 	qcom,msm-dai-mi2s {
@@ -1369,6 +1371,12 @@
 		qcom,calib-mode = "fuse_map1";
 	};
 
+	jtag_fuse: jtagfuse@fc4be024 {
+		compatible = "qcom,jtag-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+	};
+
 	qcom,msm-rtb {
 		compatible = "qcom,msm-rtb";
 		qcom,memory-reservation-type = "EBI1";
@@ -1518,8 +1526,15 @@
 		reg = <0xf995d000 0x1000>,
 			<0xf9944000 0x19000>;
 		reg-names = "core_mem", "bam_mem";
-		interrupts = <0 113 0>, <0 239 0>;
-		interrupt-names = "core_irq", "bam_irq";
+		interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+		#address-cells = <0>;
+		interrupt-parent = <&uart7>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 113 0
+				1 &intc 0 239 0
+				2 &msmgpio 42 0>;
 
 		qcom,bam-tx-ep-pipe-index = <0>;
 		qcom,bam-rx-ep-pipe-index = <1>;
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd.dts b/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
similarity index 61%
copy from arch/arm/boot/dts/msm8226-v2-qrd.dts
copy to arch/arm/boot/dts/msm8974pro-ab-cdp.dts
index ad6d154..74bd23d 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
@@ -11,16 +11,18 @@
  */
 
 /dts-v1/;
-/include/ "msm8226-v2.dtsi"
-/include/ "msm8226-qrd.dtsi"
-/include/ "msm8226-camera-sensor-cdp.dtsi"
+
+/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974-cdp.dtsi"
 
 / {
-	model = "Qualcomm MSM 8226v2 QRD";
-	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
-	qcom,msm-id = <145 11 0x20000>,
-		      <158 11 0x20000>,
-		      <159 11 0x20000>,
-		      <198 11 0x20000>,
-		      <205 11 0x20000>;
+	model = "Qualcomm MSM 8974Pro CDP";
+	compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
+	qcom,msm-id = <209 1 0x10000>,
+		      <211 1 0x10000>,
+		      <212 1 0x10000>,
+		      <214 1 0x10000>,
+		      <215 1 0x10000>,
+		      <217 1 0x10000>,
+		      <218 1 0x10000>;
 };
diff --git a/arch/arm/boot/dts/apq8026-xpm.dts b/arch/arm/boot/dts/msm8974pro-ab-fluid.dts
similarity index 61%
copy from arch/arm/boot/dts/apq8026-xpm.dts
copy to arch/arm/boot/dts/msm8974pro-ab-fluid.dts
index 67152af..9a31834 100644
--- a/arch/arm/boot/dts/apq8026-xpm.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-fluid.dts
@@ -10,13 +10,19 @@
  * GNU General Public License for more details.
  */
 
-
 /dts-v1/;
-/include/ "apq8026.dtsi"
-/include/ "msm8226-cdp.dtsi"
+
+/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974-fluid.dtsi"
 
 / {
-	model = "Qualcomm APQ 8026 XPM";
-	compatible = "qcom,apq8026-xpm", "qcom,apq8026", "qcom,xpm";
-	qcom,msm-id = <199 14 0>;
+	model = "Qualcomm MSM 8974Pro FLUID";
+	compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
+	qcom,msm-id = <209 3 0x10000>,
+		      <211 3 0x10000>,
+		      <212 3 0x10000>,
+		      <214 3 0x10000>,
+		      <215 3 0x10000>,
+		      <217 3 0x10000>,
+		      <218 3 0x10000>;
 };
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd.dts b/arch/arm/boot/dts/msm8974pro-ab-liquid.dts
similarity index 60%
copy from arch/arm/boot/dts/msm8226-v2-qrd.dts
copy to arch/arm/boot/dts/msm8974pro-ab-liquid.dts
index ad6d154..0ec9d8a 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-liquid.dts
@@ -11,16 +11,18 @@
  */
 
 /dts-v1/;
-/include/ "msm8226-v2.dtsi"
-/include/ "msm8226-qrd.dtsi"
-/include/ "msm8226-camera-sensor-cdp.dtsi"
+
+/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974-liquid.dtsi"
 
 / {
-	model = "Qualcomm MSM 8226v2 QRD";
-	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
-	qcom,msm-id = <145 11 0x20000>,
-		      <158 11 0x20000>,
-		      <159 11 0x20000>,
-		      <198 11 0x20000>,
-		      <205 11 0x20000>;
+	model = "Qualcomm MSM 8974Pro LIQUID";
+	compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
+	qcom,msm-id = <209 9 0x10000>,
+		      <211 9 0x10000>,
+		      <212 9 0x10000>,
+		      <214 9 0x10000>,
+		      <215 9 0x10000>,
+		      <217 9 0x10000>,
+		      <218 9 0x10000>;
 };
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd.dts b/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
similarity index 61%
copy from arch/arm/boot/dts/msm8226-v2-qrd.dts
copy to arch/arm/boot/dts/msm8974pro-ab-mtp.dts
index ad6d154..002baf7 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
@@ -11,16 +11,18 @@
  */
 
 /dts-v1/;
-/include/ "msm8226-v2.dtsi"
-/include/ "msm8226-qrd.dtsi"
-/include/ "msm8226-camera-sensor-cdp.dtsi"
+
+/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974-mtp.dtsi"
 
 / {
-	model = "Qualcomm MSM 8226v2 QRD";
-	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
-	qcom,msm-id = <145 11 0x20000>,
-		      <158 11 0x20000>,
-		      <159 11 0x20000>,
-		      <198 11 0x20000>,
-		      <205 11 0x20000>;
+	model = "Qualcomm MSM 8974Pro MTP";
+	compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
+	qcom,msm-id = <209 8 0x10000>,
+		      <211 8 0x10000>,
+		      <212 8 0x10000>,
+		      <214 8 0x10000>,
+		      <215 8 0x10000>,
+		      <217 8 0x10000>,
+		      <218 8 0x10000>;
 };
diff --git a/arch/arm/boot/dts/apq8026-xpm.dts b/arch/arm/boot/dts/msm8974pro-ab.dtsi
similarity index 69%
copy from arch/arm/boot/dts/apq8026-xpm.dts
copy to arch/arm/boot/dts/msm8974pro-ab.dtsi
index 67152af..9240514 100644
--- a/arch/arm/boot/dts/apq8026-xpm.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab.dtsi
@@ -10,13 +10,10 @@
  * GNU General Public License for more details.
  */
 
+/*
+ * As a general rule, only chipset-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi / msm8974pro.dtsi file(s).
+ */
 
-/dts-v1/;
-/include/ "apq8026.dtsi"
-/include/ "msm8226-cdp.dtsi"
-
-/ {
-	model = "Qualcomm APQ 8026 XPM";
-	compatible = "qcom,apq8026-xpm", "qcom,apq8026", "qcom,xpm";
-	qcom,msm-id = <199 14 0>;
-};
+/include/ "msm8974pro.dtsi"
diff --git a/arch/arm/boot/dts/apq8026-mtp.dts b/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
similarity index 67%
copy from arch/arm/boot/dts/apq8026-mtp.dts
copy to arch/arm/boot/dts/msm8974pro-ac-mtp.dts
index e14a6856..c5042b7 100644
--- a/arch/arm/boot/dts/apq8026-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
@@ -10,13 +10,16 @@
  * GNU General Public License for more details.
  */
 
-
 /dts-v1/;
-/include/ "apq8026.dtsi"
-/include/ "msm8226-mtp.dtsi"
+
+/include/ "msm8974pro-ac.dtsi"
+/include/ "msm8974-mtp.dtsi"
 
 / {
-	model = "Qualcomm APQ 8026 MTP";
-	compatible = "qcom,apq8026-mtp", "qcom,apq8026", "qcom,mtp";
-	qcom,msm-id = <199 8 0>;
+	model = "Qualcomm MSM 8974Pro-AC MTP";
+	compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
+	qcom,msm-id = <194 8 0x10000>,
+		      <210 8 0x10000>,
+		      <213 8 0x10000>,
+		      <216 8 0x10000>;
 };
diff --git a/arch/arm/boot/dts/apq8026-xpm.dts b/arch/arm/boot/dts/msm8974pro-ac.dtsi
similarity index 69%
copy from arch/arm/boot/dts/apq8026-xpm.dts
copy to arch/arm/boot/dts/msm8974pro-ac.dtsi
index 67152af..9240514 100644
--- a/arch/arm/boot/dts/apq8026-xpm.dts
+++ b/arch/arm/boot/dts/msm8974pro-ac.dtsi
@@ -10,13 +10,10 @@
  * GNU General Public License for more details.
  */
 
+/*
+ * As a general rule, only chipset-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi / msm8974pro.dtsi file(s).
+ */
 
-/dts-v1/;
-/include/ "apq8026.dtsi"
-/include/ "msm8226-cdp.dtsi"
-
-/ {
-	model = "Qualcomm APQ 8026 XPM";
-	compatible = "qcom,apq8026-xpm", "qcom,apq8026", "qcom,xpm";
-	qcom,msm-id = <199 14 0>;
-};
+/include/ "msm8974pro.dtsi"
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
new file mode 100644
index 0000000..96e78ac
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -0,0 +1,138 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi file.
+ */
+
+/include/ "msm8974.dtsi"
+/include/ "msm8974-v2-iommu.dtsi"
+/include/ "msm8974-v2-iommu-domains.dtsi"
+/include/ "msm8974-v2-pm.dtsi"
+
+&soc {
+	android_usb@fe8050c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfe8050c8 0xc8>;
+		qcom,android-usb-swfi-latency = <1>;
+	};
+
+	qcom,msm-imem@fe805000 {
+		compatible = "qcom,msm-imem";
+		reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
+	};
+};
+
+/* GPU overrides */
+&msm_gpu {
+	/* Updated chip ID */
+	qcom,chipid = <0x03030001>;
+
+	/* Updated bus bandwidth requirements */
+	qcom,msm-bus,vectors-KBps =
+		/* Off */
+		<26 512 0 0>, <89 604 0 0>,
+		/* SVS */
+		<26 512 0 2400000>, <89 604 0 3000000>,
+		/* Nominal / SVS */
+		<26 512 0 4656000>, <89 604 0 3000000>,
+		/* Nominal */
+		<26 512 0 4656000>, <89 604 0 5120000>,
+		/* Turbo / Nominal */
+		<26 512 0 7464000>, <89 604 0 5120000>,
+		/* Turbo */
+		<26 512 0 7464000>, <89 604 0 6400000>;
+};
+
+&mdss_mdp {
+	qcom,vbif-settings = <0x0004 0x00000001>;
+
+	qcom,mdss-wb-off = <0x00011100 0x00011500
+			    0x00011900 0x00011D00 0x00012100>;
+	qcom,mdss-intf-off = <0x00012500 0x00012700
+			      0x00012900 0x00012b00>;
+	qcom,mdss-pingpong-off = <0x00012D00 0x00012E00 0x00012F00>;
+	qcom,mdss-has-bwc;
+	qcom,mdss-has-decimation;
+	qcom,mdss-ad-off = <0x0013100 0x00013300>;
+};
+
+&mdss_hdmi_tx {
+	reg =	<0xfd922100 0x370>,
+		<0xfd922500 0x7C>,
+		<0xfc4b8000 0x60F0>;
+	reg-names = "core_physical", "phy_physical", "qfprom_physical";
+};
+
+&msm_vidc {
+	qcom,vidc-ns-map = <0x40000000 0x40000000>;
+	qcom,load-freq-tbl = <979200 465000000>,
+		<783360 465000000>,
+		<489600 266670000>,
+		<244800 133330000>;
+	qcom,reg-presets = <0x80004 0x1>,
+		<0x80070 0x11FFF>,
+		<0x80074 0xA4>,
+		<0x800A8 0x1FFF>,
+		<0x80124 0x3>,
+		<0xE0020 0x5555556>,
+		<0xE0024 0x0>;
+	qcom,bus-ports = <1>;
+	qcom,enc-ocmem-ab-ib = <0 0>,
+		<138000 1034000>,
+		<414000 1034000>,
+		<940000 1034000>,
+		<1880000 2068000>,
+		<3008000 3309000>,
+		<3760000 4136000>,
+		<4468000 2457000>;
+	qcom,dec-ocmem-ab-ib = <0 0>,
+		<176000 519000>,
+		<456000 519000>,
+		<864000 519000>,
+		<1728000 1038000>,
+		<2766000 1661000>,
+		<3456000 2076000>,
+		<3662000 2198000>;
+	qcom,enc-ddr-ab-ib = <0 0>,
+		<120000 302000>,
+		<364000 302000>,
+		<804000 302000>,
+		<1608000 604000>,
+		<2576000 967000>,
+		<4680000 1404000>,
+		<49880000 1496000>;
+	qcom,dec-ddr-ab-ib = <0 0>,
+		<208000 303000>,
+		<536000 303000>,
+		<1012000 303000>,
+		<2024000 606000>,
+		<3240000 970000>,
+		<4048000 1212000>,
+		<4264000 1279000>;
+	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>;
+	qcom,buffer-type-tz-usage-table = <0x91 0x1>,
+					<0x42 0x2>,
+					<0x120 0x3>;
+};
+
+&krait_pdn {
+	qcom,use-phase-switching;
+};
+
+&tspp {
+	vdd_cx-supply = <&pm8841_s2_corner>;
+};
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 8eb1119..24c6143 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -294,4 +294,10 @@
 		reg-names = "phys_addr_base";
 		qcom,sleep-stats-version = <2>;
 	};
+
+	qcom,rpm-rbcpr-stats@fc000000 {
+		compatible = "qcom,rpmrbcpr-stats";
+		reg = <0xfc000000 0x1a0000>;
+		qcom,start-offset = <0x190010>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 616995f..638ab6b 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -195,6 +195,7 @@
 		hsic,consider-ipa-handshake;
 		hsic,log2-itc = <3>;
 		qcom,ahb-async-bridge-bypass;
+		hsic,disable-cerr;
 	};
 
 	qcom,usbbam@f9a44000 {
@@ -748,9 +749,8 @@
 		compatible = "qcom,msm-stub-codec";
 	};
 
-	qcom,msm-auxpcm {
-		compatible = "qcom,msm-auxpcm-resource";
-		qcom,msm-cpudai-auxpcm-clk = "pcm_clk";
+	qcom,msm-pri-auxpcm {
+		compatible = "qcom,msm-auxpcm-dev";
 		qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
 		qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
 		qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
@@ -758,16 +758,7 @@
 		qcom,msm-cpudai-auxpcm-slot = <1>, <1>;
 		qcom,msm-cpudai-auxpcm-data = <0>, <0>;
 		qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
-
-		qcom,msm-auxpcm-rx {
-			qcom,msm-auxpcm-dev-id = <4106>;
-			compatible = "qcom,msm-auxpcm-dev";
-		};
-
-		qcom,msm-auxpcm-tx {
-			qcom,msm-auxpcm-dev-id = <4107>;
-			compatible = "qcom,msm-auxpcm-dev";
-		};
+		qcom,msm-auxpcm-interface = "primary";
 	};
 
 	qcom,msm-dai-mi2s {
diff --git a/arch/arm/boot/dts/msmsamarium-smp2p.dtsi b/arch/arm/boot/dts/msmsamarium-smp2p.dtsi
new file mode 100644
index 0000000..3d8441b
--- /dev/null
+++ b/arch/arm/boot/dts/msmsamarium-smp2p.dtsi
@@ -0,0 +1,160 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+&soc {
+	qcom,smp2p-modem {
+		compatible = "qcom,smp2p";
+		reg = <0xf9011008 0x4>;
+		qcom,remote-pid = <1>;
+		qcom,irq-bitmask = <0x4000>;
+		interrupts = <0 27 1>;
+	};
+
+	qcom,smp2p-adsp {
+		compatible = "qcom,smp2p";
+		reg = <0xf9011008 0x4>;
+		qcom,remote-pid = <2>;
+		qcom,irq-bitmask = <0x400>;
+		interrupts = <0 158 1>;
+	};
+
+	qcom,smp2p-wcnss {
+		compatible = "qcom,smp2p";
+		reg = <0xf9011008 0x4>;
+		qcom,remote-pid = <4>;
+		qcom,irq-bitmask = <0x40000>;
+		interrupts = <0 143 1>;
+	};
+
+	smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <7>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_7_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_7_in";
+		gpios = <&smp2pgpio_smp2p_7_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <7>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_7_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_7_out";
+		gpios = <&smp2pgpio_smp2p_7_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+		gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+		gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <2>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_2_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_2_in";
+		gpios = <&smp2pgpio_smp2p_2_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_2_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_2_out";
+		gpios = <&smp2pgpio_smp2p_2_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <4>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_4_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_4_in";
+		gpios = <&smp2pgpio_smp2p_4_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_4_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_4_out";
+		gpios = <&smp2pgpio_smp2p_4_out 0 0>;
+	};
+};
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
index a9cca0b..e743989 100644
--- a/arch/arm/boot/dts/msmsamarium.dtsi
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -20,6 +20,7 @@
 };
 
 /include/ "msmsamarium-ion.dtsi"
+/include/ "msmsamarium-smp2p.dtsi"
 
 &soc {
 	#address-cells = <1>;
@@ -101,4 +102,85 @@
 		compatible = "qcom,msm-mem-hole";
 		qcom,memblock-remove = <0x07f00000 0x8000000>; /* Address and size of hole */
 	};
+
+	qcom,ipc-spinlock@fd484000 {
+		compatible = "qcom,ipc-spinlock-sfpb";
+		reg = <0xfd484000 0x400>;
+		qcom,num-locks = <8>;
+	};
+
+	qcom,smem@fa00000 {
+		compatible = "qcom,smem";
+		reg = <0xfa00000 0x200000>,
+			<0xf9011000 0x1000>,
+			<0xfc428000 0x4000>;
+		reg-names = "smem", "irq-reg-base", "aux-mem1";
+
+		qcom,smd-modem {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <0>;
+			qcom,smd-irq-offset = <0x8>;
+			qcom,smd-irq-bitmask = <0x1000>;
+			qcom,pil-string = "modem";
+			interrupts = <0 25 1>;
+		};
+
+		qcom,smsm-modem {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <0>;
+			qcom,smsm-irq-offset = <0x8>;
+			qcom,smsm-irq-bitmask = <0x2000>;
+			interrupts = <0 26 1>;
+		};
+
+		qcom,smd-adsp {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <1>;
+			qcom,smd-irq-offset = <0x8>;
+			qcom,smd-irq-bitmask = <0x100>;
+			qcom,pil-string = "adsp";
+			interrupts = <0 156 1>;
+		};
+
+		qcom,smsm-adsp {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <1>;
+			qcom,smsm-irq-offset = <0x8>;
+			qcom,smsm-irq-bitmask = <0x200>;
+			interrupts = <0 157 1>;
+		};
+
+		qcom,smd-wcnss {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <6>;
+			qcom,smd-irq-offset = <0x8>;
+			qcom,smd-irq-bitmask = <0x20000>;
+			qcom,pil-string = "wcnss";
+			interrupts = <0 142 1>;
+		};
+
+		qcom,smsm-wcnss {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <6>;
+			qcom,smsm-irq-offset = <0x8>;
+			qcom,smsm-irq-bitmask = <0x80000>;
+			interrupts = <0 144 1>;
+		};
+
+		qcom,smd-rpm {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <15>;
+			qcom,smd-irq-offset = <0x8>;
+			qcom,smd-irq-bitmask = <0x1>;
+			interrupts = <0 168 1>;
+			qcom,irq-no-suspend;
+		};
+	};
+
+	qcom,bam_dmux@fc834000 {
+		compatible = "qcom,bam_dmux";
+		reg = <0xfc834000 0x7000>;
+		interrupts = <0 29 1>;
+		qcom,rx-ring-size = <64>;
+	};
 };
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index 9cd37d1..2965607 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -399,3 +399,8 @@
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_TMC=y
+CONFIG_CORESIGHT_FUNNEL=y
+CONFIG_CORESIGHT_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 4a5c9a7..f618297 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -292,6 +292,7 @@
 CONFIG_MSM_ISPIF=y
 CONFIG_MSMB_CAMERA=y
 CONFIG_OV9724=y
+CONFIG_MT9M114=y
 CONFIG_MSMB_JPEG=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_WFD=y
@@ -398,20 +399,8 @@
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
-CONFIG_DEBUG_KMEMLEAK=y
-CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_ATOMIC_SLEEP=y
-CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_DEBUG_LIST=y
-CONFIG_FAULT_INJECTION=y
-CONFIG_FAIL_PAGE_ALLOC=y
-CONFIG_FAULT_INJECTION_DEBUG_FS=y
-CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
-CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 02d4873..e249d81 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -295,6 +295,7 @@
 CONFIG_MSM_ISPIF=y
 CONFIG_MSMB_CAMERA=y
 CONFIG_OV9724=y
+CONFIG_MT9M114=y
 CONFIG_MSMB_JPEG=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_WFD=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 07f7ed9..29ef385 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -384,3 +384,5 @@
 CONFIG_CRC_CCITT=y
 CONFIG_INPUT_KXTJ9=y
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
+CONFIG_SENSORS_STK3X1X=y
+CONFIG_SENSORS_MMA8X5X=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 34c0905..77a1048 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -427,3 +427,5 @@
 CONFIG_CRC_CCITT=y
 CONFIG_INPUT_KXTJ9=y
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
+CONFIG_SENSORS_STK3X1X=y
+CONFIG_SENSORS_MMA8X5X=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index cdf4263..a26d8e6 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -398,8 +398,6 @@
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_STORAGE_ENE_UB6250=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
-CONFIG_USB_QCOM_DIAG_BRIDGE=y
-CONFIG_USB_QCOM_KS_BRIDGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_CI13XXX_MSM=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 19d428b..8447dd55 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -404,8 +404,6 @@
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_STORAGE_ENE_UB6250=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
-CONFIG_USB_QCOM_DIAG_BRIDGE=y
-CONFIG_USB_QCOM_KS_BRIDGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_CI13XXX_MSM=y
@@ -456,6 +454,7 @@
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
 CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_FUSE=y
 CONFIG_CORESIGHT_TMC=y
 CONFIG_CORESIGHT_TPIU=y
 CONFIG_CORESIGHT_FUNNEL=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index d02f5da..6471673 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -317,3 +317,4 @@
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
+CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 64c8535..0ff4efa 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -327,3 +327,4 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
+CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 6e94b32..0241da1 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -902,11 +902,13 @@
 static int perf_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd,
 		void *v)
 {
+	struct pmu *pmu;
 	switch (cmd) {
 	case CPU_PM_ENTER:
 		if (cpu_has_active_perf((int)v)) {
 			armpmu_update_counters();
-			perf_pmu_disable(&cpu_pmu->pmu);
+			pmu = &cpu_pmu->pmu;
+			pmu->pmu_disable(pmu);
 		}
 		break;
 
@@ -919,7 +921,8 @@
 			 */
 			__get_cpu_var(from_idle) = 1;
 			cpu_pmu->reset(NULL);
-			perf_pmu_enable(&cpu_pmu->pmu);
+			pmu = &cpu_pmu->pmu;
+			pmu->pmu_enable(pmu);
 		}
 		break;
 	}
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index e0f9e8a..174a576 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -528,6 +528,7 @@
 	select ARM_HAS_SG_CHAIN
 	select MSM_RUN_QUEUE_STATS
 	select ARCH_WANT_KMAP_ATOMIC_FLUSH
+	select QMI_ENCDEC
 endmenu
 
 choice
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 17db01e..68e9282 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -62,8 +62,8 @@
 obj-$(CONFIG_MSM_AVS_HW) += avs.o
 obj-$(CONFIG_CPU_V6) += idle-v6.o
 obj-$(CONFIG_CPU_V7) += idle-v7.o
-obj-$(CONFIG_MSM_JTAG) += jtag.o
-obj-$(CONFIG_MSM_JTAG_MM) +=  jtag-mm.o
+obj-$(CONFIG_MSM_JTAG) += jtag-fuse.o jtag.o
+obj-$(CONFIG_MSM_JTAG_MM) +=  jtag-fuse.o jtag-mm.o
 
 msm-etm-objs := etm.o
 obj-$(CONFIG_MSM_ETM) += msm-etm.o
@@ -87,7 +87,7 @@
 obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V4) += pil-q6v4.o pil-q6v4-lpass.o
 obj-$(CONFIG_MSM_PIL_MODEM_QDSP6V4) += pil-q6v4.o pil-q6v4-mss.o
 obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V5) += pil-q6v5.o pil-q6v5-lpass.o
-obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-q6v5-mss.o
+obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-msa.o pil-q6v5-mss.o
 obj-$(CONFIG_MSM_PIL_RIVA) += pil-riva.o
 obj-$(CONFIG_MSM_PIL_TZAPPS) += pil-tzapps.o
 obj-$(CONFIG_MSM_PIL_VIDC) += pil-vidc.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 3469c66..1ec850f 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -86,15 +86,21 @@
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-sim.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-cdp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-mtp.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-evt.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-dvt.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-cdp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-mtp.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-evt.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-dvt.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-cdp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-mtp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-qrd.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-xpm.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-mtp.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-skuf.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-skuf.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-xpm.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-mtp.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-xpm.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-mtp.dtb
 
 # FSM9XXX
    zreladdr-$(CONFIG_ARCH_FSM9XXX)	:= 0x10008000
@@ -113,6 +119,7 @@
    zreladdr-$(CONFIG_ARCH_MSM8610)	:= 0x00008000
         dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-rumi.dtb
         dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-sim.dtb
+        dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-qrd.dtb
 
 # MSMSAMARIUM
    zreladdr-$(CONFIG_ARCH_MSMSAMARIUM)	:= 0x00008000
diff --git a/arch/arm/mach-msm/board-8084.c b/arch/arm/mach-msm/board-8084.c
index 7dc9a90..2a6bbb7 100644
--- a/arch/arm/mach-msm/board-8084.c
+++ b/arch/arm/mach-msm/board-8084.c
@@ -28,6 +28,7 @@
 #include <mach/restart.h>
 #include <mach/socinfo.h>
 #include <mach/clk-provider.h>
+#include <mach/msm_smem.h>
 #include "board-dt.h"
 #include "clock.h"
 #include "devices.h"
@@ -84,6 +85,7 @@
  */
 void __init apq8084_add_drivers(void)
 {
+	msm_smem_init();
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_clock_init(&msm8084_clock_init_data);
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 39efcd8..5ad6175 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -44,6 +44,7 @@
 #include <mach/msm_smd.h>
 #include <mach/rpm-smd.h>
 #include <mach/rpm-regulator-smd.h>
+#include <mach/msm_smem.h>
 #include <linux/msm_thermal.h>
 #include "board-dt.h"
 #include "clock.h"
@@ -107,6 +108,7 @@
  */
 void __init msm8226_add_drivers(void)
 {
+	msm_smem_init();
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index b4d77f1..c6c9d14 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -45,6 +45,7 @@
 #include <mach/msm_smd.h>
 #include <mach/rpm-smd.h>
 #include <mach/rpm-regulator-smd.h>
+#include <mach/msm_smem.h>
 #include <linux/msm_thermal.h>
 #include "board-dt.h"
 #include "clock.h"
@@ -102,6 +103,7 @@
 
 void __init msm8610_add_drivers(void)
 {
+	msm_smem_init();
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 771359c..68af757 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -40,6 +40,7 @@
 #include <mach/rpm-smd.h>
 #include <mach/rpm-regulator-smd.h>
 #include <mach/socinfo.h>
+#include <mach/msm_smem.h>
 #include "board-dt.h"
 #include "clock.h"
 #include "devices.h"
@@ -91,6 +92,7 @@
  */
 void __init msm8974_add_drivers(void)
 {
+	msm_smem_init();
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 56246dd..fad2efc 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -39,6 +39,7 @@
 #include <mach/rpm-regulator-smd.h>
 #include "board-dt.h"
 #include <mach/msm_bus_board.h>
+#include <mach/msm_smem.h>
 #include "clock.h"
 #include "modem_notifier.h"
 #include "lpm_resources.h"
@@ -231,6 +232,7 @@
  */
 void __init msm9625_add_drivers(void)
 {
+	msm_smem_init();
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
diff --git a/arch/arm/mach-msm/board-samarium.c b/arch/arm/mach-msm/board-samarium.c
index 574c979..be09b54 100644
--- a/arch/arm/mach-msm/board-samarium.c
+++ b/arch/arm/mach-msm/board-samarium.c
@@ -26,10 +26,13 @@
 #include <mach/restart.h>
 #include <mach/socinfo.h>
 #include <mach/clk-provider.h>
+#include <mach/msm_smem.h>
+#include <mach/msm_smd.h>
 #include "board-dt.h"
 #include "clock.h"
 #include "devices.h"
 #include "platsmp.h"
+#include "modem_notifier.h"
 
 static struct clk_lookup msm_clocks_dummy[] = {
 	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
@@ -38,6 +41,9 @@
 	CLK_DUMMY("iface_clk",	SDC1_P_CLK,	"msm_sdcc.1", OFF),
 	CLK_DUMMY("core_clk",	SDC2_CLK,	"msm_sdcc.2", OFF),
 	CLK_DUMMY("iface_clk",	SDC2_P_CLK,	"msm_sdcc.2", OFF),
+	CLK_DUMMY("core_clk",	USB_HS_SYSTEM_CLK, "msm_otg", OFF),
+	CLK_DUMMY("iface_clk",	USB_HS_AHB_CLK,    "msm_otg", OFF),
+	CLK_DUMMY("xo",         CXO_OTG_CLK,       "msm_otg", OFF),
 };
 
 static struct clock_init_data msm_dummy_clock_init_data __initdata = {
@@ -50,6 +56,8 @@
 			"msm_sdcc.1", NULL),
 	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98A4000, \
 			"msm_sdcc.2", NULL),
+	OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
+			"msm_otg", NULL),
 	{},
 };
 
@@ -95,6 +103,9 @@
  */
 void __init msmsamarium_add_drivers(void)
 {
+	msm_smem_init();
+	msm_init_modem_notifier_list();
+	msm_smd_init();
 	msm_clock_init(&msm_dummy_clock_init_data);
 }
 
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index bec9f1b4..605a7ae 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -307,8 +307,9 @@
 	CLK_DUMMY("",	camss_vfe_vfe1_clk.c,	"", OFF),
 	CLK_DUMMY("",	camss_vfe_vfe_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	camss_vfe_vfe_axi_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_ahb_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_axi_clk.c,	"", OFF),
+	CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+	CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+	CLK_DUMMY("core_clk_src", mdp_clk_src.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("",	mdss_byte0_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_byte1_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_edpaux_clk.c,	"", OFF),
@@ -319,11 +320,11 @@
 	CLK_DUMMY("",	mdss_extpclk_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_hdmi_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_hdmi_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_mdp_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_mdp_lut_clk.c,	"", OFF),
+	CLK_DUMMY("core_clk", mdss_mdp_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+	CLK_DUMMY("lut_clk", mdss_mdp_lut_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("",	mdss_pclk0_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_pclk1_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_vsync_clk.c,	"", OFF),
+	CLK_DUMMY("vsync_clk", mdss_vsync_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("",	mmss_misc_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mmss_mmssnoc_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mmss_mmssnoc_axi_clk.c,	"", OFF),
@@ -341,6 +342,12 @@
 	CLK_DUMMY("",	venus0_core1_vcodec_clk.c,	"", OFF),
 	CLK_DUMMY("",	venus0_ocmemnoc_clk.c,	"", OFF),
 	CLK_DUMMY("",	venus0_vcodec0_clk.c,	"", OFF),
+	CLK_DUMMY("iface_clk",	venus0_ahb_clk.c, "fdce0000.qcom,venus", OFF),
+	CLK_DUMMY("bus_clk",	venus0_axi_clk.c, "fdce0000.qcom,venus", OFF),
+	CLK_DUMMY("mem_clk",	venus0_ocmemnoc_clk.c,
+						 "fdce0000.qcom,venus", OFF),
+	CLK_DUMMY("core_clk",	venus0_vcodec0_clk.c,
+						 "fdce0000.qcom,venus", OFF),
 	CLK_DUMMY("",	vpu_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	vpu_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	vpu_bus_clk.c,	"", OFF),
@@ -369,6 +376,27 @@
 	CLK_DUMMY("core_clk", NULL, "fe054000.qcom,iommu", OFF),
 	CLK_DUMMY("iface_clk", NULL, "fe064000.qcom,iommu", OFF),
 	CLK_DUMMY("core_clk", NULL, "fe064000.qcom,iommu", OFF),
+
+	/* CoreSight clocks */
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc326000.tmc", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc324000.replicator", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc325000.tmc", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc323000.funnel", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc321000.funnel", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc322000.funnel", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc345000.funnel", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc36c000.funnel", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc302000.stm", OFF),
+
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc326000.tmc", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc324000.replicator", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc325000.tmc", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc323000.funnel", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc321000.funnel", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc322000.funnel", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc345000.funnel", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc36c000.funnel", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc302000.stm", OFF),
 };
 
 struct clock_init_data msm8084_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 2a4617d..452bc28 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -2857,7 +2857,6 @@
 static struct clk_freq_tbl ftbl_kpss_ahb_clk[] = {
 	F_GCC(19200000, xo_a_clk, 0, 0, 0),
 	F_GCC(37500000, gpll0, 16, 0, 0),
-	F_GCC(75000000, gpll0,  8, 0, 0),
 	F_END
 };
 
@@ -2870,7 +2869,6 @@
 	.c = {
 		.dbg_name = "kpss_ahb_clk_src",
 		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP2(LOW, 37500000, NOMINAL, 75000000),
 		CLK_INIT(kpss_ahb_clk_src.c),
 	},
 };
@@ -3378,10 +3376,10 @@
 
 	/* MM sensor clocks */
 	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6f.qcom,camera"),
-	CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "90.qcom,camera"),
+	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "90.qcom,camera"),
 	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6d.qcom,camera"),
 	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6f.qcom,camera"),
-	CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, "90.qcom,camera"),
+	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "90.qcom,camera"),
 	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6d.qcom,camera"),
 
 	/* CCI clocks */
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index bd5a12e..4b8fb45 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -336,6 +336,8 @@
 #define USB_HS_AHB_CBCR                          0x0488
 #define SDCC1_APPS_CBCR                          0x04C4
 #define SDCC1_AHB_CBCR                           0x04C8
+#define SDCC1_CDCCAL_SLEEP_CBCR                  0x04E4
+#define SDCC1_CDCCAL_FF_CBCR                     0x04E8
 #define SDCC2_APPS_CBCR                          0x0504
 #define SDCC2_AHB_CBCR                           0x0508
 #define SDCC3_APPS_CBCR                          0x0544
@@ -810,7 +812,6 @@
 static DEFINE_CLK_VOTER(snoc_msmbus_clk, &snoc_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(cnoc_msmbus_clk, &cnoc_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(pnoc_msmbus_a_clk, &pnoc_a_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(pnoc_pm_clk, &pnoc_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(snoc_msmbus_a_clk, &snoc_a_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(cnoc_msmbus_a_clk, &cnoc_a_clk.c, LONG_MAX);
 
@@ -822,6 +823,7 @@
 static DEFINE_CLK_VOTER(ocmemgx_msmbus_a_clk, &ocmemgx_a_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(ocmemgx_core_clk, &ocmemgx_clk.c, LONG_MAX);
 
+static DEFINE_CLK_VOTER(pnoc_keepalive_a_clk, &pnoc_a_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, 0);
 
 static DEFINE_CLK_BRANCH_VOTER(cxo_otg_clk, &cxo_clk_src.c);
@@ -2315,6 +2317,28 @@
 	},
 };
 
+static struct branch_clk gcc_sdcc1_cdccal_ff_clk = {
+	.cbcr_reg = SDCC1_CDCCAL_FF_CBCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.parent = &cxo_clk_src.c,
+		.dbg_name = "gcc_sdcc1_cdccal_ff_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc1_cdccal_ff_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc1_cdccal_sleep_clk = {
+	.cbcr_reg = SDCC1_CDCCAL_SLEEP_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc1_cdccal_sleep_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc1_cdccal_sleep_clk.c),
+	},
+};
+
 static struct branch_clk gcc_sdcc2_ahb_clk = {
 	.cbcr_reg = SDCC2_AHB_CBCR,
 	.has_sibling = 1,
@@ -4432,6 +4456,8 @@
 	{&gcc_usb30_master_clk.c,		GCC_BASE, 0x0050},
 	{&gcc_blsp2_qup3_i2c_apps_clk.c,	GCC_BASE, 0x00b4},
 	{&gcc_usb_hsic_system_clk.c,		GCC_BASE, 0x0059},
+	{&gcc_sdcc1_cdccal_sleep_clk.c,		GCC_BASE, 0x006a},
+	{&gcc_sdcc1_cdccal_ff_clk.c,		GCC_BASE, 0x006b},
 	{&gcc_blsp2_uart3_apps_clk.c,		GCC_BASE, 0x00b5},
 	{&gcc_usb_hsic_io_cal_clk.c,		GCC_BASE, 0x005b},
 	{&gcc_ce2_axi_clk.c,			GCC_BASE, 0x0141},
@@ -4956,6 +4982,8 @@
 
 	CLK_LOOKUP("iface_clk", gcc_sdcc1_ahb_clk.c, "msm_sdcc.1"),
 	CLK_LOOKUP("core_clk", gcc_sdcc1_apps_clk.c, "msm_sdcc.1"),
+	CLK_LOOKUP("sleep_clk", gcc_sdcc1_cdccal_sleep_clk.c, "msm_sdcc.1"),
+	CLK_LOOKUP("cal_clk", gcc_sdcc1_cdccal_ff_clk.c, "msm_sdcc.1"),
 	CLK_LOOKUP("iface_clk", gcc_sdcc2_ahb_clk.c, "msm_sdcc.2"),
 	CLK_LOOKUP("core_clk", gcc_sdcc2_apps_clk.c, "msm_sdcc.2"),
 	CLK_LOOKUP("iface_clk", gcc_sdcc3_ahb_clk.c, "msm_sdcc.3"),
@@ -5262,6 +5290,7 @@
 	CLK_LOOKUP("core_clk", gcc_prng_ahb_clk.c, "msm_rng"),
 
 	CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
+	CLK_LOOKUP("bus_clk", pnoc_keepalive_a_clk.c, ""),
 
 	CLK_LOOKUP("bus_clk", snoc_clk.c, ""),
 	CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),
@@ -5279,7 +5308,6 @@
 	CLK_LOOKUP("bus_clk",	snoc_msmbus_clk.c,	"msm_sys_noc"),
 	CLK_LOOKUP("bus_a_clk",	snoc_msmbus_a_clk.c,	"msm_sys_noc"),
 	CLK_LOOKUP("bus_clk",	pnoc_msmbus_clk.c,	"msm_periph_noc"),
-	CLK_LOOKUP("bus_clk",   pnoc_pm_clk.c,      "pm_8x60"),
 	CLK_LOOKUP("bus_a_clk",	pnoc_msmbus_a_clk.c,	"msm_periph_noc"),
 	CLK_LOOKUP("mem_clk",	bimc_msmbus_clk.c,	"msm_bimc"),
 	CLK_LOOKUP("mem_a_clk",	bimc_msmbus_a_clk.c,	"msm_bimc"),
@@ -5535,6 +5563,12 @@
 	clk_prepare_enable(&mmssnoc_ahb_a_clk.c);
 
 	/*
+	 * Hold an active set vote for the PNOC AHB source. Sleep set vote is 0.
+	 */
+	clk_set_rate(&pnoc_keepalive_a_clk.c, 19200000);
+	clk_prepare_enable(&pnoc_keepalive_a_clk.c);
+
+	/*
 	 * Hold an active set vote for CXO; this is because CXO is expected
 	 * to remain on whenever CPUs aren't power collapsed.
 	 */
diff --git a/arch/arm/mach-msm/clock-generic.c b/arch/arm/mach-msm/clock-generic.c
index e66764f..bea82d5 100644
--- a/arch/arm/mach-msm/clock-generic.c
+++ b/arch/arm/mach-msm/clock-generic.c
@@ -266,6 +266,12 @@
 	if (rrate != rate)
 		return -EINVAL;
 
+	/*
+	 * For fixed divider clock we don't want to return an error if the
+	 * requested rate matches the achievable rate. So, don't check for
+	 * !d->ops and return an error. __div_round_rate() ensures div ==
+	 * d->div if !d->ops.
+	 */
 	if (div > d->div)
 		rc = d->ops->set_div(d, div);
 	if (rc)
@@ -299,7 +305,7 @@
 static int div_enable(struct clk *c)
 {
 	struct div_clk *d = to_div_clk(c);
-	if (d->ops->enable)
+	if (d->ops && d->ops->enable)
 		return d->ops->enable(d);
 	return 0;
 }
@@ -307,7 +313,7 @@
 static void div_disable(struct clk *c)
 {
 	struct div_clk *d = to_div_clk(c);
-	if (d->ops->disable)
+	if (d->ops && d->ops->disable)
 		return d->ops->disable(d);
 }
 
@@ -315,7 +321,7 @@
 {
 	struct div_clk *d = to_div_clk(c);
 
-	if (d->ops->get_div)
+	if (d->ops && d->ops->get_div)
 		d->div = max(d->ops->get_div(d), 1);
 	d->div = max(d->div, 1U);
 	c->rate = clk_get_rate(c->parent) / d->div;
@@ -389,8 +395,13 @@
 	if (div == d->div)
 		return 0;
 
-	if (d->ops->set_div)
-		rc = d->ops->set_div(d, div);
+	/*
+	 * For fixed divider clock we don't want to return an error if the
+	 * requested rate matches the achievable rate. So, don't check for
+	 * !d->ops and return an error. __slave_div_round_rate() ensures
+	 * div == d->div if !d->ops.
+	 */
+	rc = d->ops->set_div(d, div);
 	if (rc)
 		return rc;
 
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index 6877b4d9..70b6bea 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -854,11 +854,24 @@
 	return div;
 }
 
+static void dsi_pll_toggle_lock_detect(void)
+{
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+		0x05);
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+		0x04);
+	udelay(1);
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+		0x05);
+}
+
 static int dsi_pll_lock_status(void)
 {
 	u32 status;
 	int pll_locked = 0;
 
+	dsi_pll_toggle_lock_detect();
+
 	/* poll for PLL ready status */
 	if (readl_poll_timeout_noirq((mdss_dsi_base +
 			DSI_0_PHY_PLL_UNIPHY_PLL_STATUS),
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index 908107e..69c3751 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -57,6 +57,18 @@
 #define ENABLE_WAIT_MAX_LOOPS 200
 #define PLL_LOCKED_BIT BIT(16)
 
+static int fixed_pll_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	if (rate != c->rate)
+		return -EINVAL;
+	return 0;
+}
+
+static long fixed_pll_clk_round_rate(struct clk *c, unsigned long rate)
+{
+	return c->rate;
+}
+
 static int pll_vote_clk_enable(struct clk *c)
 {
 	u32 ena, count;
@@ -119,6 +131,8 @@
 	.enable = pll_vote_clk_enable,
 	.disable = pll_vote_clk_disable,
 	.is_enabled = pll_vote_clk_is_enabled,
+	.round_rate = fixed_pll_clk_round_rate,
+	.set_rate = fixed_pll_clk_set_rate,
 	.handoff = pll_vote_clk_handoff,
 };
 
@@ -574,6 +588,8 @@
 struct clk_ops clk_ops_pll = {
 	.enable = pll_clk_enable,
 	.disable = pll_clk_disable,
+	.round_rate = fixed_pll_clk_round_rate,
+	.set_rate = fixed_pll_clk_set_rate,
 	.handoff = pll_clk_handoff,
 	.is_enabled = pll_clk_is_enabled,
 };
@@ -625,6 +641,8 @@
 struct clk_ops clk_ops_pll_acpu_vote = {
 	.enable = pll_acpu_vote_clk_enable,
 	.disable = pll_acpu_vote_clk_disable,
+	.round_rate = fixed_pll_clk_round_rate,
+	.set_rate = fixed_pll_clk_set_rate,
 	.is_enabled = pll_vote_clk_is_enabled,
 	.handoff = pll_acpu_vote_clk_handoff,
 };
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 3c43223..527d73d 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -485,11 +485,16 @@
 
 	start_rate = clk->rate;
 
+	if (clk->ops->pre_set_rate)
+		rc = clk->ops->pre_set_rate(clk, rate);
+	if (rc)
+		goto out;
+
 	/* Enforce vdd requirements for target frequency. */
 	if (clk->prepare_count) {
 		rc = vote_rate_vdd(clk, rate);
 		if (rc)
-			goto out;
+			goto err_vote_vdd;
 	}
 
 	rc = clk->ops->set_rate(clk, rate);
@@ -501,6 +506,9 @@
 	if (clk->prepare_count)
 		unvote_rate_vdd(clk, start_rate);
 
+	if (clk->ops->post_set_rate)
+		clk->ops->post_set_rate(clk, start_rate);
+
 out:
 	mutex_unlock(&clk->prepare_lock);
 	return rc;
@@ -508,6 +516,10 @@
 err_set_rate:
 	if (clk->prepare_count)
 		unvote_rate_vdd(clk, rate);
+err_vote_vdd:
+	/* clk->rate is still the old rate. So, pass the new rate instead. */
+	if (clk->ops->post_set_rate)
+		clk->ops->post_set_rate(clk, rate);
 	goto out;
 }
 EXPORT_SYMBOL(clk_set_rate);
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 2e70c83..231a7e0 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -402,8 +402,7 @@
 		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
 	}
 
-	msm_cpufreq_wq = alloc_workqueue("msm-cpufreq",
-			WQ_MEM_RECLAIM | WQ_HIGHPRI, 1);
+	msm_cpufreq_wq = alloc_workqueue("msm-cpufreq", WQ_HIGHPRI, 0);
 	register_hotcpu_notifier(&msm_cpufreq_cpu_notifier);
 
 	return cpufreq_register_driver(&msm_cpufreq_driver);
diff --git a/arch/arm/mach-msm/hsic_sysmon.c b/arch/arm/mach-msm/hsic_sysmon.c
index 8270197..79fb1a3 100644
--- a/arch/arm/mach-msm/hsic_sysmon.c
+++ b/arch/arm/mach-msm/hsic_sysmon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -239,7 +239,7 @@
 		if (!hs)
 			continue;
 
-		ret += scnprintf(buf, DEBUG_BUF_SIZE,
+		ret += scnprintf(buf + ret, DEBUG_BUF_SIZE - ret,
 				"---HSIC Sysmon #%d---\n"
 				"epin:%d, epout:%d\n"
 				"bytes to host: %d\n"
@@ -324,15 +324,6 @@
 	struct usb_endpoint_descriptor	*ep_desc;
 	int				i;
 	int				ret = -ENOMEM;
-	__u8				ifc_num;
-
-	pr_debug("id:%lu", id->driver_info);
-
-	ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
-
-	/* is this the interface we're looking for? */
-	if (ifc_num != id->driver_info)
-		return -ENODEV;
 
 	hs = kzalloc(sizeof(*hs), GFP_KERNEL);
 	if (!hs) {
@@ -367,12 +358,17 @@
 		goto error;
 	}
 
-	hs->id = HSIC_SYSMON_DEV_EXT_MODEM;
-	hsic_sysmon_devices[HSIC_SYSMON_DEV_EXT_MODEM] = hs;
+	hs->id = HSIC_SYSMON_DEV_EXT_MODEM + id->driver_info;
+	if (hs->id >= NUM_HSIC_SYSMON_DEVS) {
+		pr_warn("invalid dev id(%d)", hs->id);
+		hs->id = 0;
+	}
+
+	hsic_sysmon_devices[hs->id] = hs;
 	usb_set_intfdata(ifc, hs);
 
 	hs->pdev.name = "sys_mon";
-	hs->pdev.id = SYSMON_SS_EXT_MODEM;
+	hs->pdev.id = SYSMON_SS_EXT_MODEM + hs->id;
 	hs->pdev.dev.release = hsic_sysmon_pdev_release;
 	platform_device_register(&hs->pdev);
 
@@ -406,11 +402,12 @@
 	return 0;
 }
 
-/* driver_info maps to the interface number corresponding to sysmon */
+/* driver_info is the instance number when multiple devices are present */
 static const struct usb_device_id hsic_sysmon_ids[] = {
-	{ USB_DEVICE(0x5c6, 0x9048), .driver_info = 1, },
-	{ USB_DEVICE(0x5c6, 0x904C), .driver_info = 1, },
-	{ USB_DEVICE(0x5c6, 0x9075), .driver_info = 1, },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9048, 1), .driver_info = 0, },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x904C, 1), .driver_info = 0, },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9075, 1), .driver_info = 0, },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9079, 1), .driver_info = 1, },
 	{} /* terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, hsic_sysmon_ids);
diff --git a/arch/arm/mach-msm/hsic_sysmon.h b/arch/arm/mach-msm/hsic_sysmon.h
index 983f464..9655dc0 100644
--- a/arch/arm/mach-msm/hsic_sysmon.h
+++ b/arch/arm/mach-msm/hsic_sysmon.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
  */
 enum hsic_sysmon_device_id {
 	HSIC_SYSMON_DEV_EXT_MODEM,
+	HSIC_SYSMON_DEV_EXT_MODEM_2,
 	NUM_HSIC_SYSMON_DEVS
 };
 
diff --git a/arch/arm/mach-msm/hsic_sysmon_test.c b/arch/arm/mach-msm/hsic_sysmon_test.c
index bc60c6e..fac6575 100644
--- a/arch/arm/mach-msm/hsic_sysmon_test.c
+++ b/arch/arm/mach-msm/hsic_sysmon_test.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,6 +15,7 @@
 
 #include <linux/slab.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/device.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
@@ -36,13 +37,14 @@
 				 size_t count, loff_t *ppos)
 {
 	struct sysmon_test_dev *dev = sysmon_dev;
+	enum hsic_sysmon_device_id id =
+				(enum hsic_sysmon_device_id)file->private_data;
 	int ret;
 
 	if (!dev)
 		return -ENODEV;
 
-	ret = hsic_sysmon_read(HSIC_SYSMON_DEV_EXT_MODEM, dev->buf, RD_BUF_SIZE,
-				&dev->buflen, 3000);
+	ret = hsic_sysmon_read(id, dev->buf, RD_BUF_SIZE, &dev->buflen, 3000);
 	if (!ret)
 		return simple_read_from_buffer(ubuf, count, ppos,
 					dev->buf, dev->buflen);
@@ -53,7 +55,9 @@
 static ssize_t sysmon_test_write(struct file *file, const char __user *ubuf,
 				 size_t count, loff_t *ppos)
 {
-	struct sysmon_test_dev	*dev = sysmon_dev;
+	struct sysmon_test_dev *dev = sysmon_dev;
+	enum hsic_sysmon_device_id id =
+				(enum hsic_sysmon_device_id)file->private_data;
 	int ret;
 
 	if (!dev)
@@ -64,8 +68,7 @@
 		return 0;
 	}
 
-	ret = hsic_sysmon_write(HSIC_SYSMON_DEV_EXT_MODEM,
-				dev->buf, count, 1000);
+	ret = hsic_sysmon_write(id, dev->buf, count, 1000);
 	if (ret < 0) {
 		pr_err("error writing to hsic_sysmon");
 		return ret;
@@ -76,38 +79,44 @@
 
 static int sysmon_test_open(struct inode *inode, struct file *file)
 {
-	return hsic_sysmon_open(HSIC_SYSMON_DEV_EXT_MODEM);
+	file->private_data = inode->i_private;
+	return hsic_sysmon_open((enum hsic_sysmon_device_id)inode->i_private);
 }
 
 static int sysmon_test_release(struct inode *inode, struct file *file)
 {
-	hsic_sysmon_close(HSIC_SYSMON_DEV_EXT_MODEM);
+	hsic_sysmon_close((enum hsic_sysmon_device_id)inode->i_private);
 	return 0;
 }
 
-static struct dentry *dfile;
-const struct file_operations sysmon_test_ops = {
+static const struct file_operations sysmon_test_ops = {
 	.read = sysmon_test_read,
 	.write = sysmon_test_write,
 	.open = sysmon_test_open,
 	.release = sysmon_test_release
 };
 
+static struct dentry *dfile0, *dfile1;
+
 static int __init sysmon_test_init(void)
 {
 	sysmon_dev = kzalloc(sizeof(*sysmon_dev), GFP_KERNEL);
 	if (!sysmon_dev)
 		return -ENOMEM;
 
-	dfile = debugfs_create_file("hsic_sysmon_test", 0666, NULL,
-			0, &sysmon_test_ops);
+	dfile0 = debugfs_create_file("hsic_sysmon_test.0", 0666, NULL,
+			(void *)HSIC_SYSMON_DEV_EXT_MODEM, &sysmon_test_ops);
+	dfile1 = debugfs_create_file("hsic_sysmon_test.1", 0666, NULL,
+			(void *)HSIC_SYSMON_DEV_EXT_MODEM_2, &sysmon_test_ops);
 	return 0;
 }
 
 static void __exit sysmon_test_exit(void)
 {
-	if (dfile)
-		debugfs_remove(dfile);
+	if (dfile0)
+		debugfs_remove(dfile0);
+	if (dfile1)
+		debugfs_remove(dfile1);
 	kfree(sysmon_dev);
 }
 
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 27c6df4..1fad7f6 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -108,7 +108,9 @@
 	int (*in_hwcg_mode)(struct clk *clk);
 	enum handoff (*handoff)(struct clk *clk);
 	int (*reset)(struct clk *clk, enum clk_reset_action action);
+	int (*pre_set_rate)(struct clk *clk, unsigned long new_rate);
 	int (*set_rate)(struct clk *clk, unsigned long rate);
+	void (*post_set_rate)(struct clk *clk, unsigned long old_rate);
 	int (*set_max_rate)(struct clk *clk, unsigned long rate);
 	int (*set_flags)(struct clk *clk, unsigned flags);
 	unsigned long (*get_rate)(struct clk *clk);
diff --git a/arch/arm/mach-msm/include/mach/clock-generic.h b/arch/arm/mach-msm/include/mach/clock-generic.h
index 0f689f1..f6feda0 100644
--- a/arch/arm/mach-msm/include/mach/clock-generic.h
+++ b/arch/arm/mach-msm/include/mach/clock-generic.h
@@ -72,8 +72,6 @@
 struct clk_div_ops {
 	int (*set_div)(struct div_clk *clk, int div);
 	int (*get_div)(struct div_clk *clk);
-
-	/* Optional */
 	bool (*is_enabled)(struct div_clk *clk);
 	int (*enable)(struct div_clk *clk);
 	void (*disable)(struct div_clk *clk);
@@ -84,6 +82,7 @@
 	unsigned int	min_div;
 	unsigned int	max_div;
 	unsigned long	rate_margin;
+	/* Optional */
 	struct clk_div_ops *ops;
 
 	/* Fields not used by helper function. */
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 541ca44..c979e0c 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -197,8 +197,10 @@
 	DUMP_REG_FSR,
 	DUMP_REG_FSYNR0,
 	DUMP_REG_FSYNR1,
-	DUMP_REG_TTBR0,
-	DUMP_REG_TTBR1,
+	DUMP_REG_TTBR0_0,
+	DUMP_REG_TTBR0_1,
+	DUMP_REG_TTBR1_0,
+	DUMP_REG_TTBR1_1,
 	DUMP_REG_SCTLR,
 	DUMP_REG_ACTLR,
 	DUMP_REG_PRRR,
@@ -216,6 +218,7 @@
 	unsigned long key;
 	const char *name;
 	int offset;
+	int must_be_present;
 };
 extern struct dump_regs_tbl dump_regs_tbl[MAX_DUMP_REGS];
 
diff --git a/arch/arm/mach-msm/include/mach/ipa.h b/arch/arm/mach-msm/include/mach/ipa.h
index 697de5e..b6acef2 100644
--- a/arch/arm/mach-msm/include/mach/ipa.h
+++ b/arch/arm/mach-msm/include/mach/ipa.h
@@ -648,6 +648,8 @@
 
 int a2_mux_write(enum a2_mux_logical_channel_id lcid, struct sk_buff *skb);
 
+int a2_mux_is_ch_empty(enum a2_mux_logical_channel_id lcid);
+
 int a2_mux_is_ch_low(enum a2_mux_logical_channel_id lcid);
 
 int a2_mux_is_ch_full(enum a2_mux_logical_channel_id lcid);
@@ -667,6 +669,8 @@
 
 int teth_bridge_set_aggr_params(struct teth_aggr_params *aggr_params);
 
+void ipa_bam_reg_dump(void);
+
 #else /* CONFIG_IPA */
 
 static inline int a2_mux_open_channel(enum a2_mux_logical_channel_id lcid,
@@ -686,6 +690,11 @@
 	return -EPERM;
 }
 
+static inline int a2_mux_is_ch_empty(enum a2_mux_logical_channel_id lcid)
+{
+	return -EPERM;
+}
+
 static inline int a2_mux_is_ch_low(enum a2_mux_logical_channel_id lcid)
 {
 	return -EPERM;
@@ -1099,6 +1108,11 @@
 	return -EPERM;
 }
 
+static inline void ipa_bam_reg_dump(void)
+{
+	return;
+}
+
 #endif /* CONFIG_IPA*/
 
 #endif /* _IPA_H_ */
diff --git a/arch/arm/mach-msm/include/mach/jtag.h b/arch/arm/mach-msm/include/mach/jtag.h
index 2131be6..ae006be 100644
--- a/arch/arm/mach-msm/include/mach/jtag.h
+++ b/arch/arm/mach-msm/include/mach/jtag.h
@@ -16,9 +16,11 @@
 #if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
 extern void msm_jtag_save_state(void);
 extern void msm_jtag_restore_state(void);
+extern bool msm_jtag_fuse_apps_access_disabled(void);
 #else
 static inline void msm_jtag_save_state(void) {}
 static inline void msm_jtag_restore_state(void) {}
+static inline bool msm_jtag_fuse_apps_access_disabled(void) { return false; }
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_ipc_logging.h b/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
index 0a91719..b3bf07c 100644
--- a/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
+++ b/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
@@ -115,6 +115,20 @@
  */
 int ipc_log_string(void *ilctxt, const char *fmt, ...) __printf(2, 3);
 
+/**
+ * ipc_log_extract - Reads and deserializes log
+ *
+ * @ilctxt:  logging context
+ * @buff:    buffer to receive the data
+ * @size:    size of the buffer
+ * @returns: 0 if no data read; >0 number of bytes read; < 0 error
+ *
+ * If no data is available to be read, then the ilctxt::read_avail
+ * completion is reinitialized.  This allows clients to block
+ * until new log data is save.
+ */
+int ipc_log_extract(void *ilctxt, char *buff, int size);
+
 /*
  * Print a string to decode context.
  * @dctxt   Decode context
@@ -220,6 +234,9 @@
 static inline int ipc_log_string(void *ilctxt, const char *fmt, ...)
 { return -EINVAL; }
 
+static inline int ipc_log_extract(void *ilctxt, char *buff, int size)
+{ return -EINVAL; }
+
 #define IPC_SPRINTF_DECODE(dctxt, args...) do { } while (0)
 
 static inline void tsv_timestamp_read(struct encode_context *ectxt,
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index 2cc7b10..62fada1 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -134,25 +134,10 @@
 	int disable_smsm_reset_handshake;
 };
 
-/*
- * Shared Memory Regions
- *
- * the array of these regions is expected to be in ascending order by phys_addr
- *
- * @phys_addr: physical base address of the region
- * @size: size of the region in bytes
- */
-struct smd_smem_regions {
-	phys_addr_t phys_addr;
-	resource_size_t size;
-};
-
 struct smd_platform {
 	uint32_t num_ss_configs;
 	struct smd_subsystem_config *smd_ss_configs;
 	struct smd_subsystem_restart_config *smd_ssr_config;
-	uint32_t num_smem_areas;
-	struct smd_smem_regions *smd_smem_areas;
 };
 
 #ifdef CONFIG_MSM_SMD
@@ -322,24 +307,6 @@
  */
 int smd_is_pkt_avail(smd_channel_t *ch);
 
-/**
- * smd_module_init_notifier_register() - Register a smd module
- *					 init notifier block
- * @nb: Notifier block to be registered
- *
- * In order to mark the dependency on SMD Driver module initialization
- * register a notifier using this API. Once the smd module_init is
- * done, notification will be passed to the registered module.
- */
-int smd_module_init_notifier_register(struct notifier_block *nb);
-
-/**
- * smd_module_init_notifier_register() - Unregister a smd module
- *					 init notifier block
- * @nb: Notifier block to be registered
- */
-int smd_module_init_notifier_unregister(struct notifier_block *nb);
-
 /*
  * SMD initialization function that registers for a SMD platform driver.
  *
@@ -474,16 +441,6 @@
 	return -ENODEV;
 }
 
-static inline int smd_module_init_notifier_register(struct notifier_block *nb)
-{
-	return -ENODEV;
-}
-
-static inline int smd_module_init_notifier_unregister(struct notifier_block *nb)
-{
-	return -ENODEV;
-}
-
 static inline int __init msm_smd_init(void)
 {
 	return 0;
diff --git a/arch/arm/mach-msm/include/mach/msm_smem.h b/arch/arm/mach-msm/include/mach/msm_smem.h
index 78d2b00..64ab6bf 100644
--- a/arch/arm/mach-msm/include/mach/msm_smem.h
+++ b/arch/arm/mach-msm/include/mach/msm_smem.h
@@ -169,6 +169,13 @@
  */
 phys_addr_t smem_virt_to_phys(void *smem_address);
 
+/**
+ * SMEM initialization function that registers for a SMEM platform driver.
+ *
+ * @returns: success on successful driver registration.
+ */
+int __init msm_smem_init(void);
+
 #else
 static inline void *smem_alloc(unsigned id, unsigned size)
 {
@@ -194,5 +201,9 @@
 {
 	return (phys_addr_t) NULL;
 }
+static int __init msm_smem_init(void)
+{
+	return 0;
+}
 #endif /* CONFIG_MSM_SMD  */
 #endif /* _ARCH_ARM_MACH_MSM_SMEM_H_ */
diff --git a/arch/arm/mach-msm/include/mach/smem_log.h b/arch/arm/mach-msm/include/mach/smem_log.h
index 992ab05..a429bc3 100644
--- a/arch/arm/mach-msm/include/mach/smem_log.h
+++ b/arch/arm/mach-msm/include/mach/smem_log.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2009, 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
@@ -51,6 +51,9 @@
 #define SMEM_LOG_DCVS_EVENT_BASE        0x00070000
 #define SMEM_LOG_SLEEP_EVENT_BASE       0x00080000
 #define SMEM_LOG_RPC_ROUTER_EVENT_BASE  0x00090000
+#define SMEM_LOG_IPC_ROUTER_EVENT_BASE  0x000D0000
+#define SMEM_LOG_QMI_CCI_EVENT_BASE     0x000E0000
+#define SMEM_LOG_QMI_CSI_EVENT_BASE     0x000F0000
 #if defined(CONFIG_MSM_N_WAY_SMSM)
 #define DEM_SMSM_ISR                    (SMEM_LOG_DEM_EVENT_BASE + 0x1)
 #define DEM_STATE_CHANGE                (SMEM_LOG_DEM_EVENT_BASE + 0x2)
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index d52686c..830992c 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -32,6 +32,7 @@
 #define SOCINFO_VERSION_MINOR(ver) (ver & 0x0000ffff)
 
 #ifdef CONFIG_OF
+#define of_board_is_cdp()	of_machine_is_compatible("qcom,cdp")
 #define of_board_is_sim()	of_machine_is_compatible("qcom,sim")
 #define of_board_is_rumi()	of_machine_is_compatible("qcom,rumi")
 #define of_board_is_fluid()	of_machine_is_compatible("qcom,fluid")
@@ -115,6 +116,9 @@
 	MSM_CPU_7X27AA,
 	MSM_CPU_9615,
 	MSM_CPU_8974,
+	MSM_CPU_8974PRO_AA,
+	MSM_CPU_8974PRO_AB,
+	MSM_CPU_8974PRO_AC,
 	MSM_CPU_8627,
 	MSM_CPU_8625,
 	MSM_CPU_9625,
@@ -434,6 +438,42 @@
 #endif
 }
 
+static inline int cpu_is_msm8974pro_aa(void)
+{
+#ifdef CONFIG_ARCH_MSM8974
+	enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+	BUG_ON(cpu == MSM_CPU_UNKNOWN);
+	return cpu == MSM_CPU_8974PRO_AA;
+#else
+	return 0;
+#endif
+}
+
+static inline int cpu_is_msm8974pro_ab(void)
+{
+#ifdef CONFIG_ARCH_MSM8974
+	enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+	BUG_ON(cpu == MSM_CPU_UNKNOWN);
+	return cpu == MSM_CPU_8974PRO_AB;
+#else
+	return 0;
+#endif
+}
+
+static inline int cpu_is_msm8974pro_ac(void)
+{
+#ifdef CONFIG_ARCH_MSM8974
+	enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+	BUG_ON(cpu == MSM_CPU_UNKNOWN);
+	return cpu == MSM_CPU_8974PRO_AC;
+#else
+	return 0;
+#endif
+}
+
 static inline int cpu_is_mpq8092(void)
 {
 #ifdef CONFIG_ARCH_MPQ8092
@@ -499,4 +539,10 @@
 	       cpu_is_msm8627();
 }
 
+static inline int soc_class_is_msm8974(void)
+{
+	return cpu_is_msm8974() || cpu_is_msm8974pro_aa() ||
+	       cpu_is_msm8974pro_ab() || cpu_is_msm8974pro_ac();
+}
+
 #endif
diff --git a/arch/arm/mach-msm/ipc_logging.c b/arch/arm/mach-msm/ipc_logging.c
index 43214cc..bad861d 100644
--- a/arch/arm/mach-msm/ipc_logging.c
+++ b/arch/arm/mach-msm/ipc_logging.c
@@ -34,6 +34,8 @@
 static LIST_HEAD(ipc_log_context_list);
 DEFINE_RWLOCK(ipc_log_context_list_lock);
 static atomic_t next_log_id = ATOMIC_INIT(0);
+static void *get_deserialization_func(struct ipc_log_context *ilctxt,
+				      int type);
 
 static struct ipc_log_page *get_first_page(struct ipc_log_context *ilctxt)
 {
@@ -339,6 +341,59 @@
 	ipc_log_write(ilctxt, &ectxt);
 	return 0;
 }
+EXPORT_SYMBOL(ipc_log_string);
+
+/**
+ * ipc_log_extract - Reads and deserializes log
+ *
+ * @ctxt:  logging context
+ * @buff:    buffer to receive the data
+ * @size:    size of the buffer
+ * @returns: 0 if no data read; >0 number of bytes read; < 0 error
+ *
+ * If no data is available to be read, then the ilctxt::read_avail
+ * completion is reinitialized.  This allows clients to block
+ * until new log data is save.
+ */
+int ipc_log_extract(void *ctxt, char *buff, int size)
+{
+	struct encode_context ectxt;
+	struct decode_context dctxt;
+	void (*deserialize_func)(struct encode_context *ectxt,
+				 struct decode_context *dctxt);
+	struct ipc_log_context *ilctxt = (struct ipc_log_context *)ctxt;
+	unsigned long flags;
+
+	if (size < MAX_MSG_DECODED_SIZE)
+		return -EINVAL;
+
+	dctxt.output_format = OUTPUT_DEBUGFS;
+	dctxt.buff = buff;
+	dctxt.size = size;
+	read_lock_irqsave(&ipc_log_context_list_lock, flags);
+	spin_lock(&ilctxt->ipc_log_context_lock);
+	while (dctxt.size >= MAX_MSG_DECODED_SIZE &&
+	       !is_ilctxt_empty(ilctxt)) {
+		msg_read(ilctxt, &ectxt);
+		deserialize_func = get_deserialization_func(ilctxt,
+							ectxt.hdr.type);
+		spin_unlock(&ilctxt->ipc_log_context_lock);
+		read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+		if (deserialize_func)
+			deserialize_func(&ectxt, &dctxt);
+		else
+			pr_err("%s: unknown message 0x%x\n",
+				__func__, ectxt.hdr.type);
+		read_lock_irqsave(&ipc_log_context_list_lock, flags);
+		spin_lock(&ilctxt->ipc_log_context_lock);
+	}
+	if ((size - dctxt.size) == 0)
+		init_completion(&ilctxt->read_avail);
+	spin_unlock(&ilctxt->ipc_log_context_lock);
+	read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	return size - dctxt.size;
+}
+EXPORT_SYMBOL(ipc_log_extract);
 
 /*
  * Helper funtion used to read data from a message context.
@@ -482,6 +537,21 @@
 }
 EXPORT_SYMBOL(add_deserialization_func);
 
+static void *get_deserialization_func(struct ipc_log_context *ilctxt,
+				      int type)
+{
+	struct dfunc_info *df_info = NULL;
+
+	if (!ilctxt)
+		return NULL;
+
+	list_for_each_entry(df_info, &ilctxt->dfunc_info_list, list) {
+		if (df_info->type == type)
+			return df_info->dfunc;
+	}
+	return NULL;
+}
+
 void *ipc_log_context_create(int max_num_pages,
 			     const char *mod_name)
 {
diff --git a/arch/arm/mach-msm/ipc_logging.h b/arch/arm/mach-msm/ipc_logging.h
index 36b4171..ddf194b 100644
--- a/arch/arm/mach-msm/ipc_logging.h
+++ b/arch/arm/mach-msm/ipc_logging.h
@@ -13,6 +13,8 @@
 #ifndef _IPC_LOGGING_H
 #define _IPC_LOGGING_H
 
+#include <mach/msm_ipc_logging.h>
+
 struct ipc_log_page_header {
 	uint32_t magic;
 	uint32_t nmagic; /* inverse of magic number */
@@ -64,6 +66,7 @@
 #define MIN(x, y) ((x) < (y) ? (x) : (y))
 #define IS_MSG_TYPE(x) (((x) > TSV_TYPE_MSG_START) && \
 			((x) < TSV_TYPE_MSG_END))
+#define MAX_MSG_DECODED_SIZE (MAX_MSG_SIZE*4)
 
 extern rwlock_t ipc_log_context_list_lock;
 
diff --git a/arch/arm/mach-msm/ipc_logging_debug.c b/arch/arm/mach-msm/ipc_logging_debug.c
index 246fb99..8a5957c 100644
--- a/arch/arm/mach-msm/ipc_logging_debug.c
+++ b/arch/arm/mach-msm/ipc_logging_debug.c
@@ -33,58 +33,6 @@
 
 static DEFINE_MUTEX(ipc_log_debugfs_init_lock);
 static struct dentry *root_dent;
-#define MAX_MSG_DECODED_SIZE (MAX_MSG_SIZE*4)
-
-static void *get_deserialization_func(struct ipc_log_context *ilctxt,
-				      int type)
-{
-	struct dfunc_info *df_info = NULL;
-
-	if (!ilctxt)
-		return NULL;
-
-	list_for_each_entry(df_info, &ilctxt->dfunc_info_list, list) {
-		if (df_info->type == type)
-			return df_info->dfunc;
-	}
-	return NULL;
-}
-
-static int deserialize_log(struct ipc_log_context *ilctxt,
-			   char *buff, int size)
-{
-	struct encode_context ectxt;
-	struct decode_context dctxt;
-	void (*deserialize_func)(struct encode_context *ectxt,
-				 struct decode_context *dctxt);
-	unsigned long flags;
-
-	dctxt.output_format = OUTPUT_DEBUGFS;
-	dctxt.buff = buff;
-	dctxt.size = size;
-	read_lock_irqsave(&ipc_log_context_list_lock, flags);
-	spin_lock(&ilctxt->ipc_log_context_lock);
-	while (dctxt.size >= MAX_MSG_DECODED_SIZE &&
-	       !is_ilctxt_empty(ilctxt)) {
-		msg_read(ilctxt, &ectxt);
-		deserialize_func = get_deserialization_func(ilctxt,
-							ectxt.hdr.type);
-		spin_unlock(&ilctxt->ipc_log_context_lock);
-		read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
-		if (deserialize_func)
-			deserialize_func(&ectxt, &dctxt);
-		else
-			pr_err("%s: unknown message 0x%x\n",
-				__func__, ectxt.hdr.type);
-		read_lock_irqsave(&ipc_log_context_list_lock, flags);
-		spin_lock(&ilctxt->ipc_log_context_lock);
-	}
-	if ((size - dctxt.size) == 0)
-		init_completion(&ilctxt->read_avail);
-	spin_unlock(&ilctxt->ipc_log_context_lock);
-	read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
-	return size - dctxt.size;
-}
 
 static int debug_log(struct ipc_log_context *ilctxt,
 		     char *buff, int size, int cont)
@@ -97,7 +45,7 @@
 		return -ENOMEM;
 	}
 	do {
-		i = deserialize_log(ilctxt, buff, size - 1);
+		i = ipc_log_extract(ilctxt, buff, size - 1);
 		if (cont && i == 0) {
 			wait_for_completion_interruptible(&ilctxt->read_avail);
 			if (signal_pending(current))
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 32589f1..aba5fee 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -95,9 +95,9 @@
 #define NTFY(x...) do { } while (0)
 #endif
 
-#define IPC_ROUTER_LOG_EVENT_ERROR      0x10
-#define IPC_ROUTER_LOG_EVENT_TX         0x11
-#define IPC_ROUTER_LOG_EVENT_RX         0x12
+#define IPC_ROUTER_LOG_EVENT_ERROR      0x00
+#define IPC_ROUTER_LOG_EVENT_TX         0x01
+#define IPC_ROUTER_LOG_EVENT_RX         0x02
 
 static LIST_HEAD(control_ports);
 static DECLARE_RWSEM(control_ports_lock_lha5);
@@ -1798,7 +1798,7 @@
 #if defined(DEBUG)
 		if (msm_ipc_router_debug_mask & SMEM_LOG) {
 			smem_log_event((SMEM_LOG_PROC_ID_APPS |
-				SMEM_LOG_RPC_ROUTER_EVENT_BASE |
+				SMEM_LOG_IPC_ROUTER_EVENT_BASE |
 				IPC_ROUTER_LOG_EVENT_RX),
 				(hdr->src_node_id << 24) |
 				(hdr->src_port_id & 0xffffff),
@@ -2117,7 +2117,7 @@
 #if defined(DEBUG)
 	if (msm_ipc_router_debug_mask & SMEM_LOG) {
 		smem_log_event((SMEM_LOG_PROC_ID_APPS |
-			SMEM_LOG_RPC_ROUTER_EVENT_BASE |
+			SMEM_LOG_IPC_ROUTER_EVENT_BASE |
 			IPC_ROUTER_LOG_EVENT_TX),
 			(hdr->src_node_id << 24) |
 			(hdr->src_port_id & 0xffffff),
@@ -2228,6 +2228,7 @@
 		pr_err("%s: msm_ipc_router_send_to failed - ret: %d\n",
 			__func__, ret);
 		msm_ipc_router_free_skb(out_skb_head);
+		return ret;
 	}
 	return 0;
 }
diff --git a/arch/arm/mach-msm/jtag-fuse.c b/arch/arm/mach-msm/jtag-fuse.c
new file mode 100644
index 0000000..ccefc41
--- /dev/null
+++ b/arch/arm/mach-msm/jtag-fuse.c
@@ -0,0 +1,140 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <mach/jtag.h>
+
+#define fuse_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
+#define fuse_readl(drvdata, off)	__raw_readl(drvdata->base + off)
+
+#define OEM_CONFIG0		(0x000)
+#define OEM_CONFIG1		(0x004)
+
+#define ALL_DEBUG_DISABLE	BIT(21)
+#define APPS_DBGEN_DISABLE	BIT(0)
+#define APPS_NIDEN_DISABLE	BIT(1)
+#define APPS_SPIDEN_DISABLE	BIT(2)
+#define APPS_SPNIDEN_DISABLE	BIT(3)
+#define DAP_DEVICEEN_DISABLE	BIT(8)
+
+struct fuse_drvdata {
+	void __iomem		*base;
+	struct device		*dev;
+};
+
+static struct fuse_drvdata *fusedrvdata;
+
+bool msm_jtag_fuse_apps_access_disabled(void)
+{
+	struct fuse_drvdata *drvdata = fusedrvdata;
+	uint32_t config0, config1;
+	bool ret;
+
+	if (!drvdata)
+		return false;
+
+	config0 = fuse_readl(drvdata, OEM_CONFIG0);
+	config1 = fuse_readl(drvdata, OEM_CONFIG1);
+
+	dev_dbg(drvdata->dev, "apps config0: %lx\n", (unsigned long)config0);
+	dev_dbg(drvdata->dev, "apps config1: %lx\n", (unsigned long)config1);
+
+	if (config0 & ALL_DEBUG_DISABLE)
+		ret = true;
+	else if (config1 & APPS_DBGEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_NIDEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_SPIDEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_SPNIDEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_DEVICEEN_DISABLE)
+		ret = true;
+	else
+		ret = false;
+
+	if (ret)
+		dev_dbg(drvdata->dev, "apps fuse disabled\n");
+
+	return ret;
+}
+EXPORT_SYMBOL(msm_jtag_fuse_apps_access_disabled);
+
+static int __devinit jtag_fuse_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct fuse_drvdata *drvdata;
+	struct resource *res;
+
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	/* Store the driver data pointer for use in exported functions */
+	fusedrvdata = drvdata;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fuse-base");
+	if (!res)
+		return -ENODEV;
+
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
+
+	dev_info(dev, "JTag Fuse initialized\n");
+	return 0;
+}
+
+static int __devexit jtag_fuse_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct of_device_id jtag_fuse_match[] = {
+	{.compatible = "qcom,jtag-fuse"},
+	{}
+};
+
+static struct platform_driver jtag_fuse_driver = {
+	.probe          = jtag_fuse_probe,
+	.remove         = __devexit_p(jtag_fuse_remove),
+	.driver         = {
+		.name   = "msm-jtag-fuse",
+		.owner	= THIS_MODULE,
+		.of_match_table = jtag_fuse_match,
+	},
+};
+
+static int __init jtag_fuse_init(void)
+{
+	return platform_driver_register(&jtag_fuse_driver);
+}
+arch_initcall(jtag_fuse_init);
+
+static void __exit jtag_fuse_exit(void)
+{
+	platform_driver_unregister(&jtag_fuse_driver);
+}
+module_exit(jtag_fuse_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("JTag Fuse driver");
diff --git a/arch/arm/mach-msm/jtag-mm.c b/arch/arm/mach-msm/jtag-mm.c
index 8a67614..55c5a7e 100644
--- a/arch/arm/mach-msm/jtag-mm.c
+++ b/arch/arm/mach-msm/jtag-mm.c
@@ -787,6 +787,9 @@
 	static uint32_t count;
 	struct device *dev = &pdev->dev;
 
+	if (msm_jtag_fuse_apps_access_disabled())
+		return -EPERM;
+
 	cpu = count;
 	count++;
 
diff --git a/arch/arm/mach-msm/jtag.c b/arch/arm/mach-msm/jtag.c
index 24e1c41..840449c 100644
--- a/arch/arm/mach-msm/jtag.c
+++ b/arch/arm/mach-msm/jtag.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1105,6 +1105,9 @@
 	int ret;
 	uint32_t dbgdidr;
 
+	if (msm_jtag_fuse_apps_access_disabled())
+		return -EPERM;
+
 	/* This will run on core0 so use it to populate parameters */
 
 	/* Populate dbg_ctx data */
@@ -1146,6 +1149,9 @@
 	uint32_t etmidr;
 	uint32_t etmccr;
 
+	if (msm_jtag_fuse_apps_access_disabled())
+		return -EPERM;
+
 	/* Vote for ETM power/clock enable */
 	etm_clk_enable();
 
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c
index 65834eb..3a996eb 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c
@@ -595,8 +595,8 @@
 		.ws = 10000,
 		.mas_hw_id = MAS_APPSS_PROC,
 		.prio_lvl = 0,
-		.prio_rd = 2,
-		.prio_wr = 2,
+		.prio_rd = 0,
+		.prio_wr = 0,
 	},
 	{
 		.id = MSM_BUS_MASTER_MSS_PROC,
diff --git a/arch/arm/mach-msm/msm_qmi_interface.c b/arch/arm/mach-msm/msm_qmi_interface.c
index 8d96bd8..a8fed52 100644
--- a/arch/arm/mach-msm/msm_qmi_interface.c
+++ b/arch/arm/mach-msm/msm_qmi_interface.c
@@ -439,12 +439,12 @@
 
 	/* Wait for the response */
 	if (!timeout_ms) {
-		rc = wait_event_interruptible(txn_handle->wait_q,
-				(txn_handle->resp_received ||
-				 handle->handle_reset ||
-				(txn_handle->send_stat < 0)));
+		wait_event(txn_handle->wait_q,
+			   (txn_handle->resp_received ||
+			    handle->handle_reset ||
+			   (txn_handle->send_stat < 0)));
 	} else {
-		rc = wait_event_interruptible_timeout(txn_handle->wait_q,
+		rc = wait_event_timeout(txn_handle->wait_q,
 				(txn_handle->resp_received ||
 				handle->handle_reset ||
 				(txn_handle->send_stat < 0)),
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 70420db..643d945 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -32,6 +32,7 @@
 	"7  Perf: Add L1 counters to tracepoints\n"
 	"8  Perf: Add cortex A7 perf support\n"
 	"9  ARM: dts: msm: add perf-events support for msm8226\n"
+	"10 Perf: Fix counts across power collapse\n"
 ;
 
 static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/pil-msa.c b/arch/arm/mach-msm/pil-msa.c
new file mode 100644
index 0000000..a8f5b0e
--- /dev/null
+++ b/arch/arm/mach-msm/pil-msa.c
@@ -0,0 +1,407 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+#include <linux/dma-mapping.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v5.h"
+#include "pil-msa.h"
+
+/* Q6 Register Offsets */
+#define QDSP6SS_RST_EVB			0x010
+
+/* AXI Halting Registers */
+#define MSS_Q6_HALT_BASE		0x180
+#define MSS_MODEM_HALT_BASE		0x200
+#define MSS_NC_HALT_BASE		0x280
+
+/* RMB Status Register Values */
+#define STATUS_PBL_SUCCESS		0x1
+#define STATUS_XPU_UNLOCKED		0x1
+#define STATUS_XPU_UNLOCKED_SCRIBBLED	0x2
+
+/* PBL/MBA interface registers */
+#define RMB_MBA_IMAGE			0x00
+#define RMB_PBL_STATUS			0x04
+#define RMB_MBA_COMMAND			0x08
+#define RMB_MBA_STATUS			0x0C
+#define RMB_PMI_META_DATA		0x10
+#define RMB_PMI_CODE_START		0x14
+#define RMB_PMI_CODE_LENGTH		0x18
+
+#define MAX_VDD_MX_UV			1150000
+
+#define POLL_INTERVAL_US		50
+
+#define CMD_META_DATA_READY		0x1
+#define CMD_LOAD_READY			0x2
+
+#define STATUS_META_DATA_AUTH_SUCCESS	0x3
+#define STATUS_AUTH_COMPLETE		0x4
+
+/* External BHS */
+#define EXTERNAL_BHS_ON			BIT(0)
+#define EXTERNAL_BHS_STATUS		BIT(4)
+#define BHS_TIMEOUT_US			50
+
+static int pbl_mba_boot_timeout_ms = 1000;
+module_param(pbl_mba_boot_timeout_ms, int, S_IRUGO | S_IWUSR);
+
+static int modem_auth_timeout_ms = 10000;
+module_param(modem_auth_timeout_ms, int, S_IRUGO | S_IWUSR);
+
+static int pil_msa_pbl_power_up(struct q6v5_data *drv)
+{
+	int ret = 0;
+	struct device *dev = drv->desc.dev;
+	u32 regval;
+
+	if (drv->vreg) {
+		ret = regulator_enable(drv->vreg);
+		if (ret)
+			dev_err(dev, "Failed to enable modem regulator.\n");
+	}
+
+	if (drv->cxrail_bhs) {
+		regval = readl_relaxed(drv->cxrail_bhs);
+		regval |= EXTERNAL_BHS_ON;
+		writel_relaxed(regval, drv->cxrail_bhs);
+
+		ret = readl_poll_timeout(drv->cxrail_bhs, regval,
+			regval & EXTERNAL_BHS_STATUS, 1, BHS_TIMEOUT_US);
+	}
+
+	return ret;
+}
+
+static int pil_msa_pbl_power_down(struct q6v5_data *drv)
+{
+	u32 regval;
+
+	if (drv->cxrail_bhs) {
+		regval = readl_relaxed(drv->cxrail_bhs);
+		regval &= ~EXTERNAL_BHS_ON;
+		writel_relaxed(regval, drv->cxrail_bhs);
+	}
+
+	if (drv->vreg)
+		return regulator_disable(drv->vreg);
+
+	return 0;
+}
+
+static int pil_msa_pbl_enable_clks(struct q6v5_data *drv)
+{
+	int ret;
+
+	ret = clk_prepare_enable(drv->ahb_clk);
+	if (ret)
+		goto err_ahb_clk;
+	ret = clk_prepare_enable(drv->axi_clk);
+	if (ret)
+		goto err_axi_clk;
+	ret = clk_prepare_enable(drv->rom_clk);
+	if (ret)
+		goto err_rom_clk;
+
+	return 0;
+
+err_rom_clk:
+	clk_disable_unprepare(drv->axi_clk);
+err_axi_clk:
+	clk_disable_unprepare(drv->ahb_clk);
+err_ahb_clk:
+	return ret;
+}
+
+static void pil_msa_pbl_disable_clks(struct q6v5_data *drv)
+{
+	clk_disable_unprepare(drv->rom_clk);
+	clk_disable_unprepare(drv->axi_clk);
+	clk_disable_unprepare(drv->ahb_clk);
+}
+
+static int pil_msa_wait_for_mba_ready(struct q6v5_data *drv)
+{
+	struct device *dev = drv->desc.dev;
+	int ret;
+	u32 status;
+
+	/* Wait for PBL completion. */
+	ret = readl_poll_timeout(drv->rmb_base + RMB_PBL_STATUS, status,
+		status != 0, POLL_INTERVAL_US, pbl_mba_boot_timeout_ms * 1000);
+	if (ret) {
+		dev_err(dev, "PBL boot timed out\n");
+		return ret;
+	}
+	if (status != STATUS_PBL_SUCCESS) {
+		dev_err(dev, "PBL returned unexpected status %d\n", status);
+		return -EINVAL;
+	}
+
+	/* Wait for MBA completion. */
+	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
+		status != 0, POLL_INTERVAL_US, pbl_mba_boot_timeout_ms * 1000);
+	if (ret) {
+		dev_err(dev, "MBA boot timed out\n");
+		return ret;
+	}
+	if (status != STATUS_XPU_UNLOCKED &&
+	    status != STATUS_XPU_UNLOCKED_SCRIBBLED) {
+		dev_err(dev, "MBA returned unexpected status %d\n", status);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int pil_msa_pbl_shutdown(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+
+	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_Q6_HALT_BASE);
+	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_MODEM_HALT_BASE);
+	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_NC_HALT_BASE);
+
+	writel_relaxed(1, drv->restart_reg);
+
+	if (drv->is_booted) {
+		pil_msa_pbl_disable_clks(drv);
+		pil_msa_pbl_power_down(drv);
+		drv->is_booted = false;
+	}
+
+	return 0;
+}
+
+static int pil_msa_pbl_reset(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
+	int ret;
+
+	/*
+	 * Bring subsystem out of reset and enable required
+	 * regulators and clocks.
+	 */
+	ret = pil_msa_pbl_power_up(drv);
+	if (ret)
+		goto err_power;
+
+	/* Deassert reset to subsystem and wait for propagation */
+	writel_relaxed(0, drv->restart_reg);
+	mb();
+	udelay(2);
+
+	ret = pil_msa_pbl_enable_clks(drv);
+	if (ret)
+		goto err_clks;
+
+	/* Program Image Address */
+	if (drv->self_auth) {
+		writel_relaxed(start_addr, drv->rmb_base + RMB_MBA_IMAGE);
+		/* Ensure write to RMB base occurs before reset is released. */
+		mb();
+	} else {
+		writel_relaxed((start_addr >> 4) & 0x0FFFFFF0,
+				drv->reg_base + QDSP6SS_RST_EVB);
+	}
+
+	ret = pil_q6v5_reset(pil);
+	if (ret)
+		goto err_q6v5_reset;
+
+	/* Wait for MBA to start. Check for PBL and MBA errors while waiting. */
+	if (drv->self_auth) {
+		ret = pil_msa_wait_for_mba_ready(drv);
+		if (ret)
+			goto err_auth;
+	}
+
+	drv->is_booted = true;
+
+	return 0;
+
+err_auth:
+	pil_q6v5_shutdown(pil);
+err_q6v5_reset:
+	pil_msa_pbl_disable_clks(drv);
+err_clks:
+	pil_msa_pbl_power_down(drv);
+err_power:
+	return ret;
+}
+
+static int pil_msa_pbl_make_proxy_votes(struct pil_desc *pil)
+{
+	int ret;
+	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+
+	ret = regulator_set_voltage(drv->vreg_mx, VDD_MSS_UV, MAX_VDD_MX_UV);
+	if (ret) {
+		dev_err(pil->dev, "Failed to request vreg_mx voltage\n");
+		return ret;
+	}
+
+	ret = regulator_enable(drv->vreg_mx);
+	if (ret) {
+		dev_err(pil->dev, "Failed to enable vreg_mx\n");
+		regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
+		return ret;
+	}
+
+	ret = pil_q6v5_make_proxy_votes(pil);
+	if (ret) {
+		regulator_disable(drv->vreg_mx);
+		regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
+	}
+
+	return ret;
+}
+
+static void pil_msa_pbl_remove_proxy_votes(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+	pil_q6v5_remove_proxy_votes(pil);
+	regulator_disable(drv->vreg_mx);
+	regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
+}
+
+struct pil_reset_ops pil_msa_pbl_ops = {
+	.proxy_vote = pil_msa_pbl_make_proxy_votes,
+	.proxy_unvote = pil_msa_pbl_remove_proxy_votes,
+	.auth_and_reset = pil_msa_pbl_reset,
+	.shutdown = pil_msa_pbl_shutdown,
+};
+
+static int pil_msa_mba_make_proxy_votes(struct pil_desc *pil)
+{
+	int ret;
+	struct mba_data *drv = container_of(pil, struct mba_data, desc);
+
+	ret = clk_prepare_enable(drv->xo);
+	if (ret) {
+		dev_err(pil->dev, "Failed to enable XO\n");
+		return ret;
+	}
+	return 0;
+}
+
+static void pil_msa_mba_remove_proxy_votes(struct pil_desc *pil)
+{
+	struct mba_data *drv = container_of(pil, struct mba_data, desc);
+	clk_disable_unprepare(drv->xo);
+}
+
+static int pil_msa_mba_init_image(struct pil_desc *pil,
+				  const u8 *metadata, size_t size)
+{
+	struct mba_data *drv = container_of(pil, struct mba_data, desc);
+	void *mdata_virt;
+	dma_addr_t mdata_phys;
+	s32 status;
+	int ret;
+
+	/* Make metadata physically contiguous and 4K aligned. */
+	mdata_virt = dma_alloc_coherent(pil->dev, size, &mdata_phys,
+					GFP_KERNEL);
+	if (!mdata_virt) {
+		dev_err(pil->dev, "MBA metadata buffer allocation failed\n");
+		return -ENOMEM;
+	}
+	memcpy(mdata_virt, metadata, size);
+	/* wmb() ensures copy completes prior to starting authentication. */
+	wmb();
+
+	/* Initialize length counter to 0 */
+	writel_relaxed(0, drv->rmb_base + RMB_PMI_CODE_LENGTH);
+
+	/* Pass address of meta-data to the MBA and perform authentication */
+	writel_relaxed(mdata_phys, drv->rmb_base + RMB_PMI_META_DATA);
+	writel_relaxed(CMD_META_DATA_READY, drv->rmb_base + RMB_MBA_COMMAND);
+	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
+		status == STATUS_META_DATA_AUTH_SUCCESS || status < 0,
+		POLL_INTERVAL_US, modem_auth_timeout_ms * 1000);
+	if (ret) {
+		dev_err(pil->dev, "MBA authentication of headers timed out\n");
+	} else if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d for headers\n",
+				status);
+		ret = -EINVAL;
+	}
+
+	dma_free_coherent(pil->dev, size, mdata_virt, mdata_phys);
+
+	return ret;
+}
+
+static int pil_msa_mba_verify_blob(struct pil_desc *pil, phys_addr_t phy_addr,
+				   size_t size)
+{
+	struct mba_data *drv = container_of(pil, struct mba_data, desc);
+	s32 status;
+	u32 img_length = readl_relaxed(drv->rmb_base + RMB_PMI_CODE_LENGTH);
+
+	/* Begin image authentication */
+	if (img_length == 0) {
+		writel_relaxed(phy_addr, drv->rmb_base + RMB_PMI_CODE_START);
+		writel_relaxed(CMD_LOAD_READY, drv->rmb_base + RMB_MBA_COMMAND);
+	}
+	/* Increment length counter */
+	img_length += size;
+	writel_relaxed(img_length, drv->rmb_base + RMB_PMI_CODE_LENGTH);
+
+	status = readl_relaxed(drv->rmb_base + RMB_MBA_STATUS);
+	if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d\n", status);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int pil_msa_mba_auth(struct pil_desc *pil)
+{
+	struct mba_data *drv = container_of(pil, struct mba_data, desc);
+	int ret;
+	s32 status;
+
+	/* Wait for all segments to be authenticated or an error to occur */
+	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
+			status == STATUS_AUTH_COMPLETE || status < 0,
+			50, modem_auth_timeout_ms * 1000);
+	if (ret) {
+		dev_err(pil->dev, "MBA authentication of image timed out\n");
+	} else if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d for image\n", status);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+struct pil_reset_ops pil_msa_mba_ops = {
+	.init_image = pil_msa_mba_init_image,
+	.proxy_vote = pil_msa_mba_make_proxy_votes,
+	.proxy_unvote = pil_msa_mba_remove_proxy_votes,
+	.verify_blob = pil_msa_mba_verify_blob,
+	.auth_and_reset = pil_msa_mba_auth,
+};
diff --git a/arch/arm/mach-msm/pil-msa.h b/arch/arm/mach-msm/pil-msa.h
new file mode 100644
index 0000000..9a7b56e
--- /dev/null
+++ b/arch/arm/mach-msm/pil-msa.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MSM_PIL_MSA_H
+#define __MSM_PIL_MSA_H
+
+#include "peripheral-loader.h"
+
+#define VDD_MSS_UV	1050000
+
+struct mba_data {
+	void __iomem *rmb_base;
+	struct clk *xo;
+	struct pil_desc desc;
+};
+
+extern struct pil_reset_ops pil_msa_pbl_ops;
+extern struct pil_reset_ops pil_msa_mba_ops;
+
+#endif
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 1085408..80c0862 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -336,6 +336,7 @@
 		pr_err("Ignoring wcnss bite irq, restart in progress\n");
 		return IRQ_HANDLED;
 	}
+	wcnss_pronto_log_debug_regs();
 
 	drv->restart_inprogress = true;
 	restart_wcnss(drv);
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index b83202b..4d76c08 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -35,64 +35,21 @@
 
 #include "peripheral-loader.h"
 #include "pil-q6v5.h"
+#include "pil-msa.h"
 #include "sysmon.h"
 
-/* Q6 Register Offsets */
-#define QDSP6SS_RST_EVB			0x010
+#define MAX_VDD_MSS_UV		1150000
+#define PROXY_TIMEOUT_MS	10000
+#define MAX_SSR_REASON_LEN	81U
+#define STOP_ACK_TIMEOUT_MS	1000
 
-/* AXI Halting Registers */
-#define MSS_Q6_HALT_BASE		0x180
-#define MSS_MODEM_HALT_BASE		0x200
-#define MSS_NC_HALT_BASE		0x280
-
-/* RMB Status Register Values */
-#define STATUS_PBL_SUCCESS		0x1
-#define STATUS_XPU_UNLOCKED		0x1
-#define STATUS_XPU_UNLOCKED_SCRIBBLED	0x2
-
-/* PBL/MBA interface registers */
-#define RMB_MBA_IMAGE			0x00
-#define RMB_PBL_STATUS			0x04
-#define RMB_MBA_COMMAND			0x08
-#define RMB_MBA_STATUS			0x0C
-#define RMB_PMI_META_DATA		0x10
-#define RMB_PMI_CODE_START		0x14
-#define RMB_PMI_CODE_LENGTH		0x18
-
-#define VDD_MSS_UV			1050000
-#define MAX_VDD_MSS_UV			1150000
-#define MAX_VDD_MX_UV			1150000
-
-#define PROXY_TIMEOUT_MS		10000
-#define POLL_INTERVAL_US		50
-
-#define CMD_META_DATA_READY		0x1
-#define CMD_LOAD_READY			0x2
-
-#define STATUS_META_DATA_AUTH_SUCCESS	0x3
-#define STATUS_AUTH_COMPLETE		0x4
-
-#define MAX_SSR_REASON_LEN 81U
-
-/* External BHS */
-#define EXTERNAL_BHS_ON			BIT(0)
-#define EXTERNAL_BHS_STATUS		BIT(4)
-#define BHS_TIMEOUT_US			50
-
-#define STOP_ACK_TIMEOUT_MS		1000
-
-struct mba_data {
-	void __iomem *rmb_base;
-	void __iomem *io_clamp_reg;
-	struct pil_desc desc;
+struct modem_data {
+	struct mba_data *mba;
+	struct q6v5_data *q6;
 	struct subsys_device *subsys;
 	struct subsys_desc subsys_desc;
 	void *adsp_state_notifier;
-	u32 img_length;
-	struct q6v5_data *q6;
-	bool self_auth;
 	void *ramdump_dev;
-	void *smem_ramdump_dev;
 	bool crash_shutdown;
 	bool ignore_errors;
 	int err_fatal_irq;
@@ -101,363 +58,16 @@
 	struct completion stop_ack;
 };
 
-static int pbl_mba_boot_timeout_ms = 1000;
-module_param(pbl_mba_boot_timeout_ms, int, S_IRUGO | S_IWUSR);
-
-static int modem_auth_timeout_ms = 10000;
-module_param(modem_auth_timeout_ms, int, S_IRUGO | S_IWUSR);
-
-static int pil_mss_power_up(struct q6v5_data *drv)
-{
-	int ret = 0;
-	struct device *dev = drv->desc.dev;
-	u32 regval;
-
-	if (drv->vreg) {
-		ret = regulator_enable(drv->vreg);
-		if (ret)
-			dev_err(dev, "Failed to enable modem regulator.\n");
-	}
-
-	if (drv->cxrail_bhs) {
-		regval = readl_relaxed(drv->cxrail_bhs);
-		regval |= EXTERNAL_BHS_ON;
-		writel_relaxed(regval, drv->cxrail_bhs);
-
-		ret = readl_poll_timeout(drv->cxrail_bhs, regval,
-			regval & EXTERNAL_BHS_STATUS, 1, BHS_TIMEOUT_US);
-	}
-
-	return ret;
-}
-
-static int pil_mss_power_down(struct q6v5_data *drv)
-{
-	u32 regval;
-
-	if (drv->cxrail_bhs) {
-		regval = readl_relaxed(drv->cxrail_bhs);
-		regval &= ~EXTERNAL_BHS_ON;
-		writel_relaxed(regval, drv->cxrail_bhs);
-	}
-
-	if (drv->vreg)
-		return regulator_disable(drv->vreg);
-
-	return 0;
-}
-
-static int pil_mss_enable_clks(struct q6v5_data *drv)
-{
-	int ret;
-
-	ret = clk_prepare_enable(drv->ahb_clk);
-	if (ret)
-		goto err_ahb_clk;
-	ret = clk_prepare_enable(drv->axi_clk);
-	if (ret)
-		goto err_axi_clk;
-	ret = clk_prepare_enable(drv->rom_clk);
-	if (ret)
-		goto err_rom_clk;
-
-	return 0;
-
-err_rom_clk:
-	clk_disable_unprepare(drv->axi_clk);
-err_axi_clk:
-	clk_disable_unprepare(drv->ahb_clk);
-err_ahb_clk:
-	return ret;
-}
-
-static void pil_mss_disable_clks(struct q6v5_data *drv)
-{
-	clk_disable_unprepare(drv->rom_clk);
-	clk_disable_unprepare(drv->axi_clk);
-	clk_disable_unprepare(drv->ahb_clk);
-}
-
-static int wait_for_mba_ready(struct q6v5_data *drv)
-{
-	struct device *dev = drv->desc.dev;
-	struct mba_data *mba = platform_get_drvdata(to_platform_device(dev));
-	int ret;
-	u32 status;
-
-	/* Wait for PBL completion. */
-	ret = readl_poll_timeout(mba->rmb_base + RMB_PBL_STATUS, status,
-		status != 0, POLL_INTERVAL_US, pbl_mba_boot_timeout_ms * 1000);
-	if (ret) {
-		dev_err(dev, "PBL boot timed out\n");
-		return ret;
-	}
-	if (status != STATUS_PBL_SUCCESS) {
-		dev_err(dev, "PBL returned unexpected status %d\n", status);
-		return -EINVAL;
-	}
-
-	/* Wait for MBA completion. */
-	ret = readl_poll_timeout(mba->rmb_base + RMB_MBA_STATUS, status,
-		status != 0, POLL_INTERVAL_US, pbl_mba_boot_timeout_ms * 1000);
-	if (ret) {
-		dev_err(dev, "MBA boot timed out\n");
-		return ret;
-	}
-	if (status != STATUS_XPU_UNLOCKED &&
-	    status != STATUS_XPU_UNLOCKED_SCRIBBLED) {
-		dev_err(dev, "MBA returned unexpected status %d\n", status);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int pil_mss_shutdown(struct pil_desc *pil)
-{
-	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
-
-	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_Q6_HALT_BASE);
-	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_MODEM_HALT_BASE);
-	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_NC_HALT_BASE);
-
-	writel_relaxed(1, drv->restart_reg);
-
-	if (drv->is_booted) {
-		pil_mss_disable_clks(drv);
-		pil_mss_power_down(drv);
-		drv->is_booted = false;
-	}
-
-	return 0;
-}
-
-static int pil_mss_reset(struct pil_desc *pil)
-{
-	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
-	struct platform_device *pdev = to_platform_device(pil->dev);
-	struct mba_data *mba = platform_get_drvdata(pdev);
-	phys_addr_t start_addr = pil_get_entry_addr(pil);
-	int ret;
-
-	/*
-	 * Bring subsystem out of reset and enable required
-	 * regulators and clocks.
-	 */
-	ret = pil_mss_power_up(drv);
-	if (ret)
-		goto err_power;
-
-	/* Deassert reset to subsystem and wait for propagation */
-	writel_relaxed(0, drv->restart_reg);
-	mb();
-	udelay(2);
-
-	ret = pil_mss_enable_clks(drv);
-	if (ret)
-		goto err_clks;
-
-	/* Program Image Address */
-	if (mba->self_auth) {
-		writel_relaxed(start_addr, mba->rmb_base + RMB_MBA_IMAGE);
-		/* Ensure write to RMB base occurs before reset is released. */
-		mb();
-	} else {
-		writel_relaxed((start_addr >> 4) & 0x0FFFFFF0,
-				drv->reg_base + QDSP6SS_RST_EVB);
-	}
-
-	ret = pil_q6v5_reset(pil);
-	if (ret)
-		goto err_q6v5_reset;
-
-	/* Wait for MBA to start. Check for PBL and MBA errors while waiting. */
-	if (mba->self_auth) {
-		ret = wait_for_mba_ready(drv);
-		if (ret)
-			goto err_auth;
-	}
-
-	drv->is_booted = true;
-
-	return 0;
-
-err_auth:
-	pil_q6v5_shutdown(pil);
-err_q6v5_reset:
-	pil_mss_disable_clks(drv);
-err_clks:
-	pil_mss_power_down(drv);
-err_power:
-	return ret;
-}
-
-static int pil_q6v5_mss_make_proxy_votes(struct pil_desc *pil)
-{
-	int ret;
-	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
-
-	ret = regulator_set_voltage(drv->vreg_mx, VDD_MSS_UV, MAX_VDD_MX_UV);
-	if (ret) {
-		dev_err(pil->dev, "Failed to request vreg_mx voltage\n");
-		return ret;
-	}
-
-	ret = regulator_enable(drv->vreg_mx);
-	if (ret) {
-		dev_err(pil->dev, "Failed to enable vreg_mx\n");
-		regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
-		return ret;
-	}
-
-	ret = pil_q6v5_make_proxy_votes(pil);
-	if (ret) {
-		regulator_disable(drv->vreg_mx);
-		regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
-	}
-
-	return ret;
-}
-
-static void pil_q6v5_mss_remove_proxy_votes(struct pil_desc *pil)
-{
-	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
-	pil_q6v5_remove_proxy_votes(pil);
-	regulator_disable(drv->vreg_mx);
-	regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
-}
-
-static struct pil_reset_ops pil_mss_ops = {
-	.proxy_vote = pil_q6v5_mss_make_proxy_votes,
-	.proxy_unvote = pil_q6v5_mss_remove_proxy_votes,
-	.auth_and_reset = pil_mss_reset,
-	.shutdown = pil_mss_shutdown,
-};
-
-static int pil_mba_make_proxy_votes(struct pil_desc *pil)
-{
-	int ret;
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-
-	ret = clk_prepare_enable(drv->q6->xo);
-	if (ret) {
-		dev_err(pil->dev, "Failed to enable XO\n");
-		return ret;
-	}
-	return 0;
-}
-
-static void pil_mba_remove_proxy_votes(struct pil_desc *pil)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	clk_disable_unprepare(drv->q6->xo);
-}
-
-static int pil_mba_init_image(struct pil_desc *pil,
-			      const u8 *metadata, size_t size)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	void *mdata_virt;
-	dma_addr_t mdata_phys;
-	s32 status;
-	int ret;
-
-	/* Make metadata physically contiguous and 4K aligned. */
-	mdata_virt = dma_alloc_coherent(pil->dev, size, &mdata_phys,
-					GFP_KERNEL);
-	if (!mdata_virt) {
-		dev_err(pil->dev, "MBA metadata buffer allocation failed\n");
-		return -ENOMEM;
-	}
-	memcpy(mdata_virt, metadata, size);
-	/* wmb() ensures copy completes prior to starting authentication. */
-	wmb();
-
-	/* Initialize length counter to 0 */
-	writel_relaxed(0, drv->rmb_base + RMB_PMI_CODE_LENGTH);
-	drv->img_length = 0;
-
-	/* Pass address of meta-data to the MBA and perform authentication */
-	writel_relaxed(mdata_phys, drv->rmb_base + RMB_PMI_META_DATA);
-	writel_relaxed(CMD_META_DATA_READY, drv->rmb_base + RMB_MBA_COMMAND);
-	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
-		status == STATUS_META_DATA_AUTH_SUCCESS || status < 0,
-		POLL_INTERVAL_US, modem_auth_timeout_ms * 1000);
-	if (ret) {
-		dev_err(pil->dev, "MBA authentication of headers timed out\n");
-	} else if (status < 0) {
-		dev_err(pil->dev, "MBA returned error %d for headers\n",
-				status);
-		ret = -EINVAL;
-	}
-
-	dma_free_coherent(pil->dev, size, mdata_virt, mdata_phys);
-
-	return ret;
-}
-
-static int pil_mba_verify_blob(struct pil_desc *pil, phys_addr_t phy_addr,
-			       size_t size)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	s32 status;
-
-	/* Begin image authentication */
-	if (drv->img_length == 0) {
-		writel_relaxed(phy_addr, drv->rmb_base + RMB_PMI_CODE_START);
-		writel_relaxed(CMD_LOAD_READY, drv->rmb_base + RMB_MBA_COMMAND);
-	}
-	/* Increment length counter */
-	drv->img_length += size;
-	writel_relaxed(drv->img_length, drv->rmb_base + RMB_PMI_CODE_LENGTH);
-
-	status = readl_relaxed(drv->rmb_base + RMB_MBA_STATUS);
-	if (status < 0) {
-		dev_err(pil->dev, "MBA returned error %d\n", status);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int pil_mba_auth(struct pil_desc *pil)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	int ret;
-	s32 status;
-
-	/* Wait for all segments to be authenticated or an error to occur */
-	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
-			status == STATUS_AUTH_COMPLETE || status < 0,
-			50, modem_auth_timeout_ms * 1000);
-	if (ret) {
-		dev_err(pil->dev, "MBA authentication of image timed out\n");
-	} else if (status < 0) {
-		dev_err(pil->dev, "MBA returned error %d for image\n", status);
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static struct pil_reset_ops pil_mba_ops = {
-	.init_image = pil_mba_init_image,
-	.proxy_vote = pil_mba_make_proxy_votes,
-	.proxy_unvote = pil_mba_remove_proxy_votes,
-	.verify_blob = pil_mba_verify_blob,
-	.auth_and_reset = pil_mba_auth,
-};
-
-#define subsys_to_drv(d) container_of(d, struct mba_data, subsys_desc)
+#define subsys_to_drv(d) container_of(d, struct modem_data, subsys_desc)
 
 static void log_modem_sfr(void)
 {
 	u32 size;
 	char *smem_reason, reason[MAX_SSR_REASON_LEN];
 
-	smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
+	smem_reason = smem_get_entry_no_rlock(SMEM_SSR_REASON_MSS0, &size);
 	if (!smem_reason || !size) {
-		pr_err("modem subsystem failure reason: (unknown, smem_get_entry failed).\n");
+		pr_err("modem subsystem failure reason: (unknown, smem_get_entry_no_rlock failed).\n");
 		return;
 	}
 	if (!smem_reason[0]) {
@@ -472,7 +82,7 @@
 	wmb();
 }
 
-static void restart_modem(struct mba_data *drv)
+static void restart_modem(struct modem_data *drv)
 {
 	log_modem_sfr();
 	drv->ignore_errors = true;
@@ -481,7 +91,7 @@
 
 static irqreturn_t modem_err_fatal_intr_handler(int irq, void *dev_id)
 {
-	struct mba_data *drv = dev_id;
+	struct modem_data *drv = dev_id;
 
 	/* Ignore if we're the one that set the force stop GPIO */
 	if (drv->crash_shutdown)
@@ -495,7 +105,7 @@
 
 static irqreturn_t modem_stop_ack_intr_handler(int irq, void *dev_id)
 {
-	struct mba_data *drv = dev_id;
+	struct modem_data *drv = dev_id;
 	pr_info("Received stop ack interrupt from modem\n");
 	complete(&drv->stop_ack);
 	return IRQ_HANDLED;
@@ -503,7 +113,7 @@
 
 static int modem_shutdown(const struct subsys_desc *subsys)
 {
-	struct mba_data *drv = subsys_to_drv(subsys);
+	struct modem_data *drv = subsys_to_drv(subsys);
 	unsigned long ret;
 
 	if (subsys->is_not_loadable)
@@ -518,14 +128,14 @@
 		gpio_set_value(drv->force_stop_gpio, 0);
 	}
 
-	pil_shutdown(&drv->desc);
+	pil_shutdown(&drv->mba->desc);
 	pil_shutdown(&drv->q6->desc);
 	return 0;
 }
 
 static int modem_powerup(const struct subsys_desc *subsys)
 {
-	struct mba_data *drv = subsys_to_drv(subsys);
+	struct modem_data *drv = subsys_to_drv(subsys);
 	int ret;
 
 	if (subsys->is_not_loadable)
@@ -535,12 +145,12 @@
 	 * run concurrently with either the watchdog bite error handler or the
 	 * SMSM callback, making it safe to unset the flag below.
 	 */
-	init_completion(&drv->stop_ack);
+	INIT_COMPLETION(drv->stop_ack);
 	drv->ignore_errors = false;
 	ret = pil_boot(&drv->q6->desc);
 	if (ret)
 		return ret;
-	ret = pil_boot(&drv->desc);
+	ret = pil_boot(&drv->mba->desc);
 	if (ret)
 		pil_shutdown(&drv->q6->desc);
 	return ret;
@@ -548,7 +158,7 @@
 
 static void modem_crash_shutdown(const struct subsys_desc *subsys)
 {
-	struct mba_data *drv = subsys_to_drv(subsys);
+	struct modem_data *drv = subsys_to_drv(subsys);
 	drv->crash_shutdown = true;
 	if (!subsys_get_crash_status(drv->subsys)) {
 		gpio_set_value(drv->force_stop_gpio, 1);
@@ -556,13 +166,9 @@
 	}
 }
 
-static struct ramdump_segment smem_segments[] = {
-	{0x0FA00000, 0x0FC00000 - 0x0FA00000},
-};
-
 static int modem_ramdump(int enable, const struct subsys_desc *subsys)
 {
-	struct mba_data *drv = subsys_to_drv(subsys);
+	struct modem_data *drv = subsys_to_drv(subsys);
 	int ret;
 
 	if (!enable)
@@ -572,20 +178,10 @@
 	if (ret)
 		return ret;
 
-	ret = pil_do_ramdump(&drv->desc, drv->ramdump_dev);
-	if (ret < 0) {
+	ret = pil_do_ramdump(&drv->mba->desc, drv->ramdump_dev);
+	if (ret < 0)
 		pr_err("Unable to dump modem fw memory (rc = %d).\n", ret);
-		goto out;
-	}
 
-	ret = do_elf_ramdump(drv->smem_ramdump_dev, smem_segments,
-		ARRAY_SIZE(smem_segments));
-	if (ret < 0) {
-		pr_err("Unable to dump smem memory (rc = %d).\n", ret);
-		goto out;
-	}
-
-out:
 	pil_shutdown(&drv->q6->desc);
 	return ret;
 }
@@ -606,7 +202,7 @@
 
 static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
 {
-	struct mba_data *drv = dev_id;
+	struct modem_data *drv = dev_id;
 	if (drv->ignore_errors)
 		return IRQ_HANDLED;
 	pr_err("Watchdog bite received from modem software!\n");
@@ -618,16 +214,16 @@
 static int mss_start(const struct subsys_desc *desc)
 {
 	int ret;
-	struct mba_data *drv = subsys_to_drv(desc);
+	struct modem_data *drv = subsys_to_drv(desc);
 
 	if (desc->is_not_loadable)
 		return 0;
 
-	init_completion(&drv->stop_ack);
+	INIT_COMPLETION(drv->stop_ack);
 	ret = pil_boot(&drv->q6->desc);
 	if (ret)
 		return ret;
-	ret = pil_boot(&drv->desc);
+	ret = pil_boot(&drv->mba->desc);
 	if (ret)
 		pil_shutdown(&drv->q6->desc);
 	return ret;
@@ -635,16 +231,16 @@
 
 static void mss_stop(const struct subsys_desc *desc)
 {
-	struct mba_data *drv = subsys_to_drv(desc);
+	struct modem_data *drv = subsys_to_drv(desc);
 
 	if (desc->is_not_loadable)
 		return;
 
-	pil_shutdown(&drv->desc);
+	pil_shutdown(&drv->mba->desc);
 	pil_shutdown(&drv->q6->desc);
 }
 
-static int __devinit pil_subsys_init(struct mba_data *drv,
+static int __devinit pil_subsys_init(struct modem_data *drv,
 					struct platform_device *pdev)
 {
 	int irq, ret;
@@ -688,14 +284,6 @@
 		goto err_ramdump;
 	}
 
-	drv->smem_ramdump_dev = create_ramdump_device("smem-modem", &pdev->dev);
-	if (!drv->smem_ramdump_dev) {
-		pr_err("%s: Unable to create an smem ramdump device.\n",
-			__func__);
-		ret = -ENOMEM;
-		goto err_ramdump_smem;
-	}
-
 	ret = devm_request_irq(&pdev->dev, irq, modem_wdog_bite_irq,
 				IRQF_TRIGGER_RISING, "modem_wdog", drv);
 	if (ret < 0) {
@@ -731,8 +319,6 @@
 	return 0;
 
 err_irq:
-	destroy_ramdump_device(drv->smem_ramdump_dev);
-err_ramdump_smem:
 	destroy_ramdump_device(drv->ramdump_dev);
 err_ramdump:
 	subsys_unregister(drv->subsys);
@@ -740,10 +326,11 @@
 	return ret;
 }
 
-static int __devinit pil_mss_loadable_init(struct mba_data *drv,
+static int __devinit pil_mss_loadable_init(struct modem_data *drv,
 					struct platform_device *pdev)
 {
 	struct q6v5_data *q6;
+	struct mba_data *mba;
 	struct pil_desc *q6_desc, *mba_desc;
 	struct resource *res;
 	struct property *prop;
@@ -758,25 +345,32 @@
 	if (clk_ready < 0)
 		return clk_ready;
 
+	mba = devm_kzalloc(&pdev->dev, sizeof(*mba), GFP_KERNEL);
+	if (IS_ERR(mba))
+		return PTR_ERR(mba);
+	drv->mba = mba;
+
 	q6 = pil_q6v5_init(pdev);
 	if (IS_ERR(q6))
 		return PTR_ERR(q6);
 	drv->q6 = q6;
+	drv->mba->xo = q6->xo;
 
 	q6_desc = &q6->desc;
-	q6_desc->ops = &pil_mss_ops;
+	q6_desc->ops = &pil_msa_pbl_ops;
 	q6_desc->owner = THIS_MODULE;
 	q6_desc->proxy_timeout = PROXY_TIMEOUT_MS;
 	q6_desc->proxy_unvote_irq = clk_ready;
 
-	drv->self_auth = of_property_read_bool(pdev->dev.of_node,
+	q6->self_auth = of_property_read_bool(pdev->dev.of_node,
 							"qcom,pil-self-auth");
-	if (drv->self_auth) {
+	if (q6->self_auth) {
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						    "rmb_base");
-		drv->rmb_base = devm_request_and_ioremap(&pdev->dev, res);
-		if (!drv->rmb_base)
+		q6->rmb_base = devm_request_and_ioremap(&pdev->dev, res);
+		if (!q6->rmb_base)
 			return -ENOMEM;
+		mba->rmb_base = q6->rmb_base;
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "restart_reg");
@@ -830,10 +424,10 @@
 	if (ret)
 		return ret;
 
-	mba_desc = &drv->desc;
+	mba_desc = &mba->desc;
 	mba_desc->name = "modem";
 	mba_desc->dev = &pdev->dev;
-	mba_desc->ops = &pil_mba_ops;
+	mba_desc->ops = &pil_msa_mba_ops;
 	mba_desc->owner = THIS_MODULE;
 	mba_desc->proxy_timeout = PROXY_TIMEOUT_MS;
 	mba_desc->proxy_unvote_irq = clk_ready;
@@ -852,7 +446,7 @@
 
 static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
 {
-	struct mba_data *drv;
+	struct modem_data *drv;
 	int ret, err_fatal_gpio, is_not_loadable, stop_ack_gpio;
 
 	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
@@ -870,6 +464,8 @@
 			return ret;
 	}
 
+	init_completion(&drv->stop_ack);
+
 	/* Get the IRQ from the GPIO for registering inbound handler */
 	err_fatal_gpio = of_get_named_gpio(pdev->dev.of_node,
 			"qcom,gpio-err-fatal", 0);
@@ -901,14 +497,13 @@
 
 static int __devexit pil_mss_driver_exit(struct platform_device *pdev)
 {
-	struct mba_data *drv = platform_get_drvdata(pdev);
+	struct modem_data *drv = platform_get_drvdata(pdev);
 
 	subsys_notif_unregister_notifier(drv->adsp_state_notifier,
 						&adsp_state_notifier_block);
 	subsys_unregister(drv->subsys);
-	destroy_ramdump_device(drv->smem_ramdump_dev);
 	destroy_ramdump_device(drv->ramdump_dev);
-	pil_desc_release(&drv->desc);
+	pil_desc_release(&drv->mba->desc);
 	pil_desc_release(&drv->q6->desc);
 	return 0;
 }
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index 48d10df..b2fb7f7 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -22,6 +22,7 @@
 
 struct q6v5_data {
 	void __iomem *reg_base;
+	void __iomem *rmb_base;
 	void __iomem *cxrail_bhs;  /* External BHS register */
 	struct clk *xo;		   /* XO clock source */
 	struct clk *ahb_clk;	   /* PIL access to registers */
@@ -37,6 +38,7 @@
 	struct regulator *vreg_pll;
 	bool is_booted;
 	struct pil_desc desc;
+	bool self_auth;
 };
 
 int pil_q6v5_make_proxy_votes(struct pil_desc *pil);
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 146dc0b..dd0599b 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -31,7 +31,6 @@
 #include <linux/of_platform.h>
 #include <linux/regulator/krait-regulator.h>
 #include <linux/cpu.h>
-#include <linux/clk.h>
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
 #include <mach/system.h>
@@ -134,7 +133,6 @@
 static bool msm_no_ramp_down_pc;
 static struct msm_pm_sleep_status_data *msm_pm_slp_sts;
 static bool msm_pm_pc_reset_timer;
-static struct clk *pnoc_clk;
 
 static int msm_pm_get_pc_mode(struct device_node *node,
 		const char *key, uint32_t *pc_mode_val)
@@ -1134,24 +1132,9 @@
 		pm_sleep_ops = *ops;
 }
 
-int msm_suspend_prepare(void)
-{
-	if (pnoc_clk != NULL)
-		clk_disable_unprepare(pnoc_clk);
-	return 0;
-}
-
-void msm_suspend_wake(void)
-{
-	if (pnoc_clk != NULL)
-		clk_prepare_enable(pnoc_clk);
-}
-
 static const struct platform_suspend_ops msm_pm_ops = {
 	.enter = msm_pm_enter,
 	.valid = suspend_valid_only_mem,
-	.prepare_late = msm_suspend_prepare,
-	.wake = msm_suspend_wake,
 };
 
 static int __devinit msm_pm_snoc_client_probe(struct platform_device *pdev)
@@ -1285,14 +1268,90 @@
 	},
 };
 
+#ifdef CONFIG_ARM_LPAE
+static int msm_pm_idmap_add_pmd(pud_t *pud, unsigned long addr,
+				unsigned long end, unsigned long prot)
+{
+	pmd_t *pmd;
+	unsigned long next;
 
-static int __init msm_pm_setup_saved_state(void)
+	if (pud_none_or_clear_bad(pud) || (pud_val(*pud) & L_PGD_SWAPPER)) {
+		pmd = pmd_alloc_one(&init_mm, addr);
+		if (!pmd)
+			return -ENOMEM;
+
+		pud_populate(&init_mm, pud, pmd);
+		pmd += pmd_index(addr);
+	} else {
+		pmd = pmd_offset(pud, addr);
+	}
+
+	do {
+		next = pmd_addr_end(addr, end);
+		*pmd = __pmd((addr & PMD_MASK) | prot);
+		flush_pmd_entry(pmd);
+	} while (pmd++, addr = next, addr != end);
+
+	return 0;
+}
+#else   /* !CONFIG_ARM_LPAE */
+static int msm_pm_idmap_add_pmd(pud_t *pud, unsigned long addr,
+				unsigned long end, unsigned long prot)
+{
+	pmd_t *pmd = pmd_offset(pud, addr);
+
+	addr = (addr & PMD_MASK) | prot;
+	pmd[0] = __pmd(addr);
+	addr += SECTION_SIZE;
+	pmd[1] = __pmd(addr);
+	flush_pmd_entry(pmd);
+
+	return 0;
+}
+#endif  /* CONFIG_ARM_LPAE */
+
+static int msm_pm_idmap_add_pud(pgd_t *pgd, unsigned long addr,
+					unsigned long end,
+					unsigned long prot)
+{
+	pud_t *pud = pud_offset(pgd, addr);
+	unsigned long next;
+	int ret;
+
+	do {
+		next = pud_addr_end(addr, end);
+		ret = msm_pm_idmap_add_pmd(pud, addr, next, prot);
+		if (ret)
+			return ret;
+	} while (pud++, addr = next, addr != end);
+
+	return 0;
+}
+
+static int msm_pm_add_idmap(pgd_t *pgd, unsigned long addr,
+						unsigned long end,
+						unsigned long prot)
+{
+	unsigned long next;
+	int ret;
+
+	pgd += pgd_index(addr);
+	do {
+		next = pgd_addr_end(addr, end);
+		ret = msm_pm_idmap_add_pud(pgd, addr, next, prot);
+		if (ret)
+			return ret;
+	} while (pgd++, addr = next, addr != end);
+
+	return 0;
+}
+
+static int msm_pm_setup_pagetable(void)
 {
 	pgd_t *pc_pgd;
-	pmd_t *pmd;
-	unsigned long pmdval;
 	unsigned long exit_phys;
-	dma_addr_t temp_phys;
+	unsigned long end;
+	int ret;
 
 	/* Page table for cores to come back up safely. */
 	pc_pgd = pgd_alloc(&init_mm);
@@ -1301,12 +1360,33 @@
 
 	exit_phys = virt_to_phys(msm_pm_collapse_exit);
 
-	pmd = pmd_offset(pud_offset(pc_pgd + pgd_index(exit_phys),exit_phys),
-					exit_phys);
-	pmdval = (exit_phys & PGDIR_MASK) |
-		     PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
-	pmd[0] = __pmd(pmdval);
-	pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
+	/*
+	 * Make the (hopefully) reasonable assumption that the code size of
+	 * msm_pm_collapse_exit won't be more than a section in size
+	 */
+	end = exit_phys + SECTION_SIZE;
+
+	ret = msm_pm_add_idmap(pc_pgd, exit_phys, end,
+					PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
+
+	if (ret)
+		return ret;
+
+	msm_pm_pc_pgd = virt_to_phys(pc_pgd);
+	clean_caches((unsigned long)&msm_pm_pc_pgd, sizeof(msm_pm_pc_pgd),
+		     virt_to_phys(&msm_pm_pc_pgd));
+
+	return 0;
+}
+
+static int __init msm_pm_setup_saved_state(void)
+{
+	int ret;
+	dma_addr_t temp_phys;
+
+	ret = msm_pm_setup_pagetable();
+	if (ret)
+		return ret;
 
 	msm_saved_state = dma_zalloc_coherent(NULL, CPU_SAVED_STATE_SIZE *
 						num_possible_cpus(),
@@ -1322,19 +1402,6 @@
 	 */
 	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
-	 * start of msm_pm_collapse_exit().
-	 * Map this megabyte in as well.
-	 */
-	pmd[2] = __pmd(pmdval + (2 << (PGDIR_SHIFT - 1)));
-	flush_pmd_entry(pmd);
-	msm_pm_pc_pgd = virt_to_phys(pc_pgd);
-	clean_caches((unsigned long)&msm_pm_pc_pgd, sizeof(msm_pm_pc_pgd),
-		     virt_to_phys(&msm_pm_pc_pgd));
-
 	return 0;
 }
 arch_initcall(msm_pm_setup_saved_state);
@@ -1631,18 +1698,6 @@
 		return rc;
 	}
 
-	pnoc_clk = clk_get_sys("pm_8x60", "bus_clk");
-
-	if (IS_ERR(pnoc_clk))
-		pnoc_clk = NULL;
-	else {
-		clk_set_rate(pnoc_clk, 19200000);
-		rc = clk_prepare_enable(pnoc_clk);
-
-		if (rc)
-			pr_err("%s: PNOC clock enable failed\n", __func__);
-	}
-
 	return platform_driver_register(&msm_pm_8x60_driver);
 }
 device_initcall(msm_pm_8x60_init);
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 38ed867..2bae37a 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -60,12 +60,13 @@
 	spinlock_t smd_lock_write;
 	spinlock_t smd_lock_read;
 	struct completion smd_open;
+	struct completion remote_open;
 };
 
 #define DEFAULT_BUFFER_SIZE 256
 #define DEBUG_PRINT_BUFFER_SIZE 512
 #define MAX_SLEEP_BUFFER 128
-
+#define SMD_CHANNEL_NOTIF_TIMEOUT 5000
 #define GFP_FLAG(noirq) (noirq ? GFP_ATOMIC : GFP_KERNEL)
 #define INV_RSC "resource does not exist"
 #define ERR "err\0"
@@ -1303,6 +1304,20 @@
 }
 EXPORT_SYMBOL(msm_rpm_exit_sleep);
 
+static int __devinit msm_rpm_smd_remote_probe(struct platform_device *pdev)
+{
+	if (pdev && pdev->id == msm_rpm_data.ch_type)
+		complete(&msm_rpm_data.remote_open);
+	return 0;
+}
+
+static struct platform_driver msm_rpm_smd_remote_driver = {
+	.probe = msm_rpm_smd_remote_probe,
+	.driver = {
+		.owner = THIS_MODULE,
+	},
+};
+
 static int __devinit msm_rpm_dev_probe(struct platform_device *pdev)
 {
 	char *key = NULL;
@@ -1323,13 +1338,21 @@
 	key = "rpm-standalone";
 	standalone = of_property_read_bool(pdev->dev.of_node, key);
 
+	msm_rpm_smd_remote_driver.driver.name = msm_rpm_data.ch_name;
+	init_completion(&msm_rpm_data.remote_open);
 	init_completion(&msm_rpm_data.smd_open);
 	spin_lock_init(&msm_rpm_data.smd_lock_write);
 	spin_lock_init(&msm_rpm_data.smd_lock_read);
 	INIT_WORK(&msm_rpm_data.work, msm_rpm_smd_work);
 
-	if (smd_named_open_on_edge(msm_rpm_data.ch_name, msm_rpm_data.ch_type,
-				&msm_rpm_data.ch_info, &msm_rpm_data,
+	platform_driver_register(&msm_rpm_smd_remote_driver);
+	ret = wait_for_completion_timeout(&msm_rpm_data.remote_open,
+			msecs_to_jiffies(SMD_CHANNEL_NOTIF_TIMEOUT));
+
+	if (!ret || smd_named_open_on_edge(msm_rpm_data.ch_name,
+				msm_rpm_data.ch_type,
+				&msm_rpm_data.ch_info,
+				&msm_rpm_data,
 				msm_rpm_notify)) {
 		pr_info("Cannot open RPM channel %s %d\n", msm_rpm_data.ch_name,
 				msm_rpm_data.ch_type);
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index 4cb43b1..b244c6f 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -268,7 +268,7 @@
 	rate = clk_round_rate(scm_clocks[CORE_CLK_SRC], 1);
 	clk_set_rate(scm_clocks[CORE_CLK_SRC], rate);
 
-	if (cpu_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
+	if (soc_class_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
 		scm_pas_bw_tbl[0].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
 		scm_pas_bw_tbl[1].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
 	} else {
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
index 6e05177..e9f44e3 100644
--- a/arch/arm/mach-msm/scm.c
+++ b/arch/arm/mach-msm/scm.c
@@ -191,12 +191,12 @@
 	u32 cmd_addr = virt_to_phys(cmd);
 
 	/*
-	 * Flush the entire cache here so callers don't have to remember
-	 * to flush the cache when passing physical addresses to the secure
-	 * side in the buffer.
+	 * Flush the command buffer so that the secure world sees
+	 * the correct data.
 	 */
-	flush_cache_all();
-	outer_flush_all();
+	__cpuc_flush_dcache_area((void *)cmd, cmd->len);
+	outer_flush_range(cmd_addr, cmd_addr + cmd->len);
+
 	ret = smc(cmd_addr);
 	if (ret < 0)
 		ret = scm_remap_error(ret);
@@ -233,6 +233,13 @@
  * @resp_len: length of the response buffer
  *
  * Sends a command to the SCM and waits for the command to finish processing.
+ *
+ * A note on cache maintenance:
+ * Note that any buffers that are expected to be accessed by the secure world
+ * must be flushed before invoking scm_call and invalidated in the cache
+ * immediately after scm_call returns. Cache maintenance on the command and
+ * response buffers is taken care of by scm_call; however, callers are
+ * responsible for any other cached buffers passed over to the secure world.
  */
 int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
 		void *resp_buf, size_t resp_len)
diff --git a/arch/arm/mach-msm/smcmod.c b/arch/arm/mach-msm/smcmod.c
index 705bab5..221a522 100644
--- a/arch/arm/mach-msm/smcmod.c
+++ b/arch/arm/mach-msm/smcmod.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -92,27 +92,6 @@
 	uint8_t verify;
 } __packed;
 
-static void smcmod_inv_range(unsigned long start, unsigned long end)
-{
-	uint32_t cacheline_size;
-	uint32_t ctr;
-
-	/* get cache line size */
-	asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
-	cacheline_size =  4 << ((ctr >> 16) & 0xf);
-
-	/* invalidate the range */
-	start = round_down(start, cacheline_size);
-	end = round_up(end, cacheline_size);
-	while (start < end) {
-		asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
-			 : "memory");
-		start += cacheline_size;
-	}
-	mb();
-	isb();
-}
-
 static int smcmod_ion_fd_to_phys(int32_t fd, struct ion_client *ion_clientp,
 	struct ion_handle **ion_handlep, uint32_t *phys_addrp, size_t *sizep)
 {
@@ -234,10 +213,18 @@
 		}
 	}
 
+	/* No need to flush the cache lines for the command buffer here,
+	 * because the buffer will be flushed by scm_call.
+	 */
+
 	/* call scm function to switch to secure world */
 	reqp->return_val = scm_call(reqp->service_id, reqp->command_id,
 		cmd_vaddrp, reqp->cmd_len, resp_vaddrp, reqp->resp_len);
 
+	/* The cache lines for the response buffer have already been
+	 * invalidated by scm_call before returning.
+	 */
+
 buf_cleanup:
 	/* if the client and handle(s) are valid, free them */
 	if (!IS_ERR_OR_NULL(ion_clientp)) {
@@ -355,45 +342,36 @@
 		goto buf_cleanup;
 	}
 
+	/* Only the scm_req structure will be flushed by scm_call,
+	 * so we must flush the cache for the input ion buffers here.
+	 */
+	msm_ion_do_cache_op(ion_clientp, ion_key_handlep, NULL,
+		scm_req.key_size, ION_IOC_CLEAN_CACHES);
+	msm_ion_do_cache_op(ion_clientp, ion_iv_handlep, NULL,
+		scm_req.init_vector_size, ION_IOC_CLEAN_CACHES);
+
+	/* For decrypt, cipher text is input, otherwise it's plain text. */
+	if (reqp->operation)
+		msm_ion_do_cache_op(ion_clientp, ion_cipher_handlep, NULL,
+			scm_req.cipher_text_size, ION_IOC_CLEAN_CACHES);
+	else
+		msm_ion_do_cache_op(ion_clientp, ion_plain_handlep, NULL,
+			scm_req.plain_text_size, ION_IOC_CLEAN_CACHES);
+
 	/* call scm function to switch to secure world */
 	reqp->return_val = scm_call(SMCMOD_SVC_CRYPTO,
 		SMCMOD_CRYPTO_CMD_CIPHER, &scm_req,
 		sizeof(scm_req), NULL, 0);
 
+	/* Invalidate the output buffer, since it's not done by scm_call */
+
 	/* for decrypt, plain text is the output, otherwise it's cipher text */
-	if (reqp->operation) {
-		void *vaddrp = NULL;
-
-		/* map the plain text region to get the virtual address */
-		vaddrp = ion_map_kernel(ion_clientp, ion_plain_handlep);
-		if (IS_ERR_OR_NULL(vaddrp)) {
-			ret = -EINVAL;
-			goto buf_cleanup;
-		}
-
-		/* invalidate the range */
-		smcmod_inv_range((unsigned long)vaddrp,
-			(unsigned long)(vaddrp + scm_req.plain_text_size));
-
-		/* unmap the mapped area */
-		ion_unmap_kernel(ion_clientp, ion_plain_handlep);
-	} else {
-		void *vaddrp = NULL;
-
-		/* map the cipher text region to get the virtual address */
-		vaddrp = ion_map_kernel(ion_clientp, ion_cipher_handlep);
-		if (IS_ERR_OR_NULL(vaddrp)) {
-			ret = -EINVAL;
-			goto buf_cleanup;
-		}
-
-		/* invalidate the range */
-		smcmod_inv_range((unsigned long)vaddrp,
-			(unsigned long)(vaddrp + scm_req.cipher_text_size));
-
-		/* unmap the mapped area */
-		ion_unmap_kernel(ion_clientp, ion_cipher_handlep);
-	}
+	if (reqp->operation)
+		msm_ion_do_cache_op(ion_clientp, ion_plain_handlep, NULL,
+			scm_req.plain_text_size, ION_IOC_INV_CACHES);
+	else
+		msm_ion_do_cache_op(ion_clientp, ion_cipher_handlep, NULL,
+			scm_req.cipher_text_size, ION_IOC_INV_CACHES);
 
 buf_cleanup:
 	/* if the client and handles are valid, free them */
@@ -424,7 +402,6 @@
 	struct ion_handle *ion_input_handlep = NULL;
 	struct ion_handle *ion_output_handlep = NULL;
 	size_t size = 0;
-	void *vaddrp = NULL;
 
 	if (IS_ERR_OR_NULL(reqp))
 		return -EINVAL;
@@ -492,6 +469,14 @@
 		goto buf_cleanup;
 	}
 
+	/* Only the scm_req structure will be flushed by scm_call,
+	 * so we must flush the cache for the input ion buffers here.
+	 */
+	msm_ion_do_cache_op(ion_clientp, ion_key_handlep, NULL,
+		scm_req.key_size, ION_IOC_CLEAN_CACHES);
+	msm_ion_do_cache_op(ion_clientp, ion_input_handlep, NULL,
+		scm_req.input_size, ION_IOC_CLEAN_CACHES);
+
 	/* call scm function to switch to secure world */
 	if (reqp->fixed_block)
 		reqp->return_val = scm_call(SMCMOD_SVC_CRYPTO,
@@ -506,20 +491,9 @@
 			sizeof(scm_req),
 			NULL, 0);
 
-
-	/* map the output region to get the virtual address */
-	vaddrp = ion_map_kernel(ion_clientp, ion_output_handlep);
-	if (IS_ERR_OR_NULL(vaddrp)) {
-		ret = -EINVAL;
-		goto buf_cleanup;
-	}
-
-	/* invalidate the range */
-	smcmod_inv_range((unsigned long)vaddrp,
-		(unsigned long)(vaddrp + scm_req.output_size));
-
-	/* unmap the mapped area */
-	ion_unmap_kernel(ion_clientp, ion_output_handlep);
+	/* Invalidate the output buffer, since it's not done by scm_call */
+	msm_ion_do_cache_op(ion_clientp, ion_output_handlep, NULL,
+		scm_req.output_size, ION_IOC_INV_CACHES);
 
 buf_cleanup:
 	/* if the client and handles are valid, free them */
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 4649390..c97ba68 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -176,8 +176,6 @@
 	},
 };
 
-static void *smd_dev;
-
 struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
 
 #define SMSM_STATE_ADDR(entry)           (smsm_info.state + entry)
@@ -381,14 +379,6 @@
 static DEFINE_MUTEX(smsm_lock);
 static struct smsm_state_info *smsm_states;
 
-/**
- * Variables to indicate smd module initialization.
- * Dependents to register for smd module init notifier.
- */
-static int smd_module_inited;
-static RAW_NOTIFIER_HEAD(smd_module_init_notifier_list);
-static DEFINE_MUTEX(smd_module_init_notifier_lock);
-static void smd_module_init_notify(uint32_t state, void *data);
 static int smd_stream_write_avail(struct smd_channel *ch);
 static int smd_stream_read_avail(struct smd_channel *ch);
 
@@ -708,6 +698,7 @@
 	uint32_t	local_pid;
 	uint32_t	remote_pid;
 	char		subsys_name[SMD_MAX_CH_NAME_LEN];
+	bool		initialized;
 };
 
 /**
@@ -762,6 +753,11 @@
 
 static int smd_alloc_channel(struct smd_alloc_elm *alloc_elm);
 
+static bool smd_edge_inited(int edge)
+{
+	return edge_to_pids[edge].initialized;
+}
+
 /* on smp systems, the probe might get called from multiple cores,
    hence use a lock */
 static DEFINE_MUTEX(smd_probe_lock);
@@ -795,6 +791,11 @@
 		if (!shared[n].name[0])
 			continue;
 
+		if (!smd_initialized && !smd_edge_inited(type)) {
+			SMD_INFO("Probe skipping ch %d, edge not inited\n", n);
+			continue;
+		}
+
 		if (!smd_alloc_channel(&shared[n]))
 			smd_ch_allocated[n] = 1;
 		else
@@ -1913,7 +1914,7 @@
 	struct smd_channel *ch;
 	unsigned long flags;
 
-	if (smd_initialized == 0) {
+	if (smd_initialized == 0 && !smd_edge_inited(edge)) {
 		SMD_INFO("smd_open() before smd_init()\n");
 		return -ENODEV;
 	}
@@ -2436,16 +2437,23 @@
 	struct smsm_size_info_type *smsm_size_info;
 	unsigned long flags;
 	unsigned long j_start;
+	static int first = 1;
+	remote_spinlock_t *remote_spinlock;
+
+	if (!first)
+		return 0;
+	first = 0;
 
 	/* Verify that remote spinlock is not deadlocked */
+	remote_spinlock = smem_get_remote_spinlock();
 	j_start = jiffies;
-	while (!remote_spin_trylock_irqsave(&remote_spinlock, flags)) {
+	while (!remote_spin_trylock_irqsave(remote_spinlock, flags)) {
 		if (jiffies_to_msecs(jiffies - j_start) > RSPIN_INIT_WAIT_MS) {
 			panic("%s: Remote processor %d will not release spinlock\n",
-				__func__, remote_spin_owner(&remote_spinlock));
+				__func__, remote_spin_owner(remote_spinlock));
 		}
 	}
-	remote_spin_unlock_irqrestore(&remote_spinlock, flags);
+	remote_spin_unlock_irqrestore(remote_spinlock, flags);
 
 	smsm_size_info = smem_alloc(SMEM_SMSM_SIZE_INFO,
 				sizeof(struct smsm_size_info_type));
@@ -2860,9 +2868,6 @@
 	int ret;
 	unsigned long flags;
 
-	if (!smd_initialized)
-		return;
-
 	while (kfifo_len(&smsm_snapshot_fifo) >= SMSM_SNAPSHOT_SIZE) {
 		mutex_lock(&smsm_lock);
 		for (n = 0; n < SMSM_NUM_ENTRIES; n++) {
@@ -3084,42 +3089,6 @@
 }
 EXPORT_SYMBOL(smsm_state_cb_deregister);
 
-int smd_module_init_notifier_register(struct notifier_block *nb)
-{
-	int ret;
-	if (!nb)
-		return -EINVAL;
-	mutex_lock(&smd_module_init_notifier_lock);
-	ret = raw_notifier_chain_register(&smd_module_init_notifier_list, nb);
-	if (smd_module_inited)
-		nb->notifier_call(nb, 0, NULL);
-	mutex_unlock(&smd_module_init_notifier_lock);
-	return ret;
-}
-EXPORT_SYMBOL(smd_module_init_notifier_register);
-
-int smd_module_init_notifier_unregister(struct notifier_block *nb)
-{
-	int ret;
-	if (!nb)
-		return -EINVAL;
-	mutex_lock(&smd_module_init_notifier_lock);
-	ret = raw_notifier_chain_unregister(&smd_module_init_notifier_list,
-					    nb);
-	mutex_unlock(&smd_module_init_notifier_lock);
-	return ret;
-}
-EXPORT_SYMBOL(smd_module_init_notifier_unregister);
-
-static void smd_module_init_notify(uint32_t state, void *data)
-{
-	mutex_lock(&smd_module_init_notifier_lock);
-	smd_module_inited = 1;
-	raw_notifier_call_chain(&smd_module_init_notifier_list,
-				state, data);
-	mutex_unlock(&smd_module_init_notifier_lock);
-}
-
 int smd_core_init(void)
 {
 	int r;
@@ -3315,9 +3284,6 @@
 	struct smd_subsystem_config *smd_ss_config_list;
 	struct smd_subsystem_config *cfg;
 	int err_ret = 0;
-	struct smd_smem_regions *smd_smem_areas;
-	struct smem_area *smem_areas_tmp = NULL;
-	int smem_idx;
 
 	smd_platform_data = pdev->dev.platform_data;
 	num_ss = smd_platform_data->num_ss_configs;
@@ -3327,57 +3293,6 @@
 		disable_smsm_reset_handshake = smd_platform_data->
 			   smd_ssr_config->disable_smsm_reset_handshake;
 
-	smd_smem_areas = smd_platform_data->smd_smem_areas;
-	num_smem_areas = smd_platform_data->num_smem_areas + 1;
-
-	/* Initialize main SMEM region */
-	smem_areas_tmp = kmalloc_array(num_smem_areas, sizeof(struct smem_area),
-				GFP_KERNEL);
-	if (!smem_areas_tmp) {
-		pr_err("%s: smem_areas kmalloc failed\n", __func__);
-		err_ret = -ENOMEM;
-		goto smem_areas_alloc_fail;
-	}
-
-	smem_areas_tmp[0].phys_addr =  msm_shared_ram_phys;
-	smem_areas_tmp[0].size = MSM_SHARED_RAM_SIZE;
-	smem_areas_tmp[0].virt_addr = MSM_SHARED_RAM_BASE;
-
-	/* Configure auxiliary SMEM regions */
-	for (smem_idx = 1; smem_idx < num_smem_areas; ++smem_idx) {
-		smem_areas_tmp[smem_idx].phys_addr =
-				smd_smem_areas[smem_idx].phys_addr;
-		smem_areas_tmp[smem_idx].size =
-				smd_smem_areas[smem_idx].size;
-		smem_areas_tmp[smem_idx].virt_addr = ioremap_nocache(
-			(unsigned long)(smem_areas_tmp[smem_idx].phys_addr),
-			smem_areas_tmp[smem_idx].size);
-		if (!smem_areas_tmp[smem_idx].virt_addr) {
-			pr_err("%s: ioremap_nocache() of addr: %pa size: %pa\n",
-				__func__,
-				&smem_areas_tmp[smem_idx].phys_addr,
-				&smem_areas_tmp[smem_idx].size);
-			err_ret = -ENOMEM;
-			goto smem_failed;
-		}
-
-		if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
-				(uintptr_t)smem_areas_tmp[smem_idx].virt_addr,
-				smem_areas_tmp[smem_idx].size)) {
-			pr_err("%s: invalid virtual address block %i: %p:%pa\n",
-					__func__, smem_idx,
-					smem_areas_tmp[smem_idx].virt_addr,
-					&smem_areas_tmp[smem_idx].size);
-			++smem_idx;
-			err_ret = -EINVAL;
-			goto smem_failed;
-		}
-
-		SMD_DBG("%s: %d = %pa %pa", __func__, smem_idx,
-				&smd_smem_areas[smem_idx].phys_addr,
-				&smd_smem_areas[smem_idx].size);
-	}
-
 	for (i = 0; i < num_ss; i++) {
 		cfg = &smd_ss_config_list[i];
 
@@ -3421,7 +3336,6 @@
 
 	SMD_INFO("smd_core_platform_init() done\n");
 
-	smem_areas = smem_areas_tmp;
 	return 0;
 
 intr_failed:
@@ -3438,19 +3352,105 @@
 				(void *)cfg->smsm_int.dev_id
 				);
 	}
-smem_failed:
-	for (smem_idx = smem_idx - 1; smem_idx >= 1; --smem_idx)
-		iounmap(smem_areas_tmp[smem_idx].virt_addr);
-
-	num_smem_areas = 0;
-	kfree(smem_areas_tmp);
-
-smem_areas_alloc_fail:
 	return err_ret;
 }
 
-static int __devinit parse_smd_devicetree(struct device_node *node,
-						void *irq_out_base)
+static int msm_smsm_probe(struct platform_device *pdev)
+{
+	uint32_t edge;
+	char *key;
+	int ret;
+	uint32_t irq_offset;
+	uint32_t irq_bitmask;
+	uint32_t irq_line;
+	struct interrupt_config_item *private_irq;
+	struct device_node *node;
+	void *irq_out_base;
+	resource_size_t irq_out_size;
+	struct platform_device *parent_pdev;
+	struct resource *r;
+
+	disable_smsm_reset_handshake = 1;
+
+	node = pdev->dev.of_node;
+
+	if (!pdev->dev.parent) {
+		pr_err("%s: missing link to parent device\n", __func__);
+		return -ENODEV;
+	}
+
+	parent_pdev = to_platform_device(pdev->dev.parent);
+
+	key = "irq-reg-base";
+	/* existance check verified in smem driver */
+	r = platform_get_resource_byname(parent_pdev, IORESOURCE_MEM, key);
+	irq_out_size = resource_size(r);
+	irq_out_base = ioremap_nocache(r->start, irq_out_size);
+	if (!irq_out_base) {
+		pr_err("%s: ioremap_nocache() of irq_out_base addr:%pr size:%pr\n",
+				__func__, &r->start, &irq_out_size);
+		return -ENOMEM;
+	}
+	SMSM_DBG("%s: %s = %p", __func__, key, irq_out_base);
+
+	key = "qcom,smsm-edge";
+	ret = of_property_read_u32(node, key, &edge);
+	if (ret)
+		goto missing_key;
+	SMSM_DBG("%s: %s = %d", __func__, key, edge);
+
+	key = "qcom,smsm-irq-offset";
+	ret = of_property_read_u32(node, key, &irq_offset);
+	if (ret)
+		goto missing_key;
+	SMSM_DBG("%s: %s = %x", __func__, key, irq_offset);
+
+	key = "qcom,smsm-irq-bitmask";
+	ret = of_property_read_u32(node, key, &irq_bitmask);
+	if (ret)
+		goto missing_key;
+	SMSM_DBG("%s: %s = %x", __func__, key, irq_bitmask);
+
+	key = "interrupts";
+	irq_line = irq_of_parse_and_map(node, 0);
+	if (!irq_line)
+		goto missing_key;
+	SMSM_DBG("%s: %s = %d", __func__, key, irq_line);
+
+	private_irq = &private_intr_config[edge_to_pids[edge].remote_pid].smsm;
+	private_irq->out_bit_pos = irq_bitmask;
+	private_irq->out_offset = irq_offset;
+	private_irq->out_base = irq_out_base;
+	private_irq->irq_id = irq_line;
+
+	ret = request_irq(irq_line,
+				private_irq->irq_handler,
+				IRQF_TRIGGER_RISING,
+				"smsm_dev",
+				NULL);
+	if (ret < 0) {
+		pr_err("%s: request_irq() failed on %d\n", __func__, irq_line);
+		return ret;
+	} else {
+		ret = enable_irq_wake(irq_line);
+		if (ret < 0)
+			pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
+					irq_line);
+	}
+
+	if (smsm_init())
+		pr_err("smsm_init() failed\n");
+
+	smsm_irq_handler(0, 0);
+
+	return 0;
+
+missing_key:
+	pr_err("%s: missing key: %s", __func__, key);
+	return -ENODEV;
+}
+
+static int msm_smd_probe(struct platform_device *pdev)
 {
 	uint32_t edge;
 	char *key;
@@ -3461,6 +3461,32 @@
 	unsigned long irq_flags = IRQF_TRIGGER_RISING;
 	const char *pilstr;
 	struct interrupt_config_item *private_irq;
+	struct device_node *node;
+	void *irq_out_base;
+	resource_size_t irq_out_size;
+	struct platform_device *parent_pdev;
+	struct resource *r;
+
+	node = pdev->dev.of_node;
+
+	if (!pdev->dev.parent) {
+		pr_err("%s: missing link to parent device\n", __func__);
+		return -ENODEV;
+	}
+
+	parent_pdev = to_platform_device(pdev->dev.parent);
+
+	key = "irq-reg-base";
+	/* existance check verified in smem driver */
+	r = platform_get_resource_byname(parent_pdev, IORESOURCE_MEM, key);
+	irq_out_size = resource_size(r);
+	irq_out_base = ioremap_nocache(r->start, irq_out_size);
+	if (!irq_out_base) {
+		pr_err("%s: ioremap_nocache() of irq_out_base addr:%pr size:%pr\n",
+				__func__, &r->start, &irq_out_size);
+		return -ENOMEM;
+	}
+	SMD_DBG("%s: %s = %p", __func__, key, irq_out_base);
 
 	key = "qcom,smd-edge";
 	ret = of_property_read_u32(node, key, &edge);
@@ -3521,68 +3547,9 @@
 		strlcpy(edge_to_pids[edge].subsys_name, pilstr,
 						SMD_MAX_CH_NAME_LEN);
 
-	return 0;
+	edge_to_pids[edge].initialized = true;
 
-missing_key:
-	pr_err("%s: missing key: %s", __func__, key);
-	return -ENODEV;
-}
-
-static int __devinit parse_smsm_devicetree(struct device_node *node,
-						void *irq_out_base)
-{
-	uint32_t edge;
-	char *key;
-	int ret;
-	uint32_t irq_offset;
-	uint32_t irq_bitmask;
-	uint32_t irq_line;
-	struct interrupt_config_item *private_irq;
-
-	key = "qcom,smsm-edge";
-	ret = of_property_read_u32(node, key, &edge);
-	if (ret)
-		goto missing_key;
-	SMD_DBG("%s: %s = %d", __func__, key, edge);
-
-	key = "qcom,smsm-irq-offset";
-	ret = of_property_read_u32(node, key, &irq_offset);
-	if (ret)
-		goto missing_key;
-	SMD_DBG("%s: %s = %x", __func__, key, irq_offset);
-
-	key = "qcom,smsm-irq-bitmask";
-	ret = of_property_read_u32(node, key, &irq_bitmask);
-	if (ret)
-		goto missing_key;
-	SMD_DBG("%s: %s = %x", __func__, key, irq_bitmask);
-
-	key = "interrupts";
-	irq_line = irq_of_parse_and_map(node, 0);
-	if (!irq_line)
-		goto missing_key;
-	SMD_DBG("%s: %s = %d", __func__, key, irq_line);
-
-	private_irq = &private_intr_config[edge_to_pids[edge].remote_pid].smsm;
-	private_irq->out_bit_pos = irq_bitmask;
-	private_irq->out_offset = irq_offset;
-	private_irq->out_base = irq_out_base;
-	private_irq->irq_id = irq_line;
-
-	ret = request_irq(irq_line,
-				private_irq->irq_handler,
-				IRQF_TRIGGER_RISING,
-				"smsm_dev",
-				NULL);
-	if (ret < 0) {
-		pr_err("%s: request_irq() failed on %d\n", __func__, irq_line);
-		return ret;
-	} else {
-		ret = enable_irq_wake(irq_line);
-		if (ret < 0)
-			pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
-					irq_line);
-	}
+	schedule_work(&probe_work);
 
 	return 0;
 
@@ -3591,213 +3558,7 @@
 	return -ENODEV;
 }
 
-static void __devinit unparse_smd_devicetree(struct device_node *node)
-{
-	uint32_t irq_line;
-
-	irq_line = irq_of_parse_and_map(node, 0);
-
-	free_irq(irq_line, NULL);
-}
-
-static void __devinit unparse_smsm_devicetree(struct device_node *node)
-{
-	uint32_t irq_line;
-
-	irq_line = irq_of_parse_and_map(node, 0);
-
-	free_irq(irq_line, NULL);
-}
-
-static int __devinit smd_core_devicetree_init(struct platform_device *pdev)
-{
-	char *key;
-	struct resource *r;
-	void *irq_out_base;
-	phys_addr_t aux_mem_base;
-	resource_size_t aux_mem_size;
-	int temp_string_size = 11; /* max 3 digit count */
-	char temp_string[temp_string_size];
-	struct device_node *node;
-	int ret;
-	const char *compatible;
-	struct ramdump_segment *ramdump_segments_tmp = NULL;
-	struct smem_area *smem_areas_tmp = NULL;
-	int smem_idx = 0;
-	int subnode_num = 0;
-	int i;
-	resource_size_t irq_out_size;
-
-	disable_smsm_reset_handshake = 1;
-
-	key = "irq-reg-base";
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
-	if (!r) {
-		pr_err("%s: missing '%s'\n", __func__, key);
-		return -ENODEV;
-	}
-	irq_out_size = resource_size(r);
-	irq_out_base = ioremap_nocache(r->start, irq_out_size);
-	if (!irq_out_base) {
-		pr_err("%s: ioremap_nocache() of irq_out_base addr:%pr size:%pr\n",
-				__func__, &r->start, &irq_out_size);
-		return -ENOMEM;
-	}
-	SMD_DBG("%s: %s = %p", __func__, key, irq_out_base);
-
-	num_smem_areas = 1;
-	while (1) {
-		scnprintf(temp_string, temp_string_size, "aux-mem%d",
-				num_smem_areas);
-		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-								temp_string);
-		if (!r)
-			break;
-
-		++num_smem_areas;
-		if (num_smem_areas > 999) {
-			pr_err("%s: max num aux mem regions reached\n",
-								__func__);
-			break;
-		}
-	}
-
-	/* Initialize main SMEM region and SSR ramdump region */
-	key = "smem";
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
-	if (!r) {
-		pr_err("%s: missing '%s'\n", __func__, key);
-		return -ENODEV;
-	}
-
-	smem_areas_tmp = kmalloc_array(num_smem_areas, sizeof(struct smem_area),
-				GFP_KERNEL);
-	if (!smem_areas_tmp) {
-		pr_err("%s: smem areas kmalloc failed\n", __func__);
-		ret = -ENOMEM;
-		goto free_smem_areas;
-	}
-
-	ramdump_segments_tmp = kmalloc_array(num_smem_areas,
-			sizeof(struct ramdump_segment), GFP_KERNEL);
-	if (!ramdump_segments_tmp) {
-		pr_err("%s: ramdump segment kmalloc failed\n", __func__);
-		ret = -ENOMEM;
-		goto free_smem_areas;
-	}
-
-	smem_areas_tmp[smem_idx].phys_addr =  r->start;
-	smem_areas_tmp[smem_idx].size = resource_size(r);
-	smem_areas_tmp[smem_idx].virt_addr = MSM_SHARED_RAM_BASE;
-
-	ramdump_segments_tmp[smem_idx].address = r->start;
-	ramdump_segments_tmp[smem_idx].size = resource_size(r);
-	++smem_idx;
-
-	/* Configure auxiliary SMEM regions */
-	while (1) {
-		scnprintf(temp_string, temp_string_size, "aux-mem%d",
-								smem_idx);
-		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-							temp_string);
-		if (!r)
-			break;
-		aux_mem_base = r->start;
-		aux_mem_size = resource_size(r);
-
-		ramdump_segments_tmp[smem_idx].address = aux_mem_base;
-		ramdump_segments_tmp[smem_idx].size = aux_mem_size;
-
-		smem_areas_tmp[smem_idx].phys_addr = aux_mem_base;
-		smem_areas_tmp[smem_idx].size = aux_mem_size;
-		smem_areas_tmp[smem_idx].virt_addr = ioremap_nocache(
-			(unsigned long)(smem_areas_tmp[smem_idx].phys_addr),
-			smem_areas_tmp[smem_idx].size);
-		SMD_DBG("%s: %s = %pa %pa -> %p", __func__, temp_string,
-				&aux_mem_base, &aux_mem_size,
-				smem_areas_tmp[smem_idx].virt_addr);
-
-		if (!smem_areas_tmp[smem_idx].virt_addr) {
-			pr_err("%s: ioremap_nocache() of addr:%pa size: %pa\n",
-				__func__,
-				&smem_areas_tmp[smem_idx].phys_addr,
-				&smem_areas_tmp[smem_idx].size);
-			ret = -ENOMEM;
-			goto free_smem_areas;
-		}
-
-		if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
-				(uintptr_t)smem_areas_tmp[smem_idx].virt_addr,
-				smem_areas_tmp[smem_idx].size)) {
-			pr_err("%s: invalid virtual address block %i: %p:%pa\n",
-					__func__, smem_idx,
-					smem_areas_tmp[smem_idx].virt_addr,
-					&smem_areas_tmp[smem_idx].size);
-			++smem_idx;
-			ret = -EINVAL;
-			goto free_smem_areas;
-		}
-
-		++smem_idx;
-		if (smem_idx > 999) {
-			pr_err("%s: max num aux mem regions reached\n",
-							__func__);
-			break;
-		}
-	}
-
-	for_each_child_of_node(pdev->dev.of_node, node) {
-		compatible = of_get_property(node, "compatible", NULL);
-		if (!compatible) {
-			pr_err("%s: invalid child node: compatible null\n",
-				__func__);
-			ret = -ENODEV;
-			goto rollback_subnodes;
-		}
-		if (!strcmp(compatible, "qcom,smd")) {
-			ret = parse_smd_devicetree(node, irq_out_base);
-			if (ret)
-				goto rollback_subnodes;
-		} else if (!strcmp(compatible, "qcom,smsm")) {
-			ret = parse_smsm_devicetree(node, irq_out_base);
-			if (ret)
-				goto rollback_subnodes;
-		} else {
-			pr_err("%s: invalid child node named: %s\n", __func__,
-							compatible);
-			ret = -ENODEV;
-			goto rollback_subnodes;
-		}
-		++subnode_num;
-	}
-
-	smem_areas = smem_areas_tmp;
-	smem_ramdump_segments = ramdump_segments_tmp;
-	return 0;
-
-rollback_subnodes:
-	i = 0;
-	for_each_child_of_node(pdev->dev.of_node, node) {
-		if (i >= subnode_num)
-			break;
-		++i;
-		compatible = of_get_property(node, "compatible", NULL);
-		if (!strcmp(compatible, "qcom,smd"))
-			unparse_smd_devicetree(node);
-		else
-			unparse_smsm_devicetree(node);
-	}
-free_smem_areas:
-	for (smem_idx = smem_idx - 1; smem_idx >= 1; --smem_idx)
-		iounmap(smem_areas_tmp[smem_idx].virt_addr);
-
-	num_smem_areas = 0;
-	kfree(ramdump_segments_tmp);
-	kfree(smem_areas_tmp);
-	return ret;
-}
-
-static int __devinit msm_smd_probe(struct platform_device *pdev)
+static int msm_smd_probe_legacy(struct platform_device *pdev)
 {
 	int ret;
 
@@ -3805,13 +3566,6 @@
 		return -ENODEV;
 
 	SMD_INFO("smd probe\n");
-	INIT_WORK(&probe_work, smd_channel_probe_worker);
-
-	channel_close_wq = create_singlethread_workqueue("smd_channel_close");
-	if (IS_ERR(channel_close_wq)) {
-		pr_err("%s: create_singlethread_workqueue ENOMEM\n", __func__);
-		return -ENOMEM;
-	}
 
 	if (smsm_init()) {
 		pr_err("smsm_init() failed\n");
@@ -3820,13 +3574,8 @@
 
 	if (pdev) {
 		if (pdev->dev.of_node) {
-			ret = smd_core_devicetree_init(pdev);
-			if (ret) {
-				pr_err("%s: device tree init failed\n",
-								__func__);
-				return ret;
-			}
-			smd_dev = &pdev->dev;
+			pr_err("%s: invalid device tree init\n", __func__);
+			return -ENODEV;
 		} else if (pdev->dev.platform_data) {
 			ret = smd_core_platform_init(pdev);
 			if (ret) {
@@ -3872,6 +3621,8 @@
 				  unsigned long code,
 				  void *data)
 {
+	remote_spinlock_t *remote_spinlock;
+
 	/*
 	 * Some SMD or SMSM clients assume SMD/SMSM SSR handling will be
 	 * done in the AFTER_SHUTDOWN level.  If this ever changes, extra
@@ -3886,7 +3637,8 @@
 				__func__, notifier->processor,
 				notifier->name);
 
-		remote_spin_release(&remote_spinlock, notifier->processor);
+		remote_spinlock = smem_get_remote_spinlock();
+		remote_spin_release(remote_spinlock, notifier->processor);
 		remote_spin_release_all(notifier->processor);
 
 		smd_channel_reset(notifier->processor);
@@ -3912,17 +3664,39 @@
 }
 late_initcall(modem_restart_late_init);
 
-static struct of_device_id msm_smem_match_table[] = {
-	{ .compatible = "qcom,smem" },
+static struct of_device_id msm_smd_match_table[] = {
+	{ .compatible = "qcom,smd" },
 	{},
 };
 
 static struct platform_driver msm_smd_driver = {
 	.probe = msm_smd_probe,
 	.driver = {
+		.name = "msm_smd_dt",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_smd_match_table,
+	},
+};
+
+static struct of_device_id msm_smsm_match_table[] = {
+	{ .compatible = "qcom,smsm" },
+	{},
+};
+
+static struct platform_driver msm_smsm_driver = {
+	.probe = msm_smsm_probe,
+	.driver = {
+		.name = "msm_smsm",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_smsm_match_table,
+	},
+};
+
+static struct platform_driver msm_smd_driver_legacy = {
+	.probe = msm_smd_probe_legacy,
+	.driver = {
 		.name = MODULE_NAME,
 		.owner = THIS_MODULE,
-		.of_match_table = msm_smem_match_table,
 	},
 };
 
@@ -3941,9 +3715,19 @@
 	}
 
 	registered = true;
-	rc = init_smem_remote_spinlock();
+
+	INIT_WORK(&probe_work, smd_channel_probe_worker);
+
+	channel_close_wq = create_singlethread_workqueue("smd_channel_close");
+	if (IS_ERR(channel_close_wq)) {
+		pr_err("%s: create_singlethread_workqueue ENOMEM\n", __func__);
+		return -ENOMEM;
+	}
+
+	rc = platform_driver_register(&msm_smd_driver_legacy);
 	if (rc) {
-		pr_err("%s: remote spinlock init failed %d\n", __func__, rc);
+		pr_err("%s: msm_smd_driver_legacy register failed %d\n",
+			__func__, rc);
 		return rc;
 	}
 
@@ -3954,7 +3738,12 @@
 		return rc;
 	}
 
-	smd_module_init_notify(0, NULL);
+	rc = platform_driver_register(&msm_smsm_driver);
+	if (rc) {
+		pr_err("%s: msm_smsm_driver register failed %d\n",
+			__func__, rc);
+		return rc;
+	}
 
 	return 0;
 }
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 0b270b7..3461e49 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -175,8 +175,10 @@
 		if (dev == smd_tty[num_dev].device_ptr)
 			break;
 	}
-	if (num_dev >= MAX_SMD_TTYS)
+	if (num_dev >= MAX_SMD_TTYS) {
 		SMD_TTY_ERR("[%s]: Device Not Found", __func__);
+		return -EINVAL;
+	}
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 			smd_tty[num_dev].open_wait);
diff --git a/arch/arm/mach-msm/smem.c b/arch/arm/mach-msm/smem.c
index 181b504..1ec2a78 100644
--- a/arch/arm/mach-msm/smem.c
+++ b/arch/arm/mach-msm/smem.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/moduleparam.h>
 #include <linux/printk.h>
+#include <linux/notifier.h>
 
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
@@ -53,15 +54,20 @@
 			pr_debug(x);                      \
 	} while (0)
 
-remote_spinlock_t remote_spinlock;
-int spinlocks_initialized;
-uint32_t num_smem_areas;
-struct smem_area *smem_areas;
-struct ramdump_segment *smem_ramdump_segments;
+#define SMEM_SPINLOCK_SMEM_ALLOC       "S:3"
 
+static remote_spinlock_t remote_spinlock;
+static uint32_t num_smem_areas;
+static struct smem_area *smem_areas;
+static struct ramdump_segment *smem_ramdump_segments;
+static int spinlocks_initialized;
 static void *smem_ramdump_dev;
 static DEFINE_MUTEX(spinlock_init_lock);
 static DEFINE_SPINLOCK(smem_init_check_lock);
+static int smem_module_inited;
+static RAW_NOTIFIER_HEAD(smem_module_init_notifier_list);
+static DEFINE_MUTEX(smem_module_init_notifier_lock);
+
 
 struct restart_notifier_block {
 	unsigned processor;
@@ -82,6 +88,8 @@
 	{SMEM_Q6, "adsp", .nb.notifier_call = restart_notifier_cb},
 };
 
+static int init_smem_remote_spinlock(void);
+
 /**
  * smem_phys_to_virt() - Convert a physical base and offset to virtual address
  *
@@ -350,6 +358,8 @@
  */
 remote_spinlock_t *smem_get_remote_spinlock(void)
 {
+	if (unlikely(!spinlocks_initialized))
+		init_smem_remote_spinlock();
 	return &remote_spinlock;
 }
 EXPORT_SYMBOL(smem_get_remote_spinlock);
@@ -359,7 +369,7 @@
  *
  * @returns: sucess or error code for failure
  */
-int init_smem_remote_spinlock(void)
+static int init_smem_remote_spinlock(void)
 {
 	int rc = 0;
 
@@ -499,3 +509,223 @@
 	return 0;
 }
 late_initcall(modem_restart_late_init);
+
+int smem_module_init_notifier_register(struct notifier_block *nb)
+{
+	int ret;
+	if (!nb)
+		return -EINVAL;
+	mutex_lock(&smem_module_init_notifier_lock);
+	ret = raw_notifier_chain_register(&smem_module_init_notifier_list, nb);
+	if (smem_module_inited)
+		nb->notifier_call(nb, 0, NULL);
+	mutex_unlock(&smem_module_init_notifier_lock);
+	return ret;
+}
+EXPORT_SYMBOL(smem_module_init_notifier_register);
+
+int smem_module_init_notifier_unregister(struct notifier_block *nb)
+{
+	int ret;
+	if (!nb)
+		return -EINVAL;
+	mutex_lock(&smem_module_init_notifier_lock);
+	ret = raw_notifier_chain_unregister(&smem_module_init_notifier_list,
+						nb);
+	mutex_unlock(&smem_module_init_notifier_lock);
+	return ret;
+}
+EXPORT_SYMBOL(smem_module_init_notifier_unregister);
+
+static void smem_module_init_notify(uint32_t state, void *data)
+{
+	mutex_lock(&smem_module_init_notifier_lock);
+	smem_module_inited = 1;
+	raw_notifier_call_chain(&smem_module_init_notifier_list,
+					state, data);
+	mutex_unlock(&smem_module_init_notifier_lock);
+}
+
+static int msm_smem_probe(struct platform_device *pdev)
+{
+	char *key;
+	struct resource *r;
+	phys_addr_t aux_mem_base;
+	resource_size_t aux_mem_size;
+	int temp_string_size = 11; /* max 3 digit count */
+	char temp_string[temp_string_size];
+	int ret;
+	struct ramdump_segment *ramdump_segments_tmp = NULL;
+	struct smem_area *smem_areas_tmp = NULL;
+	int smem_idx = 0;
+
+	if (!smem_initialized_check())
+		return -ENODEV;
+
+	key = "irq-reg-base";
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
+	if (!r) {
+		pr_err("%s: missing '%s'\n", __func__, key);
+		return -ENODEV;
+	}
+
+	num_smem_areas = 1;
+	while (1) {
+		scnprintf(temp_string, temp_string_size, "aux-mem%d",
+				num_smem_areas);
+		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+								temp_string);
+		if (!r)
+			break;
+
+		++num_smem_areas;
+		if (num_smem_areas > 999) {
+			pr_err("%s: max num aux mem regions reached\n",
+								__func__);
+			break;
+		}
+	}
+	/* Initialize main SMEM region and SSR ramdump region */
+	key = "smem";
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
+	if (!r) {
+		pr_err("%s: missing '%s'\n", __func__, key);
+		return -ENODEV;
+	}
+
+	smem_areas_tmp = kmalloc_array(num_smem_areas, sizeof(struct smem_area),
+				GFP_KERNEL);
+	if (!smem_areas_tmp) {
+		pr_err("%s: smem areas kmalloc failed\n", __func__);
+		ret = -ENOMEM;
+		goto free_smem_areas;
+	}
+
+	ramdump_segments_tmp = kmalloc_array(num_smem_areas,
+			sizeof(struct ramdump_segment), GFP_KERNEL);
+	if (!ramdump_segments_tmp) {
+		pr_err("%s: ramdump segment kmalloc failed\n", __func__);
+		ret = -ENOMEM;
+		goto free_smem_areas;
+	}
+	smem_areas_tmp[smem_idx].phys_addr =  r->start;
+	smem_areas_tmp[smem_idx].size = resource_size(r);
+	smem_areas_tmp[smem_idx].virt_addr = MSM_SHARED_RAM_BASE;
+
+	ramdump_segments_tmp[smem_idx].address = r->start;
+	ramdump_segments_tmp[smem_idx].size = resource_size(r);
+	++smem_idx;
+
+	/* Configure auxiliary SMEM regions */
+	while (1) {
+		scnprintf(temp_string, temp_string_size, "aux-mem%d",
+								smem_idx);
+		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+							temp_string);
+		if (!r)
+			break;
+		aux_mem_base = r->start;
+		aux_mem_size = resource_size(r);
+
+		ramdump_segments_tmp[smem_idx].address = aux_mem_base;
+		ramdump_segments_tmp[smem_idx].size = aux_mem_size;
+
+		smem_areas_tmp[smem_idx].phys_addr = aux_mem_base;
+		smem_areas_tmp[smem_idx].size = aux_mem_size;
+		smem_areas_tmp[smem_idx].virt_addr = ioremap_nocache(
+			(unsigned long)(smem_areas_tmp[smem_idx].phys_addr),
+			smem_areas_tmp[smem_idx].size);
+		SMEM_DBG("%s: %s = %pa %pa -> %p", __func__, temp_string,
+				&aux_mem_base, &aux_mem_size,
+				smem_areas_tmp[smem_idx].virt_addr);
+
+		if (!smem_areas_tmp[smem_idx].virt_addr) {
+			pr_err("%s: ioremap_nocache() of addr:%pa size: %pa\n",
+				__func__,
+				&smem_areas_tmp[smem_idx].phys_addr,
+				&smem_areas_tmp[smem_idx].size);
+			ret = -ENOMEM;
+			goto free_smem_areas;
+		}
+
+		if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
+				(uintptr_t)smem_areas_tmp[smem_idx].virt_addr,
+				smem_areas_tmp[smem_idx].size)) {
+			pr_err("%s: invalid virtual address block %i: %p:%pa\n",
+					__func__, smem_idx,
+					smem_areas_tmp[smem_idx].virt_addr,
+					&smem_areas_tmp[smem_idx].size);
+			++smem_idx;
+			ret = -EINVAL;
+			goto free_smem_areas;
+		}
+
+		++smem_idx;
+		if (smem_idx > 999) {
+			pr_err("%s: max num aux mem regions reached\n",
+							__func__);
+			break;
+		}
+	}
+
+	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	if (ret)
+		pr_err("%s: of_platform_populate failed %d\n", __func__, ret);
+
+	smem_areas = smem_areas_tmp;
+	smem_ramdump_segments = ramdump_segments_tmp;
+	return 0;
+
+free_smem_areas:
+	for (smem_idx = smem_idx - 1; smem_idx >= 1; --smem_idx)
+		iounmap(smem_areas_tmp[smem_idx].virt_addr);
+
+	num_smem_areas = 0;
+	kfree(ramdump_segments_tmp);
+	kfree(smem_areas_tmp);
+	return ret;
+}
+
+static struct of_device_id msm_smem_match_table[] = {
+	{ .compatible = "qcom,smem" },
+	{},
+};
+
+static struct platform_driver msm_smem_driver = {
+	.probe = msm_smem_probe,
+	.driver = {
+		.name = "msm_smem",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_smem_match_table,
+	},
+};
+
+int __init msm_smem_init(void)
+{
+	static bool registered;
+	int rc;
+
+	if (registered)
+		return 0;
+
+	registered = true;
+
+	rc = init_smem_remote_spinlock();
+	if (rc) {
+		pr_err("%s: remote spinlock init failed %d\n", __func__, rc);
+		return rc;
+	}
+
+	rc = platform_driver_register(&msm_smem_driver);
+	if (rc) {
+		pr_err("%s: msm_smem_driver register failed %d\n",
+							__func__, rc);
+		return rc;
+	}
+
+	smem_module_init_notify(0, NULL);
+
+	return 0;
+}
+
+module_init(msm_smem_init);
diff --git a/arch/arm/mach-msm/smem_log.c b/arch/arm/mach-msm/smem_log.c
index 87f141d2..35a6e15 100644
--- a/arch/arm/mach-msm/smem_log.c
+++ b/arch/arm/mach-msm/smem_log.c
@@ -39,6 +39,7 @@
 #include "smd_private.h"
 #include "smd_rpc_sym.h"
 #include "modem_notifier.h"
+#include "smem_private.h"
 
 #define DEBUG
 #undef DEBUG
@@ -158,7 +159,10 @@
 	{ SMEM_LOG_ERROR_EVENT_BASE, "ERROR" },
 	{ SMEM_LOG_DCVS_EVENT_BASE, "DCVS" },
 	{ SMEM_LOG_SLEEP_EVENT_BASE, "SLEEP" },
-	{ SMEM_LOG_RPC_ROUTER_EVENT_BASE, "ROUTER" },
+	{ SMEM_LOG_RPC_ROUTER_EVENT_BASE, "RPCROUTER" },
+	{ SMEM_LOG_QMI_CCI_EVENT_BASE, "QCCI" },
+	{ SMEM_LOG_QMI_CSI_EVENT_BASE, "QCSI" },
+	{ SMEM_LOG_IPC_ROUTER_EVENT_BASE, "IPCROUTER" },
 };
 
 struct sym event_syms[] = {
@@ -2005,7 +2009,7 @@
 	return ret;
 }
 
-static int smd_module_init_notifier(struct notifier_block *this,
+static int smem_module_init_notifier(struct notifier_block *this,
 				    unsigned long code,
 				    void *_cmd)
 {
@@ -2016,12 +2020,12 @@
 }
 
 static struct notifier_block nb = {
-	.notifier_call = smd_module_init_notifier,
+	.notifier_call = smem_module_init_notifier,
 };
 
 static int __init smem_log_init(void)
 {
-	return smd_module_init_notifier_register(&nb);
+	return smem_module_init_notifier_register(&nb);
 }
 
 
diff --git a/arch/arm/mach-msm/smem_private.h b/arch/arm/mach-msm/smem_private.h
index c4f9a77..ceb8028 100644
--- a/arch/arm/mach-msm/smem_private.h
+++ b/arch/arm/mach-msm/smem_private.h
@@ -17,10 +17,6 @@
 
 #include <mach/ramdump.h>
 
-#define SMEM_SPINLOCK_SMEM_ALLOC       "S:3"
-extern remote_spinlock_t remote_spinlock;
-extern int spinlocks_initialized; /* only modify in init_smem_remote_spinlock */
-
 #define SMD_HEAP_SIZE 512
 
 struct smem_heap_info {
@@ -58,19 +54,26 @@
 	void __iomem *virt_addr;
 };
 
-extern uint32_t num_smem_areas;
-extern struct smem_area *smem_areas;
-
-extern struct ramdump_segment *smem_ramdump_segments;
-
 /* used for unit testing spinlocks */
 remote_spinlock_t *smem_get_remote_spinlock(void);
 
-/*
- * used to ensure the remote spinlock is only inited once since local
- * spinlock init code appears non-reentrant
- */
-int init_smem_remote_spinlock(void);
-
 bool smem_initialized_check(void);
+
+/**
+ * smem_module_init_notifier_register() - Register a smem module
+ *                                       init notifier block
+ * @nb: Notifier block to be registered
+ *
+ * In order to mark the dependency on SMEM Driver module initialization
+ * register a notifier using this API. Once the smem module_init is
+ * done, notification will be passed to the registered module.
+ */
+int smem_module_init_notifier_register(struct notifier_block *nb);
+
+/**
+ * smem_module_init_notifier_register() - Unregister a smem module
+ *                                       init notifier block
+ * @nb: Notifier block to be unregistered
+ */
+int smem_module_init_notifier_unregister(struct notifier_block *nb);
 #endif /* _ARCH_ARM_MACH_MSM_SMEM_PRIVATE_H_ */
diff --git a/arch/arm/mach-msm/smp2p.c b/arch/arm/mach-msm/smp2p.c
index ee262b0..4b69cf0 100644
--- a/arch/arm/mach-msm/smp2p.c
+++ b/arch/arm/mach-msm/smp2p.c
@@ -379,7 +379,7 @@
 	struct smp2p_out_list_item *out_item)
 {
 	void *item_ptr = NULL;
-	unsigned size;
+	unsigned size = 0;
 
 	if (!out_item)
 		return item_ptr;
@@ -1241,7 +1241,7 @@
 {
 	unsigned long flags;
 	struct smp2p_out_list_item *out_item;
-	uint32_t *entry_ptr;
+	uint32_t *entry_ptr = NULL;
 
 	if (remote_pid >= SMP2P_NUM_PROCS)
 		return -EINVAL;
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 575cb49..6cb04c7 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -71,6 +71,21 @@
 };
 
 enum {
+	PLATFORM_SUBTYPE_QRD = 0x0,
+	PLATFORM_SUBTYPE_SKUAA = 0x1,
+	PLATFORM_SUBTYPE_SKUF = 0x2,
+	PLATFORM_SUBTYPE_SKUAB = 0x3,
+	PLATFORM_SUBTYPE_QRD_INVALID,
+};
+
+const char *qrd_hw_platform_subtype[] = {
+	[PLATFORM_SUBTYPE_QRD] = "QRD",
+	[PLATFORM_SUBTYPE_SKUAA] = "SKUAA",
+	[PLATFORM_SUBTYPE_SKUF] = "SKUF",
+	[PLATFORM_SUBTYPE_SKUAB] = "SKUAB",
+};
+
+enum {
 	PLATFORM_SUBTYPE_UNKNOWN = 0x0,
 	PLATFORM_SUBTYPE_CHARM = 0x1,
 	PLATFORM_SUBTYPE_STRANGE = 0x2,
@@ -282,6 +297,24 @@
 	[185] = MSM_CPU_8974,
 	[186] = MSM_CPU_8974,
 
+	/* 8974AA IDs */
+	[208] = MSM_CPU_8974PRO_AA,
+	[211] = MSM_CPU_8974PRO_AA,
+	[214] = MSM_CPU_8974PRO_AA,
+	[217] = MSM_CPU_8974PRO_AA,
+
+	/* 8974AB IDs */
+	[209] = MSM_CPU_8974PRO_AB,
+	[212] = MSM_CPU_8974PRO_AB,
+	[215] = MSM_CPU_8974PRO_AB,
+	[218] = MSM_CPU_8974PRO_AB,
+
+	/* 8974AC IDs */
+	[194] = MSM_CPU_8974PRO_AC,
+	[210] = MSM_CPU_8974PRO_AC,
+	[213] = MSM_CPU_8974PRO_AC,
+	[216] = MSM_CPU_8974PRO_AC,
+
 	/* 8625 IDs */
 	[127] = MSM_CPU_8625,
 	[128] = MSM_CPU_8625,
@@ -629,9 +662,18 @@
 	}
 
 	hw_subtype = socinfo_get_platform_subtype();
+	if (HW_PLATFORM_QRD == socinfo_get_platform_type()) {
+		if (hw_subtype >= PLATFORM_SUBTYPE_QRD_INVALID) {
+			pr_err("%s: Invalid hardware platform sub type for qrd found\n",
+				__func__);
+			hw_subtype = PLATFORM_SUBTYPE_QRD;
+		}
+		return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+					qrd_hw_platform_subtype[hw_subtype]);
+	}
 	if (hw_subtype >= PLATFORM_SUBTYPE_INVALID) {
 		pr_err("%s: Invalid hardware platform sub type found\n",
-								   __func__);
+			   __func__);
 		hw_subtype = PLATFORM_SUBTYPE_UNKNOWN;
 	}
 	return snprintf(buf, PAGE_SIZE, "%-.32s\n",
diff --git a/block/blk-core.c b/block/blk-core.c
index 153240e..8e12c45 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -30,6 +30,7 @@
 #include <linux/list_sort.h>
 #include <linux/delay.h>
 #include <linux/ratelimit.h>
+#include <linux/pm_runtime.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/block.h>
@@ -1195,6 +1196,16 @@
 }
 EXPORT_SYMBOL_GPL(part_round_stats);
 
+#ifdef CONFIG_PM_RUNTIME
+static void blk_pm_put_request(struct request *rq)
+{
+	if (rq->q->dev && !(rq->cmd_flags & REQ_PM) && !--rq->q->nr_pending)
+		pm_runtime_mark_last_busy(rq->q->dev);
+}
+#else
+static inline void blk_pm_put_request(struct request *rq) {}
+#endif
+
 /*
  * queue lock must be held
  */
@@ -1205,6 +1216,8 @@
 	if (unlikely(--req->ref_count))
 		return;
 
+	blk_pm_put_request(req);
+
 	elv_completed_request(q, req);
 
 	/* this is a bio leak */
@@ -1981,6 +1994,28 @@
 	}
 }
 
+#ifdef CONFIG_PM_RUNTIME
+/*
+ * Don't process normal requests when queue is suspended
+ * or in the process of suspending/resuming
+ */
+static struct request *blk_pm_peek_request(struct request_queue *q,
+					   struct request *rq)
+{
+	if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
+	    (q->rpm_status != RPM_ACTIVE && !(rq->cmd_flags & REQ_PM))))
+		return NULL;
+	else
+		return rq;
+}
+#else
+static inline struct request *blk_pm_peek_request(struct request_queue *q,
+						  struct request *rq)
+{
+	return rq;
+}
+#endif
+
 /**
  * blk_peek_request - peek at the top of a request queue
  * @q: request queue to peek at
@@ -2003,6 +2038,11 @@
 	int ret;
 
 	while ((rq = __elv_next_request(q)) != NULL) {
+
+		rq = blk_pm_peek_request(q, rq);
+		if (!rq)
+			break;
+
 		if (!(rq->cmd_flags & REQ_STARTED)) {
 			/*
 			 * This is the first time the device driver
@@ -2979,6 +3019,149 @@
 }
 EXPORT_SYMBOL(blk_finish_plug);
 
+#ifdef CONFIG_PM_RUNTIME
+/**
+ * blk_pm_runtime_init - Block layer runtime PM initialization routine
+ * @q: the queue of the device
+ * @dev: the device the queue belongs to
+ *
+ * Description:
+ *    Initialize runtime-PM-related fields for @q and start auto suspend for
+ *    @dev. Drivers that want to take advantage of request-based runtime PM
+ *    should call this function after @dev has been initialized, and its
+ *    request queue @q has been allocated, and runtime PM for it can not happen
+ *    yet(either due to disabled/forbidden or its usage_count > 0). In most
+ *    cases, driver should call this function before any I/O has taken place.
+ *
+ *    This function takes care of setting up using auto suspend for the device,
+ *    the autosuspend delay is set to -1 to make runtime suspend impossible
+ *    until an updated value is either set by user or by driver. Drivers do
+ *    not need to touch other autosuspend settings.
+ *
+ *    The block layer runtime PM is request based, so only works for drivers
+ *    that use request as their IO unit instead of those directly use bio's.
+ */
+void blk_pm_runtime_init(struct request_queue *q, struct device *dev)
+{
+	q->dev = dev;
+	q->rpm_status = RPM_ACTIVE;
+	pm_runtime_set_autosuspend_delay(q->dev, -1);
+	pm_runtime_use_autosuspend(q->dev);
+}
+EXPORT_SYMBOL(blk_pm_runtime_init);
+
+/**
+ * blk_pre_runtime_suspend - Pre runtime suspend check
+ * @q: the queue of the device
+ *
+ * Description:
+ *    This function will check if runtime suspend is allowed for the device
+ *    by examining if there are any requests pending in the queue. If there
+ *    are requests pending, the device can not be runtime suspended; otherwise,
+ *    the queue's status will be updated to SUSPENDING and the driver can
+ *    proceed to suspend the device.
+ *
+ *    For the not allowed case, we mark last busy for the device so that
+ *    runtime PM core will try to autosuspend it some time later.
+ *
+ *    This function should be called near the start of the device's
+ *    runtime_suspend callback.
+ *
+ * Return:
+ *    0		- OK to runtime suspend the device
+ *    -EBUSY	- Device should not be runtime suspended
+ */
+int blk_pre_runtime_suspend(struct request_queue *q)
+{
+	int ret = 0;
+
+	spin_lock_irq(q->queue_lock);
+	if (q->nr_pending) {
+		ret = -EBUSY;
+		pm_runtime_mark_last_busy(q->dev);
+	} else {
+		q->rpm_status = RPM_SUSPENDING;
+	}
+	spin_unlock_irq(q->queue_lock);
+	return ret;
+}
+EXPORT_SYMBOL(blk_pre_runtime_suspend);
+
+/**
+ * blk_post_runtime_suspend - Post runtime suspend processing
+ * @q: the queue of the device
+ * @err: return value of the device's runtime_suspend function
+ *
+ * Description:
+ *    Update the queue's runtime status according to the return value of the
+ *    device's runtime suspend function and mark last busy for the device so
+ *    that PM core will try to auto suspend the device at a later time.
+ *
+ *    This function should be called near the end of the device's
+ *    runtime_suspend callback.
+ */
+void blk_post_runtime_suspend(struct request_queue *q, int err)
+{
+	spin_lock_irq(q->queue_lock);
+	if (!err) {
+		q->rpm_status = RPM_SUSPENDED;
+	} else {
+		q->rpm_status = RPM_ACTIVE;
+		pm_runtime_mark_last_busy(q->dev);
+	}
+	spin_unlock_irq(q->queue_lock);
+}
+EXPORT_SYMBOL(blk_post_runtime_suspend);
+
+/**
+ * blk_pre_runtime_resume - Pre runtime resume processing
+ * @q: the queue of the device
+ *
+ * Description:
+ *    Update the queue's runtime status to RESUMING in preparation for the
+ *    runtime resume of the device.
+ *
+ *    This function should be called near the start of the device's
+ *    runtime_resume callback.
+ */
+void blk_pre_runtime_resume(struct request_queue *q)
+{
+	spin_lock_irq(q->queue_lock);
+	q->rpm_status = RPM_RESUMING;
+	spin_unlock_irq(q->queue_lock);
+}
+EXPORT_SYMBOL(blk_pre_runtime_resume);
+
+/**
+ * blk_post_runtime_resume - Post runtime resume processing
+ * @q: the queue of the device
+ * @err: return value of the device's runtime_resume function
+ *
+ * Description:
+ *    Update the queue's runtime status according to the return value of the
+ *    device's runtime_resume function. If it is successfully resumed, process
+ *    the requests that are queued into the device's queue when it is resuming
+ *    and then mark last busy and initiate autosuspend for it.
+ *
+ *    This function should be called near the end of the device's
+ *    runtime_resume callback.
+ */
+void blk_post_runtime_resume(struct request_queue *q, int err)
+{
+	spin_lock_irq(q->queue_lock);
+	if (!err) {
+		q->rpm_status = RPM_ACTIVE;
+		__blk_run_queue(q);
+		pm_runtime_mark_last_busy(q->dev);
+		pm_runtime_autosuspend(q->dev);
+	} else {
+		q->rpm_status = RPM_SUSPENDED;
+	}
+	spin_unlock_irq(q->queue_lock);
+}
+EXPORT_SYMBOL(blk_post_runtime_resume);
+#endif
+
 int __init blk_dev_init(void)
 {
 	BUILD_BUG_ON(__REQ_NR_BITS > 8 *
diff --git a/block/elevator.c b/block/elevator.c
index 27adf7c..44193a8 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -34,6 +34,7 @@
 #include <linux/blktrace_api.h>
 #include <linux/hash.h>
 #include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
 
 #include <trace/events/block.h>
 
@@ -568,6 +569,27 @@
 		e->type->ops.elevator_bio_merged_fn(q, rq, bio);
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static void blk_pm_requeue_request(struct request *rq)
+{
+	if (rq->q->dev && !(rq->cmd_flags & REQ_PM))
+		rq->q->nr_pending--;
+}
+
+static void blk_pm_add_request(struct request_queue *q, struct request *rq)
+{
+	if (q->dev && !(rq->cmd_flags & REQ_PM) && q->nr_pending++ == 0 &&
+	    (q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING))
+		pm_request_resume(q->dev);
+}
+#else
+static inline void blk_pm_requeue_request(struct request *rq) {}
+static inline void blk_pm_add_request(struct request_queue *q,
+				      struct request *rq)
+{
+}
+#endif
+
 void elv_requeue_request(struct request_queue *q, struct request *rq)
 {
 	/*
@@ -582,6 +604,8 @@
 
 	rq->cmd_flags &= ~REQ_STARTED;
 
+	blk_pm_requeue_request(rq);
+
 	__elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE);
 }
 
@@ -658,6 +682,8 @@
 {
 	trace_block_rq_insert(q, rq);
 
+	blk_pm_add_request(q, rq);
+
 	rq->q = q;
 
 	if (rq->cmd_flags & REQ_SOFTBARRIER) {
diff --git a/block/row-iosched.c b/block/row-iosched.c
index e71f6af..3fa3b1a 100644
--- a/block/row-iosched.c
+++ b/block/row-iosched.c
@@ -97,7 +97,7 @@
 
 /* Default values for idling on read queues (in msec) */
 #define ROW_IDLE_TIME_MSEC 5
-#define ROW_READ_FREQ_MSEC 20
+#define ROW_READ_FREQ_MSEC 5
 
 /**
  * struct rowq_idling_data -  parameters for idling on the queue
@@ -331,6 +331,10 @@
 	struct row_queue *rqueue = RQ_ROWQ(rq);
 	s64 diff_ms;
 	bool queue_was_empty = list_empty(&rqueue->fifo);
+	unsigned long bv_page_flags = 0;
+
+	if (rq->bio && rq->bio->bi_io_vec && rq->bio->bi_io_vec->bv_page)
+		bv_page_flags = rq->bio->bi_io_vec->bv_page->flags;
 
 	list_add_tail(&rq->queuelist, &rqueue->fifo);
 	rd->nr_reqs[rq_data_dir(rq)]++;
@@ -360,7 +364,9 @@
 			rqueue->idle_data.begin_idling = false;
 			return;
 		}
-		if (diff_ms < rd->rd_idle_data.freq_ms) {
+
+		if ((bv_page_flags & (1L << PG_readahead)) ||
+		    (diff_ms < rd->rd_idle_data.freq_ms)) {
 			rqueue->idle_data.begin_idling = true;
 			row_log_rowq(rd, rqueue->prio, "Enable idling");
 		} else {
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 5027107..d01496e 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -515,6 +515,7 @@
 
 	if (!temp) {
 		pr_err("diag: Invalid buffer in %s\n", __func__);
+		return -ENOMEM;
 	}
 
 	/* This is Pkt request/response transaction */
@@ -1239,6 +1240,10 @@
 
 	if (driver->diag_dci_wq)
 		destroy_workqueue(driver->diag_dci_wq);
+	mutex_destroy(&driver->dci_mutex);
+	mutex_destroy(&dci_log_mask_mutex);
+	mutex_destroy(&dci_event_mask_mutex);
+	mutex_destroy(&dci_health_mutex);
 	return DIAG_DCI_NO_REG;
 }
 
@@ -1381,4 +1386,25 @@
 	return 0;
 }
 
+uint8_t diag_dci_get_cumulative_real_time()
+{
+	uint8_t real_time = MODE_NONREALTIME, i;
+	for (i = 0; i < MAX_DCI_CLIENTS; i++)
+		if (driver->dci_client_tbl[i].client &&
+				driver->dci_client_tbl[i].real_time ==
+				MODE_REALTIME) {
+			real_time = 1;
+			break;
+		}
+	return real_time;
+}
 
+int diag_dci_set_real_time(int client_id, uint8_t real_time)
+{
+	int i = DCI_CLIENT_INDEX_INVALID;
+	i = diag_dci_find_client_index(client_id);
+
+	if (i != DCI_CLIENT_INDEX_INVALID)
+		driver->dci_client_tbl[i].real_time = real_time;
+	return i;
+}
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 22f2cad..2335d37 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -66,6 +66,7 @@
 	int received_logs;
 	int received_events;
 	struct mutex data_mutex;
+	uint8_t real_time;
 };
 
 /* This is used for DCI health stats */
@@ -135,4 +136,6 @@
 int diag_dci_clear_event_mask(void);
 int diag_dci_query_event_mask(uint16_t event_id);
 void diag_dci_smd_record_info(int read_bytes);
+uint8_t diag_dci_get_cumulative_real_time(void);
+int diag_dci_set_real_time(int client_id, uint8_t real_time);
 #endif
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index 6b0931c..81c5e57 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -70,7 +70,8 @@
 		"Modem CMD in_busy_1: %d\n"
 		"Modem CMD in_busy_2: %d\n"
 		"DCI CMD Modem in_busy_1: %d\n"
-		"logging_mode: %d\n",
+		"logging_mode: %d\n"
+		"real_time_mode: %d\n",
 		(unsigned int)driver->smd_data[MODEM_DATA].ch,
 		(unsigned int)driver->smd_data[LPASS_DATA].ch,
 		(unsigned int)driver->smd_data[WCNSS_DATA].ch,
@@ -100,7 +101,8 @@
 		driver->smd_cmd[MODEM_DATA].in_busy_1,
 		driver->smd_cmd[MODEM_DATA].in_busy_2,
 		driver->smd_dci_cmd[MODEM_DATA].in_busy_1,
-		driver->logging_mode);
+		driver->logging_mode,
+		driver->real_time_mode);
 
 #ifdef CONFIG_DIAG_OVER_USB
 	ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
@@ -137,8 +139,12 @@
 	if (diag_dbgfs_dci_data_index == 0) {
 		bytes_written =
 			scnprintf(buf, buf_size,
-			"number of clients: %d\n",
-			driver->num_dci_client);
+			"number of clients: %d\n"
+			"dci proc active: %d\n"
+			"dci real time vote: %d\n",
+			driver->num_dci_client,
+			(driver->proc_active_mask & DIAG_PROC_DCI) ? 1 : 0,
+			(driver->proc_rt_vote_mask & DIAG_PROC_DCI) ? 1 : 0);
 		bytes_in_buf += bytes_written;
 		bytes_remaining -= bytes_written;
 #ifdef CONFIG_DIAG_OVER_USB
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 5aed793..d838714 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -307,7 +307,8 @@
 	diag_send_feature_mask_update(smd_info);
 
 	if (smd_info->notify_context == SMD_EVENT_OPEN)
-		diag_send_diag_mode_update_by_smd(smd_info, MODE_REALTIME);
+		diag_send_diag_mode_update_by_smd(smd_info,
+						driver->real_time_mode);
 
 	smd_info->notify_context = 0;
 }
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 1f45a32..1495ad5 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -113,6 +113,14 @@
 #define SMD_CMD_TYPE 3
 #define SMD_DCI_CMD_TYPE 4
 
+#define DIAG_PROC_DCI			1
+#define DIAG_PROC_MEMORY_DEVICE		2
+
+/* Flags to vote the DCI or Memory device process up or down
+   when it becomes active or inactive */
+#define VOTE_DOWN			0
+#define VOTE_UP				1
+
 #define DIAG_TS_SIZE	50
 
 /* Maximum number of pkt reg supported at initialization*/
@@ -182,6 +190,11 @@
 	spinlock_t read_spinlock;
 };
 
+struct real_time_vote_t {
+	uint16_t proc;
+	uint8_t real_time_vote;
+};
+
 /* This structure is defined in USB header file */
 #ifndef CONFIG_DIAG_OVER_USB
 struct diag_request {
@@ -286,7 +299,6 @@
 	struct diag_ctrl_msg_mask *msg_mask;
 	struct diag_ctrl_feature_mask *feature_mask;
 	/* State for diag forwarding */
-	int real_time_mode;
 	struct diag_smd_info smd_data[NUM_SMD_DATA_CHANNELS];
 	struct diag_smd_info smd_cntl[NUM_SMD_CONTROL_CHANNELS];
 	struct diag_smd_info smd_dci[NUM_SMD_DCI_CHANNELS];
@@ -306,6 +318,14 @@
 	unsigned hdlc_count;
 	unsigned hdlc_escape;
 	int in_busy_pktdata;
+	/* Variables for non real time mode */
+	int real_time_mode;
+	int real_time_update_busy;
+	uint16_t proc_active_mask;
+	uint16_t proc_rt_vote_mask;
+	struct mutex real_time_mutex;
+	struct work_struct diag_real_time_work;
+	struct workqueue_struct *diag_real_time_wq;
 #ifdef CONFIG_DIAG_OVER_USB
 	int usb_connected;
 	struct usb_diag_ch *legacy_ch;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 1a2f431..12c40da 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -270,20 +270,24 @@
 		 DCI_CLIENT_INDEX_INVALID)
 		diagchar_ioctl(NULL, DIAG_IOCTL_DCI_DEINIT, 0);
 	/* If the exiting process is the socket process */
+	mutex_lock(&driver->diagchar_mutex);
 	if (driver->socket_process &&
 		(driver->socket_process->tgid == current->tgid)) {
 		driver->socket_process = NULL;
+		diag_update_proc_vote(DIAG_PROC_MEMORY_DEVICE, VOTE_DOWN);
 	}
 	if (driver->callback_process &&
 		(driver->callback_process->tgid == current->tgid)) {
 		driver->callback_process = NULL;
+		diag_update_proc_vote(DIAG_PROC_MEMORY_DEVICE, VOTE_DOWN);
 	}
+	mutex_unlock(&driver->diagchar_mutex);
 
 #ifdef CONFIG_DIAG_OVER_USB
 	/* If the SD logging process exits, change logging to USB mode */
 	if (driver->logging_process_id == current->tgid) {
 		driver->logging_mode = USB_MODE;
-		diag_send_diag_mode_update(MODE_REALTIME);
+		diag_update_proc_vote(DIAG_PROC_MEMORY_DEVICE, VOTE_DOWN);
 		diagfwd_connect();
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 		diag_clear_hsic_tbl();
@@ -796,7 +800,6 @@
 int diag_switch_logging(unsigned long ioarg)
 {
 	int temp = 0, success = -EINVAL, status = 0;
-	int temp_realtime_mode = driver->real_time_mode;
 	int requested_mode = (int)ioarg;
 
 	switch (requested_mode) {
@@ -806,7 +809,6 @@
 	case UART_MODE:
 	case SOCKET_MODE:
 	case CALLBACK_MODE:
-	case MEMORY_DEVICE_MODE_NRT:
 		break;
 	default:
 		pr_err("diag: In %s, request to switch to invalid mode: %d\n",
@@ -814,26 +816,28 @@
 		return -EINVAL;
 	}
 
-	mutex_lock(&driver->diagchar_mutex);
-	temp = driver->logging_mode;
-	driver->logging_mode = requested_mode;
-
-	if (driver->logging_mode == MEMORY_DEVICE_MODE_NRT) {
-		diag_send_diag_mode_update(MODE_NONREALTIME);
-		driver->logging_mode = MEMORY_DEVICE_MODE;
-	} else {
-		diag_send_diag_mode_update(MODE_REALTIME);
-	}
-
-	if (temp == driver->logging_mode) {
-		mutex_unlock(&driver->diagchar_mutex);
-		if (driver->logging_mode != MEMORY_DEVICE_MODE ||
-			temp_realtime_mode)
+	if (requested_mode == driver->logging_mode) {
+		if (requested_mode != MEMORY_DEVICE_MODE ||
+					driver->real_time_mode)
 			pr_info_ratelimited("diag: Already in logging mode change requested, mode: %d\n",
 					driver->logging_mode);
 		return 0;
 	}
 
+	diag_update_proc_vote(DIAG_PROC_MEMORY_DEVICE, VOTE_UP);
+	if (requested_mode != MEMORY_DEVICE_MODE)
+		diag_update_real_time_vote(DIAG_PROC_MEMORY_DEVICE,
+								MODE_REALTIME);
+
+	if (!(requested_mode == MEMORY_DEVICE_MODE &&
+					driver->logging_mode == USB_MODE))
+		queue_work(driver->diag_real_time_wq,
+						&driver->diag_real_time_work);
+
+	mutex_lock(&driver->diagchar_mutex);
+	temp = driver->logging_mode;
+	driver->logging_mode = requested_mode;
+
 	if (driver->logging_mode == MEMORY_DEVICE_MODE) {
 		diag_clear_hsic_tbl();
 		driver->mask_check = 1;
@@ -911,12 +915,14 @@
 long diagchar_ioctl(struct file *filp,
 			   unsigned int iocmd, unsigned long ioarg)
 {
-	int i, result = -EINVAL, interim_size = 0, client_id = 0;
+	int i, result = -EINVAL, interim_size = 0, client_id = 0, real_time = 0;
+	int retry_count = 0, timer = 0;
 	uint16_t support_list = 0, interim_rsp_id, remote_dev;
 	struct diag_dci_client_tbl *dci_params;
 	struct diag_dci_health_stats stats;
 	struct diag_log_event_stats le_stats;
 	struct diagpkt_delay_params delay_params;
+	struct real_time_vote_t rt_vote;
 
 	switch (iocmd) {
 	case DIAG_IOCTL_COMMAND_REG:
@@ -966,6 +972,10 @@
 					driver->smd_dci_cmd[i].in_busy_1 = 0;
 		}
 		driver->num_dci_client++;
+		if (driver->num_dci_client == 1)
+			diag_update_proc_vote(DIAG_PROC_DCI, VOTE_UP);
+		queue_work(driver->diag_real_time_wq,
+				 &driver->diag_real_time_work);
 		pr_debug("diag: In %s, id = %d\n",
 				__func__, driver->dci_client_id);
 		driver->dci_client_id++;
@@ -989,6 +999,7 @@
 				driver->dci_client_tbl[i].dropped_events = 0;
 				driver->dci_client_tbl[i].received_logs = 0;
 				driver->dci_client_tbl[i].received_events = 0;
+				driver->dci_client_tbl[i].real_time = 1;
 				mutex_init(&driver->dci_client_tbl[i].
 								data_mutex);
 				break;
@@ -1037,6 +1048,15 @@
 			mutex_destroy(&driver->dci_client_tbl[result].
 								data_mutex);
 			driver->num_dci_client--;
+			if (driver->num_dci_client == 0) {
+				diag_update_proc_vote(DIAG_PROC_DCI, VOTE_DOWN);
+			} else {
+				real_time = diag_dci_get_cumulative_real_time();
+				diag_update_real_time_vote(DIAG_PROC_DCI,
+								real_time);
+			}
+			queue_work(driver->diag_real_time_wq,
+				   &driver->diag_real_time_work);
 		}
 		mutex_unlock(&driver->dci_mutex);
 		break;
@@ -1131,6 +1151,44 @@
 		else
 			result = 1;
 		break;
+	case DIAG_IOCTL_VOTE_REAL_TIME:
+		if (copy_from_user(&rt_vote, (void *)ioarg, sizeof(struct
+							real_time_vote_t)))
+			result = -EFAULT;
+		driver->real_time_update_busy++;
+		if (rt_vote.proc == DIAG_PROC_DCI) {
+			diag_dci_set_real_time(current->tgid,
+						rt_vote.real_time_vote);
+			real_time = diag_dci_get_cumulative_real_time();
+		} else {
+			real_time = rt_vote.real_time_vote;
+		}
+		diag_update_real_time_vote(rt_vote.proc, real_time);
+		queue_work(driver->diag_real_time_wq,
+				 &driver->diag_real_time_work);
+		result = 0;
+		break;
+	case DIAG_IOCTL_GET_REAL_TIME:
+		if (copy_from_user(&real_time, (void *)ioarg, sizeof(int)))
+			return -EFAULT;
+		while (retry_count < 3) {
+			if (driver->real_time_update_busy > 0) {
+				retry_count++;
+				/* The value 10000 was chosen empirically as an
+				   optimum value in order to give the work in
+				   diag_real_time_wq to complete processing.*/
+				for (timer = 0; timer < 5; timer++)
+					usleep_range(10000, 10100);
+			} else {
+				real_time = driver->real_time_mode;
+				if (copy_to_user((void *)ioarg, &real_time,
+								sizeof(int)))
+					return -EFAULT;
+				result = 0;
+				break;
+			}
+		}
+		break;
 	}
 	return result;
 }
@@ -1422,7 +1480,8 @@
 				size_t count, loff_t *ppos)
 {
 	int err, ret = 0, pkt_type, token_offset = 0;
-	int remote_proc = 0, index;
+	int remote_proc = 0;
+	uint8_t index;
 #ifdef DIAG_DEBUG
 	int length = 0, i;
 #endif
@@ -1862,6 +1921,21 @@
 	return ret;
 }
 
+static void diag_real_time_info_init(void)
+{
+	if (!driver)
+		return;
+	driver->real_time_mode = 1;
+	driver->real_time_update_busy = 0;
+	driver->proc_active_mask = 0;
+	driver->proc_rt_vote_mask |= DIAG_PROC_DCI;
+	driver->proc_rt_vote_mask |= DIAG_PROC_MEMORY_DEVICE;
+	driver->diag_real_time_wq = create_singlethread_workqueue(
+							"diag_real_time_wq");
+	INIT_WORK(&(driver->diag_real_time_work), diag_real_time_work_fn);
+	mutex_init(&driver->real_time_mutex);
+}
+
 int mask_request_validate(unsigned char mask_buf[])
 {
 	uint8_t packet_id;
@@ -2063,6 +2137,7 @@
 		init_waitqueue_head(&driver->wait_q);
 		init_waitqueue_head(&driver->smd_wait_q);
 		INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn);
+		diag_real_time_info_init();
 		diag_debugfs_init();
 		diag_masks_init();
 		diagfwd_init();
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6851fd8..d07cc04 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1384,6 +1384,8 @@
 		/* Poll SMD CNTL channels to check for data */
 		diag_smd_notify(&(driver->smd_cntl[i]), SMD_EVENT_DATA);
 	}
+	queue_work(driver->diag_real_time_wq,
+				 &driver->diag_real_time_work);
 
 	/* Poll USB channel to check for data*/
 	queue_work(driver->diag_wq, &(driver->diag_read_work));
@@ -1419,6 +1421,8 @@
 			}
 		}
 	}
+	queue_work(driver->diag_real_time_wq,
+				 &driver->diag_real_time_work);
 #ifdef CONFIG_DIAG_SDIO_PIPE
 	if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
 		if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c
index 8c07219b..e5a6734 100644
--- a/drivers/char/diag/diagfwd_bridge.c
+++ b/drivers/char/diag/diagfwd_bridge.c
@@ -35,7 +35,7 @@
 /* diagfwd_connect_bridge is called when the USB mdm channel is connected */
 int diagfwd_connect_bridge(int process_cable)
 {
-	int i;
+	uint8_t i;
 
 	pr_debug("diag: in %s\n", __func__);
 
@@ -45,7 +45,7 @@
 	return 0;
 }
 
-void connect_bridge(int process_cable, int index)
+void connect_bridge(int process_cable, uint8_t index)
 {
 	int err;
 
@@ -65,6 +65,12 @@
 		driver->in_busy_smux = 0;
 		diagfwd_connect_smux();
 	} else {
+		if (index >= MAX_HSIC_CH) {
+			pr_err("diag: Invalid hsic channel index %d in %s\n",
+							index, __func__);
+			mutex_unlock(&diag_bridge[index].bridge_mutex);
+			return;
+		}
 		if (diag_hsic[index].hsic_device_enabled &&
 			(driver->logging_mode != MEMORY_DEVICE_MODE ||
 			diag_hsic[index].hsic_data_requested)) {
@@ -74,7 +80,7 @@
 			 * device is not open */
 			if (!diag_hsic[index].hsic_device_opened) {
 				hsic_diag_bridge_ops[index].ctxt =
-							(void *)(index);
+							(void *)(int)(index);
 				err = diag_bridge_open(index,
 						 &hsic_diag_bridge_ops[index]);
 				if (err) {
diff --git a/drivers/char/diag/diagfwd_bridge.h b/drivers/char/diag/diagfwd_bridge.h
index 88c96ab..ae1259b 100644
--- a/drivers/char/diag/diagfwd_bridge.h
+++ b/drivers/char/diag/diagfwd_bridge.h
@@ -21,7 +21,7 @@
 #define SMUX	4
 
 int diagfwd_connect_bridge(int);
-void connect_bridge(int, int);
+void connect_bridge(int, uint8_t);
 int diagfwd_disconnect_bridge(int);
 void diagfwd_bridge_init(int index);
 void diagfwd_bridge_exit(void);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 13cbc8f..b36b7dd 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -151,15 +151,85 @@
 	return flag;
 }
 
-void diag_send_diag_mode_update(int real_time)
+void diag_update_proc_vote(uint16_t proc, uint8_t vote)
 {
-	int i;
-
-	for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
-		diag_send_diag_mode_update_by_smd(&driver->smd_cntl[i],
-							real_time);
+	mutex_lock(&driver->real_time_mutex);
+	if (vote)
+		driver->proc_active_mask |= proc;
+	else {
+		driver->proc_active_mask &= ~proc;
+		driver->proc_rt_vote_mask |= proc;
+	}
+	mutex_unlock(&driver->real_time_mutex);
 }
 
+void diag_update_real_time_vote(uint16_t proc, uint8_t real_time)
+{
+	mutex_lock(&driver->real_time_mutex);
+	if (real_time)
+		driver->proc_rt_vote_mask |= proc;
+	else
+		driver->proc_rt_vote_mask &= ~proc;
+	mutex_unlock(&driver->real_time_mutex);
+}
+
+#ifdef CONFIG_DIAG_OVER_USB
+void diag_real_time_work_fn(struct work_struct *work)
+{
+	int temp_real_time = MODE_REALTIME, i;
+
+	/* If any of the process is voting for Real time, then Diag
+	   should be in real time mode irrespective of other clauses. If
+	   USB is connected, check what the memory device process is
+	   voting for. If it is voting for Non real time, the final mode
+	   should be Non real time, real time otherwise. If USB is
+	   disconncted and no process is voting for real time, the
+	   resultant mode should be Non Real Time.
+	*/
+	if ((driver->proc_rt_vote_mask & driver->proc_active_mask) &&
+					(driver->proc_active_mask != 0))
+			temp_real_time = MODE_REALTIME;
+	else if (driver->usb_connected)
+		if ((driver->proc_rt_vote_mask & DIAG_PROC_MEMORY_DEVICE) == 0)
+			temp_real_time = MODE_NONREALTIME;
+		else
+			temp_real_time = MODE_REALTIME;
+	else
+		temp_real_time = MODE_NONREALTIME;
+
+	if (temp_real_time != driver->real_time_mode) {
+		for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
+			diag_send_diag_mode_update_by_smd(&driver->smd_cntl[i],
+							temp_real_time);
+	} else {
+		pr_info("diag: did not update real time mode, already in the req mode %d",
+					temp_real_time);
+	}
+	if (driver->real_time_update_busy > 0)
+		driver->real_time_update_busy--;
+}
+#else
+void diag_real_time_work_fn(struct work_struct *work)
+{
+	int temp_real_time = MODE_REALTIME, i;
+
+	if (!(driver->proc_rt_vote_mask & driver->proc_active_mask) &&
+					(driver->proc_active_mask != 0))
+		temp_real_time = MODE_NONREALTIME;
+
+	if (temp_real_time != driver->real_time_mode) {
+		for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
+			diag_send_diag_mode_update_by_smd(&driver->smd_cntl[i],
+							temp_real_time);
+	} else {
+		pr_warn("diag: did not update real time mode, already in the req mode %d",
+					temp_real_time);
+	}
+	if (driver->real_time_update_busy > 0)
+		driver->real_time_update_busy--;
+}
+#endif
+
 void diag_send_diag_mode_update_by_smd(struct diag_smd_info *smd_info,
 							int real_time)
 {
@@ -343,6 +413,7 @@
 		diag_smd_destructor(&driver->smd_cntl[i]);
 
 	destroy_workqueue(driver->diag_cntl_wq);
+	destroy_workqueue(driver->diag_real_time_wq);
 
 	platform_driver_unregister(&msm_smd_ch1_cntl_driver);
 	platform_driver_unregister(&diag_smd_lite_cntl_driver);
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index 02b9757..ddefe10 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -124,8 +124,9 @@
 void diag_clean_reg_fn(struct work_struct *work);
 int diag_process_smd_cntl_read_data(struct diag_smd_info *smd_info, void *buf,
 								int total_recd);
-void diag_send_diag_mode_update(int real_time);
 void diag_send_diag_mode_update_by_smd(struct diag_smd_info *smd_info,
 							int real_time);
-
+void diag_update_proc_vote(uint16_t proc, uint8_t vote);
+void diag_update_real_time_vote(uint16_t proc, uint8_t real_time);
+void diag_real_time_work_fn(struct work_struct *work);
 #endif
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index f22b4c2..a6ef3ca 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -151,8 +151,9 @@
 		if (diag_hsic[index].diag_hsic_pool &&
 				(diag_hsic[index].hsic_inited == 0)) {
 			if (diag_hsic[index].count_hsic_pool == 0) {
-				mempool_destroy(driver->diag_hdlc_pool);
-				driver->diag_hdlc_pool = NULL;
+				mempool_destroy(
+					diag_hsic[index].diag_hsic_pool);
+				diag_hsic[index].diag_hsic_pool = NULL;
 			} else if (pool_type == POOL_TYPE_ALL)
 				pr_err("Unable to destroy HDLC mempool for ch %d"
 								, index);
diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig
index 7ec83dd..5e2acfb 100644
--- a/drivers/coresight/Kconfig
+++ b/drivers/coresight/Kconfig
@@ -24,6 +24,15 @@
 config HAVE_CORESIGHT_SINK
 	bool
 
+config CORESIGHT_FUSE
+	bool "CoreSight Fuse driver"
+	help
+	  This driver provides support for CoreSight Fuse state checks that
+	  other CoreSight drivers can query to determine existence of
+	  Hardware functionality they support. Drivers can then take necessary
+	  actions like failing the probe if the Hardware they manage is
+	  functionally disabled.
+
 config CORESIGHT_CTI
 	bool "CoreSight Cross Trigger Interface driver"
 	help
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 2b14f86..23352a7 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -2,6 +2,7 @@
 # Makefile for CoreSight drivers.
 #
 obj-$(CONFIG_CORESIGHT) += coresight.o
+obj-$(CONFIG_CORESIGHT_FUSE) += coresight-fuse.o
 obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o
 obj-$(CONFIG_CORESIGHT_CSR) += coresight-csr.o
 obj-$(CONFIG_CORESIGHT_TMC) += coresight-tmc.o
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index 8195184..132df90 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -168,6 +168,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-cti.c b/drivers/coresight/coresight-cti.c
index 6a8d412..d0900d1 100644
--- a/drivers/coresight/coresight-cti.c
+++ b/drivers/coresight/coresight-cti.c
@@ -388,6 +388,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-etb.c b/drivers/coresight/coresight-etb.c
index 31f85dc..473b4cb 100644
--- a/drivers/coresight/coresight-etb.c
+++ b/drivers/coresight/coresight-etb.c
@@ -362,6 +362,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index de86622..52f3027 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -2113,6 +2113,10 @@
 	struct msm_client_dump dump;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled() ||
+	    coresight_fuse_apps_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-funnel.c b/drivers/coresight/coresight-funnel.c
index 625f481..771321d 100644
--- a/drivers/coresight/coresight-funnel.c
+++ b/drivers/coresight/coresight-funnel.c
@@ -174,6 +174,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-fuse.c b/drivers/coresight/coresight-fuse.c
new file mode 100644
index 0000000..7af5c6c8
--- /dev/null
+++ b/drivers/coresight/coresight-fuse.c
@@ -0,0 +1,202 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+#define fuse_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
+#define fuse_readl(drvdata, off)	__raw_readl(drvdata->base + off)
+
+#define OEM_CONFIG0		(0x000)
+#define OEM_CONFIG1		(0x004)
+
+#define ALL_DEBUG_DISABLE	BIT(21)
+#define APPS_DBGEN_DISABLE	BIT(0)
+#define APPS_NIDEN_DISABLE	BIT(1)
+#define APPS_SPIDEN_DISABLE	BIT(2)
+#define APPS_SPNIDEN_DISABLE	BIT(3)
+#define DAP_DBGEN_DISABLE	BIT(4)
+#define DAP_NIDEN_DISABLE	BIT(5)
+#define DAP_SPIDEN_DISABLE	BIT(6)
+#define DAP_SPNIDEN_DISABLE	BIT(7)
+#define DAP_DEVICEEN_DISABLE	BIT(8)
+
+struct fuse_drvdata {
+	void __iomem		*base;
+	struct device		*dev;
+	struct coresight_device	*csdev;
+};
+
+static struct fuse_drvdata *fusedrvdata;
+
+bool coresight_fuse_access_disabled(void)
+{
+	struct fuse_drvdata *drvdata = fusedrvdata;
+	uint32_t config0, config1;
+	bool ret;
+
+	config0 = fuse_readl(drvdata, OEM_CONFIG0);
+	config1 = fuse_readl(drvdata, OEM_CONFIG1);
+
+	dev_dbg(drvdata->dev, "config0: %lx\n", (unsigned long)config0);
+	dev_dbg(drvdata->dev, "config1: %lx\n", (unsigned long)config1);
+
+	if (config0 & ALL_DEBUG_DISABLE)
+		ret = true;
+	else if (config1 & DAP_DBGEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_NIDEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_SPIDEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_SPNIDEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_DEVICEEN_DISABLE)
+		ret = true;
+	else
+		ret = false;
+
+	if (ret)
+		dev_dbg(drvdata->dev, "coresight fuse disabled\n");
+
+	return ret;
+}
+EXPORT_SYMBOL(coresight_fuse_access_disabled);
+
+bool coresight_fuse_apps_access_disabled(void)
+{
+	struct fuse_drvdata *drvdata = fusedrvdata;
+	uint32_t config0, config1;
+	bool ret;
+
+	config0 = fuse_readl(drvdata, OEM_CONFIG0);
+	config1 = fuse_readl(drvdata, OEM_CONFIG1);
+
+	dev_dbg(drvdata->dev, "apps config0: %lx\n", (unsigned long)config0);
+	dev_dbg(drvdata->dev, "apps config1: %lx\n", (unsigned long)config1);
+
+	if (config0 & ALL_DEBUG_DISABLE)
+		ret = true;
+	else if (config1 & APPS_DBGEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_NIDEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_SPIDEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_SPNIDEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_DEVICEEN_DISABLE)
+		ret = true;
+	else
+		ret = false;
+
+	if (ret)
+		dev_dbg(drvdata->dev, "apps fuse disabled\n");
+
+	return ret;
+}
+EXPORT_SYMBOL(coresight_fuse_apps_access_disabled);
+
+static int __devinit fuse_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct coresight_platform_data *pdata;
+	struct fuse_drvdata *drvdata;
+	struct resource *res;
+	struct coresight_desc *desc;
+
+	if (pdev->dev.of_node) {
+		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		pdev->dev.platform_data = pdata;
+	}
+
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	/* Store the driver data pointer for use in exported functions */
+	fusedrvdata = drvdata;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fuse-base");
+	if (!res)
+		return -ENODEV;
+
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+	desc->type = CORESIGHT_DEV_TYPE_NONE;
+	desc->pdata = pdev->dev.platform_data;
+	desc->dev = &pdev->dev;
+	desc->owner = THIS_MODULE;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev))
+		return PTR_ERR(drvdata->csdev);
+
+	dev_info(dev, "Fuse initialized\n");
+	return 0;
+}
+
+static int __devexit fuse_remove(struct platform_device *pdev)
+{
+	struct fuse_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	coresight_unregister(drvdata->csdev);
+	return 0;
+}
+
+static struct of_device_id fuse_match[] = {
+	{.compatible = "arm,coresight-fuse"},
+	{}
+};
+
+static struct platform_driver fuse_driver = {
+	.probe          = fuse_probe,
+	.remove         = __devexit_p(fuse_remove),
+	.driver         = {
+		.name   = "coresight-fuse",
+		.owner	= THIS_MODULE,
+		.of_match_table = fuse_match,
+	},
+};
+
+static int __init fuse_init(void)
+{
+	return platform_driver_register(&fuse_driver);
+}
+module_init(fuse_init);
+
+static void __exit fuse_exit(void)
+{
+	platform_driver_unregister(&fuse_driver);
+}
+module_exit(fuse_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Fuse driver");
diff --git a/drivers/coresight/coresight-hwevent.c b/drivers/coresight/coresight-hwevent.c
index 777484d..269d56e 100644
--- a/drivers/coresight/coresight-hwevent.c
+++ b/drivers/coresight/coresight-hwevent.c
@@ -211,6 +211,9 @@
 	int ret, i;
 	const char *hmux_name, *hclk_name;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
index f208185..b570252 100644
--- a/drivers/coresight/coresight-priv.h
+++ b/drivers/coresight/coresight-priv.h
@@ -36,6 +36,13 @@
 #define BMVAL(val, lsb, msb)	((val & BM(lsb, msb)) >> lsb)
 #define BVAL(val, n)		((val & BIT(n)) >> n)
 
+#ifdef CONFIG_CORESIGHT_FUSE
+extern bool coresight_fuse_access_disabled(void);
+extern bool coresight_fuse_apps_access_disabled(void);
+#else
+static inline bool coresight_fuse_access_disabled(void) { return false; }
+static inline bool coresight_fuse_apps_access_disabled(void) { return false; }
+#endif
 #ifdef CONFIG_CORESIGHT_CSR
 extern void msm_qdss_csr_enable_bam_to_usb(void);
 extern void msm_qdss_csr_disable_bam_to_usb(void);
diff --git a/drivers/coresight/coresight-replicator.c b/drivers/coresight/coresight-replicator.c
index d4afa42..9f70dc7 100644
--- a/drivers/coresight/coresight-replicator.c
+++ b/drivers/coresight/coresight-replicator.c
@@ -126,6 +126,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-stm.c b/drivers/coresight/coresight-stm.c
index 7d4dabe..085f721 100644
--- a/drivers/coresight/coresight-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -791,6 +791,9 @@
 	size_t res_size, bitmap_size;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index f39334a..4186abe 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -1134,6 +1134,9 @@
 	struct coresight_cti_data *ctidata;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-tpiu.c b/drivers/coresight/coresight-tpiu.c
index 53df0f9..032327c 100644
--- a/drivers/coresight/coresight-tpiu.c
+++ b/drivers/coresight/coresight-tpiu.c
@@ -717,6 +717,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 2fd8bef..96e759b 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -610,6 +610,9 @@
 				if (dbs_info->cur_policy) {
 					/* restart dbs timer */
 					dbs_timer_init(dbs_info);
+					/* Enable frequency synchronization
+					 * of CPUs */
+					atomic_set(&dbs_info->sync_enabled, 1);
 				}
 skip_this_cpu:
 				unlock_policy_rwsem_write(cpu);
@@ -639,15 +642,19 @@
 
 			if (dbs_info->cur_policy) {
 				/* cpu using ondemand, cancel dbs timer */
-				mutex_lock(&dbs_info->timer_mutex);
 				dbs_timer_exit(dbs_info);
+				/* Disable frequency synchronization of
+				 * CPUs to avoid re-queueing of work from
+				 * sync_thread */
+				atomic_set(&dbs_info->sync_enabled, 0);
 
+				mutex_lock(&dbs_info->timer_mutex);
 				ondemand_powersave_bias_setspeed(
 					dbs_info->cur_policy,
 					NULL,
 					input);
-
 				mutex_unlock(&dbs_info->timer_mutex);
+
 			}
 skip_this_cpu_bypass:
 			unlock_policy_rwsem_write(cpu);
@@ -1075,18 +1082,6 @@
 
 		get_online_cpus();
 
-		/* TODO: cur_policy is currently set for all CPUs when
-		 * a policy is started but cleared only on the current
-		 * CPU when the policy is stopped. If/when this is
-		 * resolved, sync_enabled can be removed and
-		 * cur_policy can be used instead.
-		 */
-		if (!atomic_read(&this_dbs_info->sync_enabled)) {
-			atomic_set(&this_dbs_info->src_sync_cpu, -1);
-			put_online_cpus();
-			continue;
-		}
-
 		src_cpu = atomic_read(&this_dbs_info->src_sync_cpu);
 		src_dbs_info = &per_cpu(od_cpu_dbs_info, src_cpu);
 		if (src_dbs_info != NULL &&
@@ -1101,6 +1096,13 @@
 		if (lock_policy_rwsem_write(cpu) < 0)
 			goto bail_acq_sema_failed;
 
+		if (!atomic_read(&this_dbs_info->sync_enabled)) {
+			atomic_set(&this_dbs_info->src_sync_cpu, -1);
+			put_online_cpus();
+			unlock_policy_rwsem_write(cpu);
+			continue;
+		}
+
 		policy = this_dbs_info->cur_policy;
 		if (!policy) {
 			/* CPU not using ondemand governor */
@@ -1238,7 +1240,8 @@
 						kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 			set_cpus_allowed(j_dbs_info->sync_thread,
 					 *cpumask_of(j));
-			atomic_set(&j_dbs_info->sync_enabled, 1);
+			if (!dbs_tuners_ins.powersave_bias)
+				atomic_set(&j_dbs_info->sync_enabled, 1);
 		}
 		this_dbs_info->cpu = cpu;
 		this_dbs_info->rate_mult = 1;
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 250b387..6777dae 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -1688,9 +1688,7 @@
 
 	heap->dev = dev;
 	down_write(&dev->lock);
-	/* use negative heap->id to reverse the priority -- when traversing
-	   the list later attempt higher id numbers first */
-	plist_node_init(&heap->node, -heap->id);
+	plist_node_init(&heap->node, heap->id);
 	plist_add(&heap->node, &dev->heaps);
 	debugfs_create_file(heap->name, 0664, dev->debug_root, heap,
 			    &debug_heap_fops);
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index b1c1c5d..a80b0c6 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -94,8 +94,10 @@
 		}
 
 		info = kmalloc(sizeof(struct page_info), GFP_KERNEL);
-		info->page = page;
-		info->order = orders[i];
+		if (info) {
+			info->page = page;
+			info->order = orders[i];
+		}
 		return info;
 	}
 	return NULL;
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index 2bab7c4..44bb86f 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -139,8 +139,10 @@
 			continue;
 
 		info = kmalloc(sizeof(struct page_info), GFP_KERNEL);
-		info->page = page;
-		info->order = orders[i];
+		if (info) {
+			info->page = page;
+			info->order = orders[i];
+		}
 		return info;
 	}
 	return NULL;
diff --git a/drivers/gpu/ion/msm/ion_iommu_map.c b/drivers/gpu/ion/msm/ion_iommu_map.c
index 0a4fe1f..3e1a7ee 100644
--- a/drivers/gpu/ion/msm/ion_iommu_map.c
+++ b/drivers/gpu/ion/msm/ion_iommu_map.c
@@ -441,6 +441,7 @@
 	BUG_ON(iommu_meta->size != size);
 	mutex_unlock(&msm_iommu_map_mutex);
 
+	mutex_lock(&iommu_meta->lock);
 	iommu_map = ion_iommu_lookup(iommu_meta, domain_num, partition_num);
 	if (!iommu_map) {
 		iommu_map = __ion_iommu_map(iommu_meta, domain_num,
@@ -451,7 +452,7 @@
 			ret = 0;
 		} else {
 			ret = PTR_ERR(iommu_map);
-			goto out;
+			goto out_unlock;
 		}
 	} else {
 		if (iommu_map->flags != iommu_flags) {
@@ -459,21 +460,24 @@
 				__func__, handle,
 				iommu_map->flags, iommu_flags);
 			ret = -EINVAL;
-			goto out;
+			goto out_unlock;
 		} else if (iommu_map->mapped_size != iova_length) {
 			pr_err("%s: handle %p is already mapped with length %x, trying to map with length %lx\n",
 				__func__, handle, iommu_map->mapped_size,
 				iova_length);
 			ret = -EINVAL;
-			goto out;
+			goto out_unlock;
 		} else {
 			kref_get(&iommu_map->ref);
 			*iova = iommu_map->iova_addr;
 		}
 	}
+	mutex_unlock(&iommu_meta->lock);
 	*buffer_size = size;
 	return ret;
 
+out_unlock:
+	mutex_unlock(&iommu_meta->lock);
 out:
 
 	ion_iommu_meta_put(iommu_meta);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 44c9c29..95eabcd 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -123,20 +123,7 @@
 #define LONG_IB_DETECT_REG_INDEX_START 1
 #define LONG_IB_DETECT_REG_INDEX_END 5
 
-unsigned int ft_detect_regs[FT_DETECT_REGS_COUNT] = {
-	A3XX_RBBM_STATUS,
-	REG_CP_RB_RPTR,   /* LONG_IB_DETECT_REG_INDEX_START */
-	REG_CP_IB1_BASE,
-	REG_CP_IB1_BUFSZ,
-	REG_CP_IB2_BASE,
-	REG_CP_IB2_BUFSZ, /* LONG_IB_DETECT_REG_INDEX_END */
-	0,
-	0,
-	0,
-	0,
-	0,
-	0
-};
+unsigned int ft_detect_regs[FT_DETECT_REGS_COUNT];
 
 /*
  * This is the master list of all GPU cores that are supported by this
@@ -258,6 +245,10 @@
 	struct adreno_perfcount_group *group;
 	unsigned int i, j;
 
+	/* perfcounter start does nothing on a2xx */
+	if (adreno_is_a2xx(adreno_dev))
+		return;
+
 	/* group id iter */
 	for (i = 0; i < counters->group_count; i++) {
 		group = &(counters->groups[i]);
@@ -265,7 +256,9 @@
 		/* countable iter */
 		for (j = 0; j < group->reg_count; j++) {
 			if (group->regs[j].countable ==
-					KGSL_PERFCOUNTER_NOT_USED)
+					KGSL_PERFCOUNTER_NOT_USED ||
+					group->regs[j].countable ==
+					KGSL_PERFCOUNTER_BROKEN)
 				continue;
 
 			if (adreno_dev->gpudev->perfcounter_enable)
@@ -726,6 +719,7 @@
 					phys_addr_t pt_val,
 					int num_iommu_units, uint32_t flags)
 {
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	phys_addr_t ttbr0_val;
 	unsigned int reg_pt_val;
 	unsigned int *cmds = cmds_orig;
@@ -755,7 +749,9 @@
 				 * WAIT_FOR_ME
 				 */
 				cmds += adreno_wait_reg_eq(cmds,
-				A3XX_CP_WFI_PEND_CTR, 1, 0xFFFFFFFF, 0xF);
+					adreno_getreg(adreno_dev,
+						ADRENO_REG_CP_WFI_PEND_CTR),
+					1, 0xFFFFFFFF, 0xF);
 
 				/* set the iommu lock bit */
 				*cmds++ = cp_type3_packet(CP_REG_RMW, 3);
@@ -1047,9 +1043,9 @@
 	if (pdata->chipid != 0)
 		return pdata->chipid;
 
-	adreno_regread(device, REG_RBBM_PERIPHID1, &coreid);
-	adreno_regread(device, REG_RBBM_PERIPHID2, &majorid);
-	adreno_regread(device, REG_RBBM_PATCH_RELEASE, &revid);
+	kgsl_regread(device, REG_RBBM_PERIPHID1, &coreid);
+	kgsl_regread(device, REG_RBBM_PERIPHID2, &majorid);
+	kgsl_regread(device, REG_RBBM_PATCH_RELEASE, &revid);
 
 	/*
 	* adreno 22x gpus are indicated by coreid 2,
@@ -1138,6 +1134,17 @@
 	adreno_dev->pfp_jt_idx = adreno_gpulist[i].pfp_jt_idx;
 	adreno_dev->pfp_jt_addr = adreno_gpulist[i].pfp_jt_addr;
 	adreno_dev->gpulist_index = i;
+	/*
+	 * Initialize uninitialzed gpu registers, only needs to be done once
+	 * Make all offsets that are not initialized to ADRENO_REG_UNUSED
+	 */
+	for (i = 0; i < ADRENO_REG_REGISTER_MAX; i++) {
+		if (adreno_dev->gpudev->reg_offsets->offset_0 != i &&
+			!adreno_dev->gpudev->reg_offsets->offsets[i]) {
+			adreno_dev->gpudev->reg_offsets->offsets[i] =
+						ADRENO_REG_UNUSED;
+		}
+	}
 }
 
 static struct platform_device_id adreno_id_table[] = {
@@ -1698,6 +1705,7 @@
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+	int i;
 
 	if (KGSL_STATE_DUMP_AND_FT != device->state)
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
@@ -1739,9 +1747,21 @@
 
 	rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
 
-	/* Assign correct RBBM status register to hang detect regs
-	 */
-	ft_detect_regs[0] = adreno_dev->gpudev->reg_rbbm_status;
+	/* Initialize ft detection register offsets */
+	ft_detect_regs[0] = adreno_getreg(adreno_dev,
+						ADRENO_REG_RBBM_STATUS);
+	ft_detect_regs[1] = adreno_getreg(adreno_dev,
+						ADRENO_REG_CP_RB_RPTR);
+	ft_detect_regs[2] = adreno_getreg(adreno_dev,
+						ADRENO_REG_CP_IB1_BASE);
+	ft_detect_regs[3] = adreno_getreg(adreno_dev,
+						ADRENO_REG_CP_IB1_BUFSZ);
+	ft_detect_regs[4] = adreno_getreg(adreno_dev,
+						ADRENO_REG_CP_IB2_BASE);
+	ft_detect_regs[5] = adreno_getreg(adreno_dev,
+						ADRENO_REG_CP_IB2_BUFSZ);
+	for (i = 6; i < FT_DETECT_REGS_COUNT; i++)
+		ft_detect_regs[i] = 0;
 
 	adreno_perfcounter_init(device);
 
@@ -2091,7 +2111,7 @@
 	ft_data->start_of_replay_cmds = 0xFFFFFFFF;
 	ft_data->replay_for_snapshot = 0xFFFFFFFF;
 
-	adreno_regread(device, REG_CP_IB1_BASE, &ft_data->ib1);
+	adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ft_data->ib1);
 
 	kgsl_sharedmem_readl(&device->memstore, &ft_data->context_id,
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
@@ -2927,7 +2947,7 @@
 	memset(prev_reg_val, 0, sizeof(prev_reg_val));
 
 	kgsl_cffdump_regpoll(device,
-		adreno_dev->gpudev->reg_rbbm_status << 2,
+		adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2,
 		0x00000000, 0x80000000);
 
 retry:
@@ -2940,8 +2960,8 @@
 	wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
 
 	while (time_before(jiffies, wait_time)) {
-		adreno_regread(device, adreno_dev->gpudev->reg_rbbm_status,
-			&rbbm_status);
+		adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS,
+					&rbbm_status);
 		if (adreno_is_a2xx(adreno_dev)) {
 			if (rbbm_status == 0x110)
 				return 0;
@@ -2986,9 +3006,8 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
 	/* Is the core idle? */
-	adreno_regread(device,
-		adreno_dev->gpudev->reg_rbbm_status,
-		&reg_rbbm_status);
+	adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS,
+				&reg_rbbm_status);
 
 	if (adreno_is_a2xx(adreno_dev)) {
 		if (reg_rbbm_status == 0x110)
@@ -3119,6 +3138,7 @@
 	return memdesc ? kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr) : NULL;
 }
 
+
 /**
  * adreno_read - General read function to read adreno device memory
  * @device - Pointer to the GPU device struct (for adreno device)
@@ -3151,7 +3171,7 @@
  * @offsetwords - Word (4 Bytes) offset to the register to be read
  * @value - Value read from device register
  */
-void adreno_regread(struct kgsl_device *device, unsigned int offsetwords,
+static void adreno_regread(struct kgsl_device *device, unsigned int offsetwords,
 	unsigned int *value)
 {
 	adreno_read(device, device->reg_virt, offsetwords, value,
@@ -3171,7 +3191,8 @@
 					device->shader_mem_len);
 }
 
-void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords,
+static void adreno_regwrite(struct kgsl_device *device,
+				unsigned int offsetwords,
 				unsigned int value)
 {
 	unsigned int *reg;
@@ -3350,9 +3371,11 @@
 
 		if (adreno_is_a2xx(adreno_dev)) {
 			unsigned int rptr;
-			adreno_regread(device, REG_CP_RB_RPTR, &rptr);
+			adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR,
+						&rptr);
 			if (rptr != adreno_dev->ringbuffer.wptr)
-				adreno_regwrite(device, REG_CP_RB_WPTR,
+				adreno_writereg(adreno_dev,
+					ADRENO_REG_CP_RB_WPTR,
 					adreno_dev->ringbuffer.wptr);
 		}
 
@@ -3375,7 +3398,7 @@
 	for (i = 0; i < FT_DETECT_REGS_COUNT; i++) {
 		if (ft_detect_regs[i] == 0)
 			continue;
-		adreno_regread(device, ft_detect_regs[i],
+		kgsl_regread(device, ft_detect_regs[i],
 			&curr_reg_val[i]);
 	}
 
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 70b07c4..b53d16f 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -168,14 +168,86 @@
 	unsigned int group_count;
 };
 
+/**
+ * adreno_regs: List of registers that are used in kgsl driver for all
+ * 3D devices. Each device type has different offset value for the same
+ * register, so an array of register offsets are declared for every device
+ * and are indexed by the enumeration values defined in this enum
+ */
+enum adreno_regs {
+	ADRENO_REG_CP_DEBUG,
+	ADRENO_REG_CP_ME_RAM_WADDR,
+	ADRENO_REG_CP_ME_RAM_DATA,
+	ADRENO_REG_CP_PFP_UCODE_DATA,
+	ADRENO_REG_CP_PFP_UCODE_ADDR,
+	ADRENO_REG_CP_WFI_PEND_CTR,
+	ADRENO_REG_CP_RB_BASE,
+	ADRENO_REG_CP_RB_RPTR_ADDR,
+	ADRENO_REG_CP_RB_RPTR,
+	ADRENO_REG_CP_RB_WPTR,
+	ADRENO_REG_CP_PROTECT_CTRL,
+	ADRENO_REG_CP_ME_CNTL,
+	ADRENO_REG_CP_RB_CNTL,
+	ADRENO_REG_CP_IB1_BASE,
+	ADRENO_REG_CP_IB1_BUFSZ,
+	ADRENO_REG_CP_IB2_BASE,
+	ADRENO_REG_CP_IB2_BUFSZ,
+	ADRENO_REG_CP_TIMESTAMP,
+	ADRENO_REG_SCRATCH_ADDR,
+	ADRENO_REG_SCRATCH_UMSK,
+	ADRENO_REG_SCRATCH_REG2,
+	ADRENO_REG_RBBM_STATUS,
+	ADRENO_REG_RBBM_PERFCTR_CTL,
+	ADRENO_REG_RBBM_PERFCTR_LOAD_CMD0,
+	ADRENO_REG_RBBM_PERFCTR_LOAD_CMD1,
+	ADRENO_REG_RBBM_PERFCTR_LOAD_CMD2,
+	ADRENO_REG_RBBM_PERFCTR_PWR_1_LO,
+	ADRENO_REG_RBBM_INT_0_MASK,
+	ADRENO_REG_RBBM_INT_0_STATUS,
+	ADRENO_REG_RBBM_AHB_ERROR_STATUS,
+	ADRENO_REG_RBBM_PM_OVERRIDE2,
+	ADRENO_REG_VPC_VPC_DEBUG_RAM_SEL,
+	ADRENO_REG_VPC_VPC_DEBUG_RAM_READ,
+	ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0,
+	ADRENO_REG_VSC_PIPE_DATA_LENGTH_7,
+	ADRENO_REG_VSC_SIZE_ADDRESS,
+	ADRENO_REG_VFD_CONTROL_0,
+	ADRENO_REG_VFD_FETCH_INSTR_0_0,
+	ADRENO_REG_VFD_FETCH_INSTR_1_F,
+	ADRENO_REG_VFD_INDEX_MAX,
+	ADRENO_REG_SP_VS_PVT_MEM_ADDR_REG,
+	ADRENO_REG_SP_FS_PVT_MEM_ADDR_REG,
+	ADRENO_REG_SP_VS_OBJ_START_REG,
+	ADRENO_REG_SP_FS_OBJ_START_REG,
+	ADRENO_REG_PA_SC_AA_CONFIG,
+	ADRENO_REG_SQ_GPR_MANAGEMENT,
+	ADRENO_REG_SQ_INST_STORE_MANAGMENT,
+	ADRENO_REG_TC_CNTL_STATUS,
+	ADRENO_REG_TP0_CHICKEN,
+	ADRENO_REG_REGISTER_MAX,
+};
+
+/**
+ * adreno_reg_offsets: Holds array of register offsets
+ * @offsets: Offset array of size defined by enum adreno_regs
+ * @offset_0: This is the index of the register in offset array whose value
+ * is 0. 0 is a valid register offset and during initialization of the
+ * offset array we need to know if an offset value is correctly defined to 0
+ */
+struct adreno_reg_offsets {
+	unsigned int *offsets;
+	enum adreno_regs offset_0;
+};
+
+#define ADRENO_REG_UNUSED	0xFFFFFFFF
+#define ADRENO_REG_DEFINE(_offset, _reg) [_offset] = _reg
+
 struct adreno_gpudev {
 	/*
-	 * These registers are in a different location on A3XX,  so define
-	 * them in the structure and use them as variables.
+	 * These registers are in a different location on different devices,
+	 * so define them in the structure and use them as variables.
 	 */
-	unsigned int reg_rbbm_status;
-	unsigned int reg_cp_pfp_ucode_data;
-	unsigned int reg_cp_pfp_ucode_addr;
+	struct adreno_reg_offsets *reg_offsets;
 	/* keeps track of when we need to execute the draw workaround code */
 	int ctx_switches_since_last_draw;
 
@@ -205,6 +277,7 @@
 	void (*coresight_config_debug_reg) (struct kgsl_device *device,
 			int debug_reg, unsigned int val);
 	void (*soft_reset)(struct adreno_device *device);
+	void (*postmortem_dump)(struct adreno_device *adreno_dev);
 };
 
 /*
@@ -249,6 +322,11 @@
 
 #define FT_DETECT_REGS_COUNT 12
 
+struct log_field {
+	bool show;
+	const char *display;
+};
+
 /* Fault Tolerance policy flags */
 #define  KGSL_FT_OFF                      BIT(0)
 #define  KGSL_FT_REPLAY                   BIT(1)
@@ -295,16 +373,15 @@
 int adreno_coresight_init(struct platform_device *pdev);
 
 int adreno_idle(struct kgsl_device *device);
-void adreno_regread(struct kgsl_device *device, unsigned int offsetwords,
-				unsigned int *value);
-void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords,
-				unsigned int value);
 
 void adreno_shadermem_regread(struct kgsl_device *device,
 						unsigned int offsetwords,
 						unsigned int *value);
 
 int adreno_dump(struct kgsl_device *device, int manual);
+void adreno_dump_fields(struct kgsl_device *device,
+			const char *start, const struct log_field *lines,
+			int num);
 unsigned int adreno_a3xx_rbbm_clock_ctl_default(struct adreno_device
 							*adreno_dev);
 
@@ -555,4 +632,66 @@
 	return cmds - start;
 }
 
+/*
+ * adreno_checkreg_off() - Checks the validity of a register enum
+ * @adreno_dev:		Pointer to adreno device
+ * @offset_name:	The register enum that is checked
+ */
+static inline bool adreno_checkreg_off(struct adreno_device *adreno_dev,
+					enum adreno_regs offset_name)
+{
+	if (offset_name >= ADRENO_REG_REGISTER_MAX ||
+		ADRENO_REG_UNUSED ==
+			adreno_dev->gpudev->reg_offsets->offsets[offset_name]) {
+		BUG_ON(1);
+	}
+	return true;
+}
+
+/*
+ * adreno_readreg() - Read a register by getting its offset from the
+ * offset array defined in gpudev node
+ * @adreno_dev:		Pointer to the the adreno device
+ * @offset_name:	The register enum that is to be read
+ * @val:		Register value read is placed here
+ */
+static inline void adreno_readreg(struct adreno_device *adreno_dev,
+				enum adreno_regs offset_name, unsigned int *val)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	if (adreno_checkreg_off(adreno_dev, offset_name))
+		kgsl_regread(device,
+			adreno_dev->gpudev->reg_offsets->offsets[offset_name],
+								val);
+}
+
+/*
+ * adreno_writereg() - Write a register by getting its offset from the
+ * offset array defined in gpudev node
+ * @adreno_dev:		Pointer to the the adreno device
+ * @offset_name:	The register enum that is to be written
+ * @val:		Value to write
+ */
+static inline void adreno_writereg(struct adreno_device *adreno_dev,
+				enum adreno_regs offset_name, unsigned int val)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	if (adreno_checkreg_off(adreno_dev, offset_name))
+		kgsl_regwrite(device,
+		adreno_dev->gpudev->reg_offsets->offsets[offset_name], val);
+}
+
+/*
+ * adreno_getreg() - Returns the offset value of a register from the
+ * register offset array in the gpudev node
+ * @adreno_dev:		Pointer to the the adreno device
+ * @offset_name:	The register enum whore offset is returned
+ */
+static inline unsigned int adreno_getreg(struct adreno_device *adreno_dev,
+				enum adreno_regs offset_name)
+{
+	if (!adreno_checkreg_off(adreno_dev, offset_name))
+		return ADRENO_REG_REGISTER_MAX;
+	return adreno_dev->gpudev->reg_offsets->offsets[offset_name];
+}
 #endif /*__ADRENO_H */
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index b0a1fe8..42137fe 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1707,11 +1707,11 @@
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	int i;
 
-	adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
+	kgsl_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
 	while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
 		(master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
-		adreno_regread(device, REG_CP_INT_STATUS, &status);
-		adreno_regread(device, REG_MASTER_INT_SIGNAL,
+		kgsl_regread(device, REG_CP_INT_STATUS, &status);
+		kgsl_regread(device, REG_MASTER_INT_SIGNAL,
 					&master_status);
 		num_reads++;
 	}
@@ -1752,7 +1752,7 @@
 
 	/* only ack bits we understand */
 	status &= CP_INT_MASK;
-	adreno_regwrite(device, REG_CP_INT_ACK, status);
+	kgsl_regwrite(device, REG_CP_INT_ACK, status);
 
 	if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
 		queue_work(device->work_queue, &device->ts_expired_ws);
@@ -1767,10 +1767,10 @@
 	unsigned int addr = 0;
 	const char *source;
 
-	adreno_regread(device, REG_RBBM_INT_STATUS, &status);
+	kgsl_regread(device, REG_RBBM_INT_STATUS, &status);
 
 	if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
-		adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
+		kgsl_regread(device, REG_RBBM_READ_ERROR, &rderr);
 		source = (rderr & RBBM_READ_ERROR_REQUESTER)
 			 ? "host" : "cp";
 		/* convert to dword address */
@@ -1794,7 +1794,7 @@
 	}
 
 	status &= RBBM_INT_MASK;
-	adreno_regwrite(device, REG_RBBM_INT_ACK, status);
+	kgsl_regwrite(device, REG_RBBM_INT_ACK, status);
 }
 
 irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
@@ -1803,7 +1803,7 @@
 	irqreturn_t result = IRQ_NONE;
 	unsigned int status;
 
-	adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
+	kgsl_regread(device, REG_MASTER_INT_SIGNAL, &status);
 
 	if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
 		kgsl_mh_intrcallback(device);
@@ -1828,14 +1828,14 @@
 	struct kgsl_device *device = &adreno_dev->dev;
 
 	if (state) {
-		adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
-		adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
-		adreno_regwrite(device, MH_INTERRUPT_MASK,
+		kgsl_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
+		kgsl_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
+		kgsl_regwrite(device, MH_INTERRUPT_MASK,
 			kgsl_mmu_get_int_mask());
 	} else {
-		adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
-		adreno_regwrite(device, REG_CP_INT_CNTL, 0);
-		adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
+		kgsl_regwrite(device, REG_RBBM_INT_CNTL, 0);
+		kgsl_regwrite(device, REG_CP_INT_CNTL, 0);
+		kgsl_regwrite(device, MH_INTERRUPT_MASK, 0);
 	}
 
 	/* Force the writes to post before touching the IRQ line */
@@ -1847,7 +1847,7 @@
 	struct kgsl_device *device = &adreno_dev->dev;
 	unsigned int status;
 
-	adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
+	kgsl_regread(device, REG_MASTER_INT_SIGNAL, &status);
 
 	return (status &
 		(MASTER_INT_SIGNAL__MH_INT_STAT |
@@ -1929,21 +1929,21 @@
 	unsigned int reg, val;
 
 	/* Freeze the counter */
-	adreno_regwrite(device, REG_CP_PERFMON_CNTL,
+	kgsl_regwrite(device, REG_CP_PERFMON_CNTL,
 		REG_PERF_MODE_CNT | REG_PERF_STATE_FREEZE);
 
 	/* Get the value */
-	adreno_regread(device, REG_RBBM_PERFCOUNTER1_LO, &val);
+	kgsl_regread(device, REG_RBBM_PERFCOUNTER1_LO, &val);
 
 	/* Reset the counter */
-	adreno_regwrite(device, REG_CP_PERFMON_CNTL,
+	kgsl_regwrite(device, REG_CP_PERFMON_CNTL,
 		REG_PERF_MODE_CNT | REG_PERF_STATE_RESET);
 
 	/* Re-Enable the performance monitors */
-	adreno_regread(device, REG_RBBM_PM_OVERRIDE2, &reg);
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, (reg | 0x40));
-	adreno_regwrite(device, REG_RBBM_PERFCOUNTER1_SELECT, 0x1);
-	adreno_regwrite(device, REG_CP_PERFMON_CNTL,
+	kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &reg);
+	kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, (reg | 0x40));
+	kgsl_regwrite(device, REG_RBBM_PERFCOUNTER1_SELECT, 0x1);
+	kgsl_regwrite(device, REG_CP_PERFMON_CNTL,
 		REG_PERF_MODE_CNT | REG_PERF_STATE_ENABLE);
 
 	return val;
@@ -1969,7 +1969,7 @@
 	/* must be aligned to size */
 	rb_edram_info.f.edram_range = (adreno_dev->gmem_base >> 14);
 
-	adreno_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val);
+	kgsl_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val);
 }
 
 static void a2xx_start(struct adreno_device *adreno_dev)
@@ -1981,8 +1981,8 @@
 	 * before issuing a soft reset.  The overrides will then be
 	 * turned off (set to 0)
 	 */
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0xfffffffe);
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xffffffff);
+	kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0xfffffffe);
+	kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xffffffff);
 
 	/*
 	 * Only reset CP block if all blocks have previously been
@@ -1990,11 +1990,11 @@
 	 */
 	if (!(device->flags & KGSL_FLAGS_SOFT_RESET) ||
 		!adreno_is_a22x(adreno_dev)) {
-		adreno_regwrite(device, REG_RBBM_SOFT_RESET,
+		kgsl_regwrite(device, REG_RBBM_SOFT_RESET,
 			0xFFFFFFFF);
 		device->flags |= KGSL_FLAGS_SOFT_RESET;
 	} else {
-		adreno_regwrite(device, REG_RBBM_SOFT_RESET,
+		kgsl_regwrite(device, REG_RBBM_SOFT_RESET,
 			0x00000001);
 	}
 	/*
@@ -2003,11 +2003,11 @@
 	 */
 	msleep(30);
 
-	adreno_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000000);
+	kgsl_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000000);
 
 	if (adreno_is_a225(adreno_dev)) {
 		/* Enable large instruction store for A225 */
-		adreno_regwrite(device, REG_SQ_FLOW_CONTROL,
+		kgsl_regwrite(device, REG_SQ_FLOW_CONTROL,
 			0x18000000);
 	}
 
@@ -2015,41 +2015,242 @@
 		/* For A20X based targets increase number of clocks
 		 * that RBBM will wait before de-asserting Register
 		 * Clock Active signal */
-		adreno_regwrite(device, REG_RBBM_CNTL, 0x0000FFFF);
+		kgsl_regwrite(device, REG_RBBM_CNTL, 0x0000FFFF);
 	else
-		adreno_regwrite(device, REG_RBBM_CNTL, 0x00004442);
+		kgsl_regwrite(device, REG_RBBM_CNTL, 0x00004442);
 
-	adreno_regwrite(device, REG_SQ_VS_PROGRAM, 0x00000000);
-	adreno_regwrite(device, REG_SQ_PS_PROGRAM, 0x00000000);
+	kgsl_regwrite(device, REG_SQ_VS_PROGRAM, 0x00000000);
+	kgsl_regwrite(device, REG_SQ_PS_PROGRAM, 0x00000000);
 
 	if (cpu_is_msm8960())
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0x200);
+		kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0x200);
 	else
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0);
+		kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0);
 
 	if (!adreno_is_a22x(adreno_dev))
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0);
+		kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0);
 	else
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80);
+		kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80);
 
-	adreno_regwrite(device, REG_RBBM_DEBUG, 0x00080000);
+	kgsl_regwrite(device, REG_RBBM_DEBUG, 0x00080000);
 
 	/* Make sure interrupts are disabled */
-	adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
-	adreno_regwrite(device, REG_CP_INT_CNTL, 0);
-	adreno_regwrite(device, REG_SQ_INT_CNTL, 0);
+	kgsl_regwrite(device, REG_RBBM_INT_CNTL, 0);
+	kgsl_regwrite(device, REG_CP_INT_CNTL, 0);
+	kgsl_regwrite(device, REG_SQ_INT_CNTL, 0);
 
 	a2xx_gmeminit(adreno_dev);
 }
 
+static void a2xx_postmortem_dump(struct adreno_device *adreno_dev)
+{
+	unsigned int r1, r2, r3, rbbm_status;
+	unsigned int cp_stat, rb_count;
+	struct kgsl_device *device = &adreno_dev->dev;
+
+	kgsl_regread(device, REG_RBBM_STATUS, &rbbm_status);
+
+	kgsl_regread(device, REG_RBBM_PM_OVERRIDE1, &r2);
+	kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &r3);
+	KGSL_LOG_DUMP(device,
+	"RBBM:   STATUS   = %08X | PM_OVERRIDE1 = %08X | PM_OVERRIDE2 = %08X\n",
+	rbbm_status, r2, r3);
+
+	kgsl_regread(device, REG_RBBM_INT_CNTL, &r1);
+	kgsl_regread(device, REG_RBBM_INT_STATUS, &r2);
+	kgsl_regread(device, REG_RBBM_READ_ERROR, &r3);
+	KGSL_LOG_DUMP(device,
+	"INT_CNTL = %08X | INT_STATUS   = %08X | READ_ERROR   = %08X\n",
+	r1, r2, r3);
+
+	{
+		char cmdFifo[16];
+		struct log_field lines[] = {
+			{rbbm_status &  0x001F, cmdFifo},
+			{rbbm_status &  BIT(5), "TC busy     "},
+			{rbbm_status &  BIT(8), "HIRQ pending"},
+			{rbbm_status &  BIT(9), "CPRQ pending"},
+			{rbbm_status & BIT(10), "CFRQ pending"},
+			{rbbm_status & BIT(11), "PFRQ pending"},
+			{rbbm_status & BIT(12), "VGT 0DMA bsy"},
+			{rbbm_status & BIT(14), "RBBM WU busy"},
+			{rbbm_status & BIT(16), "CP NRT busy "},
+			{rbbm_status & BIT(18), "MH busy     "},
+			{rbbm_status & BIT(19), "MH chncy bsy"},
+			{rbbm_status & BIT(21), "SX busy     "},
+			{rbbm_status & BIT(22), "TPC busy    "},
+			{rbbm_status & BIT(24), "SC CNTX busy"},
+			{rbbm_status & BIT(25), "PA busy     "},
+			{rbbm_status & BIT(26), "VGT busy    "},
+			{rbbm_status & BIT(27), "SQ cntx1 bsy"},
+			{rbbm_status & BIT(28), "SQ cntx0 bsy"},
+			{rbbm_status & BIT(30), "RB busy     "},
+			{rbbm_status & BIT(31), "Grphs pp bsy"},
+		};
+		snprintf(cmdFifo, sizeof(cmdFifo), "CMD FIFO=%01X  ",
+			rbbm_status & 0xf);
+		adreno_dump_fields(device, " STATUS=", lines,
+				ARRAY_SIZE(lines));
+	}
+
+	kgsl_regread(device, REG_CP_RB_BASE, &r1);
+	kgsl_regread(device, REG_CP_RB_CNTL, &r2);
+	rb_count = 2 << (r2 & (BIT(6)-1));
+	kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3);
+	KGSL_LOG_DUMP(device,
+		"	RPTR = %08X | WPTR   = %08X | RPTR_WR   = %08X"
+		"\n", r1, r2, r3);
+
+	kgsl_regread(device, REG_CP_IB1_BASE, &r1);
+	kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2);
+	KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ  = %d\n", r1, r2);
+
+	kgsl_regread(device, REG_CP_IB2_BASE, &r1);
+	kgsl_regread(device, REG_CP_IB2_BUFSZ, &r2);
+	KGSL_LOG_DUMP(device, "CP_IB2: BASE = %08X | BUFSZ  = %d\n", r1, r2);
+
+	kgsl_regread(device, REG_CP_INT_CNTL, &r1);
+	kgsl_regread(device, REG_CP_INT_STATUS, &r2);
+	KGSL_LOG_DUMP(device, "CP_INT: CNTL = %08X | STATUS = %08X\n", r1, r2);
+
+	kgsl_regread(device, REG_CP_ME_CNTL, &r1);
+	kgsl_regread(device, REG_CP_ME_STATUS, &r2);
+	kgsl_regread(device, REG_MASTER_INT_SIGNAL, &r3);
+	KGSL_LOG_DUMP(device,
+		"CP_ME:  CNTL = %08X | STATUS = %08X | MSTR_INT_SGNL = "
+		"%08X\n", r1, r2, r3);
+
+	kgsl_regread(device, REG_CP_STAT, &cp_stat);
+	KGSL_LOG_DUMP(device, "CP_STAT      = %08X\n", cp_stat);
+#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL
+	{
+		struct log_field lns[] = {
+			{cp_stat &  BIT(0), "WR_BSY     0"},
+			{cp_stat &  BIT(1), "RD_RQ_BSY  1"},
+			{cp_stat &  BIT(2), "RD_RTN_BSY 2"},
+		};
+		adreno_dump_fields(device, "    MIU=", lns, ARRAY_SIZE(lns));
+	}
+	{
+		struct log_field lns[] = {
+			{cp_stat &  BIT(5), "RING_BUSY  5"},
+			{cp_stat &  BIT(6), "NDRCTS_BSY 6"},
+			{cp_stat &  BIT(7), "NDRCT2_BSY 7"},
+			{cp_stat &  BIT(9), "ST_BUSY    9"},
+			{cp_stat & BIT(10), "BUSY      10"},
+		};
+		adreno_dump_fields(device, "    CSF=", lns, ARRAY_SIZE(lns));
+	}
+	{
+		struct log_field lns[] = {
+			{cp_stat & BIT(11), "RNG_Q_BSY 11"},
+			{cp_stat & BIT(12), "NDRCTS_Q_B12"},
+			{cp_stat & BIT(13), "NDRCT2_Q_B13"},
+			{cp_stat & BIT(16), "ST_QUEUE_B16"},
+			{cp_stat & BIT(17), "PFP_BUSY  17"},
+		};
+		adreno_dump_fields(device, "   RING=", lns, ARRAY_SIZE(lns));
+	}
+	{
+		struct log_field lns[] = {
+			{cp_stat &  BIT(3), "RBIU_BUSY  3"},
+			{cp_stat &  BIT(4), "RCIU_BUSY  4"},
+			{cp_stat & BIT(18), "MQ_RG_BSY 18"},
+			{cp_stat & BIT(19), "MQ_NDRS_BS19"},
+			{cp_stat & BIT(20), "MQ_NDR2_BS20"},
+			{cp_stat & BIT(21), "MIU_WC_STL21"},
+			{cp_stat & BIT(22), "CP_NRT_BSY22"},
+			{cp_stat & BIT(23), "3D_BUSY   23"},
+			{cp_stat & BIT(26), "ME_BUSY   26"},
+			{cp_stat & BIT(29), "ME_WC_BSY 29"},
+			{cp_stat & BIT(30), "MIU_FF EM 30"},
+			{cp_stat & BIT(31), "CP_BUSY   31"},
+		};
+		adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns));
+	}
+#endif
+
+	kgsl_regread(device, REG_SCRATCH_REG0, &r1);
+	KGSL_LOG_DUMP(device, "SCRATCH_REG0       = %08X\n", r1);
+
+	kgsl_regread(device, REG_COHER_SIZE_PM4, &r1);
+	kgsl_regread(device, REG_COHER_BASE_PM4, &r2);
+	kgsl_regread(device, REG_COHER_STATUS_PM4, &r3);
+	KGSL_LOG_DUMP(device,
+		"COHER:  SIZE_PM4   = %08X | BASE_PM4 = %08X | STATUS_PM4"
+		" = %08X\n", r1, r2, r3);
+
+	kgsl_regread(device, MH_AXI_ERROR, &r1);
+	KGSL_LOG_DUMP(device, "MH:     AXI_ERROR  = %08X\n", r1);
+
+	kgsl_regread(device, MH_MMU_PAGE_FAULT, &r1);
+	kgsl_regread(device, MH_MMU_CONFIG, &r2);
+	kgsl_regread(device, MH_MMU_MPU_BASE, &r3);
+	KGSL_LOG_DUMP(device,
+		"MH_MMU: PAGE_FAULT = %08X | CONFIG   = %08X | MPU_BASE ="
+		" %08X\n", r1, r2, r3);
+
+	kgsl_regread(device, MH_MMU_MPU_END, &r1);
+	kgsl_regread(device, MH_MMU_VA_RANGE, &r2);
+	r3 = kgsl_mmu_get_current_ptbase(&device->mmu);
+	KGSL_LOG_DUMP(device,
+		"	MPU_END    = %08X | VA_RANGE = %08X | PT_BASE  ="
+		" %08X\n", r1, r2, r3);
+
+	KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ",
+		kgsl_mmu_get_ptsize(&device->mmu));
+
+	kgsl_regread(device, MH_MMU_TRAN_ERROR, &r1);
+	KGSL_LOG_DUMP(device, "	TRAN_ERROR = %08X\n", r1);
+
+	kgsl_regread(device, MH_INTERRUPT_MASK, &r1);
+	kgsl_regread(device, MH_INTERRUPT_STATUS, &r2);
+	KGSL_LOG_DUMP(device,
+		"MH_INTERRUPT: MASK = %08X | STATUS   = %08X\n", r1, r2);
+}
+
+/* Register offset defines for A2XX */
+static unsigned int a2xx_register_offsets[ADRENO_REG_REGISTER_MAX] = {
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_DEBUG, REG_CP_DEBUG),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_WADDR, REG_CP_ME_RAM_WADDR),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_DATA, REG_CP_ME_RAM_DATA),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_DATA, REG_CP_PFP_UCODE_DATA),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_ADDR, REG_CP_PFP_UCODE_ADDR),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_BASE, REG_CP_RB_BASE),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR_ADDR, REG_CP_RB_RPTR_ADDR),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR, REG_CP_RB_RPTR),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_WPTR, REG_CP_RB_WPTR),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_CNTL, REG_CP_ME_CNTL),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_CNTL, REG_CP_RB_CNTL),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE, REG_CP_IB1_BASE),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BUFSZ, REG_CP_IB1_BUFSZ),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BASE, REG_CP_IB2_BASE),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BUFSZ, REG_CP_IB2_BUFSZ),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_TIMESTAMP, REG_CP_TIMESTAMP),
+	ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_ADDR, REG_SCRATCH_ADDR),
+	ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_UMSK, REG_SCRATCH_UMSK),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_STATUS, REG_RBBM_STATUS),
+	ADRENO_REG_DEFINE(ADRENO_REG_PA_SC_AA_CONFIG, REG_PA_SC_AA_CONFIG),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PM_OVERRIDE2, REG_RBBM_PM_OVERRIDE2),
+	ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_REG2, REG_SCRATCH_REG2),
+	ADRENO_REG_DEFINE(ADRENO_REG_SQ_GPR_MANAGEMENT, REG_SQ_GPR_MANAGEMENT),
+	ADRENO_REG_DEFINE(ADRENO_REG_SQ_INST_STORE_MANAGMENT,
+				REG_SQ_INST_STORE_MANAGMENT),
+	ADRENO_REG_DEFINE(ADRENO_REG_TC_CNTL_STATUS, REG_TC_CNTL_STATUS),
+	ADRENO_REG_DEFINE(ADRENO_REG_TP0_CHICKEN, REG_TP0_CHICKEN),
+};
+
+struct adreno_reg_offsets a2xx_reg_offsets = {
+	.offsets = a2xx_register_offsets,
+	.offset_0 = ADRENO_REG_REGISTER_MAX,
+};
+
 /* Defined in adreno_a2xx_snapshot.c */
 void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot,
 	int *remain, int hang);
 
 struct adreno_gpudev adreno_a2xx_gpudev = {
-	.reg_rbbm_status = REG_RBBM_STATUS,
-	.reg_cp_pfp_ucode_addr = REG_CP_PFP_UCODE_ADDR,
-	.reg_cp_pfp_ucode_data = REG_CP_PFP_UCODE_DATA,
+	.reg_offsets = &a2xx_reg_offsets,
 
 	.ctxt_create = a2xx_drawctxt_create,
 	.ctxt_save = a2xx_drawctxt_save,
@@ -2062,4 +2263,5 @@
 	.rb_init = a2xx_rb_init,
 	.busy_cycles = a2xx_busy_cycles,
 	.start = a2xx_start,
+	.postmortem_dump = a2xx_postmortem_dump,
 };
diff --git a/drivers/gpu/msm/adreno_a2xx_snapshot.c b/drivers/gpu/msm/adreno_a2xx_snapshot.c
index 2c86f82..5134ed6 100644
--- a/drivers/gpu/msm/adreno_a2xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a2xx_snapshot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -38,11 +38,11 @@
 	header->size = SXDEBUG_COUNT;
 
 	for (i = 0; i < SXDEBUG_COUNT; i++) {
-		adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1B00 | i);
-		adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
+		kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1B00 | i);
+		kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
 	}
 
-	adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
+	kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
 
 	return DEBUG_SECTION_SZ(SXDEBUG_COUNT);
 }
@@ -65,11 +65,11 @@
 	header->size = CPDEBUG_COUNT;
 
 	for (i = 0; i < CPDEBUG_COUNT; i++) {
-		adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1628);
-		adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
+		kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1628);
+		kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
 	}
 
-	adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
+	kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
 
 	return DEBUG_SECTION_SZ(CPDEBUG_COUNT);
 }
@@ -82,7 +82,8 @@
 
 #define SQ_DEBUG_WRITE(_device, _reg, _data, _offset) \
 	do { _data[(_offset)++] = (_reg); \
-	adreno_regread(_device, (_reg), &_data[(_offset)++]); } while (0)
+		kgsl_regread(_device, (_reg), &_data[(_offset)++]);	\
+	} while (0)
 
 #define SQ_DEBUG_BANK_SIZE 23
 
@@ -175,7 +176,7 @@
 	header->size = size;
 
 	for (i = 0; i < 16; i++) {
-		adreno_regwrite(device, REG_SQ_DEBUG_TB_STATUS_SEL,
+		kgsl_regwrite(device, REG_SQ_DEBUG_TB_STATUS_SEL,
 				i | (6<<4) | (i<<7) | (1<<11) | (1<<12)
 				| (i<<16) | (6<<20) | (i<<23));
 		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_VTX_TB_STATE_MEM,
@@ -215,11 +216,11 @@
 	header->size = MIUDEBUG_COUNT;
 
 	for (i = 0; i < MIUDEBUG_COUNT; i++) {
-		adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1600 | i);
-		adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
+		kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1600 | i);
+		kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
 	}
 
-	adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
+	kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
 
 	return DEBUG_SECTION_SZ(MIUDEBUG_COUNT);
 }
@@ -297,8 +298,8 @@
 	 * work
 	 */
 
-	adreno_regread(device, REG_RBBM_PM_OVERRIDE2, &pmoverride);
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xFF);
+	kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &pmoverride);
+	kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xFF);
 
 	/* SX debug registers */
 	snapshot = kgsl_snapshot_add_section(device,
@@ -376,7 +377,7 @@
 
 
 	/* Reset the clock gating */
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, pmoverride);
+	kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, pmoverride);
 
 	return snapshot;
 }
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index a757a22..7e5638c 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2545,7 +2545,7 @@
 	case A3XX_INT_RBBM_AHB_ERROR: {
 		unsigned int reg;
 
-		adreno_regread(device, A3XX_RBBM_AHB_ERROR_STATUS, &reg);
+		kgsl_regread(device, A3XX_RBBM_AHB_ERROR_STATUS, &reg);
 
 		/*
 		 * Return the word address of the erroring register so that it
@@ -2559,7 +2559,7 @@
 			(reg >> 24) & 0x3);
 
 		/* Clear the error */
-		adreno_regwrite(device, A3XX_RBBM_AHB_CMD, (1 << 3));
+		kgsl_regwrite(device, A3XX_RBBM_AHB_CMD, (1 << 3));
 		return;
 	}
 	case A3XX_INT_RBBM_REG_TIMEOUT:
@@ -2738,21 +2738,21 @@
 	if (countable > 1)
 		return;
 
-	adreno_regread(device, A3XX_RBBM_RBBM_CTL, &in);
+	kgsl_regread(device, A3XX_RBBM_RBBM_CTL, &in);
 
 	if (countable == 0)
 		out = in | RBBM_RBBM_CTL_RESET_PWR_CTR0;
 	else
 		out = in | RBBM_RBBM_CTL_RESET_PWR_CTR1;
 
-	adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
+	kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
 
 	if (countable == 0)
 		out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR0;
 	else
 		out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR1;
 
-	adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
+	kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
 
 	return;
 }
@@ -2766,8 +2766,8 @@
 	if (counter > 1 || countable > 0x7f)
 		return;
 
-	adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
-	adreno_regread(device, A3XX_VBIF_PERF_CNT_SEL, &sel);
+	kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
+	kgsl_regread(device, A3XX_VBIF_PERF_CNT_SEL, &sel);
 
 	if (counter == 0) {
 		bit = VBIF_PERF_CNT_0;
@@ -2780,12 +2780,12 @@
 
 	out = in | bit;
 
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_SEL, sel);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_SEL, sel);
 
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
 
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
 }
 
 static void a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device,
@@ -2796,7 +2796,7 @@
 	if (countable > 2)
 		return;
 
-	adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
+	kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
 	if (countable == 0)
 		bit = VBIF_PERF_PWR_CNT_0;
 	else if (countable == 1)
@@ -2806,10 +2806,10 @@
 
 	out = in | bit;
 
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
 
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
 }
 
 /*
@@ -2846,14 +2846,14 @@
 	reg = &(a3xx_perfcounter_reglist[group].regs[counter]);
 
 	/* Select the desired perfcounter */
-	adreno_regwrite(device, reg->select, countable);
+	kgsl_regwrite(device, reg->select, countable);
 
 	if (reg->load_bit < 32) {
 		val = 1 << reg->load_bit;
-		adreno_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, val);
+		kgsl_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, val);
 	} else {
 		val  = 1 << (reg->load_bit - 32);
-		adreno_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, val);
+		kgsl_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, val);
 	}
 }
 
@@ -2875,17 +2875,17 @@
 	reg = &(a3xx_perfcounter_reglist[group].regs[counter]);
 
 	/* Freeze the counter */
-	adreno_regread(device, A3XX_RBBM_PERFCTR_CTL, &val);
+	kgsl_regread(device, A3XX_RBBM_PERFCTR_CTL, &val);
 	val &= ~reg->load_bit;
-	adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val);
+	kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val);
 
 	/* Read the values */
-	adreno_regread(device, offset, &lo);
-	adreno_regread(device, offset + 1, &hi);
+	kgsl_regread(device, offset, &lo);
+	kgsl_regread(device, offset + 1, &hi);
 
 	/* Re-Enable the counter */
 	val |= reg->load_bit;
-	adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val);
+	kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val);
 
 	return (((uint64_t) hi) << 32) | lo;
 }
@@ -2945,7 +2945,7 @@
 	unsigned int status, tmp;
 	int i;
 
-	adreno_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status);
+	kgsl_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status);
 
 	for (tmp = status, i = 0; tmp && i < ARRAY_SIZE(a3xx_irq_funcs); i++) {
 		if (tmp & 1) {
@@ -2964,7 +2964,7 @@
 	trace_kgsl_a3xx_irq_status(device, status);
 
 	if (status)
-		adreno_regwrite(&adreno_dev->dev, A3XX_RBBM_INT_CLEAR_CMD,
+		kgsl_regwrite(&adreno_dev->dev, A3XX_RBBM_INT_CLEAR_CMD,
 			status);
 	return ret;
 }
@@ -2974,16 +2974,16 @@
 	struct kgsl_device *device = &adreno_dev->dev;
 
 	if (state)
-		adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, A3XX_INT_MASK);
+		kgsl_regwrite(device, A3XX_RBBM_INT_0_MASK, A3XX_INT_MASK);
 	else
-		adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, 0);
+		kgsl_regwrite(device, A3XX_RBBM_INT_0_MASK, 0);
 }
 
 static unsigned int a3xx_irq_pending(struct adreno_device *adreno_dev)
 {
 	unsigned int status;
 
-	adreno_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status);
+	kgsl_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status);
 
 	return (status & A3XX_INT_MASK) ? 1 : 0;
 }
@@ -2995,7 +2995,7 @@
 	unsigned int ret = 0;
 
 	/* Read the value */
-	adreno_regread(device, A3XX_RBBM_PERFCTR_PWR_1_LO, &val);
+	kgsl_regread(device, A3XX_RBBM_PERFCTR_PWR_1_LO, &val);
 
 	/* Return 0 for the first read */
 	if (adreno_dev->gpu_cycles != 0) {
@@ -3136,215 +3136,6 @@
 	{ adreno_is_a305b, a305b_vbif },
 };
 
-static void a3xx_perfcounter_init(struct adreno_device *adreno_dev)
-{
-	/*
-	 * Set SP to count SP_ALU_ACTIVE_CYCLES, it includes
-	 * all ALU instruction execution regardless precision or shader ID.
-	 * Set SP to count SP0_ICL1_MISSES, It counts
-	 * USP L1 instruction miss request.
-	 * Set SP to count SP_FS_FULL_ALU_INSTRUCTIONS, it
-	 * counts USP flow control instruction execution.
-	 * we will use this to augment our hang detection
-	 */
-	if (adreno_dev->fast_hang_detect) {
-		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
-			SP_ALU_ACTIVE_CYCLES, &ft_detect_regs[6],
-			PERFCOUNTER_FLAG_KERNEL);
-		ft_detect_regs[7] = ft_detect_regs[6] + 1;
-		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
-			SP0_ICL1_MISSES, &ft_detect_regs[8],
-			PERFCOUNTER_FLAG_KERNEL);
-		ft_detect_regs[9] = ft_detect_regs[8] + 1;
-		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
-			SP_FS_CFLOW_INSTRUCTIONS, &ft_detect_regs[10],
-			PERFCOUNTER_FLAG_KERNEL);
-		ft_detect_regs[11] = ft_detect_regs[10] + 1;
-	}
-
-	adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
-		SP_FS_FULL_ALU_INSTRUCTIONS, NULL, PERFCOUNTER_FLAG_KERNEL);
-
-	/* Reserve and start countable 1 in the PWR perfcounter group */
-	adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_PWR, 1,
-			NULL, PERFCOUNTER_FLAG_KERNEL);
-}
-
-static void a3xx_start(struct adreno_device *adreno_dev)
-{
-	struct kgsl_device *device = &adreno_dev->dev;
-	struct a3xx_vbif_data *vbif = NULL;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(a3xx_vbif_platforms); i++) {
-		if (a3xx_vbif_platforms[i].devfunc(adreno_dev)) {
-			vbif = a3xx_vbif_platforms[i].vbif;
-			break;
-		}
-	}
-
-	BUG_ON(vbif == NULL);
-
-	while (vbif->reg != 0) {
-		adreno_regwrite(device, vbif->reg, vbif->val);
-		vbif++;
-	}
-
-	/* Make all blocks contribute to the GPU BUSY perf counter */
-	adreno_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF);
-
-	/* Tune the hystersis counters for SP and CP idle detection */
-	adreno_regwrite(device, A3XX_RBBM_SP_HYST_CNT, 0x10);
-	adreno_regwrite(device, A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
-
-	/* Enable the RBBM error reporting bits.  This lets us get
-	   useful information on failure */
-
-	adreno_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001);
-
-	/* Enable AHB error reporting */
-	adreno_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF);
-
-	/* Turn on the power counters */
-	adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00030000);
-
-	/* Turn on hang detection - this spews a lot of useful information
-	 * into the RBBM registers on a hang */
-
-	adreno_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL,
-			(1 << 16) | 0xFFF);
-
-	/* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0). */
-	adreno_regwrite(device, A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
-
-	/* Enable Clock gating */
-	adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL,
-		adreno_a3xx_rbbm_clock_ctl_default(adreno_dev));
-
-	if (adreno_is_a330v2(adreno_dev))
-		adreno_regwrite(device, A3XX_RBBM_GPR0_CTL,
-			A330v2_RBBM_GPR0_CTL_DEFAULT);
-	else if (adreno_is_a330(adreno_dev))
-		adreno_regwrite(device, A3XX_RBBM_GPR0_CTL,
-			A330_RBBM_GPR0_CTL_DEFAULT);
-
-	/* Set the OCMEM base address for A330 */
-	if (adreno_is_a330(adreno_dev) ||
-		adreno_is_a305b(adreno_dev)) {
-		adreno_regwrite(device, A3XX_RB_GMEM_BASE_ADDR,
-			(unsigned int)(adreno_dev->ocmem_base >> 14));
-	}
-
-	/* Turn on performance counters */
-	adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01);
-
-	/* Turn on the GPU busy counter and let it run free */
-
-	adreno_dev->gpu_cycles = 0;
-}
-
-/**
- * a3xx_coresight_enable() - Enables debugging through coresight
- * debug bus for adreno a3xx devices.
- * @device: Pointer to GPU device structure
- */
-int a3xx_coresight_enable(struct kgsl_device *device)
-{
-	mutex_lock(&device->mutex);
-	if (!kgsl_active_count_get(device)) {
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0001093F);
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0,
-				0x00000000);
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1,
-				0xFFFFFFFE);
-		adreno_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL,
-				0x00201111);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL,
-				0x89100010);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT,
-				0x00017fff);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT,
-				0x0001000f);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT ,
-				0x0001ffff);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD,
-				0x00000001);
-		kgsl_active_count_put(device);
-	}
-	mutex_unlock(&device->mutex);
-	return 0;
-}
-
-/**
- * a3xx_coresight_disable() - Disables debugging through coresight
- * debug bus for adreno a3xx devices.
- * @device: Pointer to GPU device structure
- */
-void a3xx_coresight_disable(struct kgsl_device *device)
-{
-	mutex_lock(&device->mutex);
-	if (!kgsl_active_count_get(device)) {
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT , 0x0);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD, 0x0);
-		kgsl_active_count_put(device);
-	}
-	mutex_unlock(&device->mutex);
-}
-
-static void a3xx_coresight_write_reg(struct kgsl_device *device,
-		unsigned int wordoffset, unsigned int val)
-{
-	mutex_lock(&device->mutex);
-	if (!kgsl_active_count_get(device)) {
-		adreno_regwrite(device, wordoffset, val);
-		kgsl_active_count_put(device);
-	}
-	mutex_unlock(&device->mutex);
-}
-
-void a3xx_coresight_config_debug_reg(struct kgsl_device *device,
-		int debug_reg, unsigned int val)
-{
-	switch (debug_reg) {
-
-	case DEBUG_BUS_CTL:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_DEBUG_BUS_CTL, val);
-		break;
-
-	case TRACE_STOP_CNT:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_STOP_CNT,
-				val);
-		break;
-
-	case TRACE_START_CNT:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_START_CNT,
-				val);
-		break;
-
-	case TRACE_PERIOD_CNT:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT,
-				val);
-		break;
-
-	case TRACE_CMD:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_CMD, val);
-		break;
-
-	case TRACE_BUS_CTL:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_BUS_CTL,
-				val);
-		break;
-	}
-
-}
-
 /*
  * Define the available perfcounter groups - these get used by
  * adreno_perfcounter_get and adreno_perfcounter_put
@@ -3467,6 +3258,219 @@
 	ARRAY_SIZE(a3xx_perfcounter_groups),
 };
 
+static void a3xx_perfcounter_init(struct adreno_device *adreno_dev)
+{
+	/* SP[3] counter is broken on a330 so disable it if a330 device */
+	if (adreno_is_a330(adreno_dev))
+		a3xx_perfcounters_sp[3].countable = KGSL_PERFCOUNTER_BROKEN;
+
+	/*
+	 * Set SP to count SP_ALU_ACTIVE_CYCLES, it includes
+	 * all ALU instruction execution regardless precision or shader ID.
+	 * Set SP to count SP0_ICL1_MISSES, It counts
+	 * USP L1 instruction miss request.
+	 * Set SP to count SP_FS_FULL_ALU_INSTRUCTIONS, it
+	 * counts USP flow control instruction execution.
+	 * we will use this to augment our hang detection
+	 */
+	if (adreno_dev->fast_hang_detect) {
+		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+			SP_ALU_ACTIVE_CYCLES, &ft_detect_regs[6],
+			PERFCOUNTER_FLAG_KERNEL);
+		ft_detect_regs[7] = ft_detect_regs[6] + 1;
+		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+			SP0_ICL1_MISSES, &ft_detect_regs[8],
+			PERFCOUNTER_FLAG_KERNEL);
+		ft_detect_regs[9] = ft_detect_regs[8] + 1;
+		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+			SP_FS_CFLOW_INSTRUCTIONS, &ft_detect_regs[10],
+			PERFCOUNTER_FLAG_KERNEL);
+		ft_detect_regs[11] = ft_detect_regs[10] + 1;
+	}
+
+	adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+		SP_FS_FULL_ALU_INSTRUCTIONS, NULL, PERFCOUNTER_FLAG_KERNEL);
+
+	/* Reserve and start countable 1 in the PWR perfcounter group */
+	adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_PWR, 1,
+			NULL, PERFCOUNTER_FLAG_KERNEL);
+}
+
+static void a3xx_start(struct adreno_device *adreno_dev)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	struct a3xx_vbif_data *vbif = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(a3xx_vbif_platforms); i++) {
+		if (a3xx_vbif_platforms[i].devfunc(adreno_dev)) {
+			vbif = a3xx_vbif_platforms[i].vbif;
+			break;
+		}
+	}
+
+	BUG_ON(vbif == NULL);
+
+	while (vbif->reg != 0) {
+		kgsl_regwrite(device, vbif->reg, vbif->val);
+		vbif++;
+	}
+
+	/* Make all blocks contribute to the GPU BUSY perf counter */
+	kgsl_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF);
+
+	/* Tune the hystersis counters for SP and CP idle detection */
+	kgsl_regwrite(device, A3XX_RBBM_SP_HYST_CNT, 0x10);
+	kgsl_regwrite(device, A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
+
+	/* Enable the RBBM error reporting bits.  This lets us get
+	   useful information on failure */
+
+	kgsl_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001);
+
+	/* Enable AHB error reporting */
+	kgsl_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF);
+
+	/* Turn on the power counters */
+	kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00030000);
+
+	/* Turn on hang detection - this spews a lot of useful information
+	 * into the RBBM registers on a hang */
+
+	kgsl_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL,
+			(1 << 16) | 0xFFF);
+
+	/* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0). */
+	kgsl_regwrite(device, A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
+
+	/* Enable Clock gating */
+	kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL,
+		adreno_a3xx_rbbm_clock_ctl_default(adreno_dev));
+
+	if (adreno_is_a330v2(adreno_dev))
+		kgsl_regwrite(device, A3XX_RBBM_GPR0_CTL,
+			A330v2_RBBM_GPR0_CTL_DEFAULT);
+	else if (adreno_is_a330(adreno_dev))
+		kgsl_regwrite(device, A3XX_RBBM_GPR0_CTL,
+			A330_RBBM_GPR0_CTL_DEFAULT);
+
+	/* Set the OCMEM base address for A330 */
+	if (adreno_is_a330(adreno_dev) ||
+		adreno_is_a305b(adreno_dev)) {
+		kgsl_regwrite(device, A3XX_RB_GMEM_BASE_ADDR,
+			(unsigned int)(adreno_dev->ocmem_base >> 14));
+	}
+
+	/* Turn on performance counters */
+	kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01);
+
+	/* Turn on the GPU busy counter and let it run free */
+
+	adreno_dev->gpu_cycles = 0;
+}
+
+/**
+ * a3xx_coresight_enable() - Enables debugging through coresight
+ * debug bus for adreno a3xx devices.
+ * @device: Pointer to GPU device structure
+ */
+int a3xx_coresight_enable(struct kgsl_device *device)
+{
+	mutex_lock(&device->mutex);
+	if (!kgsl_active_count_get(device)) {
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0001093F);
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0,
+				0x00000000);
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1,
+				0xFFFFFFFE);
+		kgsl_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL,
+				0x00201111);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL,
+				0x89100010);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT,
+				0x00017fff);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT,
+				0x0001000f);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT ,
+				0x0001ffff);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD,
+				0x00000001);
+		kgsl_active_count_put(device);
+	}
+	mutex_unlock(&device->mutex);
+	return 0;
+}
+
+/**
+ * a3xx_coresight_disable() - Disables debugging through coresight
+ * debug bus for adreno a3xx devices.
+ * @device: Pointer to GPU device structure
+ */
+void a3xx_coresight_disable(struct kgsl_device *device)
+{
+	mutex_lock(&device->mutex);
+	if (!kgsl_active_count_get(device)) {
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT , 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD, 0x0);
+		kgsl_active_count_put(device);
+	}
+	mutex_unlock(&device->mutex);
+}
+
+static void a3xx_coresight_write_reg(struct kgsl_device *device,
+		unsigned int wordoffset, unsigned int val)
+{
+	mutex_lock(&device->mutex);
+	if (!kgsl_active_count_get(device)) {
+		kgsl_regwrite(device, wordoffset, val);
+		kgsl_active_count_put(device);
+	}
+	mutex_unlock(&device->mutex);
+}
+
+void a3xx_coresight_config_debug_reg(struct kgsl_device *device,
+		int debug_reg, unsigned int val)
+{
+	switch (debug_reg) {
+
+	case DEBUG_BUS_CTL:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_DEBUG_BUS_CTL, val);
+		break;
+
+	case TRACE_STOP_CNT:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_STOP_CNT,
+				val);
+		break;
+
+	case TRACE_START_CNT:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_START_CNT,
+				val);
+		break;
+
+	case TRACE_PERIOD_CNT:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT,
+				val);
+		break;
+
+	case TRACE_CMD:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_CMD, val);
+		break;
+
+	case TRACE_BUS_CTL:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_BUS_CTL,
+				val);
+		break;
+	}
+
+}
+
 /*
  * a3xx_soft_reset() - Soft reset GPU
  * @adreno_dev: Pointer to adreno device
@@ -3482,23 +3486,246 @@
 	struct kgsl_device *device = &adreno_dev->dev;
 	unsigned int reg;
 
-	adreno_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 1);
+	kgsl_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 1);
 	/*
 	 * Do a dummy read to get a brief read cycle delay for the reset to take
 	 * effect
 	 */
-	adreno_regread(device, A3XX_RBBM_SW_RESET_CMD, &reg);
-	adreno_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 0);
+	kgsl_regread(device, A3XX_RBBM_SW_RESET_CMD, &reg);
+	kgsl_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 0);
 }
 
 /* Defined in adreno_a3xx_snapshot.c */
 void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot,
 	int *remain, int hang);
 
+static void a3xx_postmortem_dump(struct adreno_device *adreno_dev)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	unsigned int r1, r2, r3, rbbm_status;
+	unsigned int cp_stat, rb_count;
+
+	kgsl_regread(device, REG_RBBM_STATUS, &rbbm_status);
+	KGSL_LOG_DUMP(device, "RBBM:   STATUS   = %08X\n", rbbm_status);
+
+	{
+		struct log_field lines[] = {
+			{rbbm_status & BIT(0),  "HI busy     "},
+			{rbbm_status & BIT(1),  "CP ME busy  "},
+			{rbbm_status & BIT(2),  "CP PFP busy "},
+			{rbbm_status & BIT(14), "CP NRT busy "},
+			{rbbm_status & BIT(15), "VBIF busy   "},
+			{rbbm_status & BIT(16), "TSE busy    "},
+			{rbbm_status & BIT(17), "RAS busy    "},
+			{rbbm_status & BIT(18), "RB busy     "},
+			{rbbm_status & BIT(19), "PC DCALL bsy"},
+			{rbbm_status & BIT(20), "PC VSD busy "},
+			{rbbm_status & BIT(21), "VFD busy    "},
+			{rbbm_status & BIT(22), "VPC busy    "},
+			{rbbm_status & BIT(23), "UCHE busy   "},
+			{rbbm_status & BIT(24), "SP busy     "},
+			{rbbm_status & BIT(25), "TPL1 busy   "},
+			{rbbm_status & BIT(26), "MARB busy   "},
+			{rbbm_status & BIT(27), "VSC busy    "},
+			{rbbm_status & BIT(28), "ARB busy    "},
+			{rbbm_status & BIT(29), "HLSQ busy   "},
+			{rbbm_status & BIT(30), "GPU bsy noHC"},
+			{rbbm_status & BIT(31), "GPU busy    "},
+			};
+		adreno_dump_fields(device, " STATUS=", lines,
+				ARRAY_SIZE(lines));
+	}
+
+	kgsl_regread(device, REG_CP_RB_BASE, &r1);
+	kgsl_regread(device, REG_CP_RB_CNTL, &r2);
+	rb_count = 2 << (r2 & (BIT(6) - 1));
+	kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3);
+	KGSL_LOG_DUMP(device,
+		"CP_RB:  BASE = %08X | CNTL   = %08X | RPTR_ADDR = %08X"
+		"| rb_count = %08X\n", r1, r2, r3, rb_count);
+
+	kgsl_regread(device, REG_CP_RB_RPTR, &r1);
+	kgsl_regread(device, REG_CP_RB_WPTR, &r2);
+	kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3);
+	KGSL_LOG_DUMP(device,
+		"CP_RB:  BASE = %08X | CNTL   = %08X | RPTR_ADDR = %08X"
+		"| rb_count = %08X\n", r1, r2, r3, rb_count);
+
+	kgsl_regread(device, REG_CP_RB_RPTR, &r1);
+	kgsl_regread(device, REG_CP_RB_WPTR, &r2);
+	kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3);
+	KGSL_LOG_DUMP(device,
+		"	RPTR = %08X | WPTR   = %08X | RPTR_WR   = %08X"
+		"\n", r1, r2, r3);
+
+	kgsl_regread(device, REG_CP_IB1_BASE, &r1);
+	kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2);
+	KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ  = %d\n", r1, r2);
+
+	kgsl_regread(device, REG_CP_ME_CNTL, &r1);
+	kgsl_regread(device, REG_CP_ME_STATUS, &r2);
+	KGSL_LOG_DUMP(device, "CP_ME:  CNTL = %08X | STATUS = %08X\n", r1, r2);
+
+	kgsl_regread(device, REG_CP_STAT, &cp_stat);
+	KGSL_LOG_DUMP(device, "CP_STAT      = %08X\n", cp_stat);
+#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL
+	{
+		struct log_field lns[] = {
+			{cp_stat & BIT(0), "WR_BSY     0"},
+			{cp_stat & BIT(1), "RD_RQ_BSY  1"},
+			{cp_stat & BIT(2), "RD_RTN_BSY 2"},
+		};
+		adreno_dump_fields(device, "    MIU=", lns, ARRAY_SIZE(lns));
+	}
+	{
+		struct log_field lns[] = {
+			{cp_stat & BIT(5), "RING_BUSY  5"},
+			{cp_stat & BIT(6), "NDRCTS_BSY 6"},
+			{cp_stat & BIT(7), "NDRCT2_BSY 7"},
+			{cp_stat & BIT(9), "ST_BUSY    9"},
+			{cp_stat & BIT(10), "BUSY      10"},
+		};
+		adreno_dump_fields(device, "    CSF=", lns, ARRAY_SIZE(lns));
+	}
+	{
+		struct log_field lns[] = {
+			{cp_stat & BIT(11), "RNG_Q_BSY 11"},
+			{cp_stat & BIT(12), "NDRCTS_Q_B12"},
+			{cp_stat & BIT(13), "NDRCT2_Q_B13"},
+			{cp_stat & BIT(16), "ST_QUEUE_B16"},
+			{cp_stat & BIT(17), "PFP_BUSY  17"},
+		};
+		adreno_dump_fields(device, "   RING=", lns, ARRAY_SIZE(lns));
+	}
+	{
+		struct log_field lns[] = {
+			{cp_stat & BIT(3), "RBIU_BUSY  3"},
+			{cp_stat & BIT(4), "RCIU_BUSY  4"},
+			{cp_stat & BIT(8), "EVENT_BUSY 8"},
+			{cp_stat & BIT(18), "MQ_RG_BSY 18"},
+			{cp_stat & BIT(19), "MQ_NDRS_BS19"},
+			{cp_stat & BIT(20), "MQ_NDR2_BS20"},
+			{cp_stat & BIT(21), "MIU_WC_STL21"},
+			{cp_stat & BIT(22), "CP_NRT_BSY22"},
+			{cp_stat & BIT(23), "3D_BUSY   23"},
+			{cp_stat & BIT(26), "ME_BUSY   26"},
+			{cp_stat & BIT(27), "RB_FFO_BSY27"},
+			{cp_stat & BIT(28), "CF_FFO_BSY28"},
+			{cp_stat & BIT(29), "PS_FFO_BSY29"},
+			{cp_stat & BIT(30), "VS_FFO_BSY30"},
+			{cp_stat & BIT(31), "CP_BUSY   31"},
+		};
+		adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns));
+	}
+#endif
+
+	kgsl_regread(device, A3XX_RBBM_INT_0_STATUS, &r1);
+	KGSL_LOG_DUMP(device, "MSTR_INT_SGNL = %08X\n", r1);
+	{
+		struct log_field ints[] = {
+			{r1 & BIT(0),  "RBBM_GPU_IDLE 0"},
+			{r1 & BIT(1),  "RBBM_AHB_ERROR 1"},
+			{r1 & BIT(2),  "RBBM_REG_TIMEOUT 2"},
+			{r1 & BIT(3),  "RBBM_ME_MS_TIMEOUT 3"},
+			{r1 & BIT(4),  "RBBM_PFP_MS_TIMEOUT 4"},
+			{r1 & BIT(5),  "RBBM_ATB_BUS_OVERFLOW 5"},
+			{r1 & BIT(6),  "VFD_ERROR 6"},
+			{r1 & BIT(7),  "CP_SW_INT 7"},
+			{r1 & BIT(8),  "CP_T0_PACKET_IN_IB 8"},
+			{r1 & BIT(9),  "CP_OPCODE_ERROR 9"},
+			{r1 & BIT(10), "CP_RESERVED_BIT_ERROR 10"},
+			{r1 & BIT(11), "CP_HW_FAULT 11"},
+			{r1 & BIT(12), "CP_DMA 12"},
+			{r1 & BIT(13), "CP_IB2_INT 13"},
+			{r1 & BIT(14), "CP_IB1_INT 14"},
+			{r1 & BIT(15), "CP_RB_INT 15"},
+			{r1 & BIT(16), "CP_REG_PROTECT_FAULT 16"},
+			{r1 & BIT(17), "CP_RB_DONE_TS 17"},
+			{r1 & BIT(18), "CP_VS_DONE_TS 18"},
+			{r1 & BIT(19), "CP_PS_DONE_TS 19"},
+			{r1 & BIT(20), "CACHE_FLUSH_TS 20"},
+			{r1 & BIT(21), "CP_AHB_ERROR_HALT 21"},
+			{r1 & BIT(24), "MISC_HANG_DETECT 24"},
+			{r1 & BIT(25), "UCHE_OOB_ACCESS 25"},
+		};
+		adreno_dump_fields(device, "INT_SGNL=", ints, ARRAY_SIZE(ints));
+	}
+}
+
+/* Register offset defines for A3XX */
+static unsigned int a3xx_register_offsets[ADRENO_REG_REGISTER_MAX] = {
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_DEBUG, REG_CP_DEBUG),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_WADDR, REG_CP_ME_RAM_WADDR),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_DATA, REG_CP_ME_RAM_DATA),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_DATA, A3XX_CP_PFP_UCODE_DATA),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_ADDR, A3XX_CP_PFP_UCODE_ADDR),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_WFI_PEND_CTR, A3XX_CP_WFI_PEND_CTR),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_BASE, REG_CP_RB_BASE),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR_ADDR, REG_CP_RB_RPTR_ADDR),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR, REG_CP_RB_RPTR),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_WPTR, REG_CP_RB_WPTR),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_PROTECT_CTRL, A3XX_CP_PROTECT_CTRL),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_CNTL, REG_CP_ME_CNTL),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_CNTL, REG_CP_RB_CNTL),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE, REG_CP_IB1_BASE),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BUFSZ, REG_CP_IB1_BUFSZ),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BASE, REG_CP_IB2_BASE),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BUFSZ, REG_CP_IB2_BUFSZ),
+	ADRENO_REG_DEFINE(ADRENO_REG_CP_TIMESTAMP, REG_CP_TIMESTAMP),
+	ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_ADDR, REG_SCRATCH_ADDR),
+	ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_UMSK, REG_SCRATCH_UMSK),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_STATUS, A3XX_RBBM_STATUS),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_CTL, A3XX_RBBM_PERFCTR_CTL),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD0,
+					A3XX_RBBM_PERFCTR_LOAD_CMD0),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD1,
+					A3XX_RBBM_PERFCTR_LOAD_CMD1),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_PWR_1_LO,
+					A3XX_RBBM_PERFCTR_PWR_1_LO),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_MASK, A3XX_RBBM_INT_0_MASK),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_STATUS, A3XX_RBBM_INT_0_STATUS),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_AHB_ERROR_STATUS,
+					A3XX_RBBM_AHB_ERROR_STATUS),
+	ADRENO_REG_DEFINE(ADRENO_REG_VPC_VPC_DEBUG_RAM_SEL,
+					A3XX_VPC_VPC_DEBUG_RAM_SEL),
+	ADRENO_REG_DEFINE(ADRENO_REG_VPC_VPC_DEBUG_RAM_READ,
+					A3XX_VPC_VPC_DEBUG_RAM_READ),
+	ADRENO_REG_DEFINE(ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0,
+				A3XX_VSC_PIPE_DATA_ADDRESS_0),
+	ADRENO_REG_DEFINE(ADRENO_REG_VSC_PIPE_DATA_LENGTH_7,
+					A3XX_VSC_PIPE_DATA_LENGTH_7),
+	ADRENO_REG_DEFINE(ADRENO_REG_VSC_SIZE_ADDRESS, A3XX_VSC_SIZE_ADDRESS),
+	ADRENO_REG_DEFINE(ADRENO_REG_VFD_CONTROL_0, A3XX_VFD_CONTROL_0),
+	ADRENO_REG_DEFINE(ADRENO_REG_VFD_FETCH_INSTR_0_0,
+					A3XX_VFD_FETCH_INSTR_0_0),
+	ADRENO_REG_DEFINE(ADRENO_REG_VFD_FETCH_INSTR_1_F,
+					A3XX_VFD_FETCH_INSTR_1_F),
+	ADRENO_REG_DEFINE(ADRENO_REG_VFD_INDEX_MAX, A3XX_VFD_INDEX_MAX),
+	ADRENO_REG_DEFINE(ADRENO_REG_SP_VS_PVT_MEM_ADDR_REG,
+				A3XX_SP_VS_PVT_MEM_ADDR_REG),
+	ADRENO_REG_DEFINE(ADRENO_REG_SP_FS_PVT_MEM_ADDR_REG,
+				A3XX_SP_FS_PVT_MEM_ADDR_REG),
+	ADRENO_REG_DEFINE(ADRENO_REG_SP_VS_OBJ_START_REG,
+				A3XX_SP_VS_OBJ_START_REG),
+	ADRENO_REG_DEFINE(ADRENO_REG_SP_FS_OBJ_START_REG,
+				A3XX_SP_FS_OBJ_START_REG),
+	ADRENO_REG_DEFINE(ADRENO_REG_PA_SC_AA_CONFIG, REG_PA_SC_AA_CONFIG),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PM_OVERRIDE2, REG_RBBM_PM_OVERRIDE2),
+	ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_REG2, REG_SCRATCH_REG2),
+	ADRENO_REG_DEFINE(ADRENO_REG_SQ_GPR_MANAGEMENT, REG_SQ_GPR_MANAGEMENT),
+	ADRENO_REG_DEFINE(ADRENO_REG_SQ_INST_STORE_MANAGMENT,
+				REG_SQ_INST_STORE_MANAGMENT),
+	ADRENO_REG_DEFINE(ADRENO_REG_TC_CNTL_STATUS, REG_TC_CNTL_STATUS),
+	ADRENO_REG_DEFINE(ADRENO_REG_TP0_CHICKEN, REG_TP0_CHICKEN),
+};
+
+struct adreno_reg_offsets a3xx_reg_offsets = {
+	.offsets = a3xx_register_offsets,
+	.offset_0 = ADRENO_REG_REGISTER_MAX,
+};
+
 struct adreno_gpudev adreno_a3xx_gpudev = {
-	.reg_rbbm_status = A3XX_RBBM_STATUS,
-	.reg_cp_pfp_ucode_addr = A3XX_CP_PFP_UCODE_ADDR,
-	.reg_cp_pfp_ucode_data = A3XX_CP_PFP_UCODE_DATA,
+	.reg_offsets = &a3xx_reg_offsets,
 	.perfcounters = &a3xx_perfcounters,
 
 	.ctxt_create = a3xx_drawctxt_create,
@@ -3519,4 +3746,5 @@
 	.coresight_disable = a3xx_coresight_disable,
 	.coresight_config_debug_reg = a3xx_coresight_config_debug_reg,
 	.soft_reset = a3xx_soft_reset,
+	.postmortem_dump = a3xx_postmortem_dump,
 };
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
index 58e3126..56c4305 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -35,8 +35,8 @@
 	unsigned int block_id, unsigned int index, unsigned int *val)
 {
 	unsigned int block = (block_id << 8) | 1 << 16;
-	adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, block | index);
-	adreno_regread(device, A3XX_RBBM_DEBUG_BUS_DATA_STATUS, val);
+	kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, block | index);
+	kgsl_regread(device, A3XX_RBBM_DEBUG_BUS_DATA_STATUS, val);
 }
 
 /**
@@ -108,9 +108,9 @@
 	for (bank = 0; bank < VPC_MEMORY_BANKS; bank++) {
 		for (addr = 0; addr < VPC_MEMORY_SIZE; addr++) {
 			unsigned int val = bank | (addr << 4);
-			adreno_regwrite(device,
+			kgsl_regwrite(device,
 				A3XX_VPC_VPC_DEBUG_RAM_SEL, val);
-			adreno_regread(device,
+			kgsl_regread(device,
 				A3XX_VPC_VPC_DEBUG_RAM_READ, &data[i++]);
 		}
 	}
@@ -134,9 +134,9 @@
 	header->type = SNAPSHOT_DEBUG_CP_MEQ;
 	header->size = CP_MEQ_SIZE;
 
-	adreno_regwrite(device, A3XX_CP_MEQ_ADDR, 0x0);
+	kgsl_regwrite(device, A3XX_CP_MEQ_ADDR, 0x0);
 	for (i = 0; i < CP_MEQ_SIZE; i++)
-		adreno_regread(device, A3XX_CP_MEQ_DATA, &data[i]);
+		kgsl_regread(device, A3XX_CP_MEQ_DATA, &data[i]);
 
 	return DEBUG_SECTION_SZ(CP_MEQ_SIZE);
 }
@@ -164,9 +164,9 @@
 	 * maintain always changing hardcoded constants
 	 */
 
-	adreno_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0);
+	kgsl_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0);
 	for (i = 0; i < size; i++)
-		adreno_regread(device, REG_CP_ME_RAM_DATA, &data[i]);
+		kgsl_regread(device, REG_CP_ME_RAM_DATA, &data[i]);
 
 	return DEBUG_SECTION_SZ(size);
 }
@@ -195,7 +195,7 @@
 	 */
 	kgsl_regwrite(device, A3XX_CP_PFP_UCODE_ADDR, 0x0);
 	for (i = 0; i < size; i++)
-		adreno_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]);
+		kgsl_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]);
 
 	return DEBUG_SECTION_SZ(size);
 }
@@ -226,9 +226,9 @@
 	header->type = SNAPSHOT_DEBUG_CP_ROQ;
 	header->size = size;
 
-	adreno_regwrite(device, A3XX_CP_ROQ_ADDR, 0x0);
+	kgsl_regwrite(device, A3XX_CP_ROQ_ADDR, 0x0);
 	for (i = 0; i < size; i++)
-		adreno_regread(device, A3XX_CP_ROQ_DATA, &data[i]);
+		kgsl_regread(device, A3XX_CP_ROQ_DATA, &data[i]);
 
 	return DEBUG_SECTION_SZ(size);
 }
@@ -253,12 +253,12 @@
 	header->type = SNAPSHOT_DEBUG_CP_MERCIU;
 	header->size = size;
 
-	adreno_regwrite(device, A3XX_CP_MERCIU_ADDR, 0x0);
+	kgsl_regwrite(device, A3XX_CP_MERCIU_ADDR, 0x0);
 
 	for (i = 0; i < A330_CP_MERCIU_QUEUE_SIZE; i++) {
-		adreno_regread(device, A3XX_CP_MERCIU_DATA,
+		kgsl_regread(device, A3XX_CP_MERCIU_DATA,
 			&data[(i * 2)]);
-		adreno_regread(device, A3XX_CP_MERCIU_DATA2,
+		kgsl_regread(device, A3XX_CP_MERCIU_DATA2,
 			&data[(i * 2) + 1]);
 	}
 
@@ -444,7 +444,7 @@
 	list.count = 0;
 
 	/* Disable Clock gating temporarily for the debug bus to work */
-	adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL, 0x00);
+	kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL, 0x00);
 
 	/* Store relevant registers in list to snapshot */
 	_snapshot_a3xx_regs(regs, &list);
@@ -516,7 +516,7 @@
 	snapshot = a3xx_snapshot_debugbus(device, snapshot, remain);
 
 	/* Enable Clock gating */
-	adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL,
+	kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL,
 		adreno_a3xx_rbbm_clock_ctl_default(adreno_dev));
 
 	return snapshot;
diff --git a/drivers/gpu/msm/adreno_coresight.c b/drivers/gpu/msm/adreno_coresight.c
index e18568d..1b827ff 100644
--- a/drivers/gpu/msm/adreno_coresight.c
+++ b/drivers/gpu/msm/adreno_coresight.c
@@ -109,7 +109,7 @@
 
 	mutex_lock(&device->mutex);
 	if (!kgsl_active_count_get(device)) {
-		adreno_regread(device, offset, &regval);
+		kgsl_regread(device, offset, &regval);
 		kgsl_active_count_put(device);
 	}
 	mutex_unlock(&device->mutex);
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index c7b6b5b..ebfd837 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -30,19 +30,19 @@
 #define NUM_DWORDS_OF_RINGBUFFER_HISTORY 100
 
 struct pm_id_name {
-	uint32_t id;
+	enum adreno_regs id;
 	char name[9];
 };
 
 static const struct pm_id_name pm0_types[] = {
-	{REG_PA_SC_AA_CONFIG,		"RPASCAAC"},
-	{REG_RBBM_PM_OVERRIDE2,		"RRBBPMO2"},
-	{REG_SCRATCH_REG2,		"RSCRTRG2"},
-	{REG_SQ_GPR_MANAGEMENT,		"RSQGPRMN"},
-	{REG_SQ_INST_STORE_MANAGMENT,	"RSQINSTS"},
-	{REG_TC_CNTL_STATUS,		"RTCCNTLS"},
-	{REG_TP0_CHICKEN,		"RTP0CHCK"},
-	{REG_CP_TIMESTAMP,		"CP_TM_ST"},
+	{ADRENO_REG_PA_SC_AA_CONFIG,		"RPASCAAC"},
+	{ADRENO_REG_RBBM_PM_OVERRIDE2,		"RRBBPMO2"},
+	{ADRENO_REG_SCRATCH_REG2,		"RSCRTRG2"},
+	{ADRENO_REG_SQ_GPR_MANAGEMENT,		"RSQGPRMN"},
+	{ADRENO_REG_SQ_INST_STORE_MANAGMENT,	"RSQINSTS"},
+	{ADRENO_REG_TC_CNTL_STATUS,		"RTCCNTLS"},
+	{ADRENO_REG_TP0_CHICKEN,		"RTP0CHCK"},
+	{ADRENO_REG_CP_TIMESTAMP,		"CP_TM_ST"},
 };
 
 static const struct pm_id_name pm3_types[] = {
@@ -89,8 +89,9 @@
 	return (word >> 16) & 0x3FFF;
 }
 
-static bool adreno_is_pm4_type(uint32_t word)
+static bool adreno_is_pm4_type(struct kgsl_device *device, uint32_t word)
 {
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	int i;
 
 	if (word == INVALID_RB_CMD)
@@ -101,7 +102,8 @@
 
 	if ((word & (3<<30)) == CP_TYPE0_PKT) {
 		for (i = 0; i < ARRAY_SIZE(pm0_types); ++i) {
-			if ((word & 0x7FFF) == pm0_types[i].id)
+			if ((word & 0x7FFF) == adreno_getreg(adreno_dev,
+							pm0_types[i].id))
 				return 1;
 		}
 		return 0;
@@ -258,8 +260,8 @@
 	}
 }
 
-static void adreno_dump_rb_buffer(const void *buf, size_t len,
-		char *linebuf, size_t linebuflen, int *argp)
+static void adreno_dump_rb_buffer(struct kgsl_device *device, const void *buf,
+		size_t len, char *linebuf, size_t linebuflen, int *argp)
 {
 	const u32 *ptr4 = buf;
 	const int ngroups = len;
@@ -274,7 +276,7 @@
 			lx += scnprintf(linebuf + lx, linebuflen - lx, "  ");
 		else
 			nxsp = 1;
-		if (!*argp && adreno_is_pm4_type(ptr4[j])) {
+		if (!*argp && adreno_is_pm4_type(device, ptr4[j])) {
 			lx += scnprintf(linebuf + lx, linebuflen - lx,
 				"%s", adreno_pm4_name(ptr4[j]));
 			*argp = -(adreno_is_pm4_len(ptr4[j])+1);
@@ -326,18 +328,13 @@
 			hex_dump_to_buffer(ptr+i, linelen*4, rowsize*4, 4,
 				linebuf, sizeof(linebuf), 0);
 		else
-			adreno_dump_rb_buffer(ptr+i, linelen, linebuf,
+			adreno_dump_rb_buffer(device, ptr+i, linelen, linebuf,
 				sizeof(linebuf), &args);
 		KGSL_LOG_DUMP(device,
 			"RB: %4.4X:%s\n", (start+i)%size, linebuf);
 	}
 }
 
-struct log_field {
-	bool show;
-	const char *display;
-};
-
 static int adreno_dump_fields_line(struct kgsl_device *device,
 				 const char *start, char *str, int slen,
 				 const struct log_field **lines,
@@ -372,7 +369,7 @@
 	return num;
 }
 
-static void adreno_dump_fields(struct kgsl_device *device,
+void adreno_dump_fields(struct kgsl_device *device,
 			     const char *start, const struct log_field *lines,
 			     int num)
 {
@@ -392,329 +389,7 @@
 		sstr = "        ";
 	}
 }
-
-static void adreno_dump_a3xx(struct kgsl_device *device)
-{
-	unsigned int r1, r2, r3, rbbm_status;
-	unsigned int cp_stat, rb_count;
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-
-	kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status);
-	KGSL_LOG_DUMP(device, "RBBM:   STATUS   = %08X\n", rbbm_status);
-
-	{
-		struct log_field lines[] = {
-			{rbbm_status & BIT(0),  "HI busy     "},
-			{rbbm_status & BIT(1),  "CP ME busy  "},
-			{rbbm_status & BIT(2),  "CP PFP busy "},
-			{rbbm_status & BIT(14), "CP NRT busy "},
-			{rbbm_status & BIT(15), "VBIF busy   "},
-			{rbbm_status & BIT(16), "TSE busy    "},
-			{rbbm_status & BIT(17), "RAS busy    "},
-			{rbbm_status & BIT(18), "RB busy     "},
-			{rbbm_status & BIT(19), "PC DCALL bsy"},
-			{rbbm_status & BIT(20), "PC VSD busy "},
-			{rbbm_status & BIT(21), "VFD busy    "},
-			{rbbm_status & BIT(22), "VPC busy    "},
-			{rbbm_status & BIT(23), "UCHE busy   "},
-			{rbbm_status & BIT(24), "SP busy     "},
-			{rbbm_status & BIT(25), "TPL1 busy   "},
-			{rbbm_status & BIT(26), "MARB busy   "},
-			{rbbm_status & BIT(27), "VSC busy    "},
-			{rbbm_status & BIT(28), "ARB busy    "},
-			{rbbm_status & BIT(29), "HLSQ busy   "},
-			{rbbm_status & BIT(30), "GPU bsy noHC"},
-			{rbbm_status & BIT(31), "GPU busy    "},
-			};
-		adreno_dump_fields(device, " STATUS=", lines,
-				ARRAY_SIZE(lines));
-	}
-
-	kgsl_regread(device, REG_CP_RB_BASE, &r1);
-	kgsl_regread(device, REG_CP_RB_CNTL, &r2);
-	rb_count = 2 << (r2 & (BIT(6) - 1));
-	kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3);
-	KGSL_LOG_DUMP(device,
-		"CP_RB:  BASE = %08X | CNTL   = %08X | RPTR_ADDR = %08X"
-		"| rb_count = %08X\n", r1, r2, r3, rb_count);
-
-	kgsl_regread(device, REG_CP_RB_RPTR, &r1);
-	kgsl_regread(device, REG_CP_RB_WPTR, &r2);
-	kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3);
-	KGSL_LOG_DUMP(device,
-		"        RPTR = %08X | WPTR   = %08X | RPTR_WR   = %08X"
-		"\n", r1, r2, r3);
-
-	kgsl_regread(device, REG_CP_IB1_BASE, &r1);
-	kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2);
-	KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ  = %d\n", r1, r2);
-
-	kgsl_regread(device, REG_CP_ME_CNTL, &r1);
-	kgsl_regread(device, REG_CP_ME_STATUS, &r2);
-	KGSL_LOG_DUMP(device, "CP_ME:  CNTL = %08X | STATUS = %08X\n", r1, r2);
-
-	kgsl_regread(device, REG_CP_STAT, &cp_stat);
-	KGSL_LOG_DUMP(device, "CP_STAT      = %08X\n", cp_stat);
-#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL
-	{
-		struct log_field lns[] = {
-			{cp_stat & BIT(0), "WR_BSY     0"},
-			{cp_stat & BIT(1), "RD_RQ_BSY  1"},
-			{cp_stat & BIT(2), "RD_RTN_BSY 2"},
-		};
-		adreno_dump_fields(device, "    MIU=", lns, ARRAY_SIZE(lns));
-	}
-	{
-		struct log_field lns[] = {
-			{cp_stat & BIT(5), "RING_BUSY  5"},
-			{cp_stat & BIT(6), "NDRCTS_BSY 6"},
-			{cp_stat & BIT(7), "NDRCT2_BSY 7"},
-			{cp_stat & BIT(9), "ST_BUSY    9"},
-			{cp_stat & BIT(10), "BUSY      10"},
-		};
-		adreno_dump_fields(device, "    CSF=", lns, ARRAY_SIZE(lns));
-	}
-	{
-		struct log_field lns[] = {
-			{cp_stat & BIT(11), "RNG_Q_BSY 11"},
-			{cp_stat & BIT(12), "NDRCTS_Q_B12"},
-			{cp_stat & BIT(13), "NDRCT2_Q_B13"},
-			{cp_stat & BIT(16), "ST_QUEUE_B16"},
-			{cp_stat & BIT(17), "PFP_BUSY  17"},
-		};
-		adreno_dump_fields(device, "   RING=", lns, ARRAY_SIZE(lns));
-	}
-	{
-		struct log_field lns[] = {
-			{cp_stat & BIT(3), "RBIU_BUSY  3"},
-			{cp_stat & BIT(4), "RCIU_BUSY  4"},
-			{cp_stat & BIT(8), "EVENT_BUSY 8"},
-			{cp_stat & BIT(18), "MQ_RG_BSY 18"},
-			{cp_stat & BIT(19), "MQ_NDRS_BS19"},
-			{cp_stat & BIT(20), "MQ_NDR2_BS20"},
-			{cp_stat & BIT(21), "MIU_WC_STL21"},
-			{cp_stat & BIT(22), "CP_NRT_BSY22"},
-			{cp_stat & BIT(23), "3D_BUSY   23"},
-			{cp_stat & BIT(26), "ME_BUSY   26"},
-			{cp_stat & BIT(27), "RB_FFO_BSY27"},
-			{cp_stat & BIT(28), "CF_FFO_BSY28"},
-			{cp_stat & BIT(29), "PS_FFO_BSY29"},
-			{cp_stat & BIT(30), "VS_FFO_BSY30"},
-			{cp_stat & BIT(31), "CP_BUSY   31"},
-		};
-		adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns));
-	}
-#endif
-
-	kgsl_regread(device, A3XX_RBBM_INT_0_STATUS, &r1);
-	KGSL_LOG_DUMP(device, "MSTR_INT_SGNL = %08X\n", r1);
-	{
-		struct log_field ints[] = {
-			{r1 & BIT(0),  "RBBM_GPU_IDLE 0"},
-			{r1 & BIT(1),  "RBBM_AHB_ERROR 1"},
-			{r1 & BIT(2),  "RBBM_REG_TIMEOUT 2"},
-			{r1 & BIT(3),  "RBBM_ME_MS_TIMEOUT 3"},
-			{r1 & BIT(4),  "RBBM_PFP_MS_TIMEOUT 4"},
-			{r1 & BIT(5),  "RBBM_ATB_BUS_OVERFLOW 5"},
-			{r1 & BIT(6),  "VFD_ERROR 6"},
-			{r1 & BIT(7),  "CP_SW_INT 7"},
-			{r1 & BIT(8),  "CP_T0_PACKET_IN_IB 8"},
-			{r1 & BIT(9),  "CP_OPCODE_ERROR 9"},
-			{r1 & BIT(10), "CP_RESERVED_BIT_ERROR 10"},
-			{r1 & BIT(11), "CP_HW_FAULT 11"},
-			{r1 & BIT(12), "CP_DMA 12"},
-			{r1 & BIT(13), "CP_IB2_INT 13"},
-			{r1 & BIT(14), "CP_IB1_INT 14"},
-			{r1 & BIT(15), "CP_RB_INT 15"},
-			{r1 & BIT(16), "CP_REG_PROTECT_FAULT 16"},
-			{r1 & BIT(17), "CP_RB_DONE_TS 17"},
-			{r1 & BIT(18), "CP_VS_DONE_TS 18"},
-			{r1 & BIT(19), "CP_PS_DONE_TS 19"},
-			{r1 & BIT(20), "CACHE_FLUSH_TS 20"},
-			{r1 & BIT(21), "CP_AHB_ERROR_HALT 21"},
-			{r1 & BIT(24), "MISC_HANG_DETECT 24"},
-			{r1 & BIT(25), "UCHE_OOB_ACCESS 25"},
-		};
-		adreno_dump_fields(device, "INT_SGNL=", ints, ARRAY_SIZE(ints));
-	}
-}
-
-static void adreno_dump_a2xx(struct kgsl_device *device)
-{
-	unsigned int r1, r2, r3, rbbm_status;
-	unsigned int cp_stat, rb_count;
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-
-	kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status);
-
-	kgsl_regread(device, REG_RBBM_PM_OVERRIDE1, &r2);
-	kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &r3);
-	KGSL_LOG_DUMP(device, "RBBM:   STATUS   = %08X | PM_OVERRIDE1 = %08X | "
-		"PM_OVERRIDE2 = %08X\n", rbbm_status, r2, r3);
-
-	kgsl_regread(device, REG_RBBM_INT_CNTL, &r1);
-	kgsl_regread(device, REG_RBBM_INT_STATUS, &r2);
-	kgsl_regread(device, REG_RBBM_READ_ERROR, &r3);
-	KGSL_LOG_DUMP(device, "        INT_CNTL = %08X | INT_STATUS   = %08X | "
-		"READ_ERROR   = %08X\n", r1, r2, r3);
-
-	{
-		char cmdFifo[16];
-		struct log_field lines[] = {
-			{rbbm_status &  0x001F, cmdFifo},
-			{rbbm_status &  BIT(5), "TC busy     "},
-			{rbbm_status &  BIT(8), "HIRQ pending"},
-			{rbbm_status &  BIT(9), "CPRQ pending"},
-			{rbbm_status & BIT(10), "CFRQ pending"},
-			{rbbm_status & BIT(11), "PFRQ pending"},
-			{rbbm_status & BIT(12), "VGT 0DMA bsy"},
-			{rbbm_status & BIT(14), "RBBM WU busy"},
-			{rbbm_status & BIT(16), "CP NRT busy "},
-			{rbbm_status & BIT(18), "MH busy     "},
-			{rbbm_status & BIT(19), "MH chncy bsy"},
-			{rbbm_status & BIT(21), "SX busy     "},
-			{rbbm_status & BIT(22), "TPC busy    "},
-			{rbbm_status & BIT(24), "SC CNTX busy"},
-			{rbbm_status & BIT(25), "PA busy     "},
-			{rbbm_status & BIT(26), "VGT busy    "},
-			{rbbm_status & BIT(27), "SQ cntx1 bsy"},
-			{rbbm_status & BIT(28), "SQ cntx0 bsy"},
-			{rbbm_status & BIT(30), "RB busy     "},
-			{rbbm_status & BIT(31), "Grphs pp bsy"},
-		};
-		snprintf(cmdFifo, sizeof(cmdFifo), "CMD FIFO=%01X  ",
-			rbbm_status & 0xf);
-		adreno_dump_fields(device, " STATUS=", lines,
-				ARRAY_SIZE(lines));
-	}
-
-	kgsl_regread(device, REG_CP_RB_BASE, &r1);
-	kgsl_regread(device, REG_CP_RB_CNTL, &r2);
-	rb_count = 2 << (r2 & (BIT(6)-1));
-	kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3);
-	KGSL_LOG_DUMP(device,
-		"CP_RB:  BASE = %08X | CNTL   = %08X | RPTR_ADDR = %08X"
-		"| rb_count = %08X\n", r1, r2, r3, rb_count);
-	{
-		struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
-		if (rb->sizedwords != rb_count)
-			rb_count = rb->sizedwords;
-	}
-
-	kgsl_regread(device, REG_CP_RB_RPTR, &r1);
-	kgsl_regread(device, REG_CP_RB_WPTR, &r2);
-	kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3);
-	KGSL_LOG_DUMP(device,
-		"        RPTR = %08X | WPTR   = %08X | RPTR_WR   = %08X"
-		"\n", r1, r2, r3);
-
-	kgsl_regread(device, REG_CP_IB1_BASE, &r1);
-	kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2);
-	KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ  = %d\n", r1, r2);
-
-	kgsl_regread(device, REG_CP_IB2_BASE, &r1);
-	kgsl_regread(device, REG_CP_IB2_BUFSZ, &r2);
-	KGSL_LOG_DUMP(device, "CP_IB2: BASE = %08X | BUFSZ  = %d\n", r1, r2);
-
-	kgsl_regread(device, REG_CP_INT_CNTL, &r1);
-	kgsl_regread(device, REG_CP_INT_STATUS, &r2);
-	KGSL_LOG_DUMP(device, "CP_INT: CNTL = %08X | STATUS = %08X\n", r1, r2);
-
-	kgsl_regread(device, REG_CP_ME_CNTL, &r1);
-	kgsl_regread(device, REG_CP_ME_STATUS, &r2);
-	kgsl_regread(device, REG_MASTER_INT_SIGNAL, &r3);
-	KGSL_LOG_DUMP(device,
-		"CP_ME:  CNTL = %08X | STATUS = %08X | MSTR_INT_SGNL = "
-		"%08X\n", r1, r2, r3);
-
-	kgsl_regread(device, REG_CP_STAT, &cp_stat);
-	KGSL_LOG_DUMP(device, "CP_STAT      = %08X\n", cp_stat);
-#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL
-	{
-		struct log_field lns[] = {
-			{cp_stat &  BIT(0), "WR_BSY     0"},
-			{cp_stat &  BIT(1), "RD_RQ_BSY  1"},
-			{cp_stat &  BIT(2), "RD_RTN_BSY 2"},
-		};
-		adreno_dump_fields(device, "    MIU=", lns, ARRAY_SIZE(lns));
-	}
-	{
-		struct log_field lns[] = {
-			{cp_stat &  BIT(5), "RING_BUSY  5"},
-			{cp_stat &  BIT(6), "NDRCTS_BSY 6"},
-			{cp_stat &  BIT(7), "NDRCT2_BSY 7"},
-			{cp_stat &  BIT(9), "ST_BUSY    9"},
-			{cp_stat & BIT(10), "BUSY      10"},
-		};
-		adreno_dump_fields(device, "    CSF=", lns, ARRAY_SIZE(lns));
-	}
-	{
-		struct log_field lns[] = {
-			{cp_stat & BIT(11), "RNG_Q_BSY 11"},
-			{cp_stat & BIT(12), "NDRCTS_Q_B12"},
-			{cp_stat & BIT(13), "NDRCT2_Q_B13"},
-			{cp_stat & BIT(16), "ST_QUEUE_B16"},
-			{cp_stat & BIT(17), "PFP_BUSY  17"},
-		};
-		adreno_dump_fields(device, "   RING=", lns, ARRAY_SIZE(lns));
-	}
-	{
-		struct log_field lns[] = {
-			{cp_stat &  BIT(3), "RBIU_BUSY  3"},
-			{cp_stat &  BIT(4), "RCIU_BUSY  4"},
-			{cp_stat & BIT(18), "MQ_RG_BSY 18"},
-			{cp_stat & BIT(19), "MQ_NDRS_BS19"},
-			{cp_stat & BIT(20), "MQ_NDR2_BS20"},
-			{cp_stat & BIT(21), "MIU_WC_STL21"},
-			{cp_stat & BIT(22), "CP_NRT_BSY22"},
-			{cp_stat & BIT(23), "3D_BUSY   23"},
-			{cp_stat & BIT(26), "ME_BUSY   26"},
-			{cp_stat & BIT(29), "ME_WC_BSY 29"},
-			{cp_stat & BIT(30), "MIU_FF EM 30"},
-			{cp_stat & BIT(31), "CP_BUSY   31"},
-		};
-		adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns));
-	}
-#endif
-
-	kgsl_regread(device, REG_SCRATCH_REG0, &r1);
-	KGSL_LOG_DUMP(device, "SCRATCH_REG0       = %08X\n", r1);
-
-	kgsl_regread(device, REG_COHER_SIZE_PM4, &r1);
-	kgsl_regread(device, REG_COHER_BASE_PM4, &r2);
-	kgsl_regread(device, REG_COHER_STATUS_PM4, &r3);
-	KGSL_LOG_DUMP(device,
-		"COHER:  SIZE_PM4   = %08X | BASE_PM4 = %08X | STATUS_PM4"
-		" = %08X\n", r1, r2, r3);
-
-	kgsl_regread(device, MH_AXI_ERROR, &r1);
-	KGSL_LOG_DUMP(device, "MH:     AXI_ERROR  = %08X\n", r1);
-
-	kgsl_regread(device, MH_MMU_PAGE_FAULT, &r1);
-	kgsl_regread(device, MH_MMU_CONFIG, &r2);
-	kgsl_regread(device, MH_MMU_MPU_BASE, &r3);
-	KGSL_LOG_DUMP(device,
-		"MH_MMU: PAGE_FAULT = %08X | CONFIG   = %08X | MPU_BASE ="
-		" %08X\n", r1, r2, r3);
-
-	kgsl_regread(device, MH_MMU_MPU_END, &r1);
-	kgsl_regread(device, MH_MMU_VA_RANGE, &r2);
-	r3 = kgsl_mmu_get_current_ptbase(&device->mmu);
-	KGSL_LOG_DUMP(device,
-		"        MPU_END    = %08X | VA_RANGE = %08X | PT_BASE  ="
-		" %08X\n", r1, r2, r3);
-
-	KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ",
-		kgsl_mmu_get_ptsize(&device->mmu));
-
-	kgsl_regread(device, MH_MMU_TRAN_ERROR, &r1);
-	KGSL_LOG_DUMP(device, "        TRAN_ERROR = %08X\n", r1);
-
-	kgsl_regread(device, MH_INTERRUPT_MASK, &r1);
-	kgsl_regread(device, MH_INTERRUPT_STATUS, &r2);
-	KGSL_LOG_DUMP(device,
-		"MH_INTERRUPT: MASK = %08X | STATUS   = %08X\n", r1, r2);
-}
+EXPORT_SYMBOL(adreno_dump_fields);
 
 int adreno_dump(struct kgsl_device *device, int manual)
 {
@@ -745,26 +420,42 @@
 	if (device->pm_dump_enable) {
 		msm_clk_dump_debug_info();
 
-		if (adreno_is_a2xx(adreno_dev))
-			adreno_dump_a2xx(device);
-		else if (adreno_is_a3xx(adreno_dev))
-			adreno_dump_a3xx(device);
+		if (adreno_dev->gpudev->postmortem_dump)
+			adreno_dev->gpudev->postmortem_dump(adreno_dev);
 	}
 
-	kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status);
+	kgsl_regread(device,
+			adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS),
+			&rbbm_status);
 
 	pt_base = kgsl_mmu_get_current_ptbase(&device->mmu);
 	cur_pt_base = pt_base;
 
-	kgsl_regread(device, REG_CP_RB_BASE, &cp_rb_base);
-	kgsl_regread(device, REG_CP_RB_CNTL, &cp_rb_ctrl);
+	kgsl_regread(device,
+		adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_BASE),
+		&cp_rb_base);
+	kgsl_regread(device,
+		adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_CNTL),
+		&cp_rb_ctrl);
 	rb_count = 2 << (cp_rb_ctrl & (BIT(6) - 1));
-	kgsl_regread(device, REG_CP_RB_RPTR, &cp_rb_rptr);
-	kgsl_regread(device, REG_CP_RB_WPTR, &cp_rb_wptr);
-	kgsl_regread(device, REG_CP_IB1_BASE, &cp_ib1_base);
-	kgsl_regread(device, REG_CP_IB1_BUFSZ, &cp_ib1_bufsz);
-	kgsl_regread(device, REG_CP_IB2_BASE, &cp_ib2_base);
-	kgsl_regread(device, REG_CP_IB2_BUFSZ, &cp_ib2_bufsz);
+	kgsl_regread(device,
+		adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_RPTR),
+		&cp_rb_rptr);
+	kgsl_regread(device,
+		adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_WPTR),
+		&cp_rb_wptr);
+	kgsl_regread(device,
+		adreno_getreg(adreno_dev, ADRENO_REG_CP_IB1_BASE),
+		&cp_ib1_base);
+	kgsl_regread(device,
+		adreno_getreg(adreno_dev, ADRENO_REG_CP_IB1_BUFSZ),
+		&cp_ib1_bufsz);
+	kgsl_regread(device,
+		adreno_getreg(adreno_dev, ADRENO_REG_CP_IB2_BASE),
+		&cp_ib2_base);
+	kgsl_regread(device,
+		adreno_getreg(adreno_dev, ADRENO_REG_CP_IB2_BUFSZ),
+		&cp_ib2_bufsz);
 
 	/* If postmortem dump is not enabled, dump minimal set and return */
 	if (!device->pm_dump_enable) {
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 2d87263..fcef296 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -40,6 +40,7 @@
 
 void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb)
 {
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
 	BUG_ON(rb->wptr == 0);
 
 	/* Let the pwrscale policy know that new commands have
@@ -51,7 +52,7 @@
 	 */
 	mb();
 
-	adreno_regwrite(rb->device, REG_CP_RB_WPTR, rb->wptr);
+	adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_WPTR, rb->wptr);
 }
 
 static int
@@ -269,11 +270,11 @@
 	KGSL_DRV_INFO(device, "loading pm4 ucode version: %d\n",
 		adreno_dev->pm4_fw_version);
 
-	adreno_regwrite(device, REG_CP_DEBUG, CP_DEBUG_DEFAULT);
-	adreno_regwrite(device, REG_CP_ME_RAM_WADDR, addr);
+	adreno_writereg(adreno_dev, ADRENO_REG_CP_DEBUG, CP_DEBUG_DEFAULT);
+	adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_RAM_WADDR, addr);
 	for (i = start; i < adreno_dev->pm4_fw_size; i++)
-		adreno_regwrite(device, REG_CP_ME_RAM_DATA,
-			adreno_dev->pm4_fw[i]);
+		adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_RAM_DATA,
+					adreno_dev->pm4_fw[i]);
 
 	return 0;
 }
@@ -332,12 +333,11 @@
 	KGSL_DRV_INFO(device, "loading pfp ucode version: %d\n",
 			adreno_dev->pfp_fw_version);
 
-	adreno_regwrite(device, adreno_dev->gpudev->reg_cp_pfp_ucode_addr,
+	adreno_writereg(adreno_dev, ADRENO_REG_CP_PFP_UCODE_ADDR,
 						addr);
 	for (i = start; i < adreno_dev->pfp_fw_size; i++)
-		adreno_regwrite(device,
-		adreno_dev->gpudev->reg_cp_pfp_ucode_data,
-		adreno_dev->pfp_fw[i]);
+		adreno_writereg(adreno_dev, ADRENO_REG_CP_PFP_UCODE_DATA,
+						adreno_dev->pfp_fw[i]);
 
 	return 0;
 }
@@ -367,17 +367,17 @@
 			   (rb->sizedwords << 2));
 
 	if (adreno_is_a2xx(adreno_dev)) {
-		adreno_regwrite(device, REG_CP_RB_WPTR_BASE,
+		kgsl_regwrite(device, REG_CP_RB_WPTR_BASE,
 			(rb->memptrs_desc.gpuaddr
 			+ GSL_RB_MEMPTRS_WPTRPOLL_OFFSET));
 
 		/* setup WPTR delay */
-		adreno_regwrite(device, REG_CP_RB_WPTR_DELAY,
+		kgsl_regwrite(device, REG_CP_RB_WPTR_DELAY,
 			0 /*0x70000010 */);
 	}
 
 	/*setup REG_CP_RB_CNTL */
-	adreno_regread(device, REG_CP_RB_CNTL, &rb_cntl);
+	adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_CNTL, &rb_cntl);
 	cp_rb_cntl.val = rb_cntl;
 
 	/*
@@ -401,64 +401,66 @@
 	/* mem RPTR writebacks */
 	cp_rb_cntl.f.rb_no_update =  GSL_RB_CNTL_NO_UPDATE;
 
-	adreno_regwrite(device, REG_CP_RB_CNTL, cp_rb_cntl.val);
+	adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_CNTL, cp_rb_cntl.val);
 
-	adreno_regwrite(device, REG_CP_RB_BASE, rb->buffer_desc.gpuaddr);
+	adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_BASE,
+					rb->buffer_desc.gpuaddr);
 
-	adreno_regwrite(device, REG_CP_RB_RPTR_ADDR,
-			     rb->memptrs_desc.gpuaddr +
-			     GSL_RB_MEMPTRS_RPTR_OFFSET);
+	adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_RPTR_ADDR,
+				rb->memptrs_desc.gpuaddr +
+				GSL_RB_MEMPTRS_RPTR_OFFSET);
 
 	if (adreno_is_a3xx(adreno_dev)) {
 		/* enable access protection to privileged registers */
-		adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);
 
 		/* RBBM registers */
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);
 
 		/* CP registers */
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);
 
 		/* RB registers */
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);
 
 		/* VBIF registers */
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
 	}
 
 	if (adreno_is_a2xx(adreno_dev)) {
 		/* explicitly clear all cp interrupts */
-		adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
+		kgsl_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
 	}
 
 	/* setup scratch/timestamp */
-	adreno_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr +
-			     KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
-				     soptimestamp));
+	adreno_writereg(adreno_dev, ADRENO_REG_SCRATCH_ADDR,
+				device->memstore.gpuaddr +
+				KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
+					soptimestamp));
 
-	adreno_regwrite(device, REG_SCRATCH_UMSK,
+	adreno_writereg(adreno_dev, ADRENO_REG_SCRATCH_UMSK,
 			     GSL_RB_MEMPTRS_SCRATCH_MASK);
 
 	/* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
 	if (adreno_is_a305(adreno_dev) || adreno_is_a305c(adreno_dev) ||
 		adreno_is_a320(adreno_dev))
-		adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602);
+		kgsl_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602);
 	else if (adreno_is_a330(adreno_dev) || adreno_is_a305b(adreno_dev))
-		adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x003E2008);
+		kgsl_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x003E2008);
 
 	rb->wptr = 0;
 
 	/* clear ME_HALT to start micro engine */
-	adreno_regwrite(device, REG_CP_ME_CNTL, 0);
+	adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_CNTL, 0);
 
 	/* ME init is GPU specific, so jump into the sub-function */
 	status = adreno_dev->gpudev->rb_init(adreno_dev, rb);
@@ -529,7 +531,7 @@
 
 	if (rb->flags & KGSL_FLAGS_STARTED) {
 		if (adreno_is_a200(adreno_dev))
-			adreno_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000);
+			kgsl_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000);
 
 		rb->flags &= ~KGSL_FLAGS_STARTED;
 	}
@@ -704,7 +706,8 @@
 
 	/* scratchpad ts for fault tolerance */
 	GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
-			cp_type0_packet(REG_CP_TIMESTAMP, 1));
+		cp_type0_packet(adreno_getreg(adreno_dev,
+			ADRENO_REG_CP_TIMESTAMP), 1));
 	GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
 			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
 
@@ -1373,12 +1376,13 @@
 	int i;
 	unsigned int *ringcmds;
 	unsigned int rcmd_gpu;
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
 
 	if (!num_rb_contents)
 		return;
 
 	if (num_rb_contents > (rb->buffer_desc.size - rb->wptr)) {
-		adreno_regwrite(rb->device, REG_CP_RB_RPTR, 0);
+		adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_RPTR, 0);
 		BUG_ON(num_rb_contents > rb->buffer_desc.size);
 	}
 	ringcmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index d6ce298..b7c2237 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -467,6 +467,7 @@
 static void ib_parse_type0(struct kgsl_device *device, unsigned int *ptr,
 	phys_addr_t ptbase)
 {
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	int size = type0_pkt_size(*ptr);
 	int offset = type0_pkt_offset(*ptr);
 	int i;
@@ -475,9 +476,12 @@
 
 		/* Visiblity stream buffer */
 
-		if (offset >= A3XX_VSC_PIPE_DATA_ADDRESS_0 &&
-			offset <= A3XX_VSC_PIPE_DATA_LENGTH_7) {
-			int index = offset - A3XX_VSC_PIPE_DATA_ADDRESS_0;
+		if (offset >= adreno_getreg(adreno_dev,
+				ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0) &&
+			offset <= adreno_getreg(adreno_dev,
+					ADRENO_REG_VSC_PIPE_DATA_LENGTH_7)) {
+			int index = offset - adreno_getreg(adreno_dev,
+					ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0);
 
 			/* Each bank of address and length registers are
 			 * interleaved with an empty register:
@@ -495,9 +499,13 @@
 				vsc_pipe[index / 3].base = ptr[i + 1];
 			else if ((index % 3) == 1)
 				vsc_pipe[index / 3].size = ptr[i + 1];
-		} else if ((offset >= A3XX_VFD_FETCH_INSTR_0_0) &&
-			(offset <= A3XX_VFD_FETCH_INSTR_1_F)) {
-			int index = offset - A3XX_VFD_FETCH_INSTR_0_0;
+		} else if ((offset >= adreno_getreg(adreno_dev,
+					ADRENO_REG_VFD_FETCH_INSTR_0_0)) &&
+			(offset <= adreno_getreg(adreno_dev,
+					ADRENO_REG_VFD_FETCH_INSTR_1_F))) {
+			int index = offset -
+				adreno_getreg(adreno_dev,
+					ADRENO_REG_VFD_FETCH_INSTR_0_0);
 
 			/*
 			 * FETCH_INSTR_0_X and FETCH_INSTR_1_X banks are
@@ -516,29 +524,30 @@
 			 * buffer sizes
 			 */
 
-			switch (offset) {
-			case A3XX_VFD_CONTROL_0:
+			if (offset ==
+				adreno_getreg(adreno_dev,
+						ADRENO_REG_VFD_CONTROL_0))
 				vfd_control_0 = ptr[i + 1];
-				break;
-			case A3XX_VFD_INDEX_MAX:
+			else if (offset ==
+				adreno_getreg(adreno_dev,
+						ADRENO_REG_VFD_INDEX_MAX))
 				vfd_index_max = ptr[i + 1];
-				break;
-			case A3XX_VSC_SIZE_ADDRESS:
+			else if (offset ==
+				adreno_getreg(adreno_dev,
+						ADRENO_REG_VSC_SIZE_ADDRESS))
 				vsc_size_address = ptr[i + 1];
-				break;
-			case A3XX_SP_VS_PVT_MEM_ADDR_REG:
+			else if (offset == adreno_getreg(adreno_dev,
+					ADRENO_REG_SP_VS_PVT_MEM_ADDR_REG))
 				sp_vs_pvt_mem_addr = ptr[i + 1];
-				break;
-			case A3XX_SP_FS_PVT_MEM_ADDR_REG:
+			else if (offset == adreno_getreg(adreno_dev,
+					ADRENO_REG_SP_FS_PVT_MEM_ADDR_REG))
 				sp_fs_pvt_mem_addr = ptr[i + 1];
-				break;
-			case A3XX_SP_VS_OBJ_START_REG:
+			else if (offset == adreno_getreg(adreno_dev,
+					ADRENO_REG_SP_VS_OBJ_START_REG))
 				sp_vs_obj_start_reg = ptr[i + 1];
-				break;
-			case A3XX_SP_FS_OBJ_START_REG:
+			else if (offset == adreno_getreg(adreno_dev,
+					ADRENO_REG_SP_FS_OBJ_START_REG))
 				sp_fs_obj_start_reg = ptr[i + 1];
-				break;
-			}
 		}
 	}
 }
@@ -629,6 +638,7 @@
 static inline int parse_ib(struct kgsl_device *device, phys_addr_t ptbase,
 		unsigned int gpuaddr, unsigned int dwords)
 {
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	unsigned int ib1base, ib2base;
 	int ret = 0;
 
@@ -638,8 +648,8 @@
 	 * it in the dynamic list
 	 */
 
-	kgsl_regread(device, REG_CP_IB1_BASE, &ib1base);
-	kgsl_regread(device, REG_CP_IB2_BASE, &ib2base);
+	adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ib1base);
+	adreno_readreg(adreno_dev, ADRENO_REG_CP_IB2_BASE, &ib2base);
 
 	if (gpuaddr == ib1base || gpuaddr == ib2base)
 		push_object(device, SNAPSHOT_OBJ_TYPE_IB, ptbase,
@@ -667,10 +677,10 @@
 	ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
 
 	/* Get the current read pointers for the RB */
-	kgsl_regread(device, REG_CP_RB_RPTR, &rptr);
+	adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &rptr);
 
 	/* Address of the last processed IB */
-	kgsl_regread(device, REG_CP_IB1_BASE, &ibbase);
+	adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ibbase);
 
 	/*
 	 * Figure out the window of ringbuffer data to dump.  First we need to
@@ -998,8 +1008,8 @@
 	 * want to be double plus sure.
 	 */
 
-	kgsl_regread(device, REG_CP_IB1_BASE, &ibbase);
-	kgsl_regread(device, REG_CP_IB1_BUFSZ, &ibsize);
+	adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ibbase);
+	adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BUFSZ, &ibsize);
 
 	/*
 	 * The problem is that IB size from the register is the unprocessed size
@@ -1016,8 +1026,8 @@
 			"Dumping %x dwords of the buffer.\n", ibsize);
 	}
 
-	kgsl_regread(device, REG_CP_IB2_BASE, &ibbase);
-	kgsl_regread(device, REG_CP_IB2_BUFSZ, &ibsize);
+	adreno_readreg(adreno_dev, ADRENO_REG_CP_IB2_BASE, &ibbase);
+	adreno_readreg(adreno_dev, ADRENO_REG_CP_IB2_BUFSZ, &ibsize);
 
 	/*
 	 * Add the last parsed IB2 to the list. The IB2 should be found as we
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index e62dac9..5c454f1 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2370,7 +2370,8 @@
 		entries[actual_count++] = entry;
 
 		/* If we exceed the breakeven point, flush the entire cache */
-		if (op_size >= kgsl_driver.full_cache_threshold &&
+		if (kgsl_driver.full_cache_threshold != 0 &&
+		    op_size >= kgsl_driver.full_cache_threshold &&
 		    param->op == KGSL_GPUMEM_CACHE_FLUSH) {
 			full_flush = true;
 			break;
@@ -2429,6 +2430,7 @@
 	int result;
 	struct kgsl_process_private *private = dev_priv->process_priv;
 	struct kgsl_mem_entry *entry;
+	int align;
 
 	/*
 	 * Mask off unknown flags from userspace. This way the caller can
@@ -2440,6 +2442,16 @@
 		| KGSL_MEMALIGN_MASK
 		| KGSL_MEMFLAGS_USE_CPU_MAP;
 
+	/* Cap the alignment bits to the highest number we can handle */
+
+	align = (flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT;
+	if (align >= 32) {
+		KGSL_CORE_ERR("Alignment too big, restricting to 2^31\n");
+
+		flags &= ~KGSL_MEMALIGN_MASK;
+		flags |= (31 << KGSL_MEMALIGN_SHIFT) & KGSL_MEMALIGN_MASK;
+	}
+
 	entry = kgsl_mem_entry_create();
 	if (entry == NULL)
 		return -ENOMEM;
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 48c7301..abb7c35 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -70,7 +70,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s ctx=%u ib=0x%u numibs=%u timestamp=0x%x "
+		"d_name=%s ctx=%u ib=0x%u numibs=%u ts=%u "
 		"flags=0x%x(%s) result=%d type=%s",
 		__get_str(device_name),
 		__entry->drawctxt_id,
@@ -116,7 +116,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s context_id=%u type=%u timestamp=0x%x",
+		"d_name=%s context_id=%u type=%u ts=%u",
 		__get_str(device_name),
 		__entry->context_id,
 		__entry->type,
@@ -154,7 +154,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s context_id=%u curr_ts=0x%x timestamp=0x%x timeout=%u",
+		"d_name=%s ctx=%u curr_ts=%u ts=%u timeout=%u",
 		__get_str(device_name),
 		__entry->context_id,
 		__entry->curr_ts,
@@ -186,7 +186,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s curr_ts=0x%x result=%d",
+		"d_name=%s curr_ts=%u result=%d",
 		__get_str(device_name),
 		__entry->curr_ts,
 		__entry->result
@@ -209,7 +209,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s %s",
+		"d_name=%s flag=%s",
 		__get_str(device_name),
 		__entry->on ? "on" : "off"
 	)
@@ -304,7 +304,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s busy=%d elapsed=%d",
+		"d_name=%s busy=%u elapsed=%d",
 		__get_str(device_name),
 		__entry->busy,
 		__entry->elapsed
@@ -327,7 +327,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s %s",
+		"d_name=%s state=%s",
 		__get_str(device_name),
 		kgsl_pwrstate_to_str(__entry->state)
 	)
@@ -369,7 +369,7 @@
 	),
 
 	TP_printk(
-		"gpuaddr=0x%08x size=%d tgid=%d usage=%s id=%d flags=0x%08x",
+		"gpuaddr=0x%08x size=%u tgid=%u usage=%s id=%u flags=0x%08x",
 		__entry->gpuaddr, __entry->size, __entry->tgid,
 		__entry->usage, __entry->id, __entry->flags
 	)
@@ -401,7 +401,7 @@
 	),
 
 	TP_printk(
-		"useraddr=%lx gpuaddr=0x%08x size=%d usage=%s id=%d"
+		"useraddr=0x%lx gpuaddr=0x%08x size=%u usage=%s id=%u"
 		" flags=0x%08x",
 		__entry->useraddr, __entry->gpuaddr, __entry->size,
 		__entry->usage, __entry->id, __entry->flags
@@ -432,7 +432,7 @@
 	),
 
 	TP_printk(
-		"id=%d hint=0x%lx len=%ld addr=0x%lx",
+		"id=%u hint=0x%lx len=%lu addr=0x%lx",
 		__entry->id, __entry->hint, __entry->len, __entry->addr
 	)
 );
@@ -465,7 +465,7 @@
 	),
 
 	TP_printk(
-		"gpuaddr=0x%08x size=%d type=%d fd=%d tgid=%d usage=%s id=%d",
+		"gpuaddr=0x%08x size=%u type=%d fd=%d tgid=%u usage=%s id=%u",
 		__entry->gpuaddr, __entry->size,
 		__entry->type, __entry->fd, __entry->tgid,
 		__entry->usage, __entry->id
@@ -499,7 +499,7 @@
 	),
 
 	TP_printk(
-		"gpuaddr=0x%08x size=%d type=%d tgid=%d usage=%s id=%d",
+		"gpuaddr=0x%08x size=%u type=%d tgid=%u usage=%s id=%u",
 		__entry->gpuaddr, __entry->size, __entry->type,
 		__entry->tgid, __entry->usage, __entry->id
 	)
@@ -531,7 +531,7 @@
 	),
 
 	TP_printk(
-		"gpuaddr=0x%08x size=%d tgid=%d usage=%s id=%d op=%c%c",
+		"gpuaddr=0x%08x size=%u tgid=%u usage=%s id=%u op=%c%c",
 		__entry->gpuaddr, __entry->size, __entry->tgid, __entry->usage,
 		__entry->id,
 		(__entry->op & KGSL_GPUMEM_CACHE_CLEAN) ? 'c' : '.',
@@ -599,8 +599,8 @@
 	),
 
 	TP_printk(
-		"d_name=%s gpuaddr=0x%08x size=%d type=%d usage=%s id=%d ctx=%u"
-		" curr_ts=0x%x free_ts=0x%x",
+		"d_name=%s gpuaddr=0x%08x size=%u type=%d usage=%s id=%u ctx=%u"
+		" curr_ts=%u free_ts=%u",
 		__get_str(device_name),
 		__entry->gpuaddr,
 		__entry->size,
@@ -700,7 +700,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s page=0x%08x pt=%d op=%s",
+		"d_name=%s page=0x%08x pt=%u op=%s",
 		__get_str(device_name), __entry->page, __entry->pt,
 		__get_str(op)
 	)
@@ -726,7 +726,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s reg=%x value=%x",
+		"d_name=%s reg=0x%x value=0x%x",
 		__get_str(device_name), __entry->offset, __entry->value
 	)
 );
@@ -743,7 +743,7 @@
 			__entry->timestamp = timestamp;
 		),
 		TP_printk(
-			"ctx=%d ts=%d",
+			"ctx=%u ts=%u",
 			__entry->id, __entry->timestamp)
 );
 
@@ -762,7 +762,7 @@
 			__entry->age = age;
 		),
 		TP_printk(
-			"ctx=%d ts=%d age=%u",
+			"ctx=%u ts=%u age=%u",
 			__entry->id, __entry->ts, __entry->age)
 );
 
@@ -785,7 +785,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s active_cnt=%x func=%pf",
+		"d_name=%s active_cnt=%u func=%pf",
 		__get_str(device_name), __entry->count, (void *) __entry->ip
 	)
 );
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index 204ad94..dd2e5d8 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -144,6 +144,13 @@
 	y = le16_to_cpu(acc_data[tj9->pdata.axis_map_y]);
 	z = le16_to_cpu(acc_data[tj9->pdata.axis_map_z]);
 
+	/* 8 bits output mode support */
+	if (!(tj9->ctrl_reg1 & RES_12BIT)) {
+		x <<= 4;
+		y <<= 4;
+		z <<= 4;
+	}
+
 	x >>= tj9->shift;
 	y >>= tj9->shift;
 	z >>= tj9->shift;
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 175328e..b9c4cae 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -843,6 +843,7 @@
 void print_ctx_regs(struct msm_iommu_context_reg regs[])
 {
 	uint32_t fsr = regs[DUMP_REG_FSR].val;
+	u64 ttbr;
 
 	pr_err("FAR    = %016llx\n",
 		COMBINE_DUMP_REG(
@@ -865,8 +866,22 @@
 
 	pr_err("FSYNR0 = %08x    FSYNR1 = %08x\n",
 		 regs[DUMP_REG_FSYNR0].val, regs[DUMP_REG_FSYNR1].val);
-	pr_err("TTBR0  = %08x    TTBR1  = %08x\n",
-		 regs[DUMP_REG_TTBR0].val, regs[DUMP_REG_TTBR1].val);
+
+	ttbr = COMBINE_DUMP_REG(regs[DUMP_REG_TTBR0_1].val,
+				regs[DUMP_REG_TTBR0_0].val);
+	if (regs[DUMP_REG_TTBR0_1].valid)
+		pr_err("TTBR0  = %016llx\n", ttbr);
+	else
+		pr_err("TTBR0  = %016llx (32b)\n", ttbr);
+
+	ttbr = COMBINE_DUMP_REG(regs[DUMP_REG_TTBR1_1].val,
+				regs[DUMP_REG_TTBR1_0].val);
+
+	if (regs[DUMP_REG_TTBR1_1].valid)
+		pr_err("TTBR1  = %016llx\n", ttbr);
+	else
+		pr_err("TTBR1  = %016llx (32b)\n", ttbr);
+
 	pr_err("SCTLR  = %08x    ACTLR  = %08x\n",
 		 regs[DUMP_REG_SCTLR].val, regs[DUMP_REG_ACTLR].val);
 	pr_err("PRRR   = %08x    NMRR   = %08x\n",
@@ -958,27 +973,30 @@
 	return __pa(priv->pt.fl_table);
 }
 
-#define DUMP_REG_INIT(dump_reg, cb_reg)				\
+#define DUMP_REG_INIT(dump_reg, cb_reg, mbp)			\
 	do {							\
 		dump_regs_tbl[dump_reg].key = cb_reg;		\
 		dump_regs_tbl[dump_reg].name = #cb_reg;		\
+		dump_regs_tbl[dump_reg].must_be_present = mbp;	\
 	} while (0)
 
 static void msm_iommu_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);
+	DUMP_REG_INIT(DUMP_REG_FAR0,	CB_FAR,       1);
+	DUMP_REG_INIT(DUMP_REG_FAR1,	CB_FAR + 4,   1);
+	DUMP_REG_INIT(DUMP_REG_PAR0,	CB_PAR,       1);
+	DUMP_REG_INIT(DUMP_REG_PAR1,	CB_PAR + 4,   1);
+	DUMP_REG_INIT(DUMP_REG_FSR,	CB_FSR,       1);
+	DUMP_REG_INIT(DUMP_REG_FSYNR0,	CB_FSYNR0,    1);
+	DUMP_REG_INIT(DUMP_REG_FSYNR1,	CB_FSYNR1,    1);
+	DUMP_REG_INIT(DUMP_REG_TTBR0_0,	CB_TTBR0,     1);
+	DUMP_REG_INIT(DUMP_REG_TTBR0_1,	CB_TTBR0 + 4, 0);
+	DUMP_REG_INIT(DUMP_REG_TTBR1_0,	CB_TTBR1,     1);
+	DUMP_REG_INIT(DUMP_REG_TTBR1_1,	CB_TTBR1 + 4, 0);
+	DUMP_REG_INIT(DUMP_REG_SCTLR,	CB_SCTLR,     1);
+	DUMP_REG_INIT(DUMP_REG_ACTLR,	CB_ACTLR,     1);
+	DUMP_REG_INIT(DUMP_REG_PRRR,	CB_PRRR,      1);
+	DUMP_REG_INIT(DUMP_REG_NMRR,	CB_NMRR,      1);
 }
 
 static struct iommu_ops msm_iommu_ops = {
diff --git a/drivers/iommu/msm_iommu_dev-v1.c b/drivers/iommu/msm_iommu_dev-v1.c
index 119a126..bbbe77b 100644
--- a/drivers/iommu/msm_iommu_dev-v1.c
+++ b/drivers/iommu/msm_iommu_dev-v1.c
@@ -32,6 +32,14 @@
 
 static struct of_device_id msm_iommu_v1_ctx_match_table[];
 
+#ifdef CONFIG_IOMMU_LPAE
+static const char *BFB_REG_NODE_NAME = "qcom,iommu-lpae-bfb-regs";
+static const char *BFB_DATA_NODE_NAME = "qcom,iommu-lpae-bfb-data";
+#else
+static const char *BFB_REG_NODE_NAME = "qcom,iommu-bfb-regs";
+static const char *BFB_DATA_NODE_NAME = "qcom,iommu-bfb-data";
+#endif
+
 static int msm_iommu_parse_bfb_settings(struct platform_device *pdev,
 				    struct msm_iommu_drvdata *drvdata)
 {
@@ -40,17 +48,17 @@
 	int ret;
 
 	/*
-	 * It is not valid for a device to have the qcom,iommu-bfb-regs
-	 * property but not the qcom,iommu-bfb-data property, and vice versa.
+	 * It is not valid for a device to have the BFB_REG_NODE_NAME
+	 * property but not the BFB_DATA_NODE_NAME property, and vice versa.
 	 */
-	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-bfb-regs", &nreg)) {
-		if (of_get_property(pdev->dev.of_node, "qcom,iommu-bfb-data",
+	if (!of_get_property(pdev->dev.of_node, BFB_REG_NODE_NAME, &nreg)) {
+		if (of_get_property(pdev->dev.of_node, BFB_DATA_NODE_NAME,
 				    &nval))
 			return -EINVAL;
 		return 0;
 	}
 
-	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-bfb-data", &nval))
+	if (!of_get_property(pdev->dev.of_node, BFB_DATA_NODE_NAME, &nval))
 		return -EINVAL;
 
 	if (nreg >= sizeof(bfb_settings->regs))
@@ -68,14 +76,14 @@
 		return -ENOMEM;
 
 	ret = of_property_read_u32_array(pdev->dev.of_node,
-					 "qcom,iommu-bfb-regs",
+					 BFB_REG_NODE_NAME,
 					 bfb_settings->regs,
 					 nreg / sizeof(*bfb_settings->regs));
 	if (ret)
 		return ret;
 
 	ret = of_property_read_u32_array(pdev->dev.of_node,
-					 "qcom,iommu-bfb-data",
+					 BFB_DATA_NODE_NAME,
 					 bfb_settings->data,
 					 nval / sizeof(*bfb_settings->data));
 	if (ret)
diff --git a/drivers/iommu/msm_iommu_pagetable.c b/drivers/iommu/msm_iommu_pagetable.c
index b871a5a..1e4bff8 100644
--- a/drivers/iommu/msm_iommu_pagetable.c
+++ b/drivers/iommu/msm_iommu_pagetable.c
@@ -24,6 +24,49 @@
 #include <trace/events/kmem.h>
 #include "msm_iommu_pagetable.h"
 
+#define NUM_FL_PTE      4096
+#define NUM_SL_PTE      256
+#define NUM_TEX_CLASS   8
+
+/* First-level page table bits */
+#define FL_BASE_MASK            0xFFFFFC00
+#define FL_TYPE_TABLE           (1 << 0)
+#define FL_TYPE_SECT            (2 << 0)
+#define FL_SUPERSECTION         (1 << 18)
+#define FL_AP0                  (1 << 10)
+#define FL_AP1                  (1 << 11)
+#define FL_AP2                  (1 << 15)
+#define FL_SHARED               (1 << 16)
+#define FL_BUFFERABLE           (1 << 2)
+#define FL_CACHEABLE            (1 << 3)
+#define FL_TEX0                 (1 << 12)
+#define FL_OFFSET(va)           (((va) & 0xFFF00000) >> 20)
+#define FL_NG                   (1 << 17)
+
+/* Second-level page table bits */
+#define SL_BASE_MASK_LARGE      0xFFFF0000
+#define SL_BASE_MASK_SMALL      0xFFFFF000
+#define SL_TYPE_LARGE           (1 << 0)
+#define SL_TYPE_SMALL           (2 << 0)
+#define SL_AP0                  (1 << 4)
+#define SL_AP1                  (2 << 4)
+#define SL_AP2                  (1 << 9)
+#define SL_SHARED               (1 << 10)
+#define SL_BUFFERABLE           (1 << 2)
+#define SL_CACHEABLE            (1 << 3)
+#define SL_TEX0                 (1 << 6)
+#define SL_OFFSET(va)           (((va) & 0xFF000) >> 12)
+#define SL_NG                   (1 << 11)
+
+/* Memory type and cache policy attributes */
+#define MT_SO                   0
+#define MT_DEV                  1
+#define MT_NORMAL               2
+#define CP_NONCACHED            0
+#define CP_WB_WA                1
+#define CP_WT                   2
+#define CP_WB_NWA               3
+
 /* Sharability attributes of MSM IOMMU mappings */
 #define MSM_IOMMU_ATTR_NON_SH		0x0
 #define MSM_IOMMU_ATTR_SH		0x4
@@ -36,6 +79,13 @@
 
 static int msm_iommu_tex_class[4];
 
+/* TEX Remap Registers */
+#define NMRR_ICP(nmrr, n) (((nmrr) & (3 << ((n) * 2))) >> ((n) * 2))
+#define NMRR_OCP(nmrr, n) (((nmrr) & (3 << ((n) * 2 + 16))) >> ((n) * 2 + 16))
+
+#define PRRR_NOS(prrr, n) ((prrr) & (1 << ((n) + 24)) ? 1 : 0)
+#define PRRR_MT(prrr, n)  ((((prrr) & (3 << ((n) * 2))) >> ((n) * 2)))
+
 static inline void clean_pte(unsigned long *start, unsigned long *end,
 				int redirect)
 {
@@ -284,79 +334,8 @@
 size_t msm_iommu_pagetable_unmap(struct msm_iommu_pt *pt, unsigned long va,
 				size_t len)
 {
-	unsigned long *fl_pte;
-	unsigned long fl_offset;
-	unsigned long *sl_table;
-	unsigned long *sl_pte;
-	unsigned long sl_offset;
-	int i, ret = 0;
-
-	if (len != SZ_16M && len != SZ_1M &&
-	    len != SZ_64K && len != SZ_4K) {
-		pr_debug("Bad length: %d\n", len);
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (!pt->fl_table) {
-		pr_debug("Null page table\n");
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	fl_offset = FL_OFFSET(va);		/* Upper 12 bits */
-	fl_pte = pt->fl_table + fl_offset;	/* int pointers, 4 bytes */
-
-	if (*fl_pte == 0) {
-		pr_debug("First level PTE is 0\n");
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	/* Unmap supersection */
-	if (len == SZ_16M) {
-		for (i = 0; i < 16; i++)
-			*(fl_pte+i) = 0;
-
-		clean_pte(fl_pte, fl_pte + 16, pt->redirect);
-	}
-
-	if (len == SZ_1M) {
-		*fl_pte = 0;
-		clean_pte(fl_pte, fl_pte + 1, pt->redirect);
-	}
-
-	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
-	sl_offset = SL_OFFSET(va);
-	sl_pte = sl_table + sl_offset;
-
-	if (len == SZ_64K) {
-		for (i = 0; i < 16; i++)
-			*(sl_pte+i) = 0;
-
-		clean_pte(sl_pte, sl_pte + 16, pt->redirect);
-	}
-
-	if (len == SZ_4K) {
-		*sl_pte = 0;
-		clean_pte(sl_pte, sl_pte + 1, pt->redirect);
-	}
-
-	if (len == SZ_4K || len == SZ_64K) {
-		int used = 0;
-
-		for (i = 0; i < NUM_SL_PTE; i++)
-			if (sl_table[i])
-				used = 1;
-		if (!used) {
-			free_page((unsigned long)sl_table);
-			*fl_pte = 0;
-			clean_pte(fl_pte, fl_pte + 1, pt->redirect);
-		}
-	}
-
-fail:
-	return ret;
+	msm_iommu_pagetable_unmap_range(pt, va, len);
+	return len;
 }
 
 static phys_addr_t get_phys_addr(struct scatterlist *sg)
diff --git a/drivers/iommu/msm_iommu_pagetable.h b/drivers/iommu/msm_iommu_pagetable.h
index 7513aa5..a5ea318 100644
--- a/drivers/iommu/msm_iommu_pagetable.h
+++ b/drivers/iommu/msm_iommu_pagetable.h
@@ -13,56 +13,6 @@
 #ifndef __ARCH_ARM_MACH_MSM_IOMMU_PAGETABLE_H
 #define __ARCH_ARM_MACH_MSM_IOMMU_PAGETABLE_H
 
-#define NUM_FL_PTE      4096
-#define NUM_SL_PTE      256
-#define NUM_TEX_CLASS   8
-
-/* First-level page table bits */
-#define FL_BASE_MASK            0xFFFFFC00
-#define FL_TYPE_TABLE           (1 << 0)
-#define FL_TYPE_SECT            (2 << 0)
-#define FL_SUPERSECTION         (1 << 18)
-#define FL_AP0                  (1 << 10)
-#define FL_AP1                  (1 << 11)
-#define FL_AP2                  (1 << 15)
-#define FL_SHARED               (1 << 16)
-#define FL_BUFFERABLE           (1 << 2)
-#define FL_CACHEABLE            (1 << 3)
-#define FL_TEX0                 (1 << 12)
-#define FL_OFFSET(va)           (((va) & 0xFFF00000) >> 20)
-#define FL_NG                   (1 << 17)
-
-/* Second-level page table bits */
-#define SL_BASE_MASK_LARGE      0xFFFF0000
-#define SL_BASE_MASK_SMALL      0xFFFFF000
-#define SL_TYPE_LARGE           (1 << 0)
-#define SL_TYPE_SMALL           (2 << 0)
-#define SL_AP0                  (1 << 4)
-#define SL_AP1                  (2 << 4)
-#define SL_AP2                  (1 << 9)
-#define SL_SHARED               (1 << 10)
-#define SL_BUFFERABLE           (1 << 2)
-#define SL_CACHEABLE            (1 << 3)
-#define SL_TEX0                 (1 << 6)
-#define SL_OFFSET(va)           (((va) & 0xFF000) >> 12)
-#define SL_NG                   (1 << 11)
-
-/* Memory type and cache policy attributes */
-#define MT_SO                   0
-#define MT_DEV                  1
-#define MT_NORMAL               2
-#define CP_NONCACHED            0
-#define CP_WB_WA                1
-#define CP_WT                   2
-#define CP_WB_NWA               3
-
-/* TEX Remap Registers */
-#define NMRR_ICP(nmrr, n) (((nmrr) & (3 << ((n) * 2))) >> ((n) * 2))
-#define NMRR_OCP(nmrr, n) (((nmrr) & (3 << ((n) * 2 + 16))) >> ((n) * 2 + 16))
-
-#define PRRR_NOS(prrr, n) ((prrr) & (1 << ((n) + 24)) ? 1 : 0)
-#define PRRR_MT(prrr, n)  ((((prrr) & (3 << ((n) * 2))) >> ((n) * 2)))
-
 #define MRC(reg, processor, op1, crn, crm, op2)                         \
 __asm__ __volatile__ (                                                  \
 "   mrc   "   #processor "," #op1 ", %0,"  #crn "," #crm "," #op2 "\n"  \
@@ -71,7 +21,10 @@
 #define RCP15_PRRR(reg)   MRC(reg, p15, 0, c10, c2, 0)
 #define RCP15_NMRR(reg)   MRC(reg, p15, 0, c10, c2, 1)
 
-struct iommu_pt;
+#define RCP15_MAIR0(reg)   MRC(reg, p15, 0, c10, c2, 0)
+#define RCP15_MAIR1(reg)   MRC(reg, p15, 0, c10, c2, 1)
+
+struct msm_iommu_pt;
 
 void msm_iommu_pagetable_init(void);
 int msm_iommu_pagetable_alloc(struct msm_iommu_pt *pt);
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 8d2cc8f..474efdf 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -172,9 +172,13 @@
 
 	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;
+			if (dump_regs_tbl[i].must_be_present) {
+				pr_err("Register missing from dump: %s, %lx\n",
+					dump_regs_tbl[i].name,
+					dump_regs_tbl[i].key);
+				ret = 1;
+			}
+			ctx_regs[i].val = 0;
 		}
 	}
 
@@ -462,7 +466,8 @@
 	 * 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));
+		sizeof(unsigned long) * 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));
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index f13e55a..159c6f6 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -300,6 +300,16 @@
 	  To compile this driver as a module, choose M here: the module will
 	  be called leds-qpnp.
 
+config LEDS_MSM_GPIO_FLASH
+	tristate "Support for GPIO Flash LEDs"
+	depends on GPIO_MSM_V3
+	help
+	  This driver supports the leds functionality of GPIO Flash LED. It
+	  includes flash mode and torch mode.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called leds-gpio-flash.
+
 config LEDS_WM831X_STATUS
 	tristate "LED support for status LEDs on WM831x PMICs"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index c688898..f20a0d0 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -54,6 +54,7 @@
 obj-$(CONFIG_LEDS_QCIBL)		+= leds-qci-backlight.o
 obj-$(CONFIG_LEDS_MSM_PDM)		+= leds-msm-pdm.o
 obj-$(CONFIG_LEDS_MSM_TRICOLOR)		+= leds-msm-tricolor.o
+obj-$(CONFIG_LEDS_MSM_GPIO_FLASH)	+= leds-msm-gpio-flash.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
diff --git a/drivers/leds/leds-msm-gpio-flash.c b/drivers/leds/leds-msm-gpio-flash.c
new file mode 100644
index 0000000..60d4681
--- /dev/null
+++ b/drivers/leds/leds-msm-gpio-flash.c
@@ -0,0 +1,208 @@
+
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/printk.h>
+
+#define LED_GPIO_FLASH_DRIVER_NAME	"qcom,leds-gpio-flash"
+#define LED_TRIGGER_DEFAULT		"none"
+
+struct led_gpio_flash_data {
+	int flash_en;
+	int flash_now;
+	int brightness;
+	struct led_classdev cdev;
+};
+
+static struct of_device_id led_gpio_flash_of_match[] = {
+	{.compatible = LED_GPIO_FLASH_DRIVER_NAME,},
+	{},
+};
+
+static void led_gpio_brightness_set(struct led_classdev *led_cdev,
+				    enum led_brightness value)
+{
+	int rc = 0;
+	struct led_gpio_flash_data *flash_led =
+	    container_of(led_cdev, struct led_gpio_flash_data, cdev);
+
+	int brightness = value;
+	int flash_en = 0, flash_now = 0;
+
+	if (brightness > LED_HALF) {
+		flash_en = 0;
+		flash_now = 1;
+	} else if (brightness > LED_OFF) {
+		flash_en = 1;
+		flash_now = 0;
+	} else {
+		flash_en = 0;
+		flash_now = 0;
+	}
+
+	rc = gpio_direction_output(flash_led->flash_en, flash_en);
+	if (rc) {
+		pr_err("%s: Failed to set gpio %d\n", __func__,
+		       flash_led->flash_en);
+		goto err;
+	}
+	rc = gpio_direction_output(flash_led->flash_now, flash_now);
+	if (rc) {
+		pr_err("%s: Failed to set gpio %d\n", __func__,
+		       flash_led->flash_now);
+		goto err;
+	}
+
+	flash_led->brightness = brightness;
+err:
+	return;
+}
+
+static enum led_brightness led_gpio_brightness_get(struct led_classdev
+						   *led_cdev)
+{
+	struct led_gpio_flash_data *flash_led =
+	    container_of(led_cdev, struct led_gpio_flash_data, cdev);
+	return flash_led->brightness;
+}
+
+int __devinit led_gpio_flash_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	const char *temp_str;
+	struct led_gpio_flash_data *flash_led = NULL;
+	struct device_node *node = pdev->dev.of_node;
+
+	flash_led = devm_kzalloc(&pdev->dev, sizeof(struct led_gpio_flash_data),
+				 GFP_KERNEL);
+	if (flash_led == NULL) {
+		dev_err(&pdev->dev, "%s:%d Unable to allocate memory\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	flash_led->cdev.default_trigger = LED_TRIGGER_DEFAULT;
+	rc = of_property_read_string(node, "linux,default-trigger", &temp_str);
+	if (!rc)
+		flash_led->cdev.default_trigger = temp_str;
+
+	flash_led->flash_en = of_get_named_gpio(node, "qcom,flash-en", 0);
+
+	if (flash_led->flash_en < 0) {
+		dev_err(&pdev->dev,
+			"Looking up %s property in node %s failed. rc =  %d\n",
+			"flash-en", node->full_name, flash_led->flash_en);
+		goto error;
+	} else {
+		rc = gpio_request(flash_led->flash_en, "FLASH_EN");
+		if (rc) {
+			dev_err(&pdev->dev,
+				"%s: Failed to request gpio %d,rc = %d\n",
+				__func__, flash_led->flash_en, rc);
+
+			goto error;
+		}
+	}
+
+	flash_led->flash_now = of_get_named_gpio(node, "qcom,flash-now", 0);
+	if (flash_led->flash_now < 0) {
+		dev_err(&pdev->dev,
+			"Looking up %s property in node %s failed. rc =  %d\n",
+			"flash-now", node->full_name, flash_led->flash_now);
+		goto error;
+	} else {
+		rc = gpio_request(flash_led->flash_now, "FLASH_NOW");
+		if (rc) {
+			dev_err(&pdev->dev,
+				"%s: Failed to request gpio %d,rc = %d\n",
+				__func__, flash_led->flash_now, rc);
+
+			goto error;
+		}
+	}
+
+	gpio_tlmm_config(GPIO_CFG(flash_led->flash_en, 0,
+				  GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
+				  GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+	gpio_tlmm_config(GPIO_CFG(flash_led->flash_now, 0,
+				  GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
+				  GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+
+	rc = of_property_read_string(node, "linux,name", &flash_led->cdev.name);
+	if (rc) {
+		dev_err(&pdev->dev, "%s: Failed to read linux name. rc = %d\n",
+			__func__, rc);
+		goto error;
+	}
+
+	platform_set_drvdata(pdev, flash_led);
+	flash_led->cdev.max_brightness = LED_FULL;
+	flash_led->cdev.brightness_set = led_gpio_brightness_set;
+	flash_led->cdev.brightness_get = led_gpio_brightness_get;
+
+	rc = led_classdev_register(&pdev->dev, &flash_led->cdev);
+	if (rc) {
+		dev_err(&pdev->dev, "%s: Failed to register led dev. rc = %d\n",
+			__func__, rc);
+		goto error;
+	}
+	return 0;
+
+error:
+	devm_kfree(&pdev->dev, flash_led);
+	return rc;
+}
+
+int __devexit led_gpio_flash_remove(struct platform_device *pdev)
+{
+	struct led_gpio_flash_data *flash_led =
+	    (struct led_gpio_flash_data *)platform_get_drvdata(pdev);
+
+	led_classdev_unregister(&flash_led->cdev);
+	devm_kfree(&pdev->dev, flash_led);
+	return 0;
+}
+
+static struct platform_driver led_gpio_flash_driver = {
+	.probe = led_gpio_flash_probe,
+	.remove = __devexit_p(led_gpio_flash_remove),
+	.driver = {
+		   .name = LED_GPIO_FLASH_DRIVER_NAME,
+		   .owner = THIS_MODULE,
+		   .of_match_table = led_gpio_flash_of_match,
+		   }
+};
+
+static int __init led_gpio_flash_init(void)
+{
+	return platform_driver_register(&led_gpio_flash_driver);
+}
+
+static void __exit led_gpio_flash_exit(void)
+{
+	return platform_driver_unregister(&led_gpio_flash_driver);
+}
+
+late_initcall(led_gpio_flash_init);
+module_exit(led_gpio_flash_exit);
+
+MODULE_DESCRIPTION("QCOM GPIO LEDs driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("leds:leds-msm-gpio-flash");
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 cb8d821..2db25a6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -39,7 +39,7 @@
 #define VFE40_BURST_LEN 3
 #define VFE40_STATS_BURST_LEN 2
 #define VFE40_UB_SIZE 1536
-#define VFE40_EQUAL_SLICE_UB 286
+#define VFE40_EQUAL_SLICE_UB 228
 #define VFE40_WM_BASE(idx) (0x6C + 0x24 * idx)
 #define VFE40_RDI_BASE(idx) (0x2E8 + 0x4 * idx)
 #define VFE40_XBAR_BASE(idx) (0x58 + 0x4 * (idx / 2))
@@ -1299,7 +1299,7 @@
 }
 
 static struct msm_vfe_axi_hardware_info msm_vfe40_axi_hw_info = {
-	.num_wm = 4,
+	.num_wm = 5,
 	.num_comp_mask = 3,
 	.num_rdi = 3,
 	.num_rdi_master = 3,
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 27aba5c..8d53e35 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -852,16 +852,19 @@
 {
 	unsigned long flags;
 	struct v4l2_subdev *subdev = NULL;
+	struct v4l2_subdev *subdev_out = NULL;
 
 	spin_lock_irqsave(&msm_v4l2_dev->lock, flags);
 	if (!list_empty(&msm_v4l2_dev->subdevs)) {
 		list_for_each_entry(subdev, &msm_v4l2_dev->subdevs, list)
-			if (!strcmp(name, subdev->name))
+			if (!strcmp(name, subdev->name)) {
+				subdev_out = subdev;
 				break;
+			}
 	}
 	spin_unlock_irqrestore(&msm_v4l2_dev->lock, flags);
 
-	return subdev;
+	return subdev_out;
 }
 
 static void msm_sd_notify(struct v4l2_subdev *sd,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index a6c5639..a27ca99 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -795,10 +795,7 @@
 		rc = msm_cci_config(sd, arg);
 		break;
 	case MSM_SD_SHUTDOWN: {
-		struct msm_camera_cci_ctrl ctrl_cmd;
-		ctrl_cmd.cmd = MSM_CCI_RELEASE;
-		rc = msm_cci_config(sd, &ctrl_cmd);
-		break;
+		return rc;
 	}
 	default:
 		rc = -ENOIOCTLCMD;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
index e096e96..4ebcfdf 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
@@ -444,14 +444,16 @@
 			spi_client->spi_master->dev.of_node;
 	else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE)
 		of_node = e_ctrl->pdev->dev.of_node;
-	rc = msm_camera_get_dt_power_setting_data(of_node,
-		  &power_info->power_setting, &power_info->power_setting_size);
-	if (rc)
-		return rc;
 
 	rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
 					     &power_info->num_vreg);
-	if (rc)
+	if (rc < 0)
+		return rc;
+
+	rc = msm_camera_get_dt_power_setting_data(of_node,
+		power_info->cam_vreg, power_info->num_vreg,
+		&power_info->power_setting, &power_info->power_setting_size);
+	if (rc < 0)
 		goto ERROR1;
 
 	power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
index 80b1ccb..40d1155 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
@@ -64,7 +64,7 @@
 }
 
 int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte)
+	uint32_t addr, uint8_t *data, uint32_t num_byte)
 {
 	int32_t rc = -EFAULT;
 	unsigned char *buf = NULL;
@@ -137,7 +137,7 @@
 }
 
 int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte)
+	uint32_t addr, uint8_t *data, uint32_t num_byte)
 {
 	int32_t rc = -EFAULT;
 	uint8_t i = 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
index 2511651..3898bd8 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
@@ -23,12 +23,13 @@
 #define CDBG(fmt, args...) do { } while (0)
 #endif
 
-int32_t msm_camera_get_dt_power_setting_data(struct device_node *of_node,
+int msm_camera_get_dt_power_setting_data(struct device_node *of_node,
+	struct camera_vreg_t *cam_vreg, int num_vreg,
 	struct msm_sensor_power_setting **power_setting,
 	uint16_t *power_setting_size)
 {
-	int32_t rc = 0, i = 0;
-	int32_t count = 0;
+	int rc = 0, i, j;
+	int count = 0;
 	const char *seq_name = NULL;
 	uint32_t *array = NULL;
 	struct msm_sensor_power_setting *ps;
@@ -43,8 +44,7 @@
 	if (count <= 0)
 		return 0;
 
-	ps = kzalloc(sizeof(struct msm_sensor_power_setting) * count,
-		GFP_KERNEL);
+	ps = kzalloc(sizeof(*ps) * count, GFP_KERNEL);
 	if (!ps) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		return -ENOMEM;
@@ -77,6 +77,10 @@
 			ps[i].seq_type = SENSOR_I2C_MUX;
 			CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__,
 				i, ps[i].seq_type);
+		} else {
+			CDBG("%s: unrecognized seq-type\n", __func__);
+			rc = -EILSEQ;
+			goto ERROR1;
 		}
 	}
 
@@ -91,24 +95,47 @@
 			pr_err("%s failed %d\n", __func__, __LINE__);
 			goto ERROR1;
 		}
-		if (!strcmp(seq_name, "cam_vdig"))
-			ps[i].seq_val = CAM_VDIG;
-		else if (!strcmp(seq_name, "cam_vio"))
-			ps[i].seq_val = CAM_VIO;
-		else if (!strcmp(seq_name, "cam_vana"))
-			ps[i].seq_val = CAM_VANA;
-		else if (!strcmp(seq_name, "cam_vaf"))
-			ps[i].seq_val = CAM_VAF;
-		else if (!strcmp(seq_name, "sensor_gpio_reset"))
-			ps[i].seq_val = SENSOR_GPIO_RESET;
-		else if (!strcmp(seq_name, "sensor_gpio_standby"))
-			ps[i].seq_val = SENSOR_GPIO_STANDBY;
-		else if (!strcmp(seq_name, "sensor_cam_mclk"))
-			ps[i].seq_val = SENSOR_CAM_MCLK;
-		else if (!strcmp(seq_name, "sensor_cam_clk"))
-			ps[i].seq_val = SENSOR_CAM_CLK;
-		else if (!strcmp(seq_name, "none"))
-			ps[i].seq_val = 0;
+		switch (ps[i].seq_type) {
+		case SENSOR_VREG:
+			for (j = 0; j < num_vreg; j++) {
+				if (!strcmp(seq_name, cam_vreg[j].reg_name))
+					break;
+			}
+			if (j < num_vreg)
+				ps[i].seq_val = j;
+			else
+				rc = -EILSEQ;
+			break;
+		case SENSOR_GPIO:
+			if (!strcmp(seq_name, "sensor_gpio_reset"))
+				ps[i].seq_val = SENSOR_GPIO_RESET;
+			else if (!strcmp(seq_name, "sensor_gpio_standby"))
+				ps[i].seq_val = SENSOR_GPIO_STANDBY;
+			else
+				rc = -EILSEQ;
+			break;
+		case SENSOR_CLK:
+			if (!strcmp(seq_name, "sensor_cam_mclk"))
+				ps[i].seq_val = SENSOR_CAM_MCLK;
+			else if (!strcmp(seq_name, "sensor_cam_clk"))
+				ps[i].seq_val = SENSOR_CAM_CLK;
+			else
+				rc = -EILSEQ;
+			break;
+		case SENSOR_I2C_MUX:
+			if (!strcmp(seq_name, "none"))
+				ps[i].seq_val = 0;
+			else
+				rc = -EILSEQ;
+			break;
+		default:
+			rc = -EILSEQ;
+			break;
+		}
+		if (rc < 0) {
+			CDBG("%s: unrecognized seq-val\n", __func__);
+			goto ERROR1;
+		}
 	}
 
 	array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
@@ -151,6 +178,7 @@
 	}
 	kfree(array);
 	return rc;
+
 ERROR2:
 	kfree(array);
 ERROR1:
@@ -159,11 +187,11 @@
 	return rc;
 }
 
-int32_t msm_camera_get_dt_gpio_req_tbl(struct device_node *of_node,
+int msm_camera_get_dt_gpio_req_tbl(struct device_node *of_node,
 	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
 	uint16_t gpio_array_size)
 {
-	int32_t rc = 0, i = 0;
+	int rc = 0, i = 0;
 	uint32_t count = 0;
 	uint32_t *val_array = NULL;
 
@@ -247,8 +275,7 @@
 	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
 	uint16_t gpio_array_size)
 {
-	int32_t rc = 0;
-	int32_t val = 0;
+	int rc = 0, val = 0;
 
 	gconf->gpio_num_info = kzalloc(sizeof(struct msm_camera_gpio_num_info),
 		GFP_KERNEL);
@@ -299,10 +326,10 @@
 	return rc;
 }
 
-int32_t msm_camera_get_dt_vreg_data(struct device_node *of_node,
+int msm_camera_get_dt_vreg_data(struct device_node *of_node,
 	struct camera_vreg_t **cam_vreg, int *num_vreg)
 {
-	int32_t rc = 0, i = 0;
+	int rc = 0, i = 0;
 	uint32_t count = 0;
 	uint32_t *vreg_array = NULL;
 	struct camera_vreg_t *vreg = NULL;
@@ -313,8 +340,7 @@
 	if (!count)
 		return 0;
 
-	vreg = kzalloc(sizeof(struct camera_vreg_t) * count,
-		GFP_KERNEL);
+	vreg = kzalloc(sizeof(*vreg) * count, GFP_KERNEL);
 	if (!vreg) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
 		return -ENOMEM;
@@ -398,7 +424,7 @@
 	return rc;
 }
 
-static int32_t msm_camera_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+static int msm_camera_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
 {
 	struct v4l2_subdev *i2c_mux_sd =
 		dev_get_drvdata(&i2c_conf->mux_dev->dev);
@@ -409,7 +435,7 @@
 	return 0;
 }
 
-static int32_t msm_camera_disable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+static int msm_camera_disable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
 {
 	struct v4l2_subdev *i2c_mux_sd =
 		dev_get_drvdata(&i2c_conf->mux_dev->dev);
@@ -418,11 +444,11 @@
 	return 0;
 }
 
-int32_t msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
+int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
 	enum msm_camera_device_type_t device_type,
 	struct msm_camera_i2c_client *sensor_i2c_client)
 {
-	int32_t rc = 0, index = 0, no_gpio = 0;
+	int rc = 0, index = 0, no_gpio = 0;
 	struct msm_sensor_power_setting *power_setting = NULL;
 
 	CDBG("%s:%d\n", __func__, __LINE__);
@@ -484,7 +510,7 @@
 					SENSOR_GPIO_MAX);
 				goto power_up_failed;
 			}
-			pr_debug("%s:%d gpio set val %d\n", __func__, __LINE__,
+			CDBG("%s:%d gpio set val %d\n", __func__, __LINE__,
 				ctrl->gpio_conf->gpio_num_info->gpio_num
 				[power_setting->seq_val]);
 			gpio_set_value_cansleep(
@@ -584,11 +610,11 @@
 	return rc;
 }
 
-int32_t msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
+int msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
 	enum msm_camera_device_type_t device_type,
 	struct msm_camera_i2c_client *sensor_i2c_client)
 {
-	int32_t index = 0;
+	int index = 0;
 	struct msm_sensor_power_setting *power_setting = NULL;
 
 	CDBG("%s:%d\n", __func__, __LINE__);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h
index 5a35747..fee2a4c 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h
@@ -19,6 +19,7 @@
 #include "msm_camera_i2c.h"
 
 int32_t msm_camera_get_dt_power_setting_data(struct device_node *of_node,
+	struct camera_vreg_t *cam_vreg, int num_vreg,
 	struct msm_sensor_power_setting **power_setting,
 	uint16_t *power_setting_size);
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
index 7af04ba..389e9d9 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
@@ -35,11 +35,11 @@
 	int (*i2c_read) (struct msm_camera_i2c_client *, uint32_t, uint16_t *,
 		enum msm_camera_i2c_data_type);
 	int32_t (*i2c_read_seq)(struct msm_camera_i2c_client *, uint32_t,
-		uint8_t *, uint16_t);
+		uint8_t *, uint32_t);
 	int (*i2c_write) (struct msm_camera_i2c_client *, uint32_t, uint16_t,
 		enum msm_camera_i2c_data_type);
 	int (*i2c_write_seq) (struct msm_camera_i2c_client *, uint32_t ,
-		uint8_t *, uint16_t);
+		uint8_t *, uint32_t);
 	int32_t (*i2c_write_table)(struct msm_camera_i2c_client *,
 		struct msm_camera_i2c_reg_setting *);
 	int32_t (*i2c_write_seq_table)(struct msm_camera_i2c_client *,
@@ -62,14 +62,14 @@
 	enum msm_camera_i2c_data_type data_type);
 
 int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte);
+	uint32_t addr, uint8_t *data, uint32_t num_byte);
 
 int32_t msm_camera_cci_i2c_write(struct msm_camera_i2c_client *client,
 	uint32_t addr, uint16_t data,
 	enum msm_camera_i2c_data_type data_type);
 
 int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte);
+	uint32_t addr, uint8_t *data, uint32_t num_byte);
 
 int32_t msm_camera_cci_i2c_write_table(
 	struct msm_camera_i2c_client *client,
@@ -101,14 +101,14 @@
 	enum msm_camera_i2c_data_type data_type);
 
 int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte);
+	uint32_t addr, uint8_t *data, uint32_t num_byte);
 
 int32_t msm_camera_qup_i2c_write(struct msm_camera_i2c_client *client,
 	uint32_t addr, uint16_t data,
 	enum msm_camera_i2c_data_type data_type);
 
 int32_t msm_camera_qup_i2c_write_seq(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte);
+	uint32_t addr, uint8_t *data, uint32_t num_byte);
 
 int32_t msm_camera_qup_i2c_write_table(struct msm_camera_i2c_client *client,
 	struct msm_camera_i2c_reg_setting *write_setting);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
index ac9cdbf..60d1509 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
@@ -107,7 +107,7 @@
 }
 
 int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte)
+	uint32_t addr, uint8_t *data, uint32_t num_byte)
 {
 	int32_t rc = -EFAULT;
 	unsigned char buf[client->addr_type+num_byte];
@@ -188,7 +188,7 @@
 }
 
 int32_t msm_camera_qup_i2c_write_seq(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte)
+	uint32_t addr, uint8_t *data, uint32_t num_byte)
 {
 	int32_t rc = -EFAULT;
 	unsigned char buf[client->addr_type+num_byte];
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.c
index d1d5f23..75b0063 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.c
@@ -67,50 +67,86 @@
 
 }
 
-static int32_t msm_camera_spi_read_helper(struct msm_camera_i2c_client *client,
-		struct msm_camera_spi_inst *inst, uint32_t addr, uint8_t *data,
-		uint16_t num_byte)
+/**
+  * msm_camera_spi_tx_helper() - wrapper for SPI transaction
+  * @client:	io client
+  * @inst:	inst of this transaction
+  * @addr:	device addr following the inst
+  * @data:	output byte array (could be NULL)
+  * @num_byte:	size of @data
+  * @tx, rx:	optional transfer buffer.  It must be at least header
+  *		+ @num_byte long.
+  *
+  * This is the core function for SPI transaction, except for writes.  It first
+  * checks address type, then allocates required memory for tx/rx buffers.
+  * It sends out <opcode><addr>, and optionally receives @num_byte of response,
+  * if @data is not NULL.  This function does not check for wait conditions,
+  * and will return immediately once bus transaction finishes.
+  *
+  * This function will allocate buffers of header + @num_byte long.  For
+  * large transfers, the allocation could fail.  External buffer @tx, @rx
+  * should be passed in to bypass allocation.  The size of buffer should be
+  * at least header + num_byte long.  Since buffer is managed externally,
+  * @data will be ignored, and read results will be in @rx.
+  * @tx, @rx also can be used for repeated transfers to improve performance.
+  */
+int32_t msm_camera_spi_tx_helper(struct msm_camera_i2c_client *client,
+	struct msm_camera_spi_inst *inst, uint32_t addr, uint8_t *data,
+	uint32_t num_byte, char *tx, char *rx)
 {
-	int32_t rc = -EFAULT;
+	int32_t rc = -EINVAL;
 	struct spi_device *spi = client->spi_client->spi_master;
-	char *tx, *rx;
-	uint16_t len;
-	int8_t retries = client->spi_client->retries;
+	char *ctx = NULL, *crx = NULL;
+	uint32_t len, hlen;
+	uint8_t retries = client->spi_client->retries;
 
 	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR)
 	    && (client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
 	    && (client->addr_type != MSM_CAMERA_I2C_3B_ADDR))
 		return rc;
 
-	len = sizeof(inst->opcode) + inst->addr_len + inst->dummy_len
-		+ num_byte;
+	hlen = msm_camera_spi_get_hlen(inst);
+	len = hlen + num_byte;
 
-	tx = kmalloc(len, GFP_KERNEL | GFP_DMA);
-	if (!tx)
+	if (tx)
+		ctx = tx;
+	else
+		ctx = kzalloc(len, GFP_KERNEL);
+	if (!ctx)
 		return -ENOMEM;
-	rx = kmalloc(len, GFP_KERNEL | GFP_DMA);
-	if (!rx) {
-		kfree(tx);
-		return -ENOMEM;
+
+	if (num_byte) {
+		if (rx)
+			crx = rx;
+		else
+			crx = kzalloc(len, GFP_KERNEL);
+		if (!crx) {
+			if (!tx)
+				kfree(ctx);
+			return -ENOMEM;
+		}
+	} else {
+		crx = NULL;
 	}
-	memset(tx, 0, len);
-	memset(rx, 0, len);
 
-	tx[0] = inst->opcode;
-	msm_camera_set_addr(addr, inst->addr_len, client->addr_type, tx + 1);
-	while ((rc = msm_camera_spi_txfr(spi, tx, rx, len)) && retries) {
+	ctx[0] = inst->opcode;
+	msm_camera_set_addr(addr, inst->addr_len, client->addr_type, ctx + 1);
+	while ((rc = msm_camera_spi_txfr(spi, ctx, crx, len)) && retries) {
 		retries--;
 		msleep(client->spi_client->retry_delay);
 	}
-	if (rc) {
+	if (rc < 0) {
 		SPIDBG("%s: failed %d\n", __func__, rc);
 		goto out;
 	}
-	len = sizeof(inst->opcode) + inst->addr_len + inst->dummy_len;
-	memcpy(data, rx + len, num_byte);
+	if (data && num_byte && !rx)
+		memcpy(data, crx + hlen, num_byte);
+
 out:
-	kfree(tx);
-	kfree(rx);
+	if (!tx)
+		kfree(ctx);
+	if (!rx)
+		kfree(crx);
 	return rc;
 }
 
@@ -118,16 +154,17 @@
 	uint32_t addr, uint16_t *data,
 	enum msm_camera_i2c_data_type data_type)
 {
-	int32_t rc = -EFAULT;
+	int32_t rc = -EINVAL;
 	uint8_t temp[2];
 
 	if ((data_type != MSM_CAMERA_I2C_BYTE_DATA)
 	    && (data_type != MSM_CAMERA_I2C_WORD_DATA))
 		return rc;
 
-	rc = msm_camera_spi_read_helper(client,
-		&client->spi_client->cmd_tbl.read, addr, &temp[0], data_type);
-	if (rc)
+	rc = msm_camera_spi_tx_helper(client,
+			&client->spi_client->cmd_tbl.read, addr, &temp[0],
+			data_type, NULL, NULL);
+	if (rc < 0)
 		return rc;
 
 	if (data_type == MSM_CAMERA_I2C_BYTE_DATA)
@@ -140,15 +177,38 @@
 }
 
 int32_t msm_camera_spi_read_seq(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte)
+	uint32_t addr, uint8_t *data, uint32_t num_byte)
 {
-	return msm_camera_spi_read_helper(client,
-		&client->spi_client->cmd_tbl.read_seq, addr, data, num_byte);
+	return msm_camera_spi_tx_helper(client,
+		&client->spi_client->cmd_tbl.read_seq, addr, data, num_byte,
+		NULL, NULL);
+}
+
+/**
+  * msm_camera_spi_read_seq_l()- function for large SPI reads
+  * @client:	io client
+  * @addr:	device address to read
+  * @num_byte:	read length
+  * @tx,rx:	pre-allocated SPI buffer.  Its size must be at least
+  *		header + num_byte
+  *
+  * This function is used for large transactions.  Instead of allocating SPI
+  * buffer each time, caller is responsible for pre-allocating memory buffers.
+  * Memory buffer must be at least header + num_byte.  Header length can be
+  * obtained by msm_camera_spi_get_hlen().
+  */
+int32_t msm_camera_spi_read_seq_l(struct msm_camera_i2c_client *client,
+	uint32_t addr, uint32_t num_byte, char *tx, char *rx)
+{
+	return msm_camera_spi_tx_helper(client,
+		&client->spi_client->cmd_tbl.read_seq, addr, NULL, num_byte,
+		tx, rx);
 }
 
 int32_t msm_camera_spi_query_id(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte)
+	uint32_t addr, uint8_t *data, uint32_t num_byte)
 {
-	return msm_camera_spi_read_helper(client,
-		&client->spi_client->cmd_tbl.query_id, addr, data, num_byte);
+	return msm_camera_spi_tx_helper(client,
+		&client->spi_client->cmd_tbl.query_id, addr, data, num_byte,
+		NULL, NULL);
 }
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.h
index 564e470..0aefa50 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.h
@@ -17,6 +17,12 @@
 #include <media/msm_cam_sensor.h>
 #include "msm_camera_i2c.h"
 
+/**
+  * Common SPI communication scheme
+  * tx: <opcode>[addr][wait][write buffer]
+  * rx: [read buffer]
+  * Some inst require polling busy reg until it's done
+  */
 struct msm_camera_spi_inst {
 	uint8_t opcode;		/* one-byte opcode */
 	uint8_t addr_len;	/* addr len in bytes */
@@ -38,14 +44,23 @@
 	uint8_t retries;	/* retry times upon failure */
 };
 
+static __always_inline
+uint16_t msm_camera_spi_get_hlen(struct msm_camera_spi_inst *inst)
+{
+	return sizeof(inst->opcode) + inst->addr_len + inst->dummy_len;
+}
+
 int32_t msm_camera_spi_read(struct msm_camera_i2c_client *client,
 	uint32_t addr, uint16_t *data,
 	enum msm_camera_i2c_data_type data_type);
 
 int32_t msm_camera_spi_read_seq(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte);
+	uint32_t addr, uint8_t *data, uint32_t num_byte);
+
+int32_t msm_camera_spi_read_seq_l(struct msm_camera_i2c_client *client,
+	uint32_t addr, uint32_t num_byte, char *tx, char *rx);
 
 int32_t msm_camera_spi_query_id(struct msm_camera_i2c_client *client,
-	uint32_t addr, uint8_t *data, uint16_t num_byte);
+	uint32_t addr, uint8_t *data, uint32_t num_byte);
 
 #endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 34f4428..7f474bb 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -1175,9 +1175,10 @@
 	case VIDIOC_MSM_SENSOR_CFG:
 		return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
 	case VIDIOC_MSM_SENSOR_RELEASE:
-	case MSM_SD_SHUTDOWN:
 		msm_sensor_stop_stream(s_ctrl);
 		return 0;
+	case MSM_SD_SHUTDOWN:
+		return 0;
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 85fdff6..23e05e2 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -692,6 +692,7 @@
 			memset(feed, 0, sizeof(*feed));
 			feed->sdmx_filter_handle = SDMX_INVALID_FILTER_HANDLE;
 			feed->mpq_demux = mpq_demux;
+			feed->session_id = 0;
 		}
 
 		/*
@@ -3776,8 +3777,10 @@
 	}
 
 init_mpq_feed_end:
-	if (!ret)
+	if (!ret) {
 		mpq_demux->num_active_feeds++;
+		mpq_feed->session_id++;
+	}
 	mutex_unlock(&mpq_demux->mutex);
 	return ret;
 }
@@ -4525,19 +4528,14 @@
 static void mpq_sdmx_process_results(struct mpq_demux *mpq_demux)
 {
 	int i;
-	int j;
 	int sdmx_filters;
 	struct sdmx_filter_status *sts;
 	struct mpq_feed *mpq_feed;
+	u8 mpq_feed_idx;
 
 	sdmx_filters = mpq_demux->sdmx_filter_count;
 	for (i = 0; i < sdmx_filters; i++) {
-		/*
-		 * MPQ_TODO: review lookup optimization
-		 * Can have the related mpq_feed index already associated with
-		 * the filter status.
-		 */
-		sts = &mpq_demux->filters_status[i];
+		sts = &mpq_demux->sdmx_filters_state.status[i];
 		MPQ_DVB_DBG_PRINT(
 			"%s: Filter: handle=%d, status=0x%x, errors=0x%x\n",
 			__func__, sts->filter_handle, sts->status_indicators,
@@ -4548,16 +4546,13 @@
 		MPQ_DVB_DBG_PRINT("%s: Data fill count=%d (write=%d)\n",
 			__func__, sts->data_fill_count, sts->data_write_offset);
 
-		for (j = 0; j < MPQ_MAX_DMX_FILES; j++) {
-			mpq_feed = &mpq_demux->feeds[j];
-			if ((mpq_feed->dvb_demux_feed->state == DMX_STATE_GO) &&
-				(sts->filter_handle ==
-					mpq_feed->sdmx_filter_handle) &&
-				(!mpq_feed->secondary_feed))
-				break;
-		}
-
-		if (j == MPQ_MAX_DMX_FILES)
+		mpq_feed_idx = mpq_demux->sdmx_filters_state.mpq_feed_idx[i];
+		mpq_feed = &mpq_demux->feeds[mpq_feed_idx];
+		if ((mpq_feed->dvb_demux_feed->state != DMX_STATE_GO) ||
+			(sts->filter_handle != mpq_feed->sdmx_filter_handle) ||
+			mpq_feed->secondary_feed ||
+			(mpq_demux->sdmx_filters_state.session_id[i] !=
+			 mpq_feed->session_id))
 			continue;
 
 		if (sts->error_indicators & SDMX_FILTER_ERR_MD_BUF_FULL)
@@ -4636,9 +4631,14 @@
 		if ((mpq_feed->sdmx_filter_handle != SDMX_INVALID_FILTER_HANDLE)
 			&& (mpq_feed->dvb_demux_feed->state == DMX_STATE_GO)
 			&& (!mpq_feed->secondary_feed)) {
-			sts = &mpq_demux->filters_status[filter_index];
+			sts = mpq_demux->sdmx_filters_state.status +
+				filter_index;
 			mpq_sdmx_prepare_filter_status(mpq_demux, sts,
 				mpq_feed);
+			mpq_demux->sdmx_filters_state.mpq_feed_idx[filter_index]
+				 = i;
+			mpq_demux->sdmx_filters_state.session_id[filter_index] =
+				mpq_feed->session_id;
 			filter_index++;
 		}
 	}
@@ -4662,7 +4662,8 @@
 	prev_fill_count = fill_count;
 	sdmx_res = sdmx_process(mpq_demux->sdmx_session_handle, flags, input,
 		&fill_count, &read_offset, &errors, &status,
-		mpq_demux->sdmx_filter_count, mpq_demux->filters_status);
+		mpq_demux->sdmx_filter_count,
+		mpq_demux->sdmx_filters_state.status);
 
 	process_end_time = current_kernel_time();
 	bytes_read = prev_fill_count - fill_count;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
index ca7c15a..31fd9b5 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
@@ -322,6 +322,8 @@
  * other feeds
  * @metadata_buf: Ring buffer object for managing the metadata buffer
  * @metadata_buf_handle: Allocation handle for the metadata buffer
+ * @session_id: Counter that is incremented every time feed is initialized
+ * through mpq_dmx_init_mpq_feed
  * @sdmx_buf: Ring buffer object for intermediate output data from the sdmx
  * @sdmx_buf_handle: Allocation handle for the sdmx intermediate data buffer
  * @video_info: Video feed specific information
@@ -338,6 +340,7 @@
 	struct dvb_ringbuffer metadata_buf;
 	struct ion_handle *metadata_buf_handle;
 
+	u8 session_id;
 	struct dvb_ringbuffer sdmx_buf;
 	struct ion_handle *sdmx_buf_handle;
 
@@ -355,23 +358,24 @@
  * @ion_client: ION demux client used to allocate memory from ION.
  * @mutex: Lock used to protect against private feed data
  * @feeds: mpq common feed object pool
+ * @plugin_priv: Underlying plugin's own private data
  * @num_active_feeds: Number of active mpq feeds
  * @num_secure_feeds: Number of secure feeds (have a sdmx filter associated)
  * currently allocated.
- * @filters_status: Array holding buffers status for each secure demux filter.
  * Used before each call to sdmx_process() to build up to date state.
  * @sdmx_session_handle: Secure demux open session handle
  * @sdmx_filter_count: Number of active secure demux filters
  * @sdmx_eos: End-of-stream indication flag for current sdmx session
- * @plugin_priv: Underlying plugin's own private data
+ * @sdmx_filters_state: Array holding buffers status for each secure
+ * demux filter.
  * @hw_notification_interval: Notification interval in msec,
- *                            exposed in debugfs.
+ * exposed in debugfs.
  * @hw_notification_min_interval: Minimum notification internal in msec,
  * exposed in debugfs.
  * @hw_notification_count: Notification count, exposed in debugfs.
  * @hw_notification_size: Notification size in bytes, exposed in debugfs.
  * @hw_notification_min_size: Minimum notification size in bytes,
- *                            exposed in debugfs.
+ * exposed in debugfs.
  * @decoder_drop_count: Accumulated number of bytes dropped due to decoder
  * buffer fullness, exposed in debugfs.
  * @decoder_out_count: Counter incremeneted for each video frame output by
@@ -403,14 +407,31 @@
 	struct ion_client *ion_client;
 	struct mutex mutex;
 	struct mpq_feed feeds[MPQ_MAX_DMX_FILES];
+	void *plugin_priv;
+
 	u32 num_active_feeds;
 	u32 num_secure_feeds;
-	struct sdmx_filter_status filters_status[MPQ_MAX_DMX_FILES];
 	int sdmx_session_handle;
 	int sdmx_session_ref_count;
 	int sdmx_filter_count;
 	int sdmx_eos;
-	void *plugin_priv;
+	struct {
+		/* SDMX filters status */
+		struct sdmx_filter_status status[MPQ_MAX_DMX_FILES];
+
+		/* Index of the feed respective to SDMX filter */
+		u8 mpq_feed_idx[MPQ_MAX_DMX_FILES];
+
+		/*
+		 * Snapshot of session_id of the feed
+		 * when SDMX process was called. This is used
+		 * to identify whether the feed has been
+		 * restarted when processing SDMX results.
+		 * May happen when demux is stalled in playback
+		 * from memory with PULL mode.
+		 */
+		u8 session_id[MPQ_MAX_DMX_FILES];
+	} sdmx_filters_state;
 
 	/* debug-fs */
 	u32 hw_notification_interval;
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 ef3f57f..5daa842 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
@@ -562,6 +562,9 @@
 	caps->demod_input_max_bitrate = 72;
 	caps->memory_input_max_bitrate = 72;
 
+	/* TSIF reports 3 bytes STC at unit of 27MHz/256 */
+	caps->max_stc = (u64)0xFFFFFF * 256;
+
 	/* Buffer requirements */
 	caps->section.flags =
 		DMX_BUFFER_EXTERNAL_SUPPORT	|
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 8e628f6..5bd008d 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
@@ -1628,6 +1628,9 @@
 	caps->demod_input_max_bitrate = 96;
 	caps->memory_input_max_bitrate = 96;
 
+	/* TSIF reports 3 bytes STC at unit of 27MHz/256 */
+	caps->max_stc = (u64)0xFFFFFF * 256;
+
 	/* Buffer requirements */
 	caps->section.flags =
 		DMX_BUFFER_EXTERNAL_SUPPORT	|
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 1ab9da1..9837e9f 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
@@ -86,6 +86,9 @@
 	caps->demod_input_max_bitrate = 96;
 	caps->memory_input_max_bitrate = 80;
 
+	/* TSIF reports 7 bytes STC at unit of 27MHz */
+	caps->max_stc = 0x00FFFFFFFFFFFFFF;
+
 	return 0;
 }
 
diff --git a/drivers/media/platform/msm/vidc/Makefile b/drivers/media/platform/msm/vidc/Makefile
index 6977165..ff6274c 100644
--- a/drivers/media/platform/msm/vidc/Makefile
+++ b/drivers/media/platform/msm/vidc/Makefile
@@ -5,6 +5,7 @@
 				msm_venc.o \
 				msm_smem.o \
 				msm_vidc_debug.o \
+				msm_vidc_res_parse.o \
 				venus_hfi.o \
 				hfi_response_handler.o \
 				hfi_packetization.o \
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 687bd71..96d95989 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -20,7 +20,6 @@
 #include <linux/debugfs.h>
 #include <linux/version.h>
 #include <linux/slab.h>
-#include <linux/of.h>
 #include <mach/board.h>
 #include <mach/iommu.h>
 #include <mach/iommu_domains.h>
@@ -31,6 +30,7 @@
 #include "msm_smem.h"
 #include "vidc_hfi_api.h"
 #include "msm_vidc_resources.h"
+#include "msm_vidc_res_parse.h"
 
 #define BASE_DEVICE_NUMBER 32
 
@@ -54,50 +54,6 @@
 	struct list_head registered_bufs;
 };
 
-struct master_slave {
-	int masters_ocmem[2];
-	int masters_ddr[2];
-	int slaves_ocmem[2];
-	int slaves_ddr[2];
-};
-
-struct bus_pdata_config {
-	int *masters;
-	int *slaves;
-	char *name;
-};
-
-static struct master_slave bus_vectors_masters_slaves = {
-	.masters_ocmem = {MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-				MSM_BUS_MASTER_VIDEO_P1_OCMEM},
-	.masters_ddr = {MSM_BUS_MASTER_VIDEO_P0, MSM_BUS_MASTER_VIDEO_P1},
-	.slaves_ocmem = {MSM_BUS_SLAVE_OCMEM, MSM_BUS_SLAVE_OCMEM},
-	.slaves_ddr = {MSM_BUS_SLAVE_EBI_CH0, MSM_BUS_SLAVE_EBI_CH0},
-};
-
-static struct bus_pdata_config bus_pdata_config_vector[] = {
-{
-	.masters = bus_vectors_masters_slaves.masters_ocmem,
-	.slaves = bus_vectors_masters_slaves.slaves_ocmem,
-	.name = "qcom,enc-ocmem-ab-ib",
-},
-{
-	.masters = bus_vectors_masters_slaves.masters_ocmem,
-	.slaves = bus_vectors_masters_slaves.slaves_ocmem,
-	.name = "qcom,dec-ocmem-ab-ib",
-},
-{
-	.masters = bus_vectors_masters_slaves.masters_ddr,
-	.slaves = bus_vectors_masters_slaves.slaves_ddr,
-	.name = "qcom,enc-ddr-ab-ib",
-},
-{
-	.masters = bus_vectors_masters_slaves.masters_ddr,
-	.slaves = bus_vectors_masters_slaves.slaves_ddr,
-	.name = "qcom,dec-ddr-ab-ib",
-},
-};
-
 static inline struct msm_vidc_inst *get_vidc_inst(struct file *filp, void *fh)
 {
 	return container_of(filp->private_data,
@@ -736,578 +692,6 @@
 {
 }
 
-static size_t get_u32_array_num_elements(struct platform_device *pdev,
-					char *name)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int len;
-	size_t num_elements = 0;
-	if (!of_get_property(np, name, &len)) {
-		dprintk(VIDC_ERR, "Failed to read %s from device tree\n",
-			name);
-		goto fail_read;
-	}
-
-	num_elements = len / sizeof(u32);
-	if (num_elements <= 0) {
-		dprintk(VIDC_ERR, "%s not specified in device tree\n",
-			name);
-		goto fail_read;
-	}
-	return num_elements / 2;
-
-fail_read:
-	return 0;
-}
-
-static int read_hfi_type(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int rc = 0;
-	const char *hfi_name = NULL;
-
-	if (np) {
-		rc = of_property_read_string(np, "qcom,hfi", &hfi_name);
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"Failed to read hfi from device tree\n");
-			goto err_hfi_read;
-		}
-		if (!strcmp(hfi_name, "venus"))
-			rc = VIDC_HFI_VENUS;
-		else if (!strcmp(hfi_name, "q6"))
-			rc = VIDC_HFI_Q6;
-		else
-			rc = -EINVAL;
-	} else
-		rc = VIDC_HFI_Q6;
-
-err_hfi_read:
-	return rc;
-}
-
-static inline void msm_vidc_free_freq_table(
-		struct msm_vidc_platform_resources *res)
-{
-	kfree(res->load_freq_tbl);
-	res->load_freq_tbl = NULL;
-}
-
-static inline void msm_vidc_free_reg_table(
-			struct msm_vidc_platform_resources *res)
-{
-	kfree(res->reg_set.reg_tbl);
-	res->reg_set.reg_tbl = NULL;
-}
-
-static inline void msm_vidc_free_bus_vectors(
-			struct msm_vidc_platform_resources *res)
-{
-	int i, j;
-	if (res->bus_pdata) {
-		for (i = 0; i < ARRAY_SIZE(bus_pdata_config_vector); i++) {
-			for (j = 0; j < res->bus_pdata[i].num_usecases; j++) {
-				kfree(res->bus_pdata[i].usecase[j].vectors);
-				res->bus_pdata[i].usecase[j].vectors = NULL;
-			}
-			kfree(res->bus_pdata[i].usecase);
-			res->bus_pdata[i].usecase = NULL;
-		}
-		kfree(res->bus_pdata);
-		res->bus_pdata = NULL;
-	}
-}
-
-static inline void msm_vidc_free_iommu_groups(
-			struct msm_vidc_platform_resources *res)
-{
-	kfree(res->iommu_group_set.iommu_maps);
-	res->iommu_group_set.iommu_maps = NULL;
-}
-
-static inline void msm_vidc_free_buffer_usage_table(
-			struct msm_vidc_platform_resources *res)
-{
-	kfree(res->buffer_usage_set.buffer_usage_tbl);
-	res->buffer_usage_set.buffer_usage_tbl = NULL;
-}
-
-static int msm_vidc_load_freq_table(struct msm_vidc_platform_resources *res)
-{
-	int rc = 0;
-	int num_elements = 0;
-	struct platform_device *pdev = res->pdev;
-
-	num_elements = get_u32_array_num_elements(pdev, "qcom,load-freq-tbl");
-	if (num_elements == 0) {
-		dprintk(VIDC_ERR, "no elements in frequency table\n");
-		return rc;
-	}
-
-	res->load_freq_tbl = kzalloc(num_elements * sizeof(*res->load_freq_tbl),
-			GFP_KERNEL);
-	if (!res->load_freq_tbl) {
-		dprintk(VIDC_ERR,
-				"%s Failed to alloc load_freq_tbl\n",
-				__func__);
-		return -ENOMEM;
-	}
-
-	if (of_property_read_u32_array(pdev->dev.of_node,
-		"qcom,load-freq-tbl", (u32 *)res->load_freq_tbl,
-		num_elements * 2)) {
-		dprintk(VIDC_ERR, "Failed to read frequency table\n");
-		msm_vidc_free_freq_table(res);
-		return -EINVAL;
-	}
-
-	res->load_freq_tbl_size = num_elements;
-	return rc;
-}
-
-static int msm_vidc_load_reg_table(struct msm_vidc_platform_resources *res)
-{
-	struct reg_set *reg_set;
-	struct platform_device *pdev = res->pdev;
-	int i;
-	int rc = 0;
-
-	reg_set = &res->reg_set;
-	reg_set->count = get_u32_array_num_elements(pdev, "qcom,reg-presets");
-	if (reg_set->count == 0) {
-		dprintk(VIDC_DBG, "no elements in reg set\n");
-		return rc;
-	}
-
-	reg_set->reg_tbl = kzalloc(reg_set->count *
-			sizeof(*(reg_set->reg_tbl)), GFP_KERNEL);
-	if (!reg_set->reg_tbl) {
-		dprintk(VIDC_ERR, "%s Failed to alloc register table\n",
-			__func__);
-		return -ENOMEM;
-	}
-
-	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,reg-presets",
-		(u32 *)reg_set->reg_tbl, reg_set->count * 2)) {
-		dprintk(VIDC_ERR, "Failed to read register table\n");
-		msm_vidc_free_reg_table(res);
-		return -EINVAL;
-	}
-	for (i = 0; i < reg_set->count; i++) {
-		dprintk(VIDC_DBG,
-			"reg = %x, value = %x\n",
-			reg_set->reg_tbl[i].reg,
-			reg_set->reg_tbl[i].value
-		);
-	}
-	return rc;
-}
-
-static void msm_vidc_free_bus_vector(struct msm_bus_scale_pdata *bus_pdata)
-{
-	int i;
-	for (i = 0; i < bus_pdata->num_usecases; i++) {
-		kfree(bus_pdata->usecase[i].vectors);
-		bus_pdata->usecase[i].vectors = NULL;
-	}
-
-	kfree(bus_pdata->usecase);
-	bus_pdata->usecase = NULL;
-}
-
-static int msm_vidc_load_bus_vector(struct platform_device *pdev,
-			struct msm_bus_scale_pdata *bus_pdata, u32 num_ports,
-			struct bus_pdata_config *bus_pdata_config)
-{
-	struct bus_values {
-	    u32 ab;
-	    u32 ib;
-	};
-	struct bus_values *values;
-	int i, j;
-	int rc = 0;
-
-	values = kzalloc(sizeof(*values) * bus_pdata->num_usecases, GFP_KERNEL);
-	if (!values) {
-		dprintk(VIDC_ERR, "%s Failed to alloc bus_values\n", __func__);
-		rc = -ENOMEM;
-		goto err_mem_alloc;
-	}
-
-	if (of_property_read_u32_array(pdev->dev.of_node,
-		    bus_pdata_config->name, (u32 *)values,
-		    bus_pdata->num_usecases * (sizeof(*values)/sizeof(u32)))) {
-		dprintk(VIDC_ERR, "%s Failed to read bus values\n", __func__);
-		rc = -EINVAL;
-		goto err_parse_dt;
-	}
-
-	bus_pdata->usecase = kzalloc(sizeof(*bus_pdata->usecase) *
-		    bus_pdata->num_usecases, GFP_KERNEL);
-	if (!bus_pdata->usecase) {
-		dprintk(VIDC_ERR,
-			"%s Failed to alloc bus_pdata usecase\n", __func__);
-		rc = -ENOMEM;
-		goto err_parse_dt;
-	}
-	bus_pdata->name = bus_pdata_config->name;
-	for (i = 0; i < bus_pdata->num_usecases; i++) {
-		bus_pdata->usecase[i].vectors = kzalloc(
-			sizeof(*bus_pdata->usecase[i].vectors) * num_ports,
-			GFP_KERNEL);
-		if (!bus_pdata->usecase) {
-			dprintk(VIDC_ERR,
-				"%s Failed to alloc bus_pdata usecase\n",
-				__func__);
-			break;
-		}
-		for (j = 0; j < num_ports; j++) {
-			bus_pdata->usecase[i].vectors[j].ab = (u64)values[i].ab
-									* 1000;
-			bus_pdata->usecase[i].vectors[j].ib = (u64)values[i].ib
-									* 1000;
-			bus_pdata->usecase[i].vectors[j].src =
-						bus_pdata_config->masters[j];
-			bus_pdata->usecase[i].vectors[j].dst =
-						bus_pdata_config->slaves[j];
-			dprintk(VIDC_DBG,
-				"ab = %llu, ib = %llu, src = %d, dst = %d\n",
-				bus_pdata->usecase[i].vectors[j].ab,
-				bus_pdata->usecase[i].vectors[j].ib,
-				bus_pdata->usecase[i].vectors[j].src,
-				bus_pdata->usecase[i].vectors[j].dst);
-		}
-		bus_pdata->usecase[i].num_paths = num_ports;
-	}
-	if (i < bus_pdata->num_usecases) {
-		for (--i; i >= 0; i--) {
-			kfree(bus_pdata->usecase[i].vectors);
-			bus_pdata->usecase[i].vectors = NULL;
-		}
-		kfree(bus_pdata->usecase);
-		bus_pdata->usecase = NULL;
-		rc = -EINVAL;
-	}
-err_parse_dt:
-	kfree(values);
-err_mem_alloc:
-	return rc;
-}
-
-static int msm_vidc_load_bus_vectors(struct msm_vidc_platform_resources *res)
-{
-	u32 num_ports = 0;
-	int rc = 0;
-	int i;
-	struct platform_device *pdev = res->pdev;
-	u32 num_bus_pdata = ARRAY_SIZE(bus_pdata_config_vector);
-
-	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,bus-ports",
-			(u32 *)&num_ports, 1) || (num_ports == 0))
-		goto err_mem_alloc;
-
-	res->bus_pdata = kzalloc(sizeof(*res->bus_pdata) * num_bus_pdata,
-				GFP_KERNEL);
-	if (!res->bus_pdata) {
-		dprintk(VIDC_ERR, "Failed to alloc memory\n");
-		rc = -ENOMEM;
-		goto err_mem_alloc;
-	}
-	for (i = 0; i < num_bus_pdata; i++) {
-		if (!res->has_ocmem &&
-			(!strcmp(bus_pdata_config_vector[i].name,
-				"qcom,enc-ocmem-ab-ib")
-			|| !strcmp(bus_pdata_config_vector[i].name,
-				"qcom,dec-ocmem-ab-ib"))) {
-			continue;
-		}
-		res->bus_pdata[i].num_usecases = get_u32_array_num_elements(
-					pdev, bus_pdata_config_vector[i].name);
-		if (res->bus_pdata[i].num_usecases == 0) {
-			dprintk(VIDC_ERR, "no elements in %s\n",
-				bus_pdata_config_vector[i].name);
-			rc = -EINVAL;
-			break;
-		}
-
-		rc = msm_vidc_load_bus_vector(pdev, &res->bus_pdata[i],
-				num_ports, &bus_pdata_config_vector[i]);
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"Failed to load bus vector: %d\n", i);
-			break;
-		}
-	}
-	if (i < num_bus_pdata) {
-		for (--i; i >= 0; i--)
-			msm_vidc_free_bus_vector(&res->bus_pdata[i]);
-		kfree(res->bus_pdata);
-		res->bus_pdata = NULL;
-	}
-err_mem_alloc:
-	return rc;
-}
-
-static int msm_vidc_load_iommu_groups(struct msm_vidc_platform_resources *res)
-{
-	int rc = 0;
-	struct platform_device *pdev = res->pdev;
-	struct device_node *ctx_node;
-	struct iommu_set *iommu_group_set = &res->iommu_group_set;
-	int array_size;
-	int i;
-	struct iommu_info *iommu_map;
-	u32 *buffer_types = NULL;
-
-	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-groups",
-				&array_size)) {
-		dprintk(VIDC_DBG, "iommu_groups property not present\n");
-		iommu_group_set->count = 0;
-		return 0;
-	}
-
-	iommu_group_set->count = array_size / sizeof(u32);
-	if (iommu_group_set->count == 0) {
-		dprintk(VIDC_ERR, "No group present in iommu_groups\n");
-		rc = -ENOENT;
-		goto err_no_of_node;
-	}
-
-	iommu_group_set->iommu_maps = kzalloc(iommu_group_set->count *
-			sizeof(*(iommu_group_set->iommu_maps)), GFP_KERNEL);
-	if (!iommu_group_set->iommu_maps) {
-		dprintk(VIDC_ERR, "%s Failed to alloc iommu_maps\n",
-			__func__);
-		rc = -ENOMEM;
-		goto err_no_of_node;
-	}
-
-	buffer_types = kzalloc(iommu_group_set->count * sizeof(*buffer_types),
-				GFP_KERNEL);
-	if (!buffer_types) {
-		dprintk(VIDC_ERR,
-			"%s Failed to alloc iommu group buffer types\n",
-			__func__);
-		rc = -ENOMEM;
-		goto err_load_groups;
-	}
-
-	rc = of_property_read_u32_array(pdev->dev.of_node,
-			"qcom,iommu-group-buffer-types", buffer_types,
-			iommu_group_set->count);
-	if (rc) {
-		dprintk(VIDC_ERR,
-		    "%s Failed to read iommu group buffer types\n", __func__);
-		goto err_load_groups;
-	}
-
-	for (i = 0; i < iommu_group_set->count; i++) {
-		iommu_map = &iommu_group_set->iommu_maps[i];
-		ctx_node = of_parse_phandle(pdev->dev.of_node,
-				"qcom,iommu-groups", i);
-		if (!ctx_node) {
-			dprintk(VIDC_ERR, "Unable to parse phandle : %u\n", i);
-			rc = -EBADHANDLE;
-			goto err_load_groups;
-		}
-
-		rc = of_property_read_string(ctx_node, "label",
-				&(iommu_map->name));
-		if (rc) {
-			dprintk(VIDC_ERR, "Could not find label property\n");
-			goto err_load_groups;
-		}
-
-		if (!of_get_property(ctx_node, "qcom,virtual-addr-pool",
-				&array_size)) {
-			dprintk(VIDC_ERR,
-				"Could not find any addr pool for group : %s\n",
-				iommu_map->name);
-			rc = -EBADHANDLE;
-			goto err_load_groups;
-		}
-
-		iommu_map->npartitions = array_size / sizeof(u32) / 2;
-
-		rc = of_property_read_u32_array(ctx_node,
-				"qcom,virtual-addr-pool",
-				(u32 *)iommu_map->addr_range,
-				iommu_map->npartitions * 2);
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"Could not read addr pool for group : %s\n",
-				iommu_map->name);
-			goto err_load_groups;
-		}
-
-		iommu_map->buffer_type = buffer_types[i];
-		iommu_map->is_secure =
-			of_property_read_bool(ctx_node,	"qcom,secure-domain");
-	}
-	kfree(buffer_types);
-	return 0;
-err_load_groups:
-	kfree(buffer_types);
-	msm_vidc_free_iommu_groups(res);
-err_no_of_node:
-	return rc;
-}
-
-static int msm_vidc_load_buffer_usage_table(
-		struct msm_vidc_platform_resources *res)
-{
-	int rc = 0;
-	struct platform_device *pdev = res->pdev;
-	struct buffer_usage_set *buffer_usage_set = &res->buffer_usage_set;
-
-	buffer_usage_set->count = get_u32_array_num_elements(
-				    pdev, "qcom,buffer-type-tz-usage-table");
-	if (buffer_usage_set->count == 0) {
-		dprintk(VIDC_DBG, "no elements in buffer usage set\n");
-		return 0;
-	}
-
-	buffer_usage_set->buffer_usage_tbl = kzalloc(buffer_usage_set->count *
-			sizeof(*(buffer_usage_set->buffer_usage_tbl)),
-			GFP_KERNEL);
-	if (!buffer_usage_set->buffer_usage_tbl) {
-		dprintk(VIDC_ERR, "%s Failed to alloc buffer usage table\n",
-			__func__);
-		rc = -ENOMEM;
-		goto err_load_buf_usage;
-	}
-
-	rc = of_property_read_u32_array(pdev->dev.of_node,
-		    "qcom,buffer-type-tz-usage-table",
-		(u32 *)buffer_usage_set->buffer_usage_tbl,
-		buffer_usage_set->count *
-		(sizeof(*buffer_usage_set->buffer_usage_tbl)/sizeof(u32)));
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to read buffer usage table\n");
-		goto err_load_buf_usage;
-	}
-
-	return 0;
-err_load_buf_usage:
-	msm_vidc_free_buffer_usage_table(res);
-	return rc;
-}
-
-
-static int read_platform_resources_from_dt(
-		struct msm_vidc_platform_resources *res)
-{
-	struct platform_device *pdev = res->pdev;
-	struct resource *kres = NULL;
-	int rc = 0;
-
-	if (!pdev->dev.of_node) {
-		dprintk(VIDC_ERR, "DT node not found\n");
-		return -ENOENT;
-	}
-
-	res->fw_base_addr = 0x0;
-
-	kres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	res->register_base = kres ? kres->start : -1;
-	res->register_size = kres ? (kres->end + 1 - kres->start) : -1;
-
-	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	res->irq = kres ? kres->start : -1;
-
-	res->has_ocmem = of_property_read_bool(pdev->dev.of_node,
-						"qcom,has-ocmem");
-
-	rc = msm_vidc_load_freq_table(res);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to load freq table: %d\n", rc);
-		goto err_load_freq_table;
-	}
-	rc = msm_vidc_load_reg_table(res);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to load reg table: %d\n", rc);
-		goto err_load_reg_table;
-	}
-	rc = msm_vidc_load_bus_vectors(res);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to load bus vectors: %d\n", rc);
-		goto err_load_bus_vectors;
-	}
-	rc = msm_vidc_load_iommu_groups(res);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to load iommu groups: %d\n", rc);
-		goto err_load_iommu_groups;
-	}
-	rc = msm_vidc_load_buffer_usage_table(res);
-	if (rc) {
-		dprintk(VIDC_ERR,
-			"Failed to load buffer usage table: %d\n", rc);
-		goto err_load_buffer_usage_table;
-	}
-
-	rc = of_property_read_u32(pdev->dev.of_node, "qcom,max-hw-load",
-			&res->max_load);
-	if (rc) {
-		dprintk(VIDC_ERR,
-			"Failed to determine max load supported: %d\n", rc);
-		goto err_load_buffer_usage_table;
-	}
-
-	return rc;
-
-err_load_buffer_usage_table:
-	msm_vidc_free_iommu_groups(res);
-err_load_iommu_groups:
-	msm_vidc_free_bus_vectors(res);
-err_load_bus_vectors:
-	msm_vidc_free_reg_table(res);
-err_load_reg_table:
-	msm_vidc_free_freq_table(res);
-err_load_freq_table:
-	return rc;
-}
-
-static int read_platform_resources_from_board(
-		struct msm_vidc_platform_resources *res)
-{
-	struct resource *kres = NULL;
-	struct platform_device *pdev = res->pdev;
-	struct msm_vidc_v4l2_platform_data *pdata = pdev->dev.platform_data;
-	int c = 0, rc = 0;
-
-	if (!pdata) {
-		dprintk(VIDC_ERR, "Platform data not found\n");
-		return -ENOENT;
-	}
-
-	res->fw_base_addr = 0x0;
-
-	kres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	res->register_base = kres ? kres->start : -1;
-	res->register_size = kres ? (kres->end + 1 - kres->start) : -1;
-
-	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	res->irq = kres ? kres->start : -1;
-
-	res->load_freq_tbl = kzalloc(pdata->num_load_table *
-			sizeof(*res->load_freq_tbl), GFP_KERNEL);
-
-	if (!res->load_freq_tbl) {
-		dprintk(VIDC_ERR, "%s Failed to alloc load_freq_tbl\n",
-				__func__);
-		return -ENOMEM;
-	}
-
-	res->load_freq_tbl_size = pdata->num_load_table;
-	for (c = 0; c > pdata->num_load_table; ++c) {
-		res->load_freq_tbl[c].load = pdata->load_table[c][0];
-		res->load_freq_tbl[c].freq = pdata->load_table[c][1];
-	}
-
-	res->max_load = pdata->max_load;
-	return rc;
-}
-
 static int read_platform_resources(struct msm_vidc_core *core,
 		struct platform_device *pdev)
 {
@@ -1521,11 +905,7 @@
 	video_unregister_device(&core->vdev[MSM_VIDC_DECODER].vdev);
 	v4l2_device_unregister(&core->v4l2_dev);
 
-	msm_vidc_free_freq_table(&core->resources);
-	msm_vidc_free_reg_table(&core->resources);
-	msm_vidc_free_bus_vectors(&core->resources);
-	msm_vidc_free_iommu_groups(&core->resources);
-	msm_vidc_free_buffer_usage_table(&core->resources);
+	msm_vidc_free_platform_resources(&core->resources);
 	kfree(core);
 	return rc;
 }
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
new file mode 100644
index 0000000..cb08da7
--- /dev/null
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -0,0 +1,642 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/of.h>
+#include <mach/board.h>
+#include "msm_vidc_resources.h"
+#include "msm_vidc_debug.h"
+#include "msm_vidc_res_parse.h"
+
+struct master_slave {
+	int masters_ocmem[2];
+	int masters_ddr[2];
+	int slaves_ocmem[2];
+	int slaves_ddr[2];
+};
+
+static struct master_slave bus_vectors_masters_slaves = {
+	.masters_ocmem = {MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+				MSM_BUS_MASTER_VIDEO_P1_OCMEM},
+	.masters_ddr = {MSM_BUS_MASTER_VIDEO_P0, MSM_BUS_MASTER_VIDEO_P1},
+	.slaves_ocmem = {MSM_BUS_SLAVE_OCMEM, MSM_BUS_SLAVE_OCMEM},
+	.slaves_ddr = {MSM_BUS_SLAVE_EBI_CH0, MSM_BUS_SLAVE_EBI_CH0},
+};
+
+struct bus_pdata_config {
+	int *masters;
+	int *slaves;
+	char *name;
+};
+
+static struct bus_pdata_config bus_pdata_config_vector[] = {
+	{
+		.masters = bus_vectors_masters_slaves.masters_ocmem,
+		.slaves = bus_vectors_masters_slaves.slaves_ocmem,
+		.name = "qcom,enc-ocmem-ab-ib",
+	},
+	{
+		.masters = bus_vectors_masters_slaves.masters_ocmem,
+		.slaves = bus_vectors_masters_slaves.slaves_ocmem,
+		.name = "qcom,dec-ocmem-ab-ib",
+	},
+	{
+		.masters = bus_vectors_masters_slaves.masters_ddr,
+		.slaves = bus_vectors_masters_slaves.slaves_ddr,
+		.name = "qcom,enc-ddr-ab-ib",
+	},
+	{
+		.masters = bus_vectors_masters_slaves.masters_ddr,
+		.slaves = bus_vectors_masters_slaves.slaves_ddr,
+		.name = "qcom,dec-ddr-ab-ib",
+	},
+};
+
+static size_t get_u32_array_num_elements(struct platform_device *pdev,
+					char *name)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int len;
+	size_t num_elements = 0;
+	if (!of_get_property(np, name, &len)) {
+		dprintk(VIDC_ERR, "Failed to read %s from device tree\n",
+			name);
+		goto fail_read;
+	}
+
+	num_elements = len / sizeof(u32);
+	if (num_elements <= 0) {
+		dprintk(VIDC_ERR, "%s not specified in device tree\n",
+			name);
+		goto fail_read;
+	}
+	return num_elements / 2;
+
+fail_read:
+	return 0;
+}
+
+int read_hfi_type(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int rc = 0;
+	const char *hfi_name = NULL;
+
+	if (np) {
+		rc = of_property_read_string(np, "qcom,hfi", &hfi_name);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"Failed to read hfi from device tree\n");
+			goto err_hfi_read;
+		}
+		if (!strcmp(hfi_name, "venus"))
+			rc = VIDC_HFI_VENUS;
+		else if (!strcmp(hfi_name, "q6"))
+			rc = VIDC_HFI_Q6;
+		else
+			rc = -EINVAL;
+	} else
+		rc = VIDC_HFI_Q6;
+
+err_hfi_read:
+	return rc;
+}
+
+static inline void msm_vidc_free_freq_table(
+		struct msm_vidc_platform_resources *res)
+{
+	kfree(res->load_freq_tbl);
+	res->load_freq_tbl = NULL;
+}
+
+static inline void msm_vidc_free_reg_table(
+			struct msm_vidc_platform_resources *res)
+{
+	kfree(res->reg_set.reg_tbl);
+	res->reg_set.reg_tbl = NULL;
+}
+
+static inline void msm_vidc_free_bus_vectors(
+			struct msm_vidc_platform_resources *res)
+{
+	int i, j;
+	if (res->bus_pdata) {
+		for (i = 0; i < ARRAY_SIZE(bus_pdata_config_vector); i++) {
+			for (j = 0; j < res->bus_pdata[i].num_usecases; j++) {
+				kfree(res->bus_pdata[i].usecase[j].vectors);
+				res->bus_pdata[i].usecase[j].vectors = NULL;
+			}
+			kfree(res->bus_pdata[i].usecase);
+			res->bus_pdata[i].usecase = NULL;
+		}
+		kfree(res->bus_pdata);
+		res->bus_pdata = NULL;
+	}
+}
+
+static inline void msm_vidc_free_iommu_groups(
+			struct msm_vidc_platform_resources *res)
+{
+	kfree(res->iommu_group_set.iommu_maps);
+	res->iommu_group_set.iommu_maps = NULL;
+}
+
+static inline void msm_vidc_free_buffer_usage_table(
+			struct msm_vidc_platform_resources *res)
+{
+	kfree(res->buffer_usage_set.buffer_usage_tbl);
+	res->buffer_usage_set.buffer_usage_tbl = NULL;
+}
+
+void msm_vidc_free_platform_resources(
+			struct msm_vidc_platform_resources *res)
+{
+	msm_vidc_free_freq_table(res);
+	msm_vidc_free_reg_table(res);
+	msm_vidc_free_bus_vectors(res);
+	msm_vidc_free_iommu_groups(res);
+	msm_vidc_free_buffer_usage_table(res);
+}
+
+static void msm_vidc_free_bus_vector(struct msm_bus_scale_pdata *bus_pdata)
+{
+	int i;
+	for (i = 0; i < bus_pdata->num_usecases; i++) {
+		kfree(bus_pdata->usecase[i].vectors);
+		bus_pdata->usecase[i].vectors = NULL;
+	}
+
+	kfree(bus_pdata->usecase);
+	bus_pdata->usecase = NULL;
+}
+
+static int msm_vidc_load_reg_table(struct msm_vidc_platform_resources *res)
+{
+	struct reg_set *reg_set;
+	struct platform_device *pdev = res->pdev;
+	int i;
+	int rc = 0;
+
+	reg_set = &res->reg_set;
+	reg_set->count = get_u32_array_num_elements(pdev, "qcom,reg-presets");
+	if (reg_set->count == 0) {
+		dprintk(VIDC_DBG, "no elements in reg set\n");
+		return rc;
+	}
+
+	reg_set->reg_tbl = kzalloc(reg_set->count *
+			sizeof(*(reg_set->reg_tbl)), GFP_KERNEL);
+	if (!reg_set->reg_tbl) {
+		dprintk(VIDC_ERR, "%s Failed to alloc register table\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,reg-presets",
+		(u32 *)reg_set->reg_tbl, reg_set->count * 2)) {
+		dprintk(VIDC_ERR, "Failed to read register table\n");
+		msm_vidc_free_reg_table(res);
+		return -EINVAL;
+	}
+	for (i = 0; i < reg_set->count; i++) {
+		dprintk(VIDC_DBG,
+			"reg = %x, value = %x\n",
+			reg_set->reg_tbl[i].reg,
+			reg_set->reg_tbl[i].value
+		);
+	}
+	return rc;
+}
+static int msm_vidc_load_freq_table(struct msm_vidc_platform_resources *res)
+{
+	int rc = 0;
+	int num_elements = 0;
+	struct platform_device *pdev = res->pdev;
+
+	num_elements = get_u32_array_num_elements(pdev, "qcom,load-freq-tbl");
+	if (num_elements == 0) {
+		dprintk(VIDC_ERR, "no elements in frequency table\n");
+		return rc;
+	}
+
+	res->load_freq_tbl = kzalloc(num_elements * sizeof(*res->load_freq_tbl),
+			GFP_KERNEL);
+	if (!res->load_freq_tbl) {
+		dprintk(VIDC_ERR,
+				"%s Failed to alloc load_freq_tbl\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	if (of_property_read_u32_array(pdev->dev.of_node,
+		"qcom,load-freq-tbl", (u32 *)res->load_freq_tbl,
+		num_elements * 2)) {
+		dprintk(VIDC_ERR, "Failed to read frequency table\n");
+		msm_vidc_free_freq_table(res);
+		return -EINVAL;
+	}
+
+	res->load_freq_tbl_size = num_elements;
+	return rc;
+}
+
+static int msm_vidc_load_bus_vector(struct platform_device *pdev,
+			struct msm_bus_scale_pdata *bus_pdata, u32 num_ports,
+			struct bus_pdata_config *bus_pdata_config)
+{
+	struct bus_values {
+	    u32 ab;
+	    u32 ib;
+	};
+	struct bus_values *values;
+	int i, j;
+	int rc = 0;
+
+	values = kzalloc(sizeof(*values) * bus_pdata->num_usecases, GFP_KERNEL);
+	if (!values) {
+		dprintk(VIDC_ERR, "%s Failed to alloc bus_values\n", __func__);
+		rc = -ENOMEM;
+		goto err_mem_alloc;
+	}
+
+	if (of_property_read_u32_array(pdev->dev.of_node,
+		    bus_pdata_config->name, (u32 *)values,
+		    bus_pdata->num_usecases * (sizeof(*values)/sizeof(u32)))) {
+		dprintk(VIDC_ERR, "%s Failed to read bus values\n", __func__);
+		rc = -EINVAL;
+		goto err_parse_dt;
+	}
+
+	bus_pdata->usecase = kzalloc(sizeof(*bus_pdata->usecase) *
+		    bus_pdata->num_usecases, GFP_KERNEL);
+	if (!bus_pdata->usecase) {
+		dprintk(VIDC_ERR,
+			"%s Failed to alloc bus_pdata usecase\n", __func__);
+		rc = -ENOMEM;
+		goto err_parse_dt;
+	}
+	bus_pdata->name = bus_pdata_config->name;
+	for (i = 0; i < bus_pdata->num_usecases; i++) {
+		bus_pdata->usecase[i].vectors = kzalloc(
+			sizeof(*bus_pdata->usecase[i].vectors) * num_ports,
+			GFP_KERNEL);
+		if (!bus_pdata->usecase) {
+			dprintk(VIDC_ERR,
+				"%s Failed to alloc bus_pdata usecase\n",
+				__func__);
+			break;
+		}
+		for (j = 0; j < num_ports; j++) {
+			bus_pdata->usecase[i].vectors[j].ab = (u64)values[i].ab
+									* 1000;
+			bus_pdata->usecase[i].vectors[j].ib = (u64)values[i].ib
+									* 1000;
+			bus_pdata->usecase[i].vectors[j].src =
+						bus_pdata_config->masters[j];
+			bus_pdata->usecase[i].vectors[j].dst =
+						bus_pdata_config->slaves[j];
+			dprintk(VIDC_DBG,
+				"ab = %llu, ib = %llu, src = %d, dst = %d\n",
+				bus_pdata->usecase[i].vectors[j].ab,
+				bus_pdata->usecase[i].vectors[j].ib,
+				bus_pdata->usecase[i].vectors[j].src,
+				bus_pdata->usecase[i].vectors[j].dst);
+		}
+		bus_pdata->usecase[i].num_paths = num_ports;
+	}
+	if (i < bus_pdata->num_usecases) {
+		for (--i; i >= 0; i--) {
+			kfree(bus_pdata->usecase[i].vectors);
+			bus_pdata->usecase[i].vectors = NULL;
+		}
+		kfree(bus_pdata->usecase);
+		bus_pdata->usecase = NULL;
+		rc = -EINVAL;
+	}
+err_parse_dt:
+	kfree(values);
+err_mem_alloc:
+	return rc;
+}
+
+static int msm_vidc_load_bus_vectors(struct msm_vidc_platform_resources *res)
+{
+	u32 num_ports = 0;
+	int rc = 0;
+	int i;
+	struct platform_device *pdev = res->pdev;
+	u32 num_bus_pdata = ARRAY_SIZE(bus_pdata_config_vector);
+
+	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,bus-ports",
+			(u32 *)&num_ports, 1) || (num_ports == 0))
+		goto err_mem_alloc;
+
+	res->bus_pdata = kzalloc(sizeof(*res->bus_pdata) * num_bus_pdata,
+				GFP_KERNEL);
+	if (!res->bus_pdata) {
+		dprintk(VIDC_ERR, "Failed to alloc memory\n");
+		rc = -ENOMEM;
+		goto err_mem_alloc;
+	}
+	for (i = 0; i < num_bus_pdata; i++) {
+		if (!res->has_ocmem &&
+			(!strcmp(bus_pdata_config_vector[i].name,
+				"qcom,enc-ocmem-ab-ib")
+			|| !strcmp(bus_pdata_config_vector[i].name,
+				"qcom,dec-ocmem-ab-ib"))) {
+			continue;
+		}
+		res->bus_pdata[i].num_usecases = get_u32_array_num_elements(
+					pdev, bus_pdata_config_vector[i].name);
+		if (res->bus_pdata[i].num_usecases == 0) {
+			dprintk(VIDC_ERR, "no elements in %s\n",
+				bus_pdata_config_vector[i].name);
+			rc = -EINVAL;
+			break;
+		}
+
+		rc = msm_vidc_load_bus_vector(pdev, &res->bus_pdata[i],
+				num_ports, &bus_pdata_config_vector[i]);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"Failed to load bus vector: %d\n", i);
+			break;
+		}
+	}
+	if (i < num_bus_pdata) {
+		for (--i; i >= 0; i--)
+			msm_vidc_free_bus_vector(&res->bus_pdata[i]);
+		kfree(res->bus_pdata);
+		res->bus_pdata = NULL;
+	}
+err_mem_alloc:
+	return rc;
+}
+
+static int msm_vidc_load_iommu_groups(struct msm_vidc_platform_resources *res)
+{
+	int rc = 0;
+	struct platform_device *pdev = res->pdev;
+	struct device_node *ctx_node;
+	struct iommu_set *iommu_group_set = &res->iommu_group_set;
+	int array_size;
+	int i;
+	struct iommu_info *iommu_map;
+	u32 *buffer_types = NULL;
+
+	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-groups",
+				&array_size)) {
+		dprintk(VIDC_DBG, "iommu_groups property not present\n");
+		iommu_group_set->count = 0;
+		return 0;
+	}
+
+	iommu_group_set->count = array_size / sizeof(u32);
+	if (iommu_group_set->count == 0) {
+		dprintk(VIDC_ERR, "No group present in iommu_groups\n");
+		rc = -ENOENT;
+		goto err_no_of_node;
+	}
+
+	iommu_group_set->iommu_maps = kzalloc(iommu_group_set->count *
+			sizeof(*(iommu_group_set->iommu_maps)), GFP_KERNEL);
+	if (!iommu_group_set->iommu_maps) {
+		dprintk(VIDC_ERR, "%s Failed to alloc iommu_maps\n",
+			__func__);
+		rc = -ENOMEM;
+		goto err_no_of_node;
+	}
+
+	buffer_types = kzalloc(iommu_group_set->count * sizeof(*buffer_types),
+				GFP_KERNEL);
+	if (!buffer_types) {
+		dprintk(VIDC_ERR,
+			"%s Failed to alloc iommu group buffer types\n",
+			__func__);
+		rc = -ENOMEM;
+		goto err_load_groups;
+	}
+
+	rc = of_property_read_u32_array(pdev->dev.of_node,
+			"qcom,iommu-group-buffer-types", buffer_types,
+			iommu_group_set->count);
+	if (rc) {
+		dprintk(VIDC_ERR,
+		    "%s Failed to read iommu group buffer types\n", __func__);
+		goto err_load_groups;
+	}
+
+	for (i = 0; i < iommu_group_set->count; i++) {
+		iommu_map = &iommu_group_set->iommu_maps[i];
+		ctx_node = of_parse_phandle(pdev->dev.of_node,
+				"qcom,iommu-groups", i);
+		if (!ctx_node) {
+			dprintk(VIDC_ERR, "Unable to parse phandle : %u\n", i);
+			rc = -EBADHANDLE;
+			goto err_load_groups;
+		}
+
+		rc = of_property_read_string(ctx_node, "label",
+				&(iommu_map->name));
+		if (rc) {
+			dprintk(VIDC_ERR, "Could not find label property\n");
+			goto err_load_groups;
+		}
+
+		if (!of_get_property(ctx_node, "qcom,virtual-addr-pool",
+				&array_size)) {
+			dprintk(VIDC_ERR,
+				"Could not find any addr pool for group : %s\n",
+				iommu_map->name);
+			rc = -EBADHANDLE;
+			goto err_load_groups;
+		}
+
+		iommu_map->npartitions = array_size / sizeof(u32) / 2;
+
+		rc = of_property_read_u32_array(ctx_node,
+				"qcom,virtual-addr-pool",
+				(u32 *)iommu_map->addr_range,
+				iommu_map->npartitions * 2);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"Could not read addr pool for group : %s\n",
+				iommu_map->name);
+			goto err_load_groups;
+		}
+
+		iommu_map->buffer_type = buffer_types[i];
+		iommu_map->is_secure =
+			of_property_read_bool(ctx_node,	"qcom,secure-domain");
+	}
+	kfree(buffer_types);
+	return 0;
+err_load_groups:
+	kfree(buffer_types);
+	msm_vidc_free_iommu_groups(res);
+err_no_of_node:
+	return rc;
+}
+
+static int msm_vidc_load_buffer_usage_table(
+		struct msm_vidc_platform_resources *res)
+{
+	int rc = 0;
+	struct platform_device *pdev = res->pdev;
+	struct buffer_usage_set *buffer_usage_set = &res->buffer_usage_set;
+
+	buffer_usage_set->count = get_u32_array_num_elements(
+				    pdev, "qcom,buffer-type-tz-usage-table");
+	if (buffer_usage_set->count == 0) {
+		dprintk(VIDC_DBG, "no elements in buffer usage set\n");
+		return 0;
+	}
+
+	buffer_usage_set->buffer_usage_tbl = kzalloc(buffer_usage_set->count *
+			sizeof(*(buffer_usage_set->buffer_usage_tbl)),
+			GFP_KERNEL);
+	if (!buffer_usage_set->buffer_usage_tbl) {
+		dprintk(VIDC_ERR, "%s Failed to alloc buffer usage table\n",
+			__func__);
+		rc = -ENOMEM;
+		goto err_load_buf_usage;
+	}
+
+	rc = of_property_read_u32_array(pdev->dev.of_node,
+		    "qcom,buffer-type-tz-usage-table",
+		(u32 *)buffer_usage_set->buffer_usage_tbl,
+		buffer_usage_set->count *
+		(sizeof(*buffer_usage_set->buffer_usage_tbl)/sizeof(u32)));
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to read buffer usage table\n");
+		goto err_load_buf_usage;
+	}
+
+	return 0;
+err_load_buf_usage:
+	msm_vidc_free_buffer_usage_table(res);
+	return rc;
+}
+
+int read_platform_resources_from_dt(
+		struct msm_vidc_platform_resources *res)
+{
+	struct platform_device *pdev = res->pdev;
+	struct resource *kres = NULL;
+	int rc = 0;
+
+	if (!pdev->dev.of_node) {
+		dprintk(VIDC_ERR, "DT node not found\n");
+		return -ENOENT;
+	}
+
+	res->fw_base_addr = 0x0;
+
+	kres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res->register_base = kres ? kres->start : -1;
+	res->register_size = kres ? (kres->end + 1 - kres->start) : -1;
+
+	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	res->irq = kres ? kres->start : -1;
+
+	res->has_ocmem = of_property_read_bool(pdev->dev.of_node,
+						"qcom,has-ocmem");
+
+	rc = msm_vidc_load_freq_table(res);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to load freq table: %d\n", rc);
+		goto err_load_freq_table;
+	}
+	rc = msm_vidc_load_reg_table(res);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to load reg table: %d\n", rc);
+		goto err_load_reg_table;
+	}
+	rc = msm_vidc_load_bus_vectors(res);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to load bus vectors: %d\n", rc);
+		goto err_load_bus_vectors;
+	}
+	rc = msm_vidc_load_iommu_groups(res);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to load iommu groups: %d\n", rc);
+		goto err_load_iommu_groups;
+	}
+	rc = msm_vidc_load_buffer_usage_table(res);
+	if (rc) {
+		dprintk(VIDC_ERR,
+			"Failed to load buffer usage table: %d\n", rc);
+		goto err_load_buffer_usage_table;
+	}
+
+	rc = of_property_read_u32(pdev->dev.of_node, "qcom,max-hw-load",
+			&res->max_load);
+	if (rc) {
+		dprintk(VIDC_ERR,
+			"Failed to determine max load supported: %d\n", rc);
+		goto err_load_buffer_usage_table;
+	}
+
+	return rc;
+
+err_load_buffer_usage_table:
+	msm_vidc_free_iommu_groups(res);
+err_load_iommu_groups:
+	msm_vidc_free_bus_vectors(res);
+err_load_bus_vectors:
+	msm_vidc_free_reg_table(res);
+err_load_reg_table:
+	msm_vidc_free_freq_table(res);
+err_load_freq_table:
+	return rc;
+}
+
+int read_platform_resources_from_board(
+		struct msm_vidc_platform_resources *res)
+{
+	struct resource *kres = NULL;
+	struct platform_device *pdev = res->pdev;
+	struct msm_vidc_v4l2_platform_data *pdata = pdev->dev.platform_data;
+	int c = 0, rc = 0;
+
+	if (!pdata) {
+		dprintk(VIDC_ERR, "Platform data not found\n");
+		return -ENOENT;
+	}
+
+	res->fw_base_addr = 0x0;
+
+	kres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res->register_base = kres ? kres->start : -1;
+	res->register_size = kres ? (kres->end + 1 - kres->start) : -1;
+
+	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	res->irq = kres ? kres->start : -1;
+
+	res->load_freq_tbl = kzalloc(pdata->num_load_table *
+			sizeof(*res->load_freq_tbl), GFP_KERNEL);
+
+	if (!res->load_freq_tbl) {
+		dprintk(VIDC_ERR, "%s Failed to alloc load_freq_tbl\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	res->load_freq_tbl_size = pdata->num_load_table;
+	for (c = 0; c > pdata->num_load_table; ++c) {
+		res->load_freq_tbl[c].load = pdata->load_table[c][0];
+		res->load_freq_tbl[c].freq = pdata->load_table[c][1];
+	}
+
+	res->max_load = pdata->max_load;
+	return rc;
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.h b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.h
new file mode 100644
index 0000000..9fe6b58
--- /dev/null
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.h
@@ -0,0 +1,30 @@
+
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef DT_PARSE
+#define DT_PARSE
+#include <linux/of.h>
+#include <mach/board.h>
+#include "msm_vidc_resources.h"
+void msm_vidc_free_platform_resources(
+		struct msm_vidc_platform_resources *res);
+
+int read_hfi_type(struct platform_device *pdev);
+
+int read_platform_resources_from_dt(
+		struct msm_vidc_platform_resources *res);
+
+int read_platform_resources_from_board(
+		struct msm_vidc_platform_resources *res);
+#endif
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 15ac493..28ea41a 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -2852,8 +2852,8 @@
 	venus_hfi_disable_clks(device);
 fail_enable_clks:
 	subsystem_put(device->resources.fw.cookie);
-	device->resources.fw.cookie = NULL;
 fail_load_fw:
+	device->resources.fw.cookie = NULL;
 	venus_hfi_iommu_detach(device);
 fail_iommu_attach:
 	return rc;
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index a395b7c..aa71b74 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -802,7 +802,7 @@
 
 		if (device->tsif_vreg) {
 			regulator_set_voltage(device->tsif_vreg,
-					RPM_REGULATOR_CORNER_SVS_SOC,
+					RPM_REGULATOR_CORNER_NONE,
 					RPM_REGULATOR_CORNER_SUPER_TURBO);
 		}
 
@@ -818,7 +818,7 @@
 		clk_disable_unprepare(device->tsif_pclk);
 		if (device->tsif_vreg) {
 			regulator_set_voltage(device->tsif_vreg,
-					RPM_REGULATOR_CORNER_SVS_SOC,
+					RPM_REGULATOR_CORNER_NONE,
 					RPM_REGULATOR_CORNER_SUPER_TURBO);
 		}
 
@@ -848,7 +848,7 @@
 
 	if (device->tsif_vreg) {
 		rc = regulator_set_voltage(device->tsif_vreg,
-					RPM_REGULATOR_CORNER_SVS_SOC,
+					RPM_REGULATOR_CORNER_NONE,
 					RPM_REGULATOR_CORNER_SUPER_TURBO);
 		if (rc)
 			pr_err("Unable to set CX voltage.\n");
@@ -2945,7 +2945,7 @@
 
 		/* Set an initial voltage and enable the regulator */
 		rc = regulator_set_voltage(device->tsif_vreg,
-					RPM_REGULATOR_CORNER_SVS_SOC,
+					RPM_REGULATOR_CORNER_NONE,
 					RPM_REGULATOR_CORNER_SUPER_TURBO);
 		if (rc) {
 			dev_err(&pdev->dev, "Unable to set CX voltage.\n");
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index b81af11..d8cff35 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -55,7 +55,7 @@
 
 	for (i = 0; i < nr_strings; i++) {
 		buffer[i] = string;
-		strlcpy(string, buf, strlen(buf));
+		strlcpy(string, buf, strlen(buf) + 1);
 		string += strlen(string) + 1;
 		buf += strlen(buf) + 1;
 	}
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index e285bfa..476e75c 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1656,6 +1656,13 @@
 	sg_miter_stop(&host->pio.sg_miter);
 }
 
+static inline void msmsdcc_clear_pio_irq_mask(struct msmsdcc_host *host)
+{
+	writel_relaxed(readl_relaxed(host->base + MMCIMASK0) & ~MCI_IRQ_PIO,
+			host->base + MMCIMASK0);
+	mb();
+}
+
 static irqreturn_t
 msmsdcc_pio_irq(int irq, void *dev_id)
 {
@@ -1668,7 +1675,7 @@
 
 	spin_lock(&host->lock);
 
-	if (!atomic_read(&host->clks_on)) {
+	if (!atomic_read(&host->clks_on) || !host->curr.data) {
 		spin_unlock(&host->lock);
 		return IRQ_NONE;
 	}
@@ -1719,25 +1726,19 @@
 	msmsdcc_sg_stop(host);
 	local_irq_restore(flags);
 
+	if (!host->curr.xfer_remain) {
+		msmsdcc_clear_pio_irq_mask(host);
+		goto out_unlock;
+	}
+
 	if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) {
 		writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
-				(~(MCI_IRQ_PIO))) | MCI_RXDATAAVLBLMASK,
-				host->base + MMCIMASK0);
-		if (!host->curr.xfer_remain) {
-			/*
-			 * back to back write to MASK0 register don't need
-			 * synchronization delay.
-			 */
-			writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
-				(~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
-		}
-		mb();
-	} else if (!host->curr.xfer_remain) {
-		writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
-				(~(MCI_IRQ_PIO))) | 0, host->base + MMCIMASK0);
+					~MCI_IRQ_PIO) | MCI_RXDATAAVLBLMASK,
+					host->base + MMCIMASK0);
 		mb();
 	}
 
+out_unlock:
 	spin_unlock(&host->lock);
 
 	return IRQ_HANDLED;
@@ -1831,6 +1832,7 @@
 			msmsdcc_sps_exit_curr_xfer(host);
 		}
 		else if (host->curr.data) { /* Non DMA */
+			msmsdcc_clear_pio_irq_mask(host);
 			msmsdcc_reset_and_restore(host);
 			msmsdcc_stop_data(host);
 			msmsdcc_request_end(host, cmd->mrq);
@@ -2002,6 +2004,7 @@
 					/* Stop current SPS transfer */
 					msmsdcc_sps_exit_curr_xfer(host);
 				} else {
+					msmsdcc_clear_pio_irq_mask(host);
 					msmsdcc_reset_and_restore(host);
 					if (host->curr.data)
 						msmsdcc_stop_data(host);
@@ -5380,6 +5383,7 @@
 				/* Stop current SPS transfer */
 				msmsdcc_sps_exit_curr_xfer(host);
 			} else {
+				msmsdcc_clear_pio_irq_mask(host);
 				msmsdcc_reset_and_restore(host);
 				msmsdcc_stop_data(host);
 				if (mrq->data && mrq->data->stop)
diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c
index f000df7..644a751 100644
--- a/drivers/net/ethernet/msm/ecm_ipa.c
+++ b/drivers/net/ethernet/msm/ecm_ipa.c
@@ -1307,6 +1307,8 @@
 			next_state = ECM_IPA_INITIALIZED;
 		else if (operation == ECM_IPA_CONNECT)
 			next_state = ECM_IPA_CONNECTED_AND_UP;
+		else if (operation == ECM_IPA_CLEANUP)
+			next_state = ECM_IPA_UNLOADED;
 		break;
 	case ECM_IPA_CONNECTED_AND_UP:
 		if (operation == ECM_IPA_STOP)
diff --git a/drivers/net/ethernet/msm/msm_rmnet_wwan.c b/drivers/net/ethernet/msm/msm_rmnet_wwan.c
index 98bdccc..3e4605f 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_wwan.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_wwan.c
@@ -188,6 +188,9 @@
 		      __func__, skb);
 		netif_wake_queue(dev);
 	}
+	if (a2_mux_is_ch_empty(a2_mux_lcid_by_ch_id[wwan_ptr->ch_id]))
+		ipa_rm_inactivity_timer_release_resource(
+			ipa_rm_resource_by_ch_id[wwan_ptr->ch_id]);
 	spin_unlock_irqrestore(&wwan_ptr->lock, flags);
 }
 
@@ -533,6 +536,7 @@
 		       __func__, skb);
 	}
 	spin_unlock_irqrestore(&wwan_ptr->lock, flags);
+	return ret;
 exit:
 	ipa_rm_inactivity_timer_release_resource(
 		ipa_rm_resource_by_ch_id[wwan_ptr->ch_id]);
@@ -548,6 +552,7 @@
 static void wwan_tx_timeout(struct net_device *dev)
 {
 	pr_warning("[%s] wwan_tx_timeout(), data stall in UL\n", dev->name);
+	ipa_bam_reg_dump();
 }
 
 /**
diff --git a/drivers/net/ethernet/msm/qfec.c b/drivers/net/ethernet/msm/qfec.c
index 164b734..e68c395 100644
--- a/drivers/net/ethernet/msm/qfec.c
+++ b/drivers/net/ethernet/msm/qfec.c
@@ -2921,6 +2921,8 @@
 	priv->mii.dev           = dev;
 	priv->mii.mdio_read     = qfec_mdio_read;
 	priv->mii.mdio_write    = qfec_mdio_write;
+	/* initialize mdio clock */
+	priv->mdio_clk    = GMII_ADR_REG_CR_62;
 
 	/* map register regions */
 	ret = qfec_map_resource(
diff --git a/drivers/net/ethernet/msm/qfec.h b/drivers/net/ethernet/msm/qfec.h
index 525fd9c..a25436f 100644
--- a/drivers/net/ethernet/msm/qfec.h
+++ b/drivers/net/ethernet/msm/qfec.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2011,2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -411,6 +411,14 @@
 # define GMII_ADR_REG_GR           0x000007c0 /* addr bits */
 # define GMII_ADR_REG_RSVRD1       0x00000020 /* */
 # define GMII_ADR_REG_CR           0x0000001c /* csr clock range */
+
+# define GMII_ADR_REG_CR_42        0x00000000 /* csr clock 42 */
+# define GMII_ADR_REG_CR_62        0x00000001 /* csr clock 62 */
+# define GMII_ADR_REG_CR_16        0x00000002 /* csr clock 16 */
+# define GMII_ADR_REG_CR_26        0x00000003 /* csr clock 26 */
+# define GMII_ADR_REG_CR_102       0x00000004 /* csr clock 102 */
+# define GMII_ADR_REG_CR_124       0x00000005 /* csr clock 124 */
+
 # define GMII_ADR_REG_GW           0x00000002 /* gmii write */
 # define GMII_ADR_REG_GB           0x00000001 /* gmii busy */
 
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index a3d7f12..5e22c35 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -112,6 +112,9 @@
 #define CCU_PRONTO_LAST_ADDR1_OFFSET		0x10
 #define CCU_PRONTO_LAST_ADDR2_OFFSET		0x14
 
+#define MSM_PRONTO_SAW2_BASE			0xfb219000
+#define PRONTO_SAW2_SPM_STS_OFFSET		0x0c
+
 #define WCNSS_DEF_WLAN_RX_BUFF_COUNT		1024
 
 #define WCNSS_CTRL_CHANNEL			"WCNSS_CTRL"
@@ -288,6 +291,7 @@
 	void __iomem *riva_ccu_base;
 	void __iomem *pronto_a2xb_base;
 	void __iomem *pronto_ccpu_base;
+	void __iomem *pronto_saw2_base;
 	void __iomem *fiq_reg;
 	int	ssr_boot;
 	int	nv_downloaded;
@@ -479,6 +483,10 @@
 	reg = readl_relaxed(reg_addr);
 	pr_info_ratelimited("%s: CCU_CCPU_LAST_ADDR2 %08x\n", __func__, reg);
 
+	reg_addr = penv->pronto_saw2_base + PRONTO_SAW2_SPM_STS_OFFSET;
+	reg = readl_relaxed(reg_addr);
+	pr_info_ratelimited("%s: PRONTO_SAW2_SPM_STS %08x\n", __func__, reg);
+
 	tst_addr = penv->pronto_a2xb_base + A2XB_TSTBUS_OFFSET;
 	tst_ctrl_addr = penv->pronto_a2xb_base + A2XB_TSTBUS_CTRL_OFFSET;
 
@@ -1683,6 +1691,14 @@
 			ret = -ENOMEM;
 			goto fail_ioremap4;
 		}
+		penv->pronto_saw2_base = ioremap_nocache(MSM_PRONTO_SAW2_BASE,
+				SZ_32);
+		if (!penv->pronto_saw2_base) {
+			pr_err("%s: ioremap wcnss physical(saw2) failed\n",
+					__func__);
+			ret = -ENOMEM;
+			goto fail_ioremap5;
+		}
 	}
 
 	/* trigger initialization of the WCNSS */
@@ -1699,6 +1715,9 @@
 fail_pil:
 	if (penv->riva_ccu_base)
 		iounmap(penv->riva_ccu_base);
+	if (penv->pronto_saw2_base)
+		iounmap(penv->pronto_saw2_base);
+fail_ioremap5:
 	if (penv->fiq_reg)
 		iounmap(penv->fiq_reg);
 fail_ioremap4:
diff --git a/drivers/platform/msm/ipa/a2_service.c b/drivers/platform/msm/ipa/a2_service.c
index 4921ec2..ae9277e 100644
--- a/drivers/platform/msm/ipa/a2_service.c
+++ b/drivers/platform/msm/ipa/a2_service.c
@@ -1469,6 +1469,35 @@
 	return ret;
 }
 
+/**
+ * a2_mux_is_ch_empty() - checks if channel is empty.
+ * @lcid: logical channel ID
+ *
+ * Returns: true if the channel is empty,
+ *		false otherwise
+ */
+int a2_mux_is_ch_empty(enum a2_mux_logical_channel_id lcid)
+{
+	unsigned long flags;
+	int ret;
+
+	if (lcid >= A2_MUX_NUM_CHANNELS ||
+			lcid < 0)
+		return -EINVAL;
+	if (!a2_mux_ctx->a2_mux_initialized)
+		return -ENODEV;
+	spin_lock_irqsave(&a2_mux_ctx->bam_ch[lcid].lock, flags);
+	a2_mux_ctx->bam_ch[lcid].use_wm = 1;
+	ret = a2_mux_ctx->bam_ch[lcid].num_tx_pkts == 0;
+	if (!bam_ch_is_local_open(lcid)) {
+		ret = -ENODEV;
+		IPAERR("%s: port not open: %d\n", __func__,
+		       a2_mux_ctx->bam_ch[lcid].status);
+	}
+	spin_unlock_irqrestore(&a2_mux_ctx->bam_ch[lcid].lock, flags);
+	return ret;
+}
+
 static int a2_mux_initialize_context(int handle)
 {
 	int i;
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index f5d7b6e..6a16cf3 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -1667,13 +1667,6 @@
 	}
 	/* register IPA with SPS driver */
 	bam_props.phys_addr = resource_p->bam_mem_base;
-	bam_props.virt_addr = ioremap(resource_p->bam_mem_base,
-			resource_p->bam_mem_size);
-	if (!bam_props.virt_addr) {
-		IPAERR(":bam-base ioremap err.\n");
-		result = -EFAULT;
-		goto fail_bam_remap;
-	}
 	bam_props.virt_size = resource_p->bam_mem_size;
 	bam_props.irq = resource_p->bam_irq;
 	bam_props.num_pipes = IPA_NUM_PIPES;
@@ -1685,7 +1678,7 @@
 	if (result) {
 		IPAERR(":bam register err.\n");
 		result = -ENODEV;
-		goto fail_bam_register;
+		goto fail_init_hw;
 	}
 
 	if (ipa_setup_bam_cfg(resource_p)) {
@@ -2006,18 +1999,12 @@
 	kmem_cache_destroy(ipa_ctx->flt_rule_cache);
 fail_flt_rule_cache:
 	sps_deregister_bam_device(ipa_ctx->bam_handle);
-fail_bam_register:
-	iounmap(bam_props.virt_addr);
-fail_bam_remap:
 fail_init_hw:
 	iounmap(ipa_ctx->mmio);
 fail_remap:
 	kfree(ipa_ctx);
 	ipa_ctx = NULL;
 fail_mem:
-	/* gate IPA clocks */
-	if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_NORMAL)
-		ipa_disable_clks();
 	return result;
 }
 
@@ -2178,8 +2165,12 @@
 
 	/* Proceed to real initialization */
 	result = ipa_init(&ipa_res);
-	if (result)
+	if (result) {
 		IPAERR("ipa_init failed\n");
+		/* gate IPA clocks */
+		if (ipa_res.ipa_hw_mode == IPA_HW_MODE_NORMAL)
+			ipa_disable_clks();
+	}
 
 	result = device_create_file(&pdev_p->dev,
 			&dev_attr_aggregation_type);
diff --git a/drivers/platform/msm/ipa/ipa_bridge.c b/drivers/platform/msm/ipa/ipa_bridge.c
index 83c4db0..f9401f0 100644
--- a/drivers/platform/msm/ipa/ipa_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_bridge.c
@@ -468,7 +468,7 @@
 {
 	int i;
 
-	ipa_ctx->smem_pipe_mem = smem_alloc(SMEM_BAM_PIPE_MEMORY,
+	ipa_ctx->smem_pipe_mem = smem_alloc2(SMEM_BAM_PIPE_MEMORY,
 			IPA_SMEM_PIPE_MEM_SZ);
 	if (!ipa_ctx->smem_pipe_mem) {
 		IPAERR("smem alloc failed\n");
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index e98c9b7..f20f37f 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -203,6 +203,7 @@
 	}
 
 	memset(&ipa_ctx->ep[ipa_ep_idx], 0, sizeof(struct ipa_ep_context));
+	ipa_enable_data_path(ipa_ep_idx);
 
 	ep->valid = 1;
 	ep->client = in->client;
@@ -380,7 +381,6 @@
 		return -EPERM;
 	}
 
-	ipa_enable_data_path(clnt_hdl);
 	memset(&ipa_ctx->ep[clnt_hdl], 0, sizeof(struct ipa_ep_context));
 
 	ipa_dec_client_disable_clks();
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index 1f232d4..e2856cf 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -641,7 +641,7 @@
 	switch (notify->event_id) {
 	case SPS_EVENT_EOT:
 		tx_pkt = notify->data.transfer.user;
-		queue_work(ipa_ctx->tx_wq, &tx_pkt->work);
+		schedule_work(&tx_pkt->work);
 		break;
 	default:
 		IPAERR("recieved unexpected event id %d\n", notify->event_id);
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index b1e2d93..e38b796 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -13,7 +13,9 @@
 #include <net/ip.h>
 #include <linux/genalloc.h>	/* gen_pool_alloc() */
 #include <linux/io.h>
+#include <linux/ratelimit.h>
 #include "ipa_i.h"
+
 static const int ipa_ofst_meq32[] = { IPA_OFFSET_MEQ32_0,
 					IPA_OFFSET_MEQ32_1, -1 };
 static const int ipa_ofst_meq128[] = { IPA_OFFSET_MEQ128_0,
@@ -1382,3 +1384,26 @@
 	else
 		return 0;
 }
+
+/**
+ * ipa_bam_reg_dump() - Dump selected BAM registers for IPA and DMA-BAM
+ *
+ * Function is rate limited to avoid flooding kernel log buffer
+ */
+void ipa_bam_reg_dump(void)
+{
+	static DEFINE_RATELIMIT_STATE(_rs, 500*HZ, 1);
+	if (__ratelimit(&_rs)) {
+		ipa_inc_client_enable_clks();
+		pr_err("IPA BAM START\n");
+		sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 1048575, 0, 0);
+		sps_get_bam_debug_info(ipa_ctx->bam_handle, 93, 0, 0, 0);
+		pr_err("BAM-DMA BAM START\n");
+		sps_get_bam_debug_info(sps_dma_get_bam_handle(), 5, 1044480,
+				0, 0);
+		sps_get_bam_debug_info(sps_dma_get_bam_handle(), 93, 0, 0, 0);
+		ipa_dec_client_disable_clks();
+	}
+}
+EXPORT_SYMBOL(ipa_bam_reg_dump);
+
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index fae09fc..4889a79 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -153,7 +153,6 @@
 	bool prod_stopped;
 
 	struct completion prod_avail[MAX_BAMS];
-	struct completion cons_released[MAX_BAMS];
 	struct completion prod_released[MAX_BAMS];
 
 	struct mutex suspend_resume_mutex;
@@ -175,7 +174,6 @@
 static int __usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
 	void *param, bool trigger_cb_per_pipe);
 static void wait_for_prod_release(enum usb_bam cur_bam);
-static void wait_for_cons_release(enum usb_bam cur_bam);
 
 void msm_bam_set_hsic_host_dev(struct device *dev)
 {
@@ -936,7 +934,6 @@
 			__func__, bam_enable_strings[cur_bam]);
 
 	info.cur_cons_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
-	complete_all(&info.cons_released[cur_bam]);
 
 	spin_lock(&usb_bam_lock);
 	if (!ctx.pipes_enabled_per_bam[cur_bam]) {
@@ -1078,7 +1075,6 @@
 		pr_debug("%s producer already released\n", __func__);
 
 	init_completion(&info.prod_released[cur_bam]);
-	init_completion(&info.cons_released[cur_bam]);
 	pr_debug("%s: Releasing %s_PROD\n", __func__,
 				bam_enable_strings[cur_bam]);
 	ret = ipa_rm_release_resource(ipa_rm_resource_prod[cur_bam]);
@@ -1908,19 +1904,6 @@
 	return 0;
 }
 
-static void wait_for_cons_release(enum usb_bam cur_bam)
-{
-	 pr_debug("%s: Waiting for CONS release\n", __func__);
-	 if (info.cur_cons_state[cur_bam] != IPA_RM_RESOURCE_RELEASED) {
-		if (!wait_for_completion_timeout(&info.cons_released[cur_bam],
-						  USB_BAM_TIMEOUT))
-			pr_err("%s: Timeout wainting for CONS_RELEASE\n",
-				__func__);
-	 } else
-		pr_debug("%s Didn't need to wait for CONS release\n",
-		     __func__);
-}
-
 int usb_bam_disconnect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
 {
 	int ret;
@@ -1987,7 +1970,6 @@
 		pipe_connect->priv = NULL;
 
 		cur_bam = pipe_connect->bam_type;
-		wait_for_cons_release(cur_bam);
 		/* close IPA -> USB pipe */
 		ret = ipa_disconnect(ipa_params->cons_clnt_hdl);
 		if (ret) {
@@ -2542,8 +2524,6 @@
 		ctx.is_bam_inactivity[i] = false;
 		init_completion(&info.prod_avail[i]);
 		complete(&info.prod_avail[i]);
-		init_completion(&info.cons_released[i]);
-		complete(&info.cons_released[i]);
 		init_completion(&info.prod_released[i]);
 		complete(&info.prod_released[i]);
 		info.cur_prod_state[i] = IPA_RM_RESOURCE_RELEASED;
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 12aef1c..4df511b 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -280,6 +280,7 @@
 	POWER_SUPPLY_PROP_CHARGE_COUNTER,
 	POWER_SUPPLY_PROP_CHARGE_COUNTER_SHADOW,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
 	POWER_SUPPLY_PROP_CYCLE_COUNT,
 };
 
@@ -1413,6 +1414,21 @@
 	return chip->fcc_mah * 1000;
 }
 
+/* Returns the current full charge in uAh */
+static int get_prop_bms_charge_full(struct qpnp_bms_chip *chip)
+{
+	int rc;
+	struct qpnp_vadc_result result;
+
+	rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
+	if (rc) {
+		pr_err("Unable to read battery temperature\n");
+		return rc;
+	}
+
+	return calculate_fcc(chip, (int)result.physical);
+}
+
 static int calculate_delta_time(unsigned long *time_stamp, int *delta_time_s)
 {
 	unsigned long now_tm_sec = 0;
@@ -2985,6 +3001,9 @@
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval = get_prop_bms_charge_full_design(chip);
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		val->intval = get_prop_bms_charge_full(chip);
+		break;
 	case POWER_SUPPLY_PROP_CYCLE_COUNT:
 		val->intval = chip->charge_cycles;
 		break;
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 85bdd67..e05c866 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -98,6 +98,7 @@
 #define BOOST_VSET				0x41
 #define BOOST_ENABLE_CONTROL			0x46
 #define COMP_OVR1				0xEA
+#define BAT_IF_BTC_CTRL				0x49
 
 #define REG_OFFSET_PERP_SUBTYPE			0x05
 
@@ -222,6 +223,7 @@
  * @dc_present:			present status of dc
  * @batt_present:		present status of battery
  * @use_default_batt_values:	flag to report default battery properties
+ * @btc_disabled		Flag to disable btc (disables hot and cold irqs)
  * @max_voltage_mv:		the max volts the batt should be charged up to
  * @min_voltage_mv:		min battery voltage before turning the FET on
  * @max_bat_chg_current:	maximum battery charge current in mA
@@ -234,6 +236,8 @@
  * @safe_current:		battery safety current setting
  * @maxinput_usb_ma:		Maximum Input current USB
  * @maxinput_dc_ma:		Maximum Input current DC
+ * @hot_batt_p			Hot battery threshold setting
+ * @cold_batt_p			Cold battery threshold setting
  * @warm_bat_decidegc		Warm battery temperature in degree Celsius
  * @cool_bat_decidegc		Cool battery temperature in degree Celsius
  * @revision:			PMIC revision
@@ -276,6 +280,7 @@
 	bool				dc_present;
 	bool				batt_present;
 	bool				charging_disabled;
+	bool				btc_disabled;
 	bool				use_default_batt_values;
 	bool				duty_cycle_100p;
 	unsigned int			bpd_detection;
@@ -293,6 +298,8 @@
 	int				term_current;
 	unsigned int			maxinput_usb_ma;
 	unsigned int			maxinput_dc_ma;
+	unsigned int			hot_batt_p;
+	unsigned int			cold_batt_p;
 	unsigned int			warm_bat_decidegc;
 	unsigned int			cool_bat_decidegc;
 	unsigned int			safe_current;
@@ -334,7 +341,21 @@
 	[BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
 };
 
-static inline int
+enum btc_type {
+	HOT_THD_25_PCT = 25,
+	HOT_THD_35_PCT = 35,
+	COLD_THD_70_PCT = 70,
+	COLD_THD_80_PCT = 80,
+};
+
+static u8 btc_value[] = {
+	[HOT_THD_25_PCT] = 0x0,
+	[HOT_THD_35_PCT] = BIT(0),
+	[COLD_THD_70_PCT] = 0x0,
+	[COLD_THD_80_PCT] = BIT(1),
+};
+
+	static inline int
 get_bpd(const char *name)
 {
 	int i = 0;
@@ -1066,6 +1087,7 @@
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
 	POWER_SUPPLY_PROP_TEMP,
 	POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
 	POWER_SUPPLY_PROP_CYCLE_COUNT,
@@ -1245,6 +1267,22 @@
 	return 0;
 }
 
+static int
+get_prop_charge_full(struct qpnp_chg_chip *chip)
+{
+	union power_supply_propval ret = {0,};
+
+	if (chip->bms_psy) {
+		chip->bms_psy->get_property(chip->bms_psy,
+			  POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
+		return ret.intval;
+	} else {
+		pr_debug("No BMS supply registered return 0\n");
+	}
+
+	return 0;
+}
+
 #define DEFAULT_CAPACITY	50
 static int
 get_prop_capacity(struct qpnp_chg_chip *chip)
@@ -1380,6 +1418,9 @@
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval = get_prop_full_design(chip);
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		val->intval = get_prop_charge_full(chip);
+		break;
 	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
 		val->intval = !(chip->charging_disabled);
 		break;
@@ -1396,7 +1437,39 @@
 	return 0;
 }
 
-#define QPNP_CHG_VINMIN_MIN_MV		3400
+#define BTC_CONFIG_ENABLED	BIT(7)
+#define BTC_COLD		BIT(1)
+#define BTC_HOT			BIT(0)
+static int
+qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
+{
+	u8 btc_cfg = 0, mask = 0;
+
+	/* Do nothing if battery peripheral not present */
+	if (!chip->bat_if_base)
+		return 0;
+
+	if ((chip->hot_batt_p == HOT_THD_25_PCT)
+			|| (chip->hot_batt_p == HOT_THD_35_PCT)) {
+		btc_cfg |= btc_value[chip->hot_batt_p];
+		mask |= BTC_HOT;
+	}
+
+	if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
+			(chip->cold_batt_p == COLD_THD_80_PCT)) {
+		btc_cfg |= btc_value[chip->cold_batt_p];
+		mask |= BTC_COLD;
+	}
+
+	if (chip->btc_disabled)
+		mask |= BTC_CONFIG_ENABLED;
+
+	return qpnp_chg_masked_write(chip,
+			chip->bat_if_base + BAT_IF_BTC_CTRL,
+			mask, btc_cfg, 1);
+}
+
+#define QPNP_CHG_VINMIN_MIN_MV		4200
 #define QPNP_CHG_VINMIN_HIGH_MIN_MV	5600
 #define QPNP_CHG_VINMIN_HIGH_MIN_VAL	0x2B
 #define QPNP_CHG_VINMIN_MAX_MV		9600
@@ -2617,6 +2690,8 @@
 	OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
 	OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
 	OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
+	OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
+	OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
 	if (rc)
 		return rc;
 
@@ -2649,6 +2724,10 @@
 			return rc;
 	}
 
+	/* Get the btc-disabled property */
+	chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
+					"qcom,btc-disabled");
+
 	/* Get the charging-disabled property */
 	chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
 					"qcom,charging-disabled");
@@ -2972,6 +3051,11 @@
 			}
 		}
 	}
+	rc = qpnp_chg_bat_if_configure_btc(chip);
+	if (rc) {
+		pr_err("failed to configure btc %d\n", rc);
+		goto unregister_batt;
+	}
 
 	qpnp_chg_charge_en(chip, !chip->charging_disabled);
 	qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index c9d0500..d859651 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -1535,7 +1535,9 @@
 			&(pdata->init_data), vreg, spmi->dev.of_node);
 	if (IS_ERR(vreg->rdev)) {
 		rc = PTR_ERR(vreg->rdev);
-		vreg_err(vreg, "regulator_register failed, rc=%d\n", rc);
+		if (rc != -EPROBE_DEFER)
+			vreg_err(vreg, "regulator_register failed, rc=%d\n",
+				rc);
 		goto cancel_ocp_work;
 	}
 
@@ -1547,7 +1549,7 @@
 	if (vreg->ocp_irq)
 		cancel_delayed_work_sync(&vreg->ocp_work);
 bail:
-	if (rc)
+	if (rc && rc != -EPROBE_DEFER)
 		vreg_err(vreg, "probe failed, rc=%d\n", rc);
 
 	kfree(vreg->rdesc.name);
diff --git a/drivers/rtc/qpnp-rtc.c b/drivers/rtc/qpnp-rtc.c
index e0bffb9..bfbae78 100644
--- a/drivers/rtc/qpnp-rtc.c
+++ b/drivers/rtc/qpnp-rtc.c
@@ -45,6 +45,11 @@
 #define TO_SECS(arr)		(arr[0] | (arr[1] << 8) | (arr[2] << 16) | \
 							(arr[3] << 24))
 
+/* Module parameter to control power-on-alarm */
+static bool poweron_alarm;
+module_param(poweron_alarm, bool, 0644);
+MODULE_PARM_DESC(poweron_alarm, "Enable/Disable power-on alarm");
+
 /* rtc driver internal structure */
 struct qpnp_rtc {
 	u8  rtc_ctrl_reg;
@@ -586,7 +591,7 @@
 	struct qpnp_rtc *rtc_dd = dev_get_drvdata(&spmi->dev);
 	bool rtc_alarm_powerup = rtc_dd->rtc_alarm_powerup;
 
-	if (!rtc_alarm_powerup) {
+	if (!rtc_alarm_powerup && !poweron_alarm) {
 		spin_lock_irqsave(&rtc_dd->alarm_ctrl_lock, irq_flags);
 		dev_dbg(&spmi->dev, "Disabling alarm interrupts\n");
 
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 5dfd749..1def2dd 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -255,11 +255,10 @@
 }
 EXPORT_SYMBOL(scsi_execute);
 
-
-int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd,
 		     int data_direction, void *buffer, unsigned bufflen,
 		     struct scsi_sense_hdr *sshdr, int timeout, int retries,
-		     int *resid)
+		     int *resid, int flags)
 {
 	char *sense = NULL;
 	int result;
@@ -270,14 +269,14 @@
 			return DRIVER_ERROR << 24;
 	}
 	result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
-			      sense, timeout, retries, 0, resid);
+			      sense, timeout, retries, flags, resid);
 	if (sshdr)
 		scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
 
 	kfree(sense);
 	return result;
 }
-EXPORT_SYMBOL(scsi_execute_req);
+EXPORT_SYMBOL(scsi_execute_req_flags);
 
 /*
  * Function:    scsi_init_cmd_errh()
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index c467064..ff78095 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -16,29 +16,28 @@
 
 #include "scsi_priv.h"
 
-static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
+static int scsi_dev_type_suspend(struct device *dev, int (*cb)(struct device *))
 {
-	struct device_driver *drv;
 	int err;
 
 	err = scsi_device_quiesce(to_scsi_device(dev));
 	if (err == 0) {
-		drv = dev->driver;
-		if (drv && drv->suspend)
-			err = drv->suspend(dev, msg);
+		if (cb) {
+			err = cb(dev);
+			if (err)
+				scsi_device_resume(to_scsi_device(dev));
+		}
 	}
 	dev_dbg(dev, "scsi suspend: %d\n", err);
 	return err;
 }
 
-static int scsi_dev_type_resume(struct device *dev)
+static int scsi_dev_type_resume(struct device *dev, int (*cb)(struct device *))
 {
-	struct device_driver *drv;
 	int err = 0;
 
-	drv = dev->driver;
-	if (drv && drv->resume)
-		err = drv->resume(dev);
+	if (cb)
+		err = cb(dev);
 	scsi_device_resume(to_scsi_device(dev));
 	dev_dbg(dev, "scsi resume: %d\n", err);
 	return err;
@@ -46,30 +45,28 @@
 
 #ifdef CONFIG_PM_SLEEP
 
-static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg)
+static int
+scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *))
 {
 	int err = 0;
 
 	if (scsi_is_sdev_device(dev)) {
 		/*
-		 * sd is the only high-level SCSI driver to implement runtime
-		 * PM, and sd treats runtime suspend, system suspend, and
-		 * system hibernate identically (but not system freeze).
+		 * All the high-level SCSI drivers that implement runtime
+		 * PM treat runtime suspend, system suspend, and system
+		 * hibernate identically.
 		 */
-		if (pm_runtime_suspended(dev)) {
-			if (msg.event == PM_EVENT_SUSPEND ||
-			    msg.event == PM_EVENT_HIBERNATE)
-				return 0;	/* already suspended */
+		if (pm_runtime_suspended(dev))
+			return 0;
 
-			/* wake up device so that FREEZE will succeed */
-			pm_runtime_resume(dev);
-		}
-		err = scsi_dev_type_suspend(dev, msg);
+		err = scsi_dev_type_suspend(dev, cb);
 	}
+
 	return err;
 }
 
-static int scsi_bus_resume_common(struct device *dev)
+static int
+scsi_bus_resume_common(struct device *dev, int (*cb)(struct device *))
 {
 	int err = 0;
 
@@ -81,7 +78,7 @@
 		 * Resume it on behalf of child.
 		 */
 		pm_runtime_get_sync(dev->parent);
-		err = scsi_dev_type_resume(dev);
+		err = scsi_dev_type_resume(dev, cb);
 		pm_runtime_put_sync(dev->parent);
 	}
 
@@ -108,55 +105,131 @@
 
 static int scsi_bus_suspend(struct device *dev)
 {
-	return scsi_bus_suspend_common(dev, PMSG_SUSPEND);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_suspend_common(dev, pm ? pm->suspend : NULL);
+}
+
+static int scsi_bus_resume(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_resume_common(dev, pm ? pm->resume : NULL);
 }
 
 static int scsi_bus_freeze(struct device *dev)
 {
-	return scsi_bus_suspend_common(dev, PMSG_FREEZE);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_suspend_common(dev, pm ? pm->freeze : NULL);
+}
+
+static int scsi_bus_thaw(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_resume_common(dev, pm ? pm->thaw : NULL);
 }
 
 static int scsi_bus_poweroff(struct device *dev)
 {
-	return scsi_bus_suspend_common(dev, PMSG_HIBERNATE);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_suspend_common(dev, pm ? pm->poweroff : NULL);
+}
+
+static int scsi_bus_restore(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_resume_common(dev, pm ? pm->restore : NULL);
 }
 
 #else /* CONFIG_PM_SLEEP */
 
-#define scsi_bus_resume_common		NULL
 #define scsi_bus_prepare		NULL
 #define scsi_bus_suspend		NULL
+#define scsi_bus_resume			NULL
 #define scsi_bus_freeze			NULL
+#define scsi_bus_thaw			NULL
 #define scsi_bus_poweroff		NULL
+#define scsi_bus_restore		NULL
 
 #endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_PM_RUNTIME
 
+static int sdev_blk_runtime_suspend(struct scsi_device *sdev,
+					int (*cb)(struct device *))
+{
+	int err;
+
+	err = blk_pre_runtime_suspend(sdev->request_queue);
+	if (err)
+		return err;
+	if (cb)
+		err = cb(&sdev->sdev_gendev);
+	blk_post_runtime_suspend(sdev->request_queue, err);
+
+	return err;
+}
+
+static int sdev_runtime_suspend(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL;
+	struct scsi_device *sdev = to_scsi_device(dev);
+	int err;
+
+	if (sdev->request_queue->dev)
+		return sdev_blk_runtime_suspend(sdev, cb);
+
+	err = scsi_dev_type_suspend(dev, cb);
+	if (err == -EAGAIN)
+		pm_schedule_suspend(dev, jiffies_to_msecs(
+					round_jiffies_up_relative(HZ/10)));
+	return err;
+}
+
 static int scsi_runtime_suspend(struct device *dev)
 {
 	int err = 0;
 
 	dev_dbg(dev, "scsi_runtime_suspend\n");
-	if (scsi_is_sdev_device(dev)) {
-		err = scsi_dev_type_suspend(dev, PMSG_AUTO_SUSPEND);
-		if (err == -EAGAIN)
-			pm_schedule_suspend(dev, jiffies_to_msecs(
-				round_jiffies_up_relative(HZ/10)));
-	}
+	if (scsi_is_sdev_device(dev))
+		err = sdev_runtime_suspend(dev);
 
 	/* Insert hooks here for targets, hosts, and transport classes */
 
 	return err;
 }
 
+static int sdev_blk_runtime_resume(struct scsi_device *sdev,
+					int (*cb)(struct device *))
+{
+	int err = 0;
+
+	blk_pre_runtime_resume(sdev->request_queue);
+	if (cb)
+		err = cb(&sdev->sdev_gendev);
+	blk_post_runtime_resume(sdev->request_queue, err);
+
+	return err;
+}
+
+static int sdev_runtime_resume(struct device *dev)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL;
+
+	if (sdev->request_queue->dev)
+		return sdev_blk_runtime_resume(sdev, cb);
+	else
+		return scsi_dev_type_resume(dev, cb);
+}
+
 static int scsi_runtime_resume(struct device *dev)
 {
 	int err = 0;
 
 	dev_dbg(dev, "scsi_runtime_resume\n");
 	if (scsi_is_sdev_device(dev))
-		err = scsi_dev_type_resume(dev);
+		err = sdev_runtime_resume(dev);
 
 	/* Insert hooks here for targets, hosts, and transport classes */
 
@@ -171,10 +244,18 @@
 
 	/* Insert hooks here for targets, hosts, and transport classes */
 
-	if (scsi_is_sdev_device(dev))
-		err = pm_schedule_suspend(dev, 100);
-	else
+	if (scsi_is_sdev_device(dev)) {
+		struct scsi_device *sdev = to_scsi_device(dev);
+
+		if (sdev->request_queue->dev) {
+			pm_runtime_mark_last_busy(dev);
+			err = pm_runtime_autosuspend(dev);
+		} else {
+			err = pm_runtime_suspend(dev);
+		}
+	} else {
 		err = pm_runtime_suspend(dev);
+	}
 	return err;
 }
 
@@ -235,11 +316,11 @@
 const struct dev_pm_ops scsi_bus_pm_ops = {
 	.prepare =		scsi_bus_prepare,
 	.suspend =		scsi_bus_suspend,
-	.resume =		scsi_bus_resume_common,
+	.resume =		scsi_bus_resume,
 	.freeze =		scsi_bus_freeze,
-	.thaw =			scsi_bus_resume_common,
+	.thaw =			scsi_bus_thaw,
 	.poweroff =		scsi_bus_poweroff,
-	.restore =		scsi_bus_resume_common,
+	.restore =		scsi_bus_restore,
 	.runtime_suspend =	scsi_runtime_suspend,
 	.runtime_resume =	scsi_runtime_resume,
 	.runtime_idle =		scsi_runtime_idle,
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 508c2bb..f454610 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -966,10 +966,6 @@
 
 	sdev = sdkp->device;
 
-	retval = scsi_autopm_get_device(sdev);
-	if (retval)
-		goto error_autopm;
-
 	/*
 	 * If the device is in error recovery, wait until it is done.
 	 * If the device is offline, then disallow any access to it.
@@ -1014,8 +1010,6 @@
 	return 0;
 
 error_out:
-	scsi_autopm_put_device(sdev);
-error_autopm:
 	scsi_disk_put(sdkp);
 	return retval;	
 }
@@ -1050,7 +1044,6 @@
 	 * XXX is followed by a "rmmod sd_mod"?
 	 */
 
-	scsi_autopm_put_device(sdev);
 	scsi_disk_put(sdkp);
 	return 0;
 }
@@ -1212,14 +1205,9 @@
 	retval = -ENODEV;
 
 	if (scsi_block_when_processing_errors(sdp)) {
-		retval = scsi_autopm_get_device(sdp);
-		if (retval)
-			goto out;
-
 		sshdr  = kzalloc(sizeof(*sshdr), GFP_KERNEL);
 		retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES,
 					      sshdr);
-		scsi_autopm_put_device(sdp);
 	}
 
 	/* failed to execute TUR, assume media not present */
@@ -1269,8 +1257,9 @@
 		 * Leave the rest of the command zero to indicate
 		 * flush everything.
 		 */
-		res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-				       SD_FLUSH_TIMEOUT, SD_MAX_RETRIES, NULL);
+		res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0,
+					     &sshdr, SD_FLUSH_TIMEOUT,
+					     SD_MAX_RETRIES, NULL, REQ_PM);
 		if (res == 0)
 			break;
 	}
@@ -2630,6 +2619,7 @@
 
 	sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
 		  sdp->removable ? "removable " : "");
+	blk_pm_runtime_init(sdp->request_queue, dev);
 	scsi_autopm_put_device(sdp);
 	put_device(&sdkp->dev);
 }
@@ -2812,8 +2802,8 @@
 	if (!scsi_device_online(sdp))
 		return -ENODEV;
 
-	res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-			       SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+	res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+			       SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM);
 	if (res) {
 		sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
 		sd_print_result(sdkp, res);
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 086ff03..139bc06 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -36,20 +36,10 @@
 #ifndef _UFS_H
 #define _UFS_H
 
-#include <linux/mutex.h>
-#include <linux/types.h>
-
 #define MAX_CDB_SIZE	16
-#define GENERAL_UPIU_REQUEST_SIZE 32
-#define UPIU_HEADER_DATA_SEGMENT_MAX_SIZE	((ALIGNED_UPIU_SIZE) - \
-					(GENERAL_UPIU_REQUEST_SIZE))
-#define QUERY_OSF_SIZE			((GENERAL_UPIU_REQUEST_SIZE) - \
-					(sizeof(struct utp_upiu_header)))
-#define UFS_QUERY_RESERVED_SCSI_CMD 0xCC
-#define UFS_QUERY_CMD_SIZE 10
 
 #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
-			cpu_to_be32((byte3 << 24) | (byte2 << 16) |\
+			((byte3 << 24) | (byte2 << 16) |\
 			 (byte1 << 8) | (byte0))
 
 /*
@@ -72,7 +62,7 @@
 	UPIU_TRANSACTION_COMMAND	= 0x01,
 	UPIU_TRANSACTION_DATA_OUT	= 0x02,
 	UPIU_TRANSACTION_TASK_REQ	= 0x04,
-	UPIU_TRANSACTION_QUERY_REQ	= 0x16,
+	UPIU_TRANSACTION_QUERY_REQ	= 0x26,
 };
 
 /* UTP UPIU Transaction Codes Target to Initiator */
@@ -83,7 +73,6 @@
 	UPIU_TRANSACTION_TASK_RSP	= 0x24,
 	UPIU_TRANSACTION_READY_XFER	= 0x31,
 	UPIU_TRANSACTION_QUERY_RSP	= 0x36,
-	UPIU_TRANSACTION_REJECT_UPIU	= 0x3F,
 };
 
 /* UPIU Read/Write flags */
@@ -101,12 +90,6 @@
 	UPIU_TASK_ATTR_ACA	= 0x03,
 };
 
-/* UPIU Query request function */
-enum {
-	UPIU_QUERY_FUNC_STANDARD_READ_REQUEST = 0x01,
-	UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81,
-};
-
 /* UTP QUERY Transaction Specific Fields OpCode */
 enum {
 	UPIU_QUERY_OPCODE_NOP		= 0x0,
@@ -120,21 +103,6 @@
 	UPIU_QUERY_OPCODE_TOGGLE_FLAG	= 0x8,
 };
 
-/* Query response result code */
-enum {
-	QUERY_RESULT_SUCCESS			= 0x00,
-	QUERY_RESULT_NOT_READABLE		= 0xF6,
-	QUERY_RESULT_NOT_WRITEABLE		= 0xF7,
-	QUERY_RESULT_ALREADY_WRITTEN		= 0xF8,
-	QUERY_RESULT_INVALID_LENGTH		= 0xF9,
-	QUERY_RESULT_INVALID_VALUE		= 0xFA,
-	QUERY_RESULT_INVALID_SELECTOR		= 0xFB,
-	QUERY_RESULT_INVALID_INDEX		= 0xFC,
-	QUERY_RESULT_INVALID_IDN		= 0xFD,
-	QUERY_RESULT_INVALID_OPCODE		= 0xFE,
-	QUERY_RESULT_GENERAL_FAILURE		= 0xFF,
-};
-
 /* UTP Transfer Request Command Type (CT) */
 enum {
 	UPIU_COMMAND_SET_TYPE_SCSI	= 0x0,
@@ -142,17 +110,10 @@
 	UPIU_COMMAND_SET_TYPE_QUERY	= 0x2,
 };
 
-/* UTP Transfer Request Command Offset */
-#define UPIU_COMMAND_TYPE_OFFSET	28
-
-/* Offset of the response code in the UPIU header */
-#define UPIU_RSP_CODE_OFFSET		8
-
 enum {
 	MASK_SCSI_STATUS	= 0xFF,
 	MASK_TASK_RESPONSE	= 0xFF00,
 	MASK_RSP_UPIU_RESULT	= 0xFFFF,
-	MASK_QUERY_DATA_SEG_LEN	= 0xFFFF,
 };
 
 /* Task management service response */
@@ -177,59 +138,26 @@
 
 /**
  * struct utp_upiu_cmd - Command UPIU structure
+ * @header: UPIU header structure DW-0 to DW-2
  * @data_transfer_len: Data Transfer Length DW-3
  * @cdb: Command Descriptor Block CDB DW-4 to DW-7
  */
 struct utp_upiu_cmd {
+	struct utp_upiu_header header;
 	u32 exp_data_transfer_len;
 	u8 cdb[MAX_CDB_SIZE];
 };
 
 /**
- * struct utp_upiu_query - upiu request buffer structure for
- * query request.
- * @opcode: command to perform B-0
- * @idn: a value that indicates the particular type of data B-1
- * @index: Index to further identify data B-2
- * @selector: Index to further identify data B-3
- * @reserved_osf: spec reserved field B-4,5
- * @length: number of descriptor bytes to read/write B-6,7
- * @value: Attribute value to be written DW-6
- * @reserved: spec reserved DW-7,8
- */
-struct utp_upiu_query {
-	u8 opcode;
-	u8 idn;
-	u8 index;
-	u8 selector;
-	u16 reserved_osf;
-	u16 length;
-	u32 value;
-	u32 reserved[2];
-};
-
-/**
- * struct utp_upiu_req - general upiu request structure
- * @header:UPIU header structure DW-0 to DW-2
- * @sc: fields structure for scsi command
- * @qr: fields structure for query request
- */
-struct utp_upiu_req {
-	struct utp_upiu_header header;
-	union {
-		struct utp_upiu_cmd sc;
-		struct utp_upiu_query qr;
-	};
-};
-
-/**
- * struct utp_cmd_rsp - Response UPIU structure
+ * struct utp_upiu_rsp - Response UPIU structure
+ * @header: UPIU header DW-0 to DW-2
  * @residual_transfer_count: Residual transfer count DW-3
  * @reserved: Reserved double words DW-4 to DW-7
  * @sense_data_len: Sense data length DW-8 U16
  * @sense_data: Sense data field DW-8 to DW-12
  */
-struct utp_cmd_rsp {
+struct utp_upiu_rsp {
+	struct utp_upiu_header header;
 	u32 residual_transfer_count;
 	u32 reserved[4];
 	u16 sense_data_len;
@@ -237,20 +165,6 @@
 };
 
 /**
- * struct utp_upiu_rsp - general upiu response structure
- * @header: UPIU header structure DW-0 to DW-2
- * @sc: fields structure for scsi command
- * @qr: fields structure for query request
- */
-struct utp_upiu_rsp {
-	struct utp_upiu_header header;
-	union {
-		struct utp_cmd_rsp sc;
-		struct utp_upiu_query qr;
-	};
-};
-
-/**
  * struct utp_upiu_task_req - Task request UPIU structure
  * @header - UPIU header structure DW0 to DW-2
  * @input_param1: Input parameter 1 DW-3
@@ -280,24 +194,4 @@
 	u32 reserved[3];
 };
 
-/**
- * struct ufs_query_req - parameters for building a query request
- * @query_func: UPIU header query function
- * @upiu_req: the query request data
- */
-struct ufs_query_req {
-	u8 query_func;
-	struct utp_upiu_query upiu_req;
-};
-
-/**
- * struct ufs_query_resp - UPIU QUERY
- * @response: device response code
- * @upiu_res: query response data
- */
-struct ufs_query_res {
-	u8 response;
-	struct utp_upiu_query upiu_res;
-};
-
 #endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5f21c7a..48a7645 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -33,8 +33,16 @@
  * this program.
  */
 
+#include <linux/async.h>
+
 #include "ufshcd.h"
 
+#define UFSHCD_ENABLE_INTRS	(UTP_TRANSFER_REQ_COMPL |\
+				 UTP_TASK_REQ_COMPL |\
+				 UFSHCD_ERROR_MASK)
+/* UIC command timeout, unit: ms */
+#define UIC_CMD_TIMEOUT	500
+
 enum {
 	UFSHCD_MAX_CHANNEL	= 0,
 	UFSHCD_MAX_ID		= 1,
@@ -64,6 +72,20 @@
 };
 
 /**
+ * ufshcd_get_intr_mask - Get the interrupt bit mask
+ * @hba - Pointer to adapter instance
+ *
+ * Returns interrupt bit mask per version
+ */
+static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
+{
+	if (hba->ufs_version == UFSHCI_VERSION_10)
+		return INTERRUPT_MASK_ALL_VER_10;
+	else
+		return INTERRUPT_MASK_ALL_VER_11;
+}
+
+/**
  * ufshcd_get_ufs_version - Get the UFS version supported by the HBA
  * @hba - Pointer to adapter instance
  *
@@ -71,7 +93,7 @@
  */
 static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
 {
-	return readl(hba->mmio_base + REG_UFS_VERSION);
+	return ufshcd_readl(hba, REG_UFS_VERSION);
 }
 
 /**
@@ -130,8 +152,7 @@
  */
 static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
 {
-	writel(~(1 << pos),
-		(hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_CLEAR));
+	ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
 }
 
 /**
@@ -165,7 +186,7 @@
  */
 static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
 {
-	return readl(hba->mmio_base + REG_UIC_COMMAND_ARG_2) &
+	return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_2) &
 	       MASK_UIC_COMMAND_RESULT;
 }
 
@@ -202,13 +223,18 @@
 }
 
 /**
- * ufshcd_get_req_rsp - returns the TR response
+ * ufshcd_is_valid_req_rsp - checks if controller TR response is valid
  * @ucd_rsp_ptr: pointer to response UPIU
+ *
+ * This function checks the response UPIU for valid transaction type in
+ * response field
+ * Returns 0 on success, non-zero on failure
  */
 static inline int
-ufshcd_get_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr)
+ufshcd_is_valid_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr)
 {
-	return be32_to_cpu(ucd_rsp_ptr->header.dword_0) >> 24;
+	return ((be32_to_cpu(ucd_rsp_ptr->header.dword_0) >> 24) ==
+		 UPIU_TRANSACTION_RESPONSE) ? 0 : DID_ERROR << 16;
 }
 
 /**
@@ -238,18 +264,15 @@
 {
 	switch (option) {
 	case INT_AGGR_RESET:
-		writel((INT_AGGR_ENABLE |
-			INT_AGGR_COUNTER_AND_TIMER_RESET),
-			(hba->mmio_base +
-			 REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
+		ufshcd_writel(hba, INT_AGGR_ENABLE |
+			      INT_AGGR_COUNTER_AND_TIMER_RESET,
+			      REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
 		break;
 	case INT_AGGR_CONFIG:
-		writel((INT_AGGR_ENABLE |
-			INT_AGGR_PARAM_WRITE |
-			INT_AGGR_COUNTER_THRESHOLD_VALUE |
-			INT_AGGR_TIMEOUT_VALUE),
-			(hba->mmio_base +
-			 REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
+		ufshcd_writel(hba, INT_AGGR_ENABLE | INT_AGGR_PARAM_WRITE |
+			      INT_AGGR_COUNTER_THRESHOLD_VALUE |
+			      INT_AGGR_TIMEOUT_VALUE,
+			      REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
 		break;
 	}
 }
@@ -262,12 +285,10 @@
  */
 static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
 {
-	writel(UTP_TASK_REQ_LIST_RUN_STOP_BIT,
-	       (hba->mmio_base +
-		REG_UTP_TASK_REQ_LIST_RUN_STOP));
-	writel(UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
-	       (hba->mmio_base +
-		REG_UTP_TRANSFER_REQ_LIST_RUN_STOP));
+	ufshcd_writel(hba, UTP_TASK_REQ_LIST_RUN_STOP_BIT,
+		      REG_UTP_TASK_REQ_LIST_RUN_STOP);
+	ufshcd_writel(hba, UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
+		      REG_UTP_TRANSFER_REQ_LIST_RUN_STOP);
 }
 
 /**
@@ -276,7 +297,7 @@
  */
 static inline void ufshcd_hba_start(struct ufs_hba *hba)
 {
-	writel(CONTROLLER_ENABLE , (hba->mmio_base + REG_CONTROLLER_ENABLE));
+	ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE);
 }
 
 /**
@@ -287,7 +308,7 @@
  */
 static inline int ufshcd_is_hba_active(struct ufs_hba *hba)
 {
-	return (readl(hba->mmio_base + REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
+	return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
 }
 
 /**
@@ -299,8 +320,7 @@
 void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
 {
 	__set_bit(task_tag, &hba->outstanding_reqs);
-	writel((1 << task_tag),
-	       (hba->mmio_base + REG_UTP_TRANSFER_REQ_DOOR_BELL));
+	ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 }
 
 /**
@@ -311,78 +331,20 @@
 {
 	int len;
 	if (lrbp->sense_buffer) {
-		len = be16_to_cpu(lrbp->ucd_rsp_ptr->sc.sense_data_len);
+		len = be16_to_cpu(lrbp->ucd_rsp_ptr->sense_data_len);
 		memcpy(lrbp->sense_buffer,
-			lrbp->ucd_rsp_ptr->sc.sense_data,
+			lrbp->ucd_rsp_ptr->sense_data,
 			min_t(int, len, SCSI_SENSE_BUFFERSIZE));
 	}
 }
 
 /**
- * ufshcd_query_to_cpu() - formats the received buffer in to the native cpu
- * endian
- * @response: upiu query response to convert
- */
-static inline void ufshcd_query_to_cpu(struct utp_upiu_query *response)
-{
-	response->length = be16_to_cpu(response->length);
-	response->value = be32_to_cpu(response->value);
-}
-
-/**
- * ufshcd_query_to_be() - formats the buffer before sending in to big endian
- * @response: upiu query request to convert
- */
-static inline void ufshcd_query_to_be(struct utp_upiu_query *request)
-{
-	request->length = cpu_to_be16(request->length);
-	request->value = cpu_to_be32(request->value);
-}
-
-/**
- * ufshcd_copy_query_response() - Copy Query Response and descriptor
- * @lrb - pointer to local reference block
- * @query_res - pointer to the query result
- */
-static
-void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
-{
-	struct ufs_query_res *query_res = hba->query.response;
-
-	/* Get the UPIU response */
-	if (query_res) {
-		query_res->response = ufshcd_get_rsp_upiu_result(
-			lrbp->ucd_rsp_ptr) >> UPIU_RSP_CODE_OFFSET;
-
-		memcpy(&query_res->upiu_res, &lrbp->ucd_rsp_ptr->qr,
-			QUERY_OSF_SIZE);
-		ufshcd_query_to_cpu(&query_res->upiu_res);
-	}
-
-	/* Get the descriptor */
-	if (hba->query.descriptor && lrbp->ucd_rsp_ptr->qr.opcode ==
-			UPIU_QUERY_OPCODE_READ_DESC) {
-		u8 *descp = (u8 *)&lrbp->ucd_rsp_ptr +
-				GENERAL_UPIU_REQUEST_SIZE;
-		u16 len;
-
-		/* data segment length */
-		len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) &
-						MASK_QUERY_DATA_SEG_LEN;
-
-		memcpy(hba->query.descriptor, descp,
-			min_t(u16, len, UPIU_HEADER_DATA_SEGMENT_MAX_SIZE));
-	}
-}
-
-/**
  * ufshcd_hba_capabilities - Read controller capabilities
  * @hba: per adapter instance
  */
 static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
 {
-	hba->capabilities =
-		readl(hba->mmio_base + REG_CONTROLLER_CAPABILITIES);
+	hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
 
 	/* nutrs and nutmrs are 0 based values */
 	hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1;
@@ -391,24 +353,119 @@
 }
 
 /**
- * ufshcd_send_uic_command - Send UIC commands to unipro layers
+ * ufshcd_ready_for_uic_cmd - Check if controller is ready
+ *                            to accept UIC commands
  * @hba: per adapter instance
- * @uic_command: UIC command
+ * Return true on success, else false
+ */
+static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
+{
+	if (ufshcd_readl(hba, REG_CONTROLLER_STATUS) & UIC_COMMAND_READY)
+		return true;
+	else
+		return false;
+}
+
+/**
+ * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Mutex must be held.
  */
 static inline void
-ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd)
+ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 {
+	WARN_ON(hba->active_uic_cmd);
+
+	hba->active_uic_cmd = uic_cmd;
+
 	/* Write Args */
-	writel(uic_cmnd->argument1,
-	      (hba->mmio_base + REG_UIC_COMMAND_ARG_1));
-	writel(uic_cmnd->argument2,
-	      (hba->mmio_base + REG_UIC_COMMAND_ARG_2));
-	writel(uic_cmnd->argument3,
-	      (hba->mmio_base + REG_UIC_COMMAND_ARG_3));
+	ufshcd_writel(hba, uic_cmd->argument1, REG_UIC_COMMAND_ARG_1);
+	ufshcd_writel(hba, uic_cmd->argument2, REG_UIC_COMMAND_ARG_2);
+	ufshcd_writel(hba, uic_cmd->argument3, REG_UIC_COMMAND_ARG_3);
 
 	/* Write UIC Cmd */
-	writel((uic_cmnd->command & COMMAND_OPCODE_MASK),
-	       (hba->mmio_base + REG_UIC_COMMAND));
+	ufshcd_writel(hba, uic_cmd->command & COMMAND_OPCODE_MASK,
+		      REG_UIC_COMMAND);
+}
+
+/**
+ * ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command
+ * @hba: per adapter instance
+ * @uic_command: UIC command
+ *
+ * Must be called with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+	int ret;
+	unsigned long flags;
+
+	if (wait_for_completion_timeout(&uic_cmd->done,
+					msecs_to_jiffies(UIC_CMD_TIMEOUT)))
+		ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
+	else
+		ret = -ETIMEDOUT;
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	hba->active_uic_cmd = NULL;
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	return ret;
+}
+
+/**
+ * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
+ * with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+	int ret;
+	unsigned long flags;
+
+	if (!ufshcd_ready_for_uic_cmd(hba)) {
+		dev_err(hba->dev,
+			"Controller not ready to accept UIC commands\n");
+		return -EIO;
+	}
+
+	init_completion(&uic_cmd->done);
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
+
+	return ret;
+}
+
+/**
+ * ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+	int ret;
+
+	mutex_lock(&hba->uic_cmd_mutex);
+	ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
+	mutex_unlock(&hba->uic_cmd_mutex);
+
+	return ret;
 }
 
 /**
@@ -452,177 +509,118 @@
 }
 
 /**
- * ufshcd_int_config - enable/disable interrupts
+ * ufshcd_enable_intr - enable interrupts
  * @hba: per adapter instance
- * @option: interrupt option
+ * @intrs: interrupt bits
  */
-static void ufshcd_int_config(struct ufs_hba *hba, u32 option)
+static void ufshcd_enable_intr(struct ufs_hba *hba, u32 intrs)
 {
-	switch (option) {
-	case UFSHCD_INT_ENABLE:
-		writel(hba->int_enable_mask,
-		      (hba->mmio_base + REG_INTERRUPT_ENABLE));
-		break;
-	case UFSHCD_INT_DISABLE:
-		if (hba->ufs_version == UFSHCI_VERSION_10)
-			writel(INTERRUPT_DISABLE_MASK_10,
-			      (hba->mmio_base + REG_INTERRUPT_ENABLE));
-		else
-			writel(INTERRUPT_DISABLE_MASK_11,
-			       (hba->mmio_base + REG_INTERRUPT_ENABLE));
-		break;
-	}
-}
+	u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
 
-/**
- * ufshcd_prepare_req_desc - Fills the requests header
- * descriptor according to request
- * lrbp: pointer to local reference block
- * upiu_flags: flags required in the header
- */
-static void ufshcd_prepare_req_desc(struct ufshcd_lrb *lrbp, u32 *upiu_flags)
-{
-	struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr;
-	enum dma_data_direction cmd_dir =
-		lrbp->cmd->sc_data_direction;
-	u32 data_direction;
-	u32 dword_0;
-
-	if (cmd_dir == DMA_FROM_DEVICE) {
-		data_direction = UTP_DEVICE_TO_HOST;
-		*upiu_flags = UPIU_CMD_FLAGS_READ;
-	} else if (cmd_dir == DMA_TO_DEVICE) {
-		data_direction = UTP_HOST_TO_DEVICE;
-		*upiu_flags = UPIU_CMD_FLAGS_WRITE;
+	if (hba->ufs_version == UFSHCI_VERSION_10) {
+		u32 rw;
+		rw = set & INTERRUPT_MASK_RW_VER_10;
+		set = rw | ((set ^ intrs) & intrs);
 	} else {
-		data_direction = UTP_NO_DATA_TRANSFER;
-		*upiu_flags = UPIU_CMD_FLAGS_NONE;
+		set |= intrs;
 	}
 
-	dword_0 = data_direction | (lrbp->command_type
-				<< UPIU_COMMAND_TYPE_OFFSET);
-
-	/* Transfer request descriptor header fields */
-	req_desc->header.dword_0 = cpu_to_le32(dword_0);
-
-	/*
-	 * assigning invalid value for command status. Controller
-	 * updates OCS on command completion, with the command
-	 * status
-	 */
-	req_desc->header.dword_2 =
-		cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
-}
-
-static inline bool ufshcd_is_query_req(struct ufshcd_lrb *lrbp)
-{
-	return lrbp->cmd ? lrbp->cmd->cmnd[0] == UFS_QUERY_RESERVED_SCSI_CMD :
-		false;
+	ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
 }
 
 /**
- * ufshcd_prepare_utp_scsi_cmd_upiu() - fills the utp_transfer_req_desc,
- * for scsi commands
- * @lrbp - local reference block pointer
- * @upiu_flags - flags
+ * ufshcd_disable_intr - disable interrupts
+ * @hba: per adapter instance
+ * @intrs: interrupt bits
  */
-static
-void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32 upiu_flags)
+static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
 {
-	struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
+	u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
 
-	/* command descriptor fields */
-	ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
-				UPIU_TRANSACTION_COMMAND, upiu_flags,
-				lrbp->lun, lrbp->task_tag);
-	ucd_req_ptr->header.dword_1 = UPIU_HEADER_DWORD(
-				UPIU_COMMAND_SET_TYPE_SCSI, 0, 0, 0);
+	if (hba->ufs_version == UFSHCI_VERSION_10) {
+		u32 rw;
+		rw = (set & INTERRUPT_MASK_RW_VER_10) &
+			~(intrs & INTERRUPT_MASK_RW_VER_10);
+		set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10);
 
-	/* Total EHS length and Data segment length will be zero */
-	ucd_req_ptr->header.dword_2 = 0;
-
-	ucd_req_ptr->sc.exp_data_transfer_len =
-		cpu_to_be32(lrbp->cmd->sdb.length);
-
-	memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd,
-		(min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE)));
-}
-
-/**
- * ufshcd_prepare_utp_query_req_upiu() - fills the utp_transfer_req_desc,
- * for query requsts
- * @hba: UFS hba
- * @lrbp: local reference block pointer
- * @upiu_flags: flags
- */
-static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
-					struct ufshcd_lrb *lrbp,
-					u32 upiu_flags)
-{
-	struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
-	u16 len = hba->query.request->upiu_req.length;
-	u8 *descp = (u8 *)lrbp->ucd_req_ptr + GENERAL_UPIU_REQUEST_SIZE;
-
-	/* Query request header */
-	ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
-			UPIU_TRANSACTION_QUERY_REQ, upiu_flags,
-			lrbp->lun, lrbp->task_tag);
-	ucd_req_ptr->header.dword_1 = UPIU_HEADER_DWORD(
-			0, hba->query.request->query_func, 0, 0);
-
-	/* Data segment length */
-	ucd_req_ptr->header.dword_2 = UPIU_HEADER_DWORD(
-			0, 0, len >> 8, (u8)len);
-
-	/* Copy the Query Request buffer as is */
-	memcpy(&lrbp->ucd_req_ptr->qr, &hba->query.request->upiu_req,
-			QUERY_OSF_SIZE);
-	ufshcd_query_to_be(&lrbp->ucd_req_ptr->qr);
-
-	/* Copy the Descriptor */
-	if (hba->query.descriptor != NULL && len > 0 &&
-		(hba->query.request->upiu_req.opcode ==
-					UPIU_QUERY_OPCODE_WRITE_DESC)) {
-		memcpy(descp, hba->query.descriptor,
-			min_t(u16, len, UPIU_HEADER_DATA_SEGMENT_MAX_SIZE));
+	} else {
+		set &= ~intrs;
 	}
 
+	ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
 }
 
 /**
  * ufshcd_compose_upiu - form UFS Protocol Information Unit(UPIU)
- * @hba - UFS hba
  * @lrb - pointer to local reference block
  */
-static int ufshcd_compose_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+static void ufshcd_compose_upiu(struct ufshcd_lrb *lrbp)
 {
+	struct utp_transfer_req_desc *req_desc;
+	struct utp_upiu_cmd *ucd_cmd_ptr;
+	u32 data_direction;
 	u32 upiu_flags;
-	int ret = 0;
+
+	ucd_cmd_ptr = lrbp->ucd_cmd_ptr;
+	req_desc = lrbp->utr_descriptor_ptr;
 
 	switch (lrbp->command_type) {
 	case UTP_CMD_TYPE_SCSI:
+		if (lrbp->cmd->sc_data_direction == DMA_FROM_DEVICE) {
+			data_direction = UTP_DEVICE_TO_HOST;
+			upiu_flags = UPIU_CMD_FLAGS_READ;
+		} else if (lrbp->cmd->sc_data_direction == DMA_TO_DEVICE) {
+			data_direction = UTP_HOST_TO_DEVICE;
+			upiu_flags = UPIU_CMD_FLAGS_WRITE;
+		} else {
+			data_direction = UTP_NO_DATA_TRANSFER;
+			upiu_flags = UPIU_CMD_FLAGS_NONE;
+		}
+
+		/* Transfer request descriptor header fields */
+		req_desc->header.dword_0 =
+			cpu_to_le32(data_direction | UTP_SCSI_COMMAND);
+
+		/*
+		 * assigning invalid value for command status. Controller
+		 * updates OCS on command completion, with the command
+		 * status
+		 */
+		req_desc->header.dword_2 =
+			cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
+
+		/* command descriptor fields */
+		ucd_cmd_ptr->header.dword_0 =
+			cpu_to_be32(UPIU_HEADER_DWORD(UPIU_TRANSACTION_COMMAND,
+						      upiu_flags,
+						      lrbp->lun,
+						      lrbp->task_tag));
+		ucd_cmd_ptr->header.dword_1 =
+			cpu_to_be32(
+				UPIU_HEADER_DWORD(UPIU_COMMAND_SET_TYPE_SCSI,
+						  0,
+						  0,
+						  0));
+
+		/* Total EHS length and Data segment length will be zero */
+		ucd_cmd_ptr->header.dword_2 = 0;
+
+		ucd_cmd_ptr->exp_data_transfer_len =
+			cpu_to_be32(lrbp->cmd->sdb.length);
+
+		memcpy(ucd_cmd_ptr->cdb,
+		       lrbp->cmd->cmnd,
+		       (min_t(unsigned short,
+			      lrbp->cmd->cmd_len,
+			      MAX_CDB_SIZE)));
+		break;
 	case UTP_CMD_TYPE_DEV_MANAGE:
-		ufshcd_prepare_req_desc(lrbp, &upiu_flags);
-		if (lrbp->command_type == UTP_CMD_TYPE_SCSI)
-			ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
-		else
-			ufshcd_prepare_utp_query_req_upiu(hba, lrbp,
-								upiu_flags);
+		/* For query function implementation */
 		break;
 	case UTP_CMD_TYPE_UFS:
 		/* For UFS native command implementation */
-		dev_err(hba->dev, "%s: UFS native command are not supported\n",
-			__func__);
-		ret = -ENOTSUPP;
-		break;
-	default:
-		ret = -ENOTSUPP;
-		dev_err(hba->dev, "%s: unknown command type: 0x%x\n",
-				__func__, lrbp->command_type);
 		break;
 	} /* end of switch */
-
-	return ret;
 }
 
 /**
@@ -657,13 +655,10 @@
 	lrbp->task_tag = tag;
 	lrbp->lun = cmd->device->lun;
 
-	if (ufshcd_is_query_req(lrbp))
-		lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
-	else
-		lrbp->command_type = UTP_CMD_TYPE_SCSI;
+	lrbp->command_type = UTP_CMD_TYPE_SCSI;
 
 	/* form UPIU before issuing the command */
-	ufshcd_compose_upiu(hba, lrbp);
+	ufshcd_compose_upiu(lrbp);
 	err = ufshcd_map_sg(lrbp);
 	if (err)
 		goto out;
@@ -677,109 +672,6 @@
 }
 
 /**
- *  ufshcd_query_request() - Entry point for issuing query request to a
- *  ufs device.
- *  @hba: ufs driver context
- *  @query: params for query request
- *  @descriptor: buffer for sending/receiving descriptor
- *  @response: pointer to a buffer that will contain the response code and
- *           response upiu
- *  @timeout: time limit for the command in seconds
- *  @retries: number of times to try executing the command
- *
- *  The query request is submitted to the same request queue as the rest of
- *  the scsi commands passed to the UFS controller. In order to use this
- *  queue, we need to receive a tag, same as all other commands. The tags
- *  are issued from the block layer. To simulate a request from the block
- *  layer, we use the same interface as the SCSI layer does when it issues
- *  commands not generated by users. To distinguish a query request from
- *  the SCSI commands, we use a vendor specific unused SCSI command
- *  op-code. This op-code is not part of the SCSI command subset used in
- *  UFS. In such way it is easy to check the command in the driver and
- *  handle it appropriately.
- *
- *  All necessary fields for issuing a query and receiving its response are
- *  stored in the UFS hba struct. We can use this method since we know
- *  there is only one active query request at all times.
- *
- *  The request that will pass to the device is stored in "query" argument
- *  passed to this function, while the "response" argument (which is output
- *  field) will hold the query response from the device along with the
- *  response code.
- */
-int ufshcd_query_request(struct ufs_hba *hba,
-			struct ufs_query_req *query,
-			u8 *descriptor,
-			struct ufs_query_res *response,
-			int timeout,
-			int retries)
-{
-	struct scsi_device *sdev;
-	u8 cmd[UFS_QUERY_CMD_SIZE] = {0};
-	int result;
-	bool sdev_lookup = true;
-
-	if (!hba || !query || !response) {
-		pr_err("%s: NULL pointer hba = %p, query = %p response = %p\n",
-			__func__, hba, query, response);
-		return -EINVAL;
-	}
-
-	/*
-	 * A SCSI command structure is composed from opcode at the
-	 * begining and 0 at the end.
-	 */
-	cmd[0] = UFS_QUERY_RESERVED_SCSI_CMD;
-
-	/* extracting the SCSI Device */
-	sdev = scsi_device_lookup(hba->host, 0, 0, 0);
-	if (!sdev) {
-		/**
-		 * There are some Query Requests that are sent during device
-		 * initialization, this happens before the scsi device was
-		 * initialized. If there is no scsi device, we generate a
-		 * temporary device to allow the Query Request flow.
-		 */
-		sdev_lookup = false;
-		sdev = scsi_get_host_dev(hba->host);
-	}
-
-	if (!sdev) {
-		dev_err(hba->dev, "%s: Could not fetch scsi device\n",
-			__func__);
-		return -ENODEV;
-	}
-
-	mutex_lock(&hba->query.lock_ufs_query);
-	hba->query.request = query;
-	hba->query.descriptor = descriptor;
-	hba->query.response = response;
-
-	/* wait until request is completed */
-	result = scsi_execute(sdev, cmd, DMA_NONE, NULL, 0, NULL,
-				timeout, retries, 0, NULL);
-	if (result) {
-		dev_err(hba->dev,
-			"%s: Query with opcode 0x%x, failed with result %d\n",
-			__func__, query->upiu_req.opcode, result);
-		result = -EIO;
-	}
-
-	hba->query.request = NULL;
-	hba->query.descriptor = NULL;
-	hba->query.response = NULL;
-	mutex_unlock(&hba->query.lock_ufs_query);
-
-	/* Releasing scsi device resource */
-	if (sdev_lookup)
-		scsi_device_put(sdev);
-	else
-		scsi_free_host_dev(sdev);
-
-	return result;
-}
-
-/**
  * ufshcd_memory_alloc - allocate memory for host memory space data structures
  * @hba: per adapter instance
  *
@@ -913,8 +805,8 @@
 				cpu_to_le16(ALIGNED_UPIU_SIZE);
 
 		hba->lrb[i].utr_descriptor_ptr = (utrdlp + i);
-		hba->lrb[i].ucd_req_ptr =
-			(struct utp_upiu_req *)(cmd_descp + i);
+		hba->lrb[i].ucd_cmd_ptr =
+			(struct utp_upiu_cmd *)(cmd_descp + i);
 		hba->lrb[i].ucd_rsp_ptr =
 			(struct utp_upiu_rsp *)cmd_descp[i].response_upiu;
 		hba->lrb[i].ucd_prdt_ptr =
@@ -935,35 +827,16 @@
  */
 static int ufshcd_dme_link_startup(struct ufs_hba *hba)
 {
-	struct uic_command *uic_cmd;
-	unsigned long flags;
+	struct uic_command uic_cmd = {0};
+	int ret;
 
-	/* check if controller is ready to accept UIC commands */
-	if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
-	    UIC_COMMAND_READY) == 0x0) {
+	uic_cmd.command = UIC_CMD_DME_LINK_STARTUP;
+
+	ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+	if (ret)
 		dev_err(hba->dev,
-			"Controller not ready"
-			" to accept UIC commands\n");
-		return -EIO;
-	}
-
-	spin_lock_irqsave(hba->host->host_lock, flags);
-
-	/* form UIC command */
-	uic_cmd = &hba->active_uic_cmd;
-	uic_cmd->command = UIC_CMD_DME_LINK_STARTUP;
-	uic_cmd->argument1 = 0;
-	uic_cmd->argument2 = 0;
-	uic_cmd->argument3 = 0;
-
-	/* enable UIC related interrupts */
-	hba->int_enable_mask |= UIC_COMMAND_COMPL;
-	ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
-
-	/* sending UIC commands to controller */
-	ufshcd_send_uic_command(hba, uic_cmd);
-	spin_unlock_irqrestore(hba->host->host_lock, flags);
-	return 0;
+			"dme-link-startup: error code %d\n", ret);
+	return ret;
 }
 
 /**
@@ -972,9 +845,10 @@
  *
  * To bring UFS host controller to operational state,
  * 1. Check if device is present
- * 2. Configure run-stop-registers
- * 3. Enable required interrupts
- * 4. Configure interrupt aggregation
+ * 2. Enable required interrupts
+ * 3. Configure interrupt aggregation
+ * 4. Program UTRL and UTMRL base addres
+ * 5. Configure run-stop-registers
  *
  * Returns 0 on success, non-zero value on failure
  */
@@ -984,13 +858,29 @@
 	u32 reg;
 
 	/* check if device present */
-	reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
+	reg = ufshcd_readl(hba, REG_CONTROLLER_STATUS);
 	if (!ufshcd_is_device_present(reg)) {
 		dev_err(hba->dev, "cc: Device not present\n");
 		err = -ENXIO;
 		goto out;
 	}
 
+	/* Enable required interrupts */
+	ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS);
+
+	/* Configure interrupt aggregation */
+	ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
+
+	/* Configure UTRL and UTMRL base address registers */
+	ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr),
+			REG_UTP_TRANSFER_REQ_LIST_BASE_L);
+	ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr),
+			REG_UTP_TRANSFER_REQ_LIST_BASE_H);
+	ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr),
+			REG_UTP_TASK_REQ_LIST_BASE_L);
+	ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr),
+			REG_UTP_TASK_REQ_LIST_BASE_H);
+
 	/*
 	 * UCRDY, UTMRLDY and UTRLRDY bits must be 1
 	 * DEI, HEI bits must be 0
@@ -1004,23 +894,11 @@
 		goto out;
 	}
 
-	/* Enable required interrupts */
-	hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL |
-				 UIC_ERROR |
-				 UTP_TASK_REQ_COMPL |
-				 DEVICE_FATAL_ERROR |
-				 CONTROLLER_FATAL_ERROR |
-				 SYSTEM_BUS_FATAL_ERROR);
-	ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
-
-	/* Configure interrupt aggregation */
-	ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
-
 	if (hba->ufshcd_state == UFSHCD_STATE_RESET)
 		scsi_unblock_requests(hba->host);
 
 	hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
-	scsi_scan_host(hba->host);
+
 out:
 	return err;
 }
@@ -1089,34 +967,28 @@
 }
 
 /**
- * ufshcd_initialize_hba - start the initialization process
+ * ufshcd_link_startup - Initialize unipro link startup
  * @hba: per adapter instance
  *
- * 1. Enable the controller via ufshcd_hba_enable.
- * 2. Program the Transfer Request List Address with the starting address of
- * UTRDL.
- * 3. Program the Task Management Request List Address with starting address
- * of UTMRDL.
- *
- * Returns 0 on success, non-zero value on failure.
+ * Returns 0 for success, non-zero in case of failure
  */
-static int ufshcd_initialize_hba(struct ufs_hba *hba)
+static int ufshcd_link_startup(struct ufs_hba *hba)
 {
-	if (ufshcd_hba_enable(hba))
-		return -EIO;
+	int ret;
 
-	/* Configure UTRL and UTMRL base address registers */
-	writel(lower_32_bits(hba->utrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
-	writel(upper_32_bits(hba->utrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H));
-	writel(lower_32_bits(hba->utmrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L));
-	writel(upper_32_bits(hba->utmrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H));
+	/* enable UIC related interrupts */
+	ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
 
-	/* Initialize unipro link startup procedure */
-	return ufshcd_dme_link_startup(hba);
+	ret = ufshcd_dme_link_startup(hba);
+	if (ret)
+		goto out;
+
+	ret = ufshcd_make_hba_operational(hba);
+
+out:
+	if (ret)
+		dev_err(hba->dev, "link startup failed %d\n", ret);
+	return ret;
 }
 
 /**
@@ -1156,12 +1028,19 @@
 	hba->outstanding_reqs = 0;
 	hba->outstanding_tasks = 0;
 
-	/* start the initialization process */
-	if (ufshcd_initialize_hba(hba)) {
+	/* Host controller enable */
+	if (ufshcd_hba_enable(hba)) {
 		dev_err(hba->dev,
 			"Reset: Controller initialization failed\n");
 		return FAILED;
 	}
+
+	if (ufshcd_link_startup(hba)) {
+		dev_err(hba->dev,
+			"Reset: Link start-up failed\n");
+		return FAILED;
+	}
+
 	return SUCCESS;
 }
 
@@ -1337,9 +1216,7 @@
  * @hba: per adapter instance
  * @lrb: pointer to local reference block of completed command
  *
- * Returns result of the command to notify SCSI midlayer. In
- * case of query request specific result, returns DID_OK, and
- * the error will be handled by the dispatcher.
+ * Returns result of the command to notify SCSI midlayer
  */
 static inline int
 ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
@@ -1353,46 +1230,27 @@
 
 	switch (ocs) {
 	case OCS_SUCCESS:
+
 		/* check if the returned transfer response is valid */
-		result = ufshcd_get_req_rsp(lrbp->ucd_rsp_ptr);
-
-		switch (result) {
-		case UPIU_TRANSACTION_RESPONSE:
-			/*
-			 * get the response UPIU result to extract
-			 * the SCSI command status
-			 */
-			result = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr);
-
-			/*
-			 * get the result based on SCSI status response
-			 * to notify the SCSI midlayer of the command status
-			 */
-			scsi_status = result & MASK_SCSI_STATUS;
-			result = ufshcd_scsi_cmd_status(lrbp, scsi_status);
-			break;
-		case UPIU_TRANSACTION_QUERY_RSP:
-			/*
-			 *  Return result = ok, since SCSI layer wouldn't
-			 *  know how to handle errors from query requests.
-			 *  The result is saved with the response so that
-			 *  the ufs_core layer will handle it.
-			 */
-			result = DID_OK << 16;
-			ufshcd_copy_query_response(hba, lrbp);
-			break;
-		case UPIU_TRANSACTION_REJECT_UPIU:
-			/* TODO: handle Reject UPIU Response */
-			result = DID_ERROR << 16;
+		result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr);
+		if (result) {
 			dev_err(hba->dev,
-				"Reject UPIU not fully implemented\n");
+				"Invalid response = %x\n", result);
 			break;
-		default:
-			result = DID_ERROR << 16;
-			dev_err(hba->dev,
-				"Unexpected request response code = %x\n",
-				result);
 		}
+
+		/*
+		 * get the response UPIU result to extract
+		 * the SCSI command status
+		 */
+		result = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr);
+
+		/*
+		 * get the result based on SCSI status response
+		 * to notify the SCSI midlayer of the command status
+		 */
+		scsi_status = result & MASK_SCSI_STATUS;
+		result = ufshcd_scsi_cmd_status(lrbp, scsi_status);
 		break;
 	case OCS_ABORTED:
 		result |= DID_ABORT << 16;
@@ -1414,6 +1272,19 @@
 }
 
 /**
+ * ufshcd_uic_cmd_compl - handle completion of uic command
+ * @hba: per adapter instance
+ */
+static void ufshcd_uic_cmd_compl(struct ufs_hba *hba)
+{
+	if (hba->active_uic_cmd) {
+		hba->active_uic_cmd->argument2 |=
+			ufshcd_get_uic_cmd_result(hba);
+		complete(&hba->active_uic_cmd->done);
+	}
+}
+
+/**
  * ufshcd_transfer_req_compl - handle SCSI and query command completion
  * @hba: per adapter instance
  */
@@ -1426,8 +1297,7 @@
 	int index;
 
 	lrb = hba->lrb;
-	tr_doorbell =
-		readl(hba->mmio_base + REG_UTP_TRANSFER_REQ_DOOR_BELL);
+	tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 	completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
 
 	for (index = 0; index < hba->nutrs; index++) {
@@ -1454,28 +1324,6 @@
 }
 
 /**
- * ufshcd_uic_cc_handler - handle UIC command completion
- * @work: pointer to a work queue structure
- *
- * Returns 0 on success, non-zero value on failure
- */
-static void ufshcd_uic_cc_handler (struct work_struct *work)
-{
-	struct ufs_hba *hba;
-
-	hba = container_of(work, struct ufs_hba, uic_workq);
-
-	if ((hba->active_uic_cmd.command == UIC_CMD_DME_LINK_STARTUP) &&
-	    !(ufshcd_get_uic_cmd_result(hba))) {
-
-		if (ufshcd_make_hba_operational(hba))
-			dev_err(hba->dev,
-				"cc: hba not operational state\n");
-		return;
-	}
-}
-
-/**
  * ufshcd_fatal_err_handler - handle fatal errors
  * @hba: per adapter instance
  */
@@ -1501,9 +1349,7 @@
 		goto fatal_eh;
 
 	if (hba->errors & UIC_ERROR) {
-
-		reg = readl(hba->mmio_base +
-			    REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
+		reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
 		if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT)
 			goto fatal_eh;
 	}
@@ -1521,7 +1367,7 @@
 {
 	u32 tm_doorbell;
 
-	tm_doorbell = readl(hba->mmio_base + REG_UTP_TASK_REQ_DOOR_BELL);
+	tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
 	hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;
 	wake_up_interruptible(&hba->ufshcd_tm_wait_queue);
 }
@@ -1538,7 +1384,7 @@
 		ufshcd_err_handler(hba);
 
 	if (intr_status & UIC_COMMAND_COMPL)
-		schedule_work(&hba->uic_workq);
+		ufshcd_uic_cmd_compl(hba);
 
 	if (intr_status & UTP_TASK_REQ_COMPL)
 		ufshcd_tmc_handler(hba);
@@ -1562,15 +1408,11 @@
 	struct ufs_hba *hba = __hba;
 
 	spin_lock(hba->host->host_lock);
-	intr_status = readl(hba->mmio_base + REG_INTERRUPT_STATUS);
+	intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
 
 	if (intr_status) {
+		ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
 		ufshcd_sl_intr(hba, intr_status);
-
-		/* If UFSHCI 1.0 then clear interrupt status register */
-		if (hba->ufs_version == UFSHCI_VERSION_10)
-			writel(intr_status,
-			       (hba->mmio_base + REG_INTERRUPT_STATUS));
 		retval = IRQ_HANDLED;
 	}
 	spin_unlock(hba->host->host_lock);
@@ -1621,10 +1463,10 @@
 	task_req_upiup =
 		(struct utp_upiu_task_req *) task_req_descp->task_req_upiu;
 	task_req_upiup->header.dword_0 =
-		UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0,
-					      lrbp->lun, lrbp->task_tag);
+		cpu_to_be32(UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0,
+					      lrbp->lun, lrbp->task_tag));
 	task_req_upiup->header.dword_1 =
-		UPIU_HEADER_DWORD(0, tm_function, 0, 0);
+	cpu_to_be32(UPIU_HEADER_DWORD(0, tm_function, 0, 0));
 
 	task_req_upiup->input_param1 = lrbp->lun;
 	task_req_upiup->input_param1 =
@@ -1635,8 +1477,7 @@
 
 	/* send command to the controller */
 	__set_bit(free_slot, &hba->outstanding_tasks);
-	writel((1 << free_slot),
-	       (hba->mmio_base + REG_UTP_TASK_REQ_DOOR_BELL));
+	ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL);
 
 	spin_unlock_irqrestore(host->host_lock, flags);
 
@@ -1766,6 +1607,21 @@
 	return err;
 }
 
+/**
+ * ufshcd_async_scan - asynchronous execution for link startup
+ * @data: data pointer to pass to this function
+ * @cookie: cookie data
+ */
+static void ufshcd_async_scan(void *data, async_cookie_t cookie)
+{
+	struct ufs_hba *hba = (struct ufs_hba *)data;
+	int ret;
+
+	ret = ufshcd_link_startup(hba);
+	if (!ret)
+		scsi_scan_host(hba->host);
+}
+
 static struct scsi_host_template ufshcd_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= UFSHCD,
@@ -1844,7 +1700,7 @@
 void ufshcd_remove(struct ufs_hba *hba)
 {
 	/* disable interrupts */
-	ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
+	ufshcd_disable_intr(hba, hba->intr_mask);
 
 	ufshcd_hba_stop(hba);
 	ufshcd_hba_free(hba);
@@ -1902,6 +1758,9 @@
 	/* Get UFS version supported by the controller */
 	hba->ufs_version = ufshcd_get_ufs_version(hba);
 
+	/* Get Interrupt bit mask per version */
+	hba->intr_mask = ufshcd_get_intr_mask(hba);
+
 	/* Allocate memory for host memory space */
 	err = ufshcd_memory_alloc(hba);
 	if (err) {
@@ -1924,11 +1783,10 @@
 	init_waitqueue_head(&hba->ufshcd_tm_wait_queue);
 
 	/* Initialize work queues */
-	INIT_WORK(&hba->uic_workq, ufshcd_uic_cc_handler);
 	INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
 
-	/* Initialize mutex for query requests */
-	mutex_init(&hba->query.lock_ufs_query);
+	/* Initialize UIC command mutex */
+	mutex_init(&hba->uic_cmd_mutex);
 
 	/* IRQ registration */
 	err = request_irq(irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
@@ -1950,14 +1808,17 @@
 		goto out_free_irq;
 	}
 
-	/* Initialization routine */
-	err = ufshcd_initialize_hba(hba);
+	/* Host controller enable */
+	err = ufshcd_hba_enable(hba);
 	if (err) {
-		dev_err(hba->dev, "Initialization failed\n");
+		dev_err(hba->dev, "Host controller enable failed\n");
 		goto out_remove_scsi_host;
 	}
+
 	*hba_handle = hba;
 
+	async_schedule(ufshcd_async_scan, hba);
+
 	return 0;
 
 out_remove_scsi_host:
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 336980b..49590ee 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -51,6 +51,7 @@
 #include <linux/bitops.h>
 #include <linux/pm_runtime.h>
 #include <linux/clk.h>
+#include <linux/completion.h>
 
 #include <asm/irq.h>
 #include <asm/byteorder.h>
@@ -60,7 +61,6 @@
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_eh.h>
-#include <scsi/scsi_device.h>
 
 #include "ufs.h"
 #include "ufshci.h"
@@ -76,6 +76,7 @@
  * @argument3: UIC command argument 3
  * @cmd_active: Indicate if UIC command is outstanding
  * @result: UIC command result
+ * @done: UIC command completion
  */
 struct uic_command {
 	u32 command;
@@ -84,12 +85,13 @@
 	u32 argument3;
 	int cmd_active;
 	int result;
+	struct completion done;
 };
 
 /**
  * struct ufshcd_lrb - local reference block
  * @utr_descriptor_ptr: UTRD address of the command
- * @ucd_req_ptr: UCD address of the command
+ * @ucd_cmd_ptr: UCD address of the command
  * @ucd_rsp_ptr: Response UPIU address for this command
  * @ucd_prdt_ptr: PRDT address of the command
  * @cmd: pointer to SCSI command
@@ -102,7 +104,7 @@
  */
 struct ufshcd_lrb {
 	struct utp_transfer_req_desc *utr_descriptor_ptr;
-	struct utp_upiu_req *ucd_req_ptr;
+	struct utp_upiu_cmd *ucd_cmd_ptr;
 	struct utp_upiu_rsp *ucd_rsp_ptr;
 	struct ufshcd_sg_entry *ucd_prdt_ptr;
 
@@ -116,19 +118,6 @@
 	unsigned int lun;
 };
 
-/**
- * struct ufs_query - keeps the query request information
- * @request: request upiu and function
- * @descriptor: buffer for sending/receiving descriptor
- * @response: response upiu and response
- * @mutex: lock to allow one query at a time
- */
-struct ufs_query {
-	struct ufs_query_req *request;
-	u8 *descriptor;
-	struct ufs_query_res *response;
-	struct mutex lock_ufs_query;
-};
 
 /**
  * struct ufs_hba - per adapter private structure
@@ -150,14 +139,13 @@
  * @ufs_version: UFS Version to which controller complies
  * @irq: Irq number of the controller
  * @active_uic_cmd: handle of active UIC command
+ * @uic_cmd_mutex: mutex for uic command
  * @ufshcd_tm_wait_queue: wait queue for task management
  * @tm_condition: condition variable for task management
  * @ufshcd_state: UFSHCD states
- * @int_enable_mask: Interrupt Mask Bits
- * @uic_workq: Work queue for UIC completion handling
+ * @intr_mask: Interrupt Mask Bits
  * @feh_workq: Work queue for fatal controller error handling
  * @errors: HBA errors
- * @query: query request information
  */
 struct ufs_hba {
 	void __iomem *mmio_base;
@@ -186,24 +174,27 @@
 	u32 ufs_version;
 	unsigned int irq;
 
-	struct uic_command active_uic_cmd;
+	struct uic_command *active_uic_cmd;
+	struct mutex uic_cmd_mutex;
+
 	wait_queue_head_t ufshcd_tm_wait_queue;
 	unsigned long tm_condition;
 
 	u32 ufshcd_state;
-	u32 int_enable_mask;
+	u32 intr_mask;
 
 	/* Work Queues */
-	struct work_struct uic_workq;
 	struct work_struct feh_workq;
 
 	/* HBA Errors */
 	u32 errors;
-
-	/* Query Request */
-	struct ufs_query query;
 };
 
+#define ufshcd_writel(hba, val, reg)	\
+	writel((val), (hba)->mmio_base + (reg))
+#define ufshcd_readl(hba, reg)	\
+	readl((hba)->mmio_base + (reg))
+
 int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * ,
 			unsigned int);
 void ufshcd_remove(struct ufs_hba *);
@@ -214,7 +205,7 @@
  */
 static inline void ufshcd_hba_stop(struct ufs_hba *hba)
 {
-	writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
+	ufshcd_writel(hba, CONTROLLER_DISABLE,  REG_CONTROLLER_ENABLE);
 }
 
 #endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 4a86247..d5c5f14 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -39,7 +39,7 @@
 enum {
 	TASK_REQ_UPIU_SIZE_DWORDS	= 8,
 	TASK_RSP_UPIU_SIZE_DWORDS	= 8,
-	ALIGNED_UPIU_SIZE		= 512,
+	ALIGNED_UPIU_SIZE		= 128,
 };
 
 /* UFSHCI Registers */
@@ -232,10 +232,11 @@
 /* Interrupt disable masks */
 enum {
 	/* Interrupt disable mask for UFSHCI v1.0 */
-	INTERRUPT_DISABLE_MASK_10	= 0xFFFF,
+	INTERRUPT_MASK_ALL_VER_10	= 0x30FFF,
+	INTERRUPT_MASK_RW_VER_10	= 0x30000,
 
 	/* Interrupt disable mask for UFSHCI v1.1 */
-	INTERRUPT_DISABLE_MASK_11	= 0x0,
+	INTERRUPT_MASK_ALL_VER_11	= 0x31FFF,
 };
 
 /*
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 97d47db..6e7a815 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -30,12 +30,6 @@
 #define MSM_SLIM_NAME	"msm_slim_ctrl"
 #define SLIM_ROOT_FREQ 24576000
 
-#define QC_MFGID_LSB	0x2
-#define QC_MFGID_MSB	0x17
-#define QC_CHIPID_SL	0x10
-#define QC_DEVID_SAT1	0x3
-#define QC_DEVID_SAT2	0x4
-#define QC_DEVID_PGD	0x5
 #define QC_MSM_DEVS	5
 
 /* Manager registers */
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 509c1e8..2f19863 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -306,8 +306,26 @@
 			txn->mc = SLIM_USR_MC_CONNECT_SINK;
 		else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
 			txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
-		if (txn->la == SLIM_LA_MGR)
+		if (txn->la == SLIM_LA_MGR) {
+			if (dev->pgdla == SLIM_LA_MGR) {
+				u8 ea[] = {0, QC_DEVID_PGD, 0, 0, QC_MFGID_MSB,
+						QC_MFGID_LSB};
+				ea[2] = (u8)(dev->pdata.eapc & 0xFF);
+				ea[3] = (u8)((dev->pdata.eapc & 0xFF00) >> 8);
+				mutex_unlock(&dev->tx_lock);
+				ret = dev->ctrl.get_laddr(&dev->ctrl, ea, 6,
+						&dev->pgdla);
+				pr_debug("SLIM PGD LA:0x%x, ret:%d", dev->pgdla,
+						ret);
+				if (ret) {
+					pr_err("Incorrect SLIM-PGD EAPC:0x%x",
+							dev->pdata.eapc);
+					return ret;
+				}
+				mutex_lock(&dev->tx_lock);
+			}
 			txn->la = dev->pgdla;
+		}
 		wbuf[i++] = txn->la;
 		la = SLIM_LA_MGR;
 		wbuf[i++] = txn->wbuf[0];
@@ -380,6 +398,8 @@
 			dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
 			goto ngd_xfer_err;
 		}
+		/* Add port-base to port number if this is manager side port */
+		puc[1] += dev->port_b;
 	}
 	dev->err = 0;
 	dev->wr_comp = &tx_sent;
@@ -1070,9 +1090,18 @@
 		}
 		rxreg_access = of_property_read_bool(pdev->dev.of_node,
 					"qcom,rxreg-access");
+		of_property_read_u32(pdev->dev.of_node, "qcom,apps-ch-pipes",
+					&dev->pdata.apps_pipes);
+		of_property_read_u32(pdev->dev.of_node, "qcom,ea-pc",
+					&dev->pdata.eapc);
 	} else {
 		dev->ctrl.nr = pdev->id;
 	}
+	/*
+	 * Keep PGD's logical address as manager's. Query it when first data
+	 * channel request comes in
+	 */
+	dev->pgdla = SLIM_LA_MGR;
 	dev->ctrl.nchans = MSM_SLIM_NCHANS;
 	dev->ctrl.nports = MSM_SLIM_NPORTS;
 	dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index a63ee76..37bc883 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -788,6 +788,10 @@
 	bam_props.options = SPS_O_DESC_DONE | SPS_O_ERROR |
 				SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
 
+	/* override apps channel pipes if specified in platform-data or DT */
+	if (dev->pdata.apps_pipes)
+		sec_props.ees[dev->ee].pipe_mask = dev->pdata.apps_pipes;
+
 	/* First 7 bits are for message Qs */
 	for (i = 7; i < 32; i++) {
 		/* Check what pipes are owned by Apps. */
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 896e196..b5c41ed 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -50,6 +50,13 @@
 #define MSM_SLIM_NPORTS			24
 #define MSM_SLIM_NCHANS			32
 
+#define QC_MFGID_LSB	0x2
+#define QC_MFGID_MSB	0x17
+#define QC_CHIPID_SL	0x10
+#define QC_DEVID_SAT1	0x3
+#define QC_DEVID_SAT2	0x4
+#define QC_DEVID_PGD	0x5
+
 #define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
 		((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
 
@@ -198,6 +205,11 @@
 	struct work_struct		ssr_up;
 };
 
+struct msm_slim_pdata {
+	u32 apps_pipes;
+	u32 eapc;
+};
+
 struct msm_slim_ctrl {
 	struct slim_controller  ctrl;
 	struct slim_framer	framer;
@@ -240,6 +252,7 @@
 	u32			ver;
 	struct work_struct	slave_notify;
 	struct msm_slim_qmi	qmi;
+	struct msm_slim_pdata	pdata;
 };
 
 struct msm_sat_chan {
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 53aa475..c7db832 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -720,6 +720,73 @@
 	}
 }
 
+static int msm_spi_bam_pipe_disconnect(struct msm_spi *dd,
+						struct msm_spi_bam_pipe  *pipe)
+{
+	int ret = sps_disconnect(pipe->handle);
+	if (ret) {
+		dev_dbg(dd->dev, "%s disconnect bam %s pipe failed\n",
+							__func__, pipe->name);
+		return ret;
+	}
+	return 0;
+}
+
+static int msm_spi_bam_pipe_connect(struct msm_spi *dd,
+		struct msm_spi_bam_pipe  *pipe, struct sps_connect *config)
+{
+	int ret;
+	struct sps_register_event event  = {
+		.mode      = SPS_TRIGGER_WAIT,
+		.options   = SPS_O_EOT,
+		.xfer_done = &dd->transfer_complete,
+	};
+
+	ret = sps_connect(pipe->handle, config);
+	if (ret) {
+		dev_err(dd->dev, "%s: sps_connect(%s:0x%p):%d",
+				__func__, pipe->name, pipe->handle, ret);
+		return ret;
+	}
+
+	ret = sps_register_event(pipe->handle, &event);
+	if (ret) {
+		dev_err(dd->dev, "%s sps_register_event(hndl:0x%p %s):%d",
+				__func__, pipe->handle, pipe->name, ret);
+		msm_spi_bam_pipe_disconnect(dd, pipe);
+		return ret;
+	}
+
+	pipe->teardown_required = true;
+	return 0;
+}
+
+
+static void msm_spi_bam_pipe_flush(struct msm_spi *dd,
+					enum msm_spi_pipe_direction pipe_dir)
+{
+	struct msm_spi_bam_pipe *pipe = (pipe_dir == SPI_BAM_CONSUMER_PIPE) ?
+					(&dd->bam.prod) : (&dd->bam.cons);
+	struct sps_connect           config  = pipe->config;
+	int    ret;
+
+	ret = msm_spi_bam_pipe_disconnect(dd, pipe);
+	if (ret)
+		return;
+
+	ret = msm_spi_bam_pipe_connect(dd, pipe, &config);
+	if (ret)
+		return;
+}
+
+static void msm_spi_bam_flush(struct msm_spi *dd)
+{
+	dev_dbg(dd->dev, "%s flushing bam for recovery\n" , __func__);
+
+	msm_spi_bam_pipe_flush(dd, SPI_BAM_CONSUMER_PIPE);
+	msm_spi_bam_pipe_flush(dd, SPI_BAM_PRODUCER_PIPE);
+}
+
 /**
  * msm_spi_bam_begin_transfer: transfer dd->tx_bytes_remaining bytes
  * using BAM.
@@ -1681,6 +1748,8 @@
 					msm_dmov_flush(dd->tx_dma_chan, 1);
 					msm_dmov_flush(dd->rx_dma_chan, 1);
 				}
+				if (dd->mode == SPI_BAM_MODE)
+					msm_spi_bam_flush(dd);
 				break;
 		}
 	} while (msm_spi_dm_send_next(dd));
@@ -2312,7 +2381,7 @@
 	if (!pipe->teardown_required)
 		return;
 
-	sps_disconnect(pipe->handle);
+	msm_spi_bam_pipe_disconnect(dd, pipe);
 	dma_free_coherent(dd->dev, pipe->config.desc.size,
 		pipe->config.desc.base, pipe->config.desc.phys_base);
 	sps_free_endpoint(pipe->handle);
@@ -2325,13 +2394,13 @@
 {
 	int rc = 0;
 	struct sps_pipe *pipe_handle;
-	struct sps_register_event event = {0};
 	struct msm_spi_bam_pipe *pipe = (pipe_dir == SPI_BAM_CONSUMER_PIPE) ?
 					(&dd->bam.prod) : (&dd->bam.cons);
 	struct sps_connect *pipe_conf = &pipe->config;
 
+	pipe->name   = (pipe_dir == SPI_BAM_CONSUMER_PIPE) ? "cons" : "prod";
 	pipe->handle = 0;
-	pipe_handle = sps_alloc_endpoint();
+	pipe_handle  = sps_alloc_endpoint();
 	if (!pipe_handle) {
 		dev_err(dd->dev, "%s: Failed to allocate BAM endpoint\n"
 								, __func__);
@@ -2373,32 +2442,16 @@
 		rc = -ENOMEM;
 		goto config_err;
 	}
-
+	/* zero descriptor FIFO for convenient debugging of first descs */
 	memset(pipe_conf->desc.base, 0x00, pipe_conf->desc.size);
 
-	rc = sps_connect(pipe_handle, pipe_conf);
-	if (rc) {
-		dev_err(dd->dev, "%s: Failed to connect BAM pipe", __func__);
-		goto connect_err;
-	}
-
-	event.mode      = SPS_TRIGGER_WAIT;
-	event.options   = SPS_O_EOT;
-	event.xfer_done = &dd->transfer_complete;
-	event.user      = (void *)dd;
-	rc = sps_register_event(pipe_handle, &event);
-	if (rc) {
-		dev_err(dd->dev, "%s: Failed to register BAM EOT event",
-			__func__);
-		goto register_err;
-	}
-
 	pipe->handle = pipe_handle;
-	pipe->teardown_required = true;
+	rc = msm_spi_bam_pipe_connect(dd, pipe, pipe_conf);
+	if (rc)
+		goto connect_err;
+
 	return 0;
 
-register_err:
-	sps_disconnect(pipe_handle);
 connect_err:
 	dma_free_coherent(dd->dev, pipe_conf->desc.size,
 		pipe_conf->desc.base, pipe_conf->desc.phys_base);
diff --git a/drivers/spi/spi_qsd.h b/drivers/spi/spi_qsd.h
index 90d7481..2a67a61 100644
--- a/drivers/spi/spi_qsd.h
+++ b/drivers/spi/spi_qsd.h
@@ -277,6 +277,7 @@
 };
 
 struct msm_spi_bam_pipe {
+	const char              *name;
 	struct sps_pipe         *handle;
 	struct sps_connect       config;
 	bool                     teardown_required;
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 7f669d8..cab7c12 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -2835,7 +2835,7 @@
 	struct resource *core_resource;
 	struct resource *bam_resource;
 	struct resource *resource;
-	int core_irqres, bam_irqres;
+	int core_irqres, bam_irqres, wakeup_irqres;
 	struct msm_serial_hs_platform_data *pdata = pdev->dev.platform_data;
 
 	if (pdev->dev.of_node) {
@@ -2894,6 +2894,7 @@
 					IORESOURCE_MEM, "bam_mem");
 		core_irqres = platform_get_irq_byname(pdev, "core_irq");
 		bam_irqres = platform_get_irq_byname(pdev, "bam_irq");
+		wakeup_irqres = platform_get_irq_byname(pdev, "wakeup_irq");
 
 		if (!core_resource) {
 			pr_err("Invalid core HSUART Resources.\n");
@@ -2913,6 +2914,8 @@
 			pr_err("Invalid bam irqres Resources.\n");
 			return -ENXIO;
 		}
+		if (!wakeup_irqres)
+			pr_debug("Wakeup irq not specified.\n");
 
 		uport->mapbase = core_resource->start;
 
@@ -2933,6 +2936,7 @@
 
 		uport->irq = core_irqres;
 		msm_uport->bam_irq = bam_irqres;
+		pdata->wakeup_irq = wakeup_irqres;
 
 		msm_uport->bus_scale_table = msm_bus_cl_get_pdata(pdev);
 		if (!msm_uport->bus_scale_table) {
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index a5f586b..2600001 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -182,6 +182,7 @@
 	struct regulator	*hsusb_vddcx;
 	struct regulator	*ssusb_1p8;
 	struct regulator	*ssusb_vddcx;
+	struct regulator	*dwc3_gdsc;
 
 	/* VBUS regulator if no OTG and running in host only mode */
 	struct regulator	*vbus_otg;
@@ -1260,6 +1261,37 @@
 	return rc < 0 ? rc : 0;
 }
 
+/*
+ * Config Global Distributed Switch Controller (GDSC)
+ * to support controller power collapse
+ */
+static int dwc3_msm_config_gdsc(struct dwc3_msm *msm, int on)
+{
+	int ret = 0;
+
+	if (IS_ERR(msm->dwc3_gdsc))
+		return 0;
+
+	if (!msm->dwc3_gdsc) {
+		msm->dwc3_gdsc = devm_regulator_get(msm->dev,
+			"USB3_GDSC");
+		if (IS_ERR(msm->dwc3_gdsc))
+			return 0;
+	}
+
+	if (on) {
+		ret = regulator_enable(msm->dwc3_gdsc);
+		if (ret) {
+			dev_err(msm->dev, "unable to enable usb3 gdsc\n");
+			return ret;
+		}
+	} else {
+		regulator_disable(msm->dwc3_gdsc);
+	}
+
+	return 0;
+}
+
 static int dwc3_msm_link_clk_reset(bool assert)
 {
 	int ret = 0;
@@ -1729,6 +1761,11 @@
 
 	/* make sure above writes are completed before turning off clocks */
 	wmb();
+
+	/* remove vote for controller power collapse */
+	if (!host_bus_suspend)
+		dwc3_msm_config_gdsc(mdwc, 0);
+
 	if (!host_bus_suspend || !host_ss_active) {
 		clk_disable_unprepare(mdwc->core_clk);
 		mdwc->lpm_flags |= MDWC3_CORECLK_OFF;
@@ -1809,6 +1846,10 @@
 		mdwc->lpm_flags &= ~MDWC3_TCXO_SHUTDOWN;
 	}
 
+	/* add vote for controller power collapse */
+	if (!host_bus_suspend)
+		dwc3_msm_config_gdsc(mdwc, 1);
+
 	if (!host_bus_suspend)
 		clk_prepare_enable(mdwc->utmi_clk);
 
@@ -2495,11 +2536,18 @@
 	INIT_DELAYED_WORK(&msm->init_adc_work, dwc3_init_adc_work);
 	init_completion(&msm->ext_chg_wait);
 
+	ret = dwc3_msm_config_gdsc(msm, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to configure usb3 gdsc\n");
+		return ret;
+	}
+
 	msm->xo_clk = clk_get(&pdev->dev, "xo");
 	if (IS_ERR(msm->xo_clk)) {
 		dev_err(&pdev->dev, "%s unable to get TCXO buffer handle\n",
 								__func__);
-		return PTR_ERR(msm->xo_clk);
+		ret = PTR_ERR(msm->xo_clk);
+		goto disable_dwc3_gdsc;
 	}
 
 	ret = clk_prepare_enable(msm->xo_clk);
@@ -2906,6 +2954,8 @@
 	clk_disable_unprepare(msm->xo_clk);
 put_xo:
 	clk_put(msm->xo_clk);
+disable_dwc3_gdsc:
+	dwc3_msm_config_gdsc(msm, 0);
 
 	return ret;
 }
@@ -2953,6 +3003,8 @@
 	clk_disable_unprepare(msm->xo_clk);
 	clk_put(msm->xo_clk);
 
+	dwc3_msm_config_gdsc(msm, 0);
+
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 3322da5..577a4fe 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -200,7 +200,6 @@
 	int ret;
 
 	pr_debug("%s: Connect workqueue started", __func__);
-	usb_bam_reset_complete();
 
 	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
 		if (d->func_type == USB_FUNC_MBIM) {
@@ -268,17 +267,18 @@
 			}
 		}
 	} else { /* transport type is USB_GADGET_XPORT_BAM2BAM */
-	ret = usb_bam_connect(d->src_connection_idx, &d->src_pipe_idx);
-	if (ret) {
-		pr_err("usb_bam_connect (src) failed: err:%d\n", ret);
-		return;
+		usb_bam_reset_complete();
+		ret = usb_bam_connect(d->src_connection_idx, &d->src_pipe_idx);
+		if (ret) {
+			pr_err("usb_bam_connect (src) failed: err:%d\n", ret);
+			return;
+		}
+		ret = usb_bam_connect(d->dst_connection_idx, &d->dst_pipe_idx);
+		if (ret) {
+			pr_err("usb_bam_connect (dst) failed: err:%d\n", ret);
+			return;
+		}
 	}
-	ret = usb_bam_connect(d->dst_connection_idx, &d->dst_pipe_idx);
-	if (ret) {
-		pr_err("usb_bam_connect (dst) failed: err:%d\n", ret);
-		return;
-	}
-}
 
 	if (!port->port_usb) {
 		pr_err("port_usb is NULL");
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 9961d00..325c2b5 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -557,6 +557,11 @@
 				switch (retval) {
 				default:
 					DBG(dev, "tx queue err %d\n", retval);
+					new_req->length = 0;
+					spin_lock(&dev->req_lock);
+					list_add_tail(&new_req->list,
+							&dev->tx_reqs);
+					spin_unlock(&dev->req_lock);
 					break;
 				case 0:
 					spin_lock(&dev->req_lock);
@@ -566,7 +571,13 @@
 				}
 			} else {
 				spin_lock(&dev->req_lock);
-				list_add(&new_req->list, &dev->tx_reqs);
+				/*
+				 * Put the idle request at the back of the
+				 * queue. The xmit function will put the
+				 * unfinished request at the beginning of the
+				 * queue.
+				 */
+				list_add_tail(&new_req->list, &dev->tx_reqs);
 				spin_unlock(&dev->req_lock);
 			}
 		} else {
@@ -787,6 +798,8 @@
 	if (retval) {
 		if (!multi_pkt_xfer)
 			dev_kfree_skb_any(skb);
+		else
+			req->length = 0;
 drop:
 		dev->net->stats.tx_dropped++;
 		spin_lock_irqsave(&dev->req_lock, flags);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 14c3323..ef45d49 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1895,6 +1895,8 @@
 				"hsic,consider-ipa-handshake"));
 	pdata->ahb_async_bridge_bypass = of_property_read_bool(node,
 				"qcom,ahb-async-bridge-bypass");
+	pdata->disable_cerr = of_property_read_bool(node,
+				"hsic,disable-cerr");
 
 	return pdata;
 }
@@ -1982,8 +1984,10 @@
 	mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
 	mehci->enable_hbm = pdata->enable_hbm;
 
-	if (pdata)
+	if (pdata) {
 		mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
+		mehci->ehci.disable_cerr = pdata->disable_cerr;
+	}
 
 	ret = msm_hsic_init_gdsc(mehci, 1);
 	if (ret) {
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 0b89dd0..823229b 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -1,6 +1,6 @@
 /* ehci-msm.c - HSUSB Host Controller Driver Implementation
  *
- * Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  *
  * Partly derived from ehci-fsl.c and ehci-hcd.c
  * Copyright (c) 2000-2004 by David Brownell
@@ -260,15 +260,23 @@
 static int ehci_msm_pm_resume(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	int ret;
 
 	dev_dbg(dev, "ehci-msm PM resume\n");
 
 	if (!hcd->rh_registered)
 		return 0;
 
-	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
+	/* Notify OTG to bring hw out of LPM before restoring wakeup flags */
+	ret = usb_phy_set_suspend(phy, 0);
+	if (ret)
+		return ret;
 
-	return usb_phy_set_suspend(phy, 0);
+	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
+	/* Resume root-hub to handle USB event if any else initiate LPM again */
+	usb_hcd_resume_root_hub(hcd);
+
+	return ret;
 }
 #endif
 
diff --git a/drivers/usb/host/ehci-msm2.c b/drivers/usb/host/ehci-msm2.c
index 60788f5..0aecaad 100644
--- a/drivers/usb/host/ehci-msm2.c
+++ b/drivers/usb/host/ehci-msm2.c
@@ -25,9 +25,12 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/err.h>
-#include <linux/wakelock.h>
+#include <linux/pm_wakeup.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/irq.h>
 
 #include <linux/usb/ulpi.h>
 #include <linux/usb/msm_hsusb_hw.h>
@@ -63,11 +66,16 @@
 	bool					pmic_gpio_dp_irq_enabled;
 	uint32_t				pmic_gpio_int_cnt;
 	atomic_t				pm_usage_cnt;
-	struct wake_lock			wlock;
+	struct wakeup_source			ws;
 	struct work_struct			phy_susp_fail_work;
 	int					async_irq;
 	bool					async_irq_enabled;
 	uint32_t				async_int_cnt;
+	int					resume_gpio;
+
+	int					wakeup_int_cnt;
+	bool					wakeup_irq_enabled;
+	int					wakeup_irq;
 };
 
 static inline struct msm_hcd *hcd_to_mhcd(struct usb_hcd *hcd)
@@ -602,8 +610,8 @@
 	msm_ehci_vbus_power(mhcd, 1);
 }
 
-#define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000)
-#define PHY_RESUME_TIMEOUT_USEC		(100 * 1000)
+#define PHY_SUSP_TIMEOUT_MSEC	500
+#define PHY_RESUME_TIMEOUT_USEC	(100 * 1000)
 
 #ifdef CONFIG_PM_SLEEP
 static int msm_ehci_suspend(struct msm_hcd *mhcd)
@@ -620,24 +628,42 @@
 
 	disable_irq(hcd->irq);
 
-	/* Set the PHCD bit, only if it is not set by the controller.
-	 * PHY may take some time or even fail to enter into low power
-	 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
-	 * in failure case.
+	/* make sure we don't race against a remote wakeup */
+	if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
+	    readl_relaxed(USB_PORTSC) & PORT_RESUME) {
+		dev_dbg(mhcd->dev, "wakeup pending, aborting suspend\n");
+		enable_irq(hcd->irq);
+		return -EBUSY;
+	}
+
+	/* If port is enabled wait 5ms for PHCD to come up. Reset PHY
+	 * and link if it fails to do so.
+	 * If port is not enabled set the PHCD bit and poll for it to
+	 * come up with in 500ms. Reset phy and link if it fails to do so.
 	 */
 	portsc = readl_relaxed(USB_PORTSC);
-	if (!(portsc & PORTSC_PHCD)) {
-		writel_relaxed(portsc | PORTSC_PHCD,
-				USB_PORTSC);
+	if (portsc & PORT_PE) {
 
-		timeout = jiffies + usecs_to_jiffies(PHY_SUSPEND_TIMEOUT_USEC);
+		usleep_range(5000, 5000);
+
+		if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD)) {
+			dev_err(mhcd->dev,
+				"Unable to suspend PHY. portsc: %8x\n",
+				readl_relaxed(USB_PORTSC));
+			goto reset_phy_and_link;
+		}
+	} else {
+		writel_relaxed(portsc | PORTSC_PHCD, USB_PORTSC);
+
+		timeout = jiffies + msecs_to_jiffies(PHY_SUSP_TIMEOUT_MSEC);
 		while (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD)) {
 			if (time_after(jiffies, timeout)) {
-				dev_err(mhcd->dev, "Unable to suspend PHY\n");
-				schedule_work(&mhcd->phy_susp_fail_work);
-				return -ETIMEDOUT;
+				dev_err(mhcd->dev,
+					"Unable to suspend PHY. portsc: %8x\n",
+					readl_relaxed(USB_PORTSC));
+				goto reset_phy_and_link;
 			}
-			udelay(1);
+			usleep_range(10000, 10000);
 		}
 	}
 
@@ -646,9 +672,14 @@
 	 * power mode (LPM). This interrupt is level triggered. So USB IRQ
 	 * line must be disabled till async interrupt enable bit is cleared
 	 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
-	 * block data communication from PHY.
+	 * block data communication from PHY.  Enable asynchronous interrupt
+	 * only when wakeup gpio IRQ is not present.
 	 */
-	writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
+	if (mhcd->wakeup_irq)
+		writel_relaxed(readl_relaxed(USB_USBCMD) | ULPI_STP_CTRL,
+				USB_USBCMD);
+	else
+		writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
 				ULPI_STP_CTRL, USB_USBCMD);
 
 	/*
@@ -674,6 +705,13 @@
 
 	atomic_set(&mhcd->in_lpm, 1);
 	enable_irq(hcd->irq);
+
+	if (mhcd->wakeup_irq) {
+		mhcd->wakeup_irq_enabled = 1;
+		enable_irq_wake(mhcd->wakeup_irq);
+		enable_irq(mhcd->wakeup_irq);
+	}
+
 	if (mhcd->pmic_gpio_dp_irq) {
 		mhcd->pmic_gpio_dp_irq_enabled = 1;
 		enable_irq_wake(mhcd->pmic_gpio_dp_irq);
@@ -684,11 +722,15 @@
 		enable_irq_wake(mhcd->async_irq);
 		enable_irq(mhcd->async_irq);
 	}
-	wake_unlock(&mhcd->wlock);
+	pm_relax(mhcd->dev);
 
 	dev_info(mhcd->dev, "EHCI USB in low power mode\n");
 
 	return 0;
+
+reset_phy_and_link:
+	schedule_work(&mhcd->phy_susp_fail_work);
+	return -ETIMEDOUT;
 }
 
 static int msm_ehci_resume(struct msm_hcd *mhcd)
@@ -709,15 +751,24 @@
 		disable_irq_nosync(mhcd->pmic_gpio_dp_irq);
 		mhcd->pmic_gpio_dp_irq_enabled = 0;
 	}
+
 	spin_lock_irqsave(&mhcd->wakeup_lock, flags);
 	if (mhcd->async_irq_enabled) {
 		disable_irq_wake(mhcd->async_irq);
 		disable_irq_nosync(mhcd->async_irq);
 		mhcd->async_irq_enabled = 0;
 	}
+
+	if (mhcd->wakeup_irq) {
+		if (mhcd->wakeup_irq_enabled) {
+			disable_irq_wake(mhcd->wakeup_irq);
+			disable_irq_nosync(mhcd->wakeup_irq);
+			mhcd->wakeup_irq_enabled = 0;
+		}
+	}
 	spin_unlock_irqrestore(&mhcd->wakeup_lock, flags);
 
-	wake_lock(&mhcd->wlock);
+	pm_stay_awake(mhcd->dev);
 
 	/* Vote for TCXO when waking up the phy */
 	if (!IS_ERR(mhcd->xo_clk)) {
@@ -784,6 +835,7 @@
 	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
 
 	if (atomic_read(&mhcd->in_lpm)) {
+		dev_dbg(mhcd->dev, "phy async intr\n");
 		disable_irq_nosync(hcd->irq);
 		mhcd->async_int = true;
 		pm_runtime_get(mhcd->dev);
@@ -802,7 +854,7 @@
 	dev_dbg(mhcd->dev, "%s: hsusb host remote wakeup interrupt cnt: %u\n",
 			__func__, mhcd->async_int_cnt);
 
-	wake_lock(&mhcd->wlock);
+	pm_stay_awake(mhcd->dev);
 
 	spin_lock(&mhcd->wakeup_lock);
 	if (mhcd->async_irq_enabled) {
@@ -833,7 +885,7 @@
 			__func__, mhcd->pmic_gpio_int_cnt);
 
 
-	wake_lock(&mhcd->wlock);
+	pm_stay_awake(mhcd->dev);
 
 	if (mhcd->pmic_gpio_dp_irq_enabled) {
 		mhcd->pmic_gpio_dp_irq_enabled = 0;
@@ -897,6 +949,20 @@
 	return 0;
 }
 
+static int msm_ehci_bus_resume_with_gpio(struct usb_hcd *hcd)
+{
+	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+	int ret;
+
+	gpio_direction_output(mhcd->resume_gpio, 1);
+
+	ret = ehci_bus_resume(hcd);
+
+	gpio_direction_output(mhcd->resume_gpio, 0);
+
+	return ret;
+}
+
 #if defined(CONFIG_DEBUG_FS)
 static u32 addr;
 #define BUF_SIZE	32
@@ -1072,6 +1138,46 @@
 	.bus_resume		= ehci_bus_resume,
 };
 
+static irqreturn_t msm_hsusb_wakeup_irq(int irq, void *data)
+{
+	struct msm_hcd *mhcd = data;
+	int ret;
+
+	mhcd->wakeup_int_cnt++;
+	dev_dbg(mhcd->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
+			__func__, mhcd->wakeup_int_cnt);
+
+	pm_stay_awake(mhcd->dev);
+
+	spin_lock(&mhcd->wakeup_lock);
+	if (mhcd->wakeup_irq_enabled) {
+		mhcd->wakeup_irq_enabled = 0;
+		disable_irq_wake(irq);
+		disable_irq_nosync(irq);
+	}
+	spin_unlock(&mhcd->wakeup_lock);
+
+	if (!atomic_read(&mhcd->pm_usage_cnt)) {
+		ret = pm_runtime_get(mhcd->dev);
+		/*
+		 * controller runtime resume can race with us.
+		 * if we are active (ret == 1) or resuming
+		 * (ret == -EINPROGRESS), decrement the
+		 * PM usage counter before returning.
+		 */
+		if ((ret == 1) || (ret == -EINPROGRESS)) {
+			pm_runtime_put_noidle(mhcd->dev);
+		} else {
+			/* Let khubd know of hub port status change */
+			if (mhcd->ehci.no_selective_suspend)
+				mhcd->ehci.suspended_ports = 1;
+			atomic_set(&mhcd->pm_usage_cnt, 1);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
 static int msm_ehci_init_clocks(struct msm_hcd *mhcd, u32 init)
 {
 	int ret = 0;
@@ -1152,6 +1258,12 @@
 					"qcom,usb2-enable-hsphy2");
 	of_property_read_u32(node, "qcom,usb2-power-budget",
 					&pdata->power_budget);
+	pdata->no_selective_suspend = of_property_read_bool(node,
+					"qcom,no-selective-suspend");
+	pdata->resume_gpio = of_get_named_gpio(node, "qcom,resume-gpio", 0);
+	if (pdata->resume_gpio < 0)
+		pdata->resume_gpio = 0;
+
 	return pdata;
 }
 
@@ -1175,6 +1287,8 @@
 	if (!pdev->dev.platform_data)
 		dev_dbg(&pdev->dev, "No platform data given\n");
 
+	pdata = pdev->dev.platform_data;
+
 	if (!pdev->dev.dma_mask)
 		pdev->dev.dma_mask = &ehci_msm_dma_mask;
 	if (!pdev->dev.coherent_dma_mask)
@@ -1252,6 +1366,22 @@
 		goto free_xo_handle;
 	}
 
+	if (pdata && pdata->resume_gpio) {
+		mhcd->resume_gpio = pdata->resume_gpio;
+		ret = gpio_request(mhcd->resume_gpio, "hsusb_resume");
+		if (ret) {
+			dev_err(&pdev->dev,
+				"resume gpio(%d) request failed:%d\n",
+				mhcd->resume_gpio, ret);
+			mhcd->resume_gpio = 0;
+		} else {
+			msm_hc2_driver.bus_resume =
+				msm_ehci_bus_resume_with_gpio;
+		}
+	}
+
+	spin_lock_init(&mhcd->wakeup_lock);
+
 	ret = msm_ehci_init_clocks(mhcd, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to initialize clocks\n");
@@ -1307,9 +1437,33 @@
 				!irq_read_line(pdata->dock_connect_irq)))
 		msm_ehci_vbus_power(mhcd, 1);
 
+	/* For peripherals directly conneted to downstream port of root hub
+	 * and require to drive suspend and resume by controller driver instead
+	 * of root hub.
+	 */
+	if (pdata)
+		mhcd->ehci.no_selective_suspend = pdata->no_selective_suspend;
+
+	mhcd->wakeup_irq = platform_get_irq_byname(pdev, "wakeup_irq");
+	if (mhcd->wakeup_irq > 0) {
+		dev_dbg(&pdev->dev, "wakeup irq:%d\n", mhcd->wakeup_irq);
+
+		irq_set_status_flags(mhcd->wakeup_irq, IRQ_NOAUTOEN);
+		ret = request_irq(mhcd->wakeup_irq, msm_hsusb_wakeup_irq,
+				IRQF_TRIGGER_HIGH,
+				"msm_hsusb_wakeup", mhcd);
+		if (ret) {
+			dev_err(&pdev->dev, "request_irq(%d) failed:%d\n",
+					mhcd->wakeup_irq, ret);
+			mhcd->wakeup_irq = 0;
+		}
+	} else {
+		mhcd->wakeup_irq = 0;
+	}
+
 	device_init_wakeup(&pdev->dev, 1);
-	wake_lock_init(&mhcd->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
-	wake_lock(&mhcd->wlock);
+	wakeup_source_init(&mhcd->ws, dev_name(&pdev->dev));
+	pm_stay_awake(mhcd->dev);
 	INIT_WORK(&mhcd->phy_susp_fail_work, msm_ehci_phy_susp_fail_work);
 	/*
 	 * This pdev->dev is assigned parent of root-hub by USB core,
@@ -1351,6 +1505,8 @@
 deinit_clocks:
 	msm_ehci_init_clocks(mhcd, 0);
 devote_xo_handle:
+	if (mhcd->resume_gpio)
+		gpio_free(mhcd->resume_gpio);
 	if (!IS_ERR(mhcd->xo_clk))
 		clk_disable_unprepare(mhcd->xo_clk);
 	else
@@ -1386,6 +1542,16 @@
 			disable_irq_wake(mhcd->async_irq);
 		free_irq(mhcd->async_irq, mhcd);
 	}
+
+	if (mhcd->wakeup_irq) {
+		if (mhcd->wakeup_irq_enabled)
+			disable_irq_wake(mhcd->wakeup_irq);
+		free_irq(mhcd->wakeup_irq, mhcd);
+	}
+
+	if (mhcd->resume_gpio)
+		gpio_free(mhcd->resume_gpio);
+
 	device_init_wakeup(&pdev->dev, 0);
 	pm_runtime_set_suspended(&pdev->dev);
 
@@ -1404,7 +1570,7 @@
 	msm_ehci_init_vddcx(mhcd, 0);
 
 	msm_ehci_init_clocks(mhcd, 0);
-	wake_lock_destroy(&mhcd->wlock);
+	wakeup_source_trash(&mhcd->ws);
 	iounmap(hcd->regs);
 	usb_put_hcd(hcd);
 
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index db49c07..b029be2 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -637,7 +637,8 @@
 	qtd->urb = urb;
 
 	token = QTD_STS_ACTIVE;
-	token |= (EHCI_TUNE_CERR << 10);
+	if (!ehci->disable_cerr)
+		token |= (EHCI_TUNE_CERR << 10);
 	/* for split transactions, SplitXState initialized to zero */
 
 	len = urb->transfer_buffer_length;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index edf2a73..0498a6a 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -154,6 +154,7 @@
 	unsigned		susp_sof_bug:1; /*Chip Idea HC*/
 	unsigned		resume_sof_bug:1;/*Chip Idea HC*/
 	unsigned		reset_sof_bug:1; /*Chip Idea HC*/
+	bool			disable_cerr;
 
 	/* required for usb32 quirk */
 	#define OHCI_CTRL_HCFS          (3 << 6)
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 717103d..1b6d15e 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -21,6 +21,7 @@
  */
 
 #include <linux/gfp.h>
+#include <linux/slab.h>
 #include <asm/unaligned.h>
 
 #include "xhci.h"
@@ -472,6 +473,149 @@
 	}
 }
 
+static void xhci_single_step_completion(struct urb *urb)
+{
+	struct completion *done = urb->context;
+
+	complete(done);
+}
+
+/*
+ * Allocate a URB and initialize the various fields of it.
+ * This API is used by the single_step_set_feature test of
+ * EHSET where IN packet of the GetDescriptor request is
+ * sent 15secs after the SETUP packet.
+ * Return NULL if failed.
+ */
+static struct urb *xhci_request_single_step_set_feature_urb(
+		struct usb_device *udev,
+		void *dr,
+		void *buf,
+		struct completion *done)
+{
+	struct urb *urb;
+	struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+	struct usb_host_endpoint *ep;
+
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb)
+		return NULL;
+
+	urb->pipe = usb_rcvctrlpipe(udev, 0);
+	ep = udev->ep_in[usb_pipeendpoint(urb->pipe)];
+	if (!ep) {
+		usb_free_urb(urb);
+		return NULL;
+	}
+
+	/*
+	 * Initialize the various URB fields as these are used by the HCD
+	 * driver to queue it and as well as when completion happens.
+	 */
+	urb->ep = ep;
+	urb->dev = udev;
+	urb->setup_packet = dr;
+	urb->transfer_buffer = buf;
+	urb->transfer_buffer_length = USB_DT_DEVICE_SIZE;
+	urb->complete = xhci_single_step_completion;
+	urb->status = -EINPROGRESS;
+	urb->actual_length = 0;
+	urb->transfer_flags = URB_DIR_IN;
+	usb_get_urb(urb);
+	atomic_inc(&urb->use_count);
+	atomic_inc(&urb->dev->urbnum);
+	usb_hcd_map_urb_for_dma(hcd, urb, GFP_KERNEL);
+	urb->context = done;
+	return urb;
+}
+
+/*
+ * This function implements the USB_PORT_FEAT_TEST handling of the
+ * SINGLE_STEP_SET_FEATURE test mode as defined in the Embedded
+ * High-Speed Electrical Test (EHSET) specification. This simply
+ * issues a GetDescriptor control transfer, with an inserted 15-second
+ * delay after the end of the SETUP stage and before the IN token of
+ * the DATA stage is set. The idea is that this gives the test operator
+ * enough time to configure the oscilloscope to perform a measurement
+ * of the response time between the DATA and ACK packets that follow.
+ */
+static int xhci_ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
+{
+	int retval;
+	struct usb_ctrlrequest *dr;
+	struct urb *urb;
+	struct usb_device *udev;
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	struct usb_device_descriptor *buf;
+	unsigned long flags;
+	DECLARE_COMPLETION_ONSTACK(done);
+
+	/* Obtain udev of the rhub's child port */
+	udev = hcd->self.root_hub->children[port];
+	if (!udev) {
+		xhci_err(xhci, "No device attached to the RootHub\n");
+		return -ENODEV;
+	}
+	buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+	if (!dr) {
+		kfree(buf);
+		return -ENOMEM;
+	}
+
+	/* Fill Setup packet for GetDescriptor */
+	dr->bRequestType = USB_DIR_IN;
+	dr->bRequest = USB_REQ_GET_DESCRIPTOR;
+	dr->wValue = cpu_to_le16(USB_DT_DEVICE << 8);
+	dr->wIndex = 0;
+	dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE);
+	urb = xhci_request_single_step_set_feature_urb(udev, dr, buf, &done);
+	if (!urb)
+		goto cleanup;
+
+	/* Now complete just the SETUP stage */
+	spin_lock_irqsave(&xhci->lock, flags);
+	retval = xhci_submit_single_step_set_feature(hcd, urb, 1);
+	spin_unlock_irqrestore(&xhci->lock, flags);
+	if (retval)
+		goto out1;
+
+	if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) {
+		usb_kill_urb(urb);
+		retval = -ETIMEDOUT;
+		xhci_err(xhci, "%s SETUP stage timed out on ep0\n", __func__);
+		goto out1;
+	}
+
+	/* Sleep for 15 seconds; HC will send SOFs during this period */
+	msleep(15 * 1000);
+
+	/* Complete remaining DATA and status stages. Re-use same URB */
+	urb->status = -EINPROGRESS;
+	usb_get_urb(urb);
+	atomic_inc(&urb->use_count);
+	atomic_inc(&urb->dev->urbnum);
+
+	spin_lock_irqsave(&xhci->lock, flags);
+	retval = xhci_submit_single_step_set_feature(hcd, urb, 0);
+	spin_unlock_irqrestore(&xhci->lock, flags);
+	if (!retval && !wait_for_completion_timeout(&done,
+						msecs_to_jiffies(2000))) {
+		usb_kill_urb(urb);
+		retval = -ETIMEDOUT;
+		xhci_err(xhci, "%s IN stage timed out on ep0\n", __func__);
+	}
+out1:
+	usb_free_urb(urb);
+cleanup:
+	kfree(dr);
+	kfree(buf);
+	return retval;
+}
+
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		u16 wIndex, char *buf, u16 wLength)
 {
@@ -778,6 +922,11 @@
 				temp = xhci_readl(xhci, port_array[wIndex] + 1);
 				temp |= test_mode << 28;
 				xhci_writel(xhci, temp, port_array[wIndex] + 1);
+			} else if (test_mode == 6) {
+				spin_unlock_irqrestore(&xhci->lock, flags);
+				retval = xhci_ehset_single_step_set_feature(hcd,
+									wIndex);
+				spin_lock_irqsave(&xhci->lock, flags);
 			} else {
 				goto error;
 			}
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 323b481..b3f3fa8 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3215,6 +3215,150 @@
 	return 0;
 }
 
+/*
+ * Variant of xhci_queue_ctrl_tx() used to implement EHSET
+ * SINGLE_STEP_SET_FEATURE test mode. It differs in that the control
+ * transfer is broken up so that the SETUP stage can happen and call
+ * the URB's completion handler before the DATA/STATUS stages are
+ * executed by the xHC hardware. This assumes the control transfer is a
+ * GetDescriptor, with a DATA stage in the IN direction, and an OUT
+ * STATUS stage.
+ *
+ * This function is called twice, usually with a 15-second delay in between.
+ * - with is_setup==true, the SETUP stage for the control request
+ *   (GetDescriptor) is queued in the TRB ring and sent to HW immediately
+ * - with is_setup==false, the DATA and STATUS TRBs are queued and exceuted
+ *
+ * Caller must have locked xhci->lock
+ */
+int xhci_submit_single_step_set_feature(struct usb_hcd *hcd, struct urb *urb,
+					int is_setup)
+{
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+	struct xhci_ring *ep_ring;
+	int num_trbs;
+	int ret;
+	unsigned int slot_id, ep_index;
+	struct usb_ctrlrequest *setup;
+	struct xhci_generic_trb *start_trb;
+	int start_cycle;
+	u32 field, length_field;
+	struct urb_priv *urb_priv;
+	struct xhci_td *td;
+
+	ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
+	if (!ep_ring)
+		return -EINVAL;
+
+	/* Need buffer for data stage */
+	if (urb->transfer_buffer_length <= 0)
+		return -EINVAL;
+
+	/*
+	 * Need to copy setup packet into setup TRB, so we can't use the setup
+	 * DMA address.
+	 */
+	if (!urb->setup_packet)
+		return -EINVAL;
+	setup = (struct usb_ctrlrequest *) urb->setup_packet;
+
+	slot_id = urb->dev->slot_id;
+	ep_index = xhci_get_endpoint_index(&urb->ep->desc);
+
+	urb_priv = kzalloc(sizeof(struct urb_priv) +
+				  sizeof(struct xhci_td *), GFP_ATOMIC);
+	if (!urb_priv)
+		return -ENOMEM;
+
+	td = urb_priv->td[0] = kzalloc(sizeof(struct xhci_td), GFP_ATOMIC);
+	if (!td) {
+		kfree(urb_priv);
+		return -ENOMEM;
+	}
+
+	urb_priv->length = 1;
+	urb_priv->td_cnt = 0;
+	urb->hcpriv = urb_priv;
+
+	num_trbs = is_setup ? 1 : 2;
+
+	ret = prepare_transfer(xhci, xhci->devs[slot_id],
+			ep_index, urb->stream_id,
+			num_trbs, urb, 0, GFP_ATOMIC);
+	if (ret < 0) {
+		kfree(td);
+		kfree(urb_priv);
+		return ret;
+	}
+
+	/*
+	 * Don't give the first TRB to the hardware (by toggling the cycle bit)
+	 * until we've finished creating all the other TRBs.  The ring's cycle
+	 * state may change as we enqueue the other TRBs, so save it too.
+	 */
+	start_trb = &ep_ring->enqueue->generic;
+	start_cycle = ep_ring->cycle_state;
+
+	if (is_setup) {
+		/* Queue only the setup TRB */
+		field = TRB_IDT | TRB_IOC | TRB_TYPE(TRB_SETUP);
+		if (start_cycle == 0)
+			field |= 0x1;
+
+		/* xHCI 1.0 6.4.1.2.1: Transfer Type field */
+		if (xhci->hci_version == 0x100) {
+			if (setup->bRequestType & USB_DIR_IN)
+				field |= TRB_TX_TYPE(TRB_DATA_IN);
+			else
+				field |= TRB_TX_TYPE(TRB_DATA_OUT);
+		}
+
+		/* Save the DMA address of the last TRB in the TD */
+		td->last_trb = ep_ring->enqueue;
+
+		queue_trb(xhci, ep_ring, false,
+			  setup->bRequestType | setup->bRequest << 8 |
+				le16_to_cpu(setup->wValue) << 16,
+			  le16_to_cpu(setup->wIndex) |
+				le16_to_cpu(setup->wLength) << 16,
+			  TRB_LEN(8) | TRB_INTR_TARGET(0),
+			  field);
+	} else {
+		/* Queue data TRB */
+		field = TRB_ISP | TRB_TYPE(TRB_DATA);
+		if (start_cycle == 0)
+			field |= 0x1;
+		if (setup->bRequestType & USB_DIR_IN)
+			field |= TRB_DIR_IN;
+
+		length_field = TRB_LEN(urb->transfer_buffer_length) |
+			xhci_td_remainder(urb->transfer_buffer_length) |
+			TRB_INTR_TARGET(0);
+		queue_trb(xhci, ep_ring, true,
+			  lower_32_bits(urb->transfer_dma),
+			  upper_32_bits(urb->transfer_dma),
+			  length_field,
+			  field);
+
+		/* Save the DMA address of the last TRB in the TD */
+		td->last_trb = ep_ring->enqueue;
+
+		/* Queue status TRB */
+		field = TRB_IOC | TRB_TYPE(TRB_STATUS);
+		if (!(setup->bRequestType & USB_DIR_IN))
+			field |= TRB_DIR_IN;
+
+		queue_trb(xhci, ep_ring, false,
+			  0,
+			  0,
+			  TRB_INTR_TARGET(0),
+			  field | ep_ring->cycle_state);
+	}
+
+	giveback_first_trb(xhci, slot_id, ep_index, 0, start_cycle, start_trb);
+	return 0;
+}
+
 static int count_isoc_trbs_needed(struct xhci_hcd *xhci,
 		struct urb *urb, int i)
 {
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 8f3651b..e47f46c 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1823,4 +1823,8 @@
 struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
 struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index);
 
+/* EHSET */
+int xhci_submit_single_step_set_feature(struct usb_hcd *hcd, struct urb *urb,
+					int is_setup);
+
 #endif /* __LINUX_XHCI_HCD_H */
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index c0b2771..72c3c7d 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -87,6 +87,11 @@
 MODULE_PARM_DESC(lpm_disconnect_thresh,
 	"Delay before entering LPM on USB disconnect");
 
+static bool floated_charger_enable;
+module_param(floated_charger_enable , bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(floated_charger_enable,
+	"Whether to enable floated charger");
+
 static DECLARE_COMPLETION(pmic_vbus_init);
 static struct msm_otg *the_msm_otg;
 static bool debug_aca_enabled;
@@ -880,6 +885,7 @@
 	struct msm_otg_platform_data *pdata = motg->pdata;
 	int cnt = 0;
 	bool host_bus_suspend, device_bus_suspend, dcp, prop_charger;
+	bool floated_charger;
 	u32 phy_ctrl_val = 0, cmd_val;
 	unsigned ret;
 	u32 portsc;
@@ -898,6 +904,7 @@
 		motg->caps & ALLOW_LPM_ON_DEV_SUSPEND;
 	dcp = motg->chg_type == USB_DCP_CHARGER;
 	prop_charger = motg->chg_type == USB_PROPRIETARY_CHARGER;
+	floated_charger = motg->chg_type == USB_FLOATED_CHARGER;
 
 	/*
 	 * Abort suspend when,
@@ -906,7 +913,8 @@
 	 */
 
 	if ((test_bit(B_SESS_VLD, &motg->inputs) && !device_bus_suspend &&
-		!dcp && !prop_charger) || test_bit(A_BUS_REQ, &motg->inputs)) {
+		!dcp && !prop_charger && !floated_charger) ||
+		test_bit(A_BUS_REQ, &motg->inputs)) {
 		enable_irq(motg->irq);
 		return -EBUSY;
 	}
@@ -2211,6 +2219,7 @@
 	case USB_ACA_C_CHARGER:		return "USB_ACA_C_CHARGER";
 	case USB_ACA_DOCK_CHARGER:	return "USB_ACA_DOCK_CHARGER";
 	case USB_PROPRIETARY_CHARGER:	return "USB_PROPRIETARY_CHARGER";
+	case USB_FLOATED_CHARGER:	return "USB_FLOATED_CHARGER";
 	default:			return "INVALID_CHARGER";
 	}
 }
@@ -2224,6 +2233,7 @@
 	struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
 	struct usb_phy *phy = &motg->phy;
 	bool is_dcd = false, tmout, vout, is_aca;
+	static bool dcd;
 	u32 line_state, dm_vlgc;
 	unsigned long delay;
 
@@ -2268,6 +2278,10 @@
 		motg->dcd_time += MSM_CHG_DCD_POLL_TIME;
 		tmout = motg->dcd_time >= MSM_CHG_DCD_TIMEOUT;
 		if (is_dcd || tmout) {
+			if (is_dcd)
+				dcd = true;
+			else
+				dcd = false;
 			msm_chg_disable_dcd(motg);
 			msm_chg_enable_primary_det(motg);
 			delay = MSM_CHG_PRIMARY_DET_TIME;
@@ -2306,6 +2320,8 @@
 
 			if (line_state) /* DP > VLGC or/and DM > VLGC */
 				motg->chg_type = USB_PROPRIETARY_CHARGER;
+			else if (!dcd && floated_charger_enable)
+				motg->chg_type = USB_FLOATED_CHARGER;
 			else
 				motg->chg_type = USB_SDP_CHARGER;
 
@@ -2482,6 +2498,12 @@
 					pm_runtime_put_noidle(otg->phy->dev);
 					pm_runtime_suspend(otg->phy->dev);
 					break;
+				case USB_FLOATED_CHARGER:
+					msm_otg_notify_charger(motg,
+							IDEV_CHG_MAX);
+					pm_runtime_put_noidle(otg->phy->dev);
+					pm_runtime_suspend(otg->phy->dev);
+					break;
 				case USB_ACA_B_CHARGER:
 					msm_otg_notify_charger(motg,
 							IDEV_ACA_CHG_MAX);
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index aecb19d..91e70a7 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -539,13 +539,6 @@
 	return 0;
 }
 
-static int mdp3_iommu_fault_handler(struct iommu_domain *domain,
-		struct device *dev, unsigned long iova, int flags, void *token)
-{
-	pr_err("MDP IOMMU page fault: iova 0x%lx\n", iova);
-	return 0;
-}
-
 int mdp3_iommu_attach(int context)
 {
 	struct mdp3_iommu_ctx_map *context_map;
@@ -621,9 +614,6 @@
 			else
 				return PTR_ERR(mdp3_iommu_domains[i].domain);
 		}
-		iommu_set_fault_handler(mdp3_iommu_domains[i].domain,
-					mdp3_iommu_fault_handler,
-					NULL);
 	}
 
 	mdp3_res->domains = mdp3_iommu_domains;
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 1311dab..078960b 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -73,6 +73,7 @@
 	u32 irq_buzy;
 	u32 has_bwc;
 	u32 has_decimation;
+	u8 has_wfd_blk;
 
 	u32 mdp_irq_mask;
 	u32 mdp_hist_irq_mask;
@@ -121,6 +122,7 @@
 	struct early_suspend early_suspend;
 	void *debug_data;
 	int current_bus_idx;
+	bool mixer_switched;
 };
 extern struct mdss_data_type *mdss_res;
 
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 366209b..fb0e8ba 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -416,6 +416,14 @@
 
 	mdss_dsi_clk_ctrl(ctrl_pdata, 0);
 
+	ret = mdss_dsi_enable_bus_clocks(ctrl_pdata);
+	if (ret) {
+		pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__,
+			ret);
+		mdss_dsi_panel_power_on(pdata, 0);
+		return ret;
+	}
+
 	/* disable DSI phy */
 	mdss_dsi_phy_enable(ctrl_pdata, 0);
 
@@ -479,6 +487,7 @@
 
 	mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
 	mdss_dsi_phy_init(pdata);
+	mdss_dsi_disable_bus_clocks(ctrl_pdata);
 
 	mdss_dsi_clk_ctrl(ctrl_pdata, 1);
 
@@ -593,6 +602,13 @@
 	}
 	mdss_dsi_op_mode_config(mipi->mode, pdata);
 
+	if (pdata->panel_info.type == MIPI_CMD_PANEL) {
+		if (mipi->vsync_enable && mipi->hw_vsync_mode
+			&& gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+				mdss_dsi_set_tear_on(ctrl_pdata);
+		}
+	}
+
 	pr_debug("%s-:\n", __func__);
 
 	return ret;
@@ -601,6 +617,7 @@
 static int mdss_dsi_blank(struct mdss_panel_data *pdata)
 {
 	int ret = 0;
+	struct mipi_panel_info *mipi;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
 	pr_debug("%s+:\n", __func__);
@@ -612,9 +629,17 @@
 
 	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
 				panel_data);
+	mipi = &pdata->panel_info.mipi;
 
 	mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata);
 
+	if (pdata->panel_info.type == MIPI_CMD_PANEL) {
+		if (mipi->vsync_enable && mipi->hw_vsync_mode
+			&& gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+			mdss_dsi_set_tear_off(ctrl_pdata);
+		}
+	}
+
 	if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
 		ret = ctrl_pdata->off(pdata);
 		if (ret) {
@@ -1143,15 +1168,6 @@
 			return rc;
 		}
 
-		rc = mdss_dsi_enable_bus_clocks(ctrl_pdata);
-		if (rc) {
-			pr_err("%s: failed to enable bus clocks. rc=%d\n",
-				__func__, rc);
-			rc = mdss_dsi_panel_power_on(
-				&(ctrl_pdata->panel_data), 0);
-			return rc;
-		}
-
 		mdss_dsi_clk_ctrl(ctrl_pdata, 1);
 		ctrl_pdata->ctrl_state |=
 			(CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE);
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 965a23f..8a8e4ca 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -382,6 +382,8 @@
 
 void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
 				struct mdss_panel_data *pdata);
+void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl);
 void mdss_dsi_op_mode_config(int mode,
 				struct mdss_panel_data *pdata);
 void mdss_dsi_cmd_mode_ctrl(int enable);
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 60b8b2e..2f29b3d 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -80,6 +80,7 @@
 	mutex_lock(&ctrl->mutex);
 	if (enable) {
 		if (ctrl->clk_cnt == 0) {
+			mdss_dsi_enable_bus_clocks(ctrl);
 			mdss_dsi_prepare_clocks(ctrl);
 			mdss_dsi_clk_enable(ctrl);
 		}
@@ -90,6 +91,7 @@
 			if (ctrl->clk_cnt == 0) {
 				mdss_dsi_clk_disable(ctrl);
 				mdss_dsi_unprepare_clocks(ctrl);
+				mdss_dsi_disable_bus_clocks(ctrl);
 			}
 		}
 	}
@@ -1098,6 +1100,40 @@
 	pr_debug("%s: BTA done, status = %d\n", __func__, status);
 }
 
+static char set_tear_on[2] = {0x35, 0x00};
+static struct dsi_cmd_desc dsi_tear_on_cmd = {
+	{DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_tear_on)}, set_tear_on};
+
+static char set_tear_off[2] = {0x34, 0x00};
+static struct dsi_cmd_desc dsi_tear_off_cmd = {
+	{DTYPE_DCS_WRITE, 1, 0, 0, 0, sizeof(set_tear_off)}, set_tear_off};
+
+void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	struct dcs_cmd_req cmdreq;
+
+	cmdreq.cmds = &dsi_tear_on_cmd;
+	cmdreq.cmds_cnt = 1;
+	cmdreq.flags = CMD_REQ_COMMIT;
+	cmdreq.rlen = 0;
+	cmdreq.cb = NULL;
+
+	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
+
+void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	struct dcs_cmd_req cmdreq;
+
+	cmdreq.cmds = &dsi_tear_off_cmd;
+	cmdreq.cmds_cnt = 1;
+	cmdreq.flags = CMD_REQ_COMMIT;
+	cmdreq.rlen = 0;
+	cmdreq.cb = NULL;
+
+	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
+
 int mdss_dsi_cmd_reg_tx(u32 data,
 			unsigned char *ctrl_base)
 {
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index 1876057..9a5b20b 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -854,7 +854,8 @@
 static void hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
 	struct hdmi_edid_sink_data *sink_data, u32 num_of_cea_blocks)
 {
-	u8 len, offset, present_multi_3d, hdmi_vic_len, hdmi_3d_len;
+	u8 len, offset, present_multi_3d, hdmi_vic_len;
+	int hdmi_3d_len;
 	u16 structure_all, structure_mask;
 	const u8 *vsd = num_of_cea_blocks ?
 		hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 287f2cd..91e5660 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -2250,6 +2250,8 @@
 	 */
 	hdmi_ctrl->pdata.power_data[HDMI_TX_CORE_PM].clk_config[0].rate = 0;
 
+	hdmi_cec_deconfig(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]);
+
 	hdmi_tx_core_off(hdmi_ctrl);
 
 	if (hdmi_ctrl->hpd_off_pending) {
@@ -2257,8 +2259,6 @@
 		hdmi_ctrl->hpd_off_pending = false;
 	}
 
-	hdmi_cec_deconfig(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]);
-
 	mutex_lock(&hdmi_ctrl->mutex);
 	hdmi_ctrl->panel_power_on = false;
 	mutex_unlock(&hdmi_ctrl->mutex);
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index c4bf67e..56a4ac4 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -68,6 +68,10 @@
 	.fb_stride = mdss_mdp_fb_stride,
 };
 
+#define DEFAULT_TOTAL_RGB_PIPES 3
+#define DEFAULT_TOTAL_VIG_PIPES 3
+#define DEFAULT_TOTAL_DMA_PIPES 2
+
 #define IB_QUOTA 800000000
 #define AB_QUOTA 800000000
 
@@ -703,13 +707,6 @@
 	return 0;
 }
 
-static int mdss_iommu_fault_handler(struct iommu_domain *domain,
-		struct device *dev, unsigned long iova, int flags, void *token)
-{
-	pr_err("MDP IOMMU page fault: iova 0x%lx\n", iova);
-	return 0;
-}
-
 int mdss_iommu_attach(struct mdss_data_type *mdata)
 {
 	struct iommu_domain *domain;
@@ -796,7 +793,6 @@
 				iomap->domain_idx);
 			return -EINVAL;
 		}
-		iommu_set_fault_handler(domain, mdss_iommu_fault_handler, NULL);
 
 		iomap->ctx = msm_iommu_get_ctx(iomap->ctx_name);
 		if (!iomap->ctx) {
@@ -1154,9 +1150,9 @@
 
 static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev)
 {
-	u32 npipes, off;
+	u32 npipes, dma_off;
 	int rc = 0;
-	u32 nids = 0;
+	u32 nids = 0, setup_cnt = 0, len;
 	u32 *offsets = NULL, *ftch_id = NULL;
 
 	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
@@ -1184,17 +1180,41 @@
 
 	offsets = kzalloc(sizeof(u32) * npipes, GFP_KERNEL);
 	if (!offsets) {
-		pr_err("no mem assigned: kzalloc fail\n");
+		pr_err("no mem assigned for offsets: kzalloc fail\n");
 		return -ENOMEM;
 	}
 
 	ftch_id = kzalloc(sizeof(u32) * nids, GFP_KERNEL);
 	if (!ftch_id) {
-		pr_err("no mem assigned: kzalloc fail\n");
+		pr_err("no mem assigned for ftch_id: kzalloc fail\n");
 		rc = -ENOMEM;
 		goto ftch_alloc_fail;
 	}
 
+	mdata->vig_pipes = devm_kzalloc(&mdata->pdev->dev,
+		sizeof(struct mdss_mdp_pipe) * mdata->nvig_pipes, GFP_KERNEL);
+	if (!mdata->vig_pipes) {
+		pr_err("no mem for vig_pipes: kzalloc fail\n");
+		rc = -ENOMEM;
+		goto vig_alloc_fail;
+	}
+
+	mdata->rgb_pipes = devm_kzalloc(&mdata->pdev->dev,
+		sizeof(struct mdss_mdp_pipe) * mdata->nrgb_pipes, GFP_KERNEL);
+	if (!mdata->rgb_pipes) {
+		pr_err("no mem for rgb_pipes: kzalloc fail\n");
+		rc = -ENOMEM;
+		goto rgb_alloc_fail;
+	}
+
+	mdata->dma_pipes = devm_kzalloc(&mdata->pdev->dev,
+		sizeof(struct mdss_mdp_pipe) * mdata->ndma_pipes, GFP_KERNEL);
+	if (!mdata->dma_pipes) {
+		pr_err("no mem for dma_pipes: kzalloc fail\n");
+		rc = -ENOMEM;
+		goto dma_alloc_fail;
+	}
+
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-vig-fetch-id",
 		ftch_id, mdata->nvig_pipes);
 	if (rc)
@@ -1203,47 +1223,91 @@
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-vig-off",
 		offsets, mdata->nvig_pipes);
 	if (rc)
-		goto parse_done;
+		goto parse_fail;
 
-	rc = mdss_mdp_pipe_addr_setup(mdata, offsets, ftch_id,
-		MDSS_MDP_PIPE_TYPE_VIG, MDSS_MDP_SSPP_VIG0, mdata->nvig_pipes);
+	len = min_t(int, DEFAULT_TOTAL_VIG_PIPES, (int)mdata->nvig_pipes);
+	rc = mdss_mdp_pipe_addr_setup(mdata, mdata->vig_pipes, offsets, ftch_id,
+		MDSS_MDP_PIPE_TYPE_VIG, MDSS_MDP_SSPP_VIG0, len);
 	if (rc)
-		goto parse_done;
+		goto parse_fail;
+
+	setup_cnt += len;
 
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-rgb-fetch-id",
 		ftch_id + mdata->nvig_pipes, mdata->nrgb_pipes);
 	if (rc)
-		goto parse_done;
+		goto parse_fail;
 
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-rgb-off",
 		offsets + mdata->nvig_pipes, mdata->nrgb_pipes);
 	if (rc)
-		goto parse_done;
+		goto parse_fail;
 
-	rc = mdss_mdp_pipe_addr_setup(mdata, offsets + mdata->nvig_pipes,
-		ftch_id + mdata->nvig_pipes, MDSS_MDP_PIPE_TYPE_RGB,
-		MDSS_MDP_SSPP_RGB0, mdata->nrgb_pipes);
+	len = min_t(int, DEFAULT_TOTAL_RGB_PIPES, (int)mdata->nrgb_pipes);
+	rc = mdss_mdp_pipe_addr_setup(mdata, mdata->rgb_pipes,
+		offsets + mdata->nvig_pipes, ftch_id + mdata->nvig_pipes,
+		MDSS_MDP_PIPE_TYPE_RGB, MDSS_MDP_SSPP_RGB0, len);
 	if (rc)
-		goto parse_done;
+		goto parse_fail;
 
-	off = mdata->nvig_pipes + mdata->nrgb_pipes;
+	setup_cnt += len;
+	dma_off = mdata->nvig_pipes + mdata->nrgb_pipes;
 
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-dma-fetch-id",
-		ftch_id + off, mdata->ndma_pipes);
+		ftch_id + dma_off, mdata->ndma_pipes);
 	if (rc)
-		goto parse_done;
+		goto parse_fail;
 
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-dma-off",
-		offsets + off, mdata->ndma_pipes);
+		offsets + dma_off, mdata->ndma_pipes);
 	if (rc)
-		goto parse_done;
+		goto parse_fail;
 
-	rc = mdss_mdp_pipe_addr_setup(mdata, offsets + off, ftch_id + off,
-		MDSS_MDP_PIPE_TYPE_DMA, MDSS_MDP_SSPP_DMA0, mdata->ndma_pipes);
+	len = mdata->ndma_pipes;
+	rc = mdss_mdp_pipe_addr_setup(mdata, mdata->dma_pipes,
+		 offsets + dma_off, ftch_id + dma_off, MDSS_MDP_PIPE_TYPE_DMA,
+		 MDSS_MDP_SSPP_DMA0, len);
 	if (rc)
-		goto parse_done;
+		goto parse_fail;
 
+	setup_cnt += len;
+
+	if (mdata->nvig_pipes > DEFAULT_TOTAL_VIG_PIPES) {
+		rc = mdss_mdp_pipe_addr_setup(mdata,
+			mdata->vig_pipes + DEFAULT_TOTAL_VIG_PIPES,
+			offsets + DEFAULT_TOTAL_VIG_PIPES,
+			ftch_id + DEFAULT_TOTAL_VIG_PIPES,
+			MDSS_MDP_PIPE_TYPE_VIG, setup_cnt,
+			mdata->nvig_pipes - DEFAULT_TOTAL_VIG_PIPES);
+		if (rc)
+			goto parse_fail;
+
+		setup_cnt += mdata->nvig_pipes - DEFAULT_TOTAL_VIG_PIPES;
+	}
+
+	if (mdata->nrgb_pipes > DEFAULT_TOTAL_RGB_PIPES) {
+		rc = mdss_mdp_pipe_addr_setup(mdata,
+			mdata->rgb_pipes + DEFAULT_TOTAL_RGB_PIPES,
+			offsets + mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES,
+			ftch_id + mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES,
+			MDSS_MDP_PIPE_TYPE_RGB, setup_cnt,
+			mdata->nrgb_pipes - DEFAULT_TOTAL_RGB_PIPES);
+		if (rc)
+			goto parse_fail;
+
+		setup_cnt += mdata->nrgb_pipes - DEFAULT_TOTAL_RGB_PIPES;
+	}
+
+	goto parse_done;
+
+parse_fail:
+	kfree(mdata->dma_pipes);
+dma_alloc_fail:
+	kfree(mdata->rgb_pipes);
+rgb_alloc_fail:
+	kfree(mdata->vig_pipes);
 parse_done:
+vig_alloc_fail:
 	kfree(ftch_id);
 ftch_alloc_fail:
 	kfree(offsets);
@@ -1467,6 +1531,8 @@
 					       "qcom,mdss-has-bwc");
 	mdata->has_decimation = of_property_read_bool(pdev->dev.of_node,
 		"qcom,mdss-has-decimation");
+	mdata->has_wfd_blk = of_property_read_bool(pdev->dev.of_node,
+		"qcom,mdss-has-wfd-blk");
 	return 0;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 52224e2..8ecc861 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -118,6 +118,11 @@
 	struct list_head list;
 };
 
+enum mdss_mdp_wb_ctl_type {
+	MDSS_MDP_WB_CTL_TYPE_BLOCK = 1,
+	MDSS_MDP_WB_CTL_TYPE_LINE
+};
+
 struct mdss_mdp_ctl {
 	u32 num;
 	char __iomem *base;
@@ -151,6 +156,7 @@
 	struct mdss_mdp_mixer *mixer_left;
 	struct mdss_mdp_mixer *mixer_right;
 	struct mutex lock;
+	struct mutex *shared_lock;
 
 	struct mdss_panel_data *panel_data;
 	struct mdss_mdp_vsync_handler vsync_handler;
@@ -168,6 +174,7 @@
 					struct mdss_mdp_vsync_handler *);
 
 	void *priv_data;
+	u32 wb_type;
 };
 
 struct mdss_mdp_mixer {
@@ -430,6 +437,7 @@
 struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
 					struct msm_fb_data_type *mfd);
 int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_video_copy_splash_screen(struct mdss_panel_data *pdata);
 void mdss_mdp_ctl_splash_start(struct mdss_panel_data *pdata);
 int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl);
@@ -524,8 +532,9 @@
 void mdss_mdp_smp_unreserve(struct mdss_mdp_pipe *pipe);
 void mdss_mdp_smp_release(struct mdss_mdp_pipe *pipe);
 
-int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata, u32 *offsets,
-		u32 *ftch_y_id, u32 type, u32 num_base, u32 len);
+int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata,
+	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_y_id, u32 type,
+	u32 num_base, u32 len);
 int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata, u32 *mixer_offsets,
 		u32 *dspp_offsets, u32 *pingpong_offsets, u32 type, u32 len);
 int mdss_mdp_ctl_addr_setup(struct mdss_data_type *mdata, u32 *ctl_offsets,
@@ -558,8 +567,13 @@
 int mdss_panel_register_done(struct mdss_panel_data *pdata);
 int mdss_mdp_limited_lut_igc_config(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_calib_config(struct mdp_calib_config_data *cfg, u32 *copyback);
+int mdss_mdp_calib_config_buffer(struct mdp_calib_config_buffer *cfg,
+						u32 *copyback);
 
 int mdss_mdp_pipe_is_staged(struct mdss_mdp_pipe *pipe);
+int mdss_mdp_writeback_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
+struct mdss_mdp_ctl *mdss_mdp_ctl_mixer_switch(struct mdss_mdp_ctl *ctl,
+					       u32 return_type);
 
 #define mfd_to_mdp5_data(mfd) (mfd->mdp.private1)
 #define mfd_to_mdata(mfd) (((struct mdss_overlay_private *)\
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 9eaff61..e656131 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -299,9 +299,13 @@
 {
 	struct mdss_mdp_ctl *ctl = NULL;
 	u32 cnum;
+	u32 nctl = mdata->nctl;
 
 	mutex_lock(&mdss_mdp_ctl_lock);
-	for (cnum = off; cnum < mdata->nctl; cnum++) {
+	if (!mdata->has_wfd_blk)
+		nctl++;
+
+	for (cnum = off; cnum < nctl; cnum++) {
 		ctl = mdata->ctl_off + cnum;
 		if (ctl->ref_cnt == 0) {
 			ctl->ref_cnt++;
@@ -399,13 +403,18 @@
 			(mixer_pool[MDSS_MDP_INTF_LAYERMIXER2].ref_cnt == 0))
 		mixer_pool += MDSS_MDP_INTF_LAYERMIXER2;
 
+	/*Allocate virtual wb mixer if no dedicated wfd wb blk is present*/
+	if (!ctl->mdata->has_wfd_blk && (type == MDSS_MDP_MIXER_TYPE_WRITEBACK))
+		nmixers += 1;
+
 	for (i = 0; i < nmixers; i++) {
 		mixer = mixer_pool + i;
 		if (mixer->ref_cnt == 0) {
 			mixer->ref_cnt++;
 			mixer->params_changed++;
 			mixer->ctl = ctl;
-			pr_debug("alloc mixer num%d\n", mixer->num);
+			pr_debug("alloc mixer num %d for ctl=%d\n",
+				 mixer->num, ctl->num);
 			break;
 		}
 		mixer = NULL;
@@ -440,12 +449,16 @@
 	struct mdss_mdp_mixer *mixer = NULL;
 
 	ctl = mdss_mdp_ctl_alloc(mdss_res, mdss_res->nmixers_intf);
-	if (!ctl)
+	if (!ctl) {
+		pr_err("unable to allocate wb ctl\n");
 		return NULL;
+	}
 
 	mixer = mdss_mdp_mixer_alloc(ctl, MDSS_MDP_MIXER_TYPE_WRITEBACK, false);
-	if (!mixer)
+	if (!mixer) {
+		pr_err("unable to allocate wb mixer\n");
 		goto error;
+	}
 
 	mixer->rotator_mode = rotator;
 
@@ -467,6 +480,9 @@
 
 	ctl->start_fnc = mdss_mdp_writeback_start;
 	ctl->power_on = true;
+	ctl->wb_type = (rotator ? MDSS_MDP_WB_CTL_TYPE_BLOCK :
+			MDSS_MDP_WB_CTL_TYPE_LINE);
+	mixer->ctl = ctl;
 
 	if (ctl->start_fnc)
 		ctl->start_fnc(ctl);
@@ -517,6 +533,7 @@
 	case MIPI_VIDEO_PANEL:
 		return mdss_mdp_video_reconfigure_splash_done(ctl);
 	case MIPI_CMD_PANEL:
+		return mdss_mdp_cmd_reconfigure_splash_done(ctl);
 	default:
 		return 0;
 	}
@@ -704,6 +721,7 @@
 			mdss_mdp_mixer_free(mixer);
 			return -EINVAL;
 		}
+		ctl->wb_type = MDSS_MDP_WB_CTL_TYPE_LINE;
 	}
 	ctl->mixer_left = mixer;
 
@@ -1118,7 +1136,13 @@
 	if (pipe == NULL) {
 		mixercfg = MDSS_MDP_LM_BORDER_COLOR;
 	} else {
-		mixercfg = 1 << (3 * pipe->num);
+		if (pipe->num == MDSS_MDP_SSPP_VIG3 ||
+			pipe->num == MDSS_MDP_SSPP_RGB3) {
+			/* Add 2 to account for Cursor & Border bits */
+			mixercfg = 1 << ((3 * pipe->num)+2);
+		} else {
+			mixercfg = 1 << (3 * pipe->num);
+		}
 		if (pipe->src_fmt->alpha_enable)
 			bgalpha = 1;
 		secure = pipe->flags & MDP_SECURE_OVERLAY_SESSION;
@@ -1186,7 +1210,10 @@
 
 	pr_debug("mixer=%d mixer_cfg=%x\n", mixer->num, mixercfg);
 
-	ctl->flush_bits |= BIT(6) << mixer->num;	/* LAYER_MIXER */
+	if (mixer->num == MDSS_MDP_INTF_LAYERMIXER3)
+		ctl->flush_bits |= BIT(20);
+	else
+		ctl->flush_bits |= BIT(6) << mixer->num;
 
 	mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OP_MODE, blend_color_out);
 	off = __mdss_mdp_ctl_get_mixer_off(mixer);
@@ -1202,9 +1229,13 @@
 	struct mdss_mdp_mixer *head;
 	u32 i;
 	int rc = 0;
+	u32 size = len;
+
+	if ((type == MDSS_MDP_MIXER_TYPE_WRITEBACK) && !mdata->has_wfd_blk)
+		size++;
 
 	head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_mixer) *
-			len, GFP_KERNEL);
+			size, GFP_KERNEL);
 
 	if (!head) {
 		pr_err("unable to setup mixer type=%d :kzalloc fail\n",
@@ -1224,6 +1255,13 @@
 		}
 	}
 
+	/*
+	 * Duplicate the last writeback mixer for concurrent line and block mode
+	 * operations
+	*/
+	if ((type == MDSS_MDP_MIXER_TYPE_WRITEBACK) && !mdata->has_wfd_blk)
+		head[len] = head[len - 1];
+
 	switch (type) {
 
 	case MDSS_MDP_MIXER_TYPE_INTF:
@@ -1247,10 +1285,24 @@
 	u32 *ctl_offsets, u32 *wb_offsets, u32 len)
 {
 	struct mdss_mdp_ctl *head;
+	struct mutex *shared_lock = NULL;
 	u32 i;
+	u32 size = len;
+
+	if (!mdata->has_wfd_blk) {
+		size++;
+		shared_lock = devm_kzalloc(&mdata->pdev->dev,
+					   sizeof(struct mutex),
+					   GFP_KERNEL);
+		if (!shared_lock) {
+			pr_err("unable to allocate mem for mutex\n");
+			return -ENOMEM;
+		}
+		mutex_init(shared_lock);
+	}
 
 	head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_ctl) *
-			len, GFP_KERNEL);
+			size, GFP_KERNEL);
 
 	if (!head) {
 		pr_err("unable to setup ctl and wb: kzalloc fail\n");
@@ -1264,6 +1316,16 @@
 		head[i].ref_cnt = 0;
 	}
 
+	if (!mdata->has_wfd_blk) {
+		head[len - 1].shared_lock = shared_lock;
+		/*
+		 * Allocate a virtual ctl to be able to perform simultaneous
+		 * line mode and block mode operations on the same
+		 * writeback block
+		*/
+		head[len] = head[len - 1];
+		head[len].num = -1;
+	}
 	mdata->ctl_off = head;
 
 	return 0;
@@ -1348,7 +1410,10 @@
 
 	if (pipe->type == MDSS_MDP_PIPE_TYPE_DMA)
 		ctl->flush_bits |= BIT(pipe->num) << 5;
-	else /* RGB/VIG pipe */
+	else if (pipe->num == MDSS_MDP_SSPP_VIG3 ||
+			pipe->num == MDSS_MDP_SSPP_RGB3)
+		ctl->flush_bits |= BIT(pipe->num) << 10;
+	else /* RGB/VIG 0-2 pipes */
 		ctl->flush_bits |= BIT(pipe->num);
 
 	mutex_unlock(&ctl->lock);
@@ -1387,11 +1452,19 @@
 
 static int mdss_mdp_mixer_update(struct mdss_mdp_mixer *mixer)
 {
+	u32 off = 0;
+	if (!mixer)
+		return -EINVAL;
+
 	mixer->params_changed = 0;
 
 	/* skip mixer setup for rotator */
-	if (!mixer->rotator_mode)
+	if (!mixer->rotator_mode) {
 		mdss_mdp_mixer_setup(mixer->ctl, mixer);
+	} else {
+		off = __mdss_mdp_ctl_get_mixer_off(mixer);
+		mdss_mdp_ctl_write(mixer->ctl, off, 0);
+	}
 
 	return 0;
 }
@@ -1520,12 +1593,9 @@
 		return -ENODEV;
 	}
 
+	mutex_lock(&ctl->lock);
 	pr_debug("commit ctl=%d play_cnt=%d\n", ctl->num, ctl->play_cnt);
 
-	ret = mutex_lock_interruptible(&ctl->lock);
-	if (ret)
-		return ret;
-
 	if (!ctl->power_on) {
 		mutex_unlock(&ctl->lock);
 		return 0;
@@ -1620,6 +1690,36 @@
 	return mixer_cnt;
 }
 
+/**
+ * @mdss_mdp_ctl_mixer_switch() - return ctl mixer of @return_type
+ * @ctl: Pointer to ctl structure to be switched.
+ * @return_type: wb_type of the ctl to be switched to.
+ *
+ * Virtual mixer switch should be performed only when there is no
+ * dedicated wfd block and writeback block is shared.
+ */
+struct mdss_mdp_ctl *mdss_mdp_ctl_mixer_switch(struct mdss_mdp_ctl *ctl,
+					       u32 return_type)
+{
+	int i;
+	struct mdss_data_type *mdata = ctl->mdata;
+
+	if (ctl->wb_type == return_type) {
+		mdata->mixer_switched = false;
+		return ctl;
+	}
+	for (i = 0; i <= mdata->nctl; i++) {
+		if (mdata->ctl_off[i].wb_type == return_type) {
+			pr_debug("switching mixer from ctl=%d to ctl=%d\n",
+				 ctl->num, mdata->ctl_off[i].num);
+			mdata->mixer_switched = true;
+			return mdata->ctl_off + i;
+		}
+	}
+	pr_err("unable to switch mixer to type=%d\n", return_type);
+	return NULL;
+}
+
 static inline int __mdss_mdp_ctl_get_mixer_off(struct mdss_mdp_mixer *mixer)
 {
 	if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF)
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 4779d20..8e5534d 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -23,6 +23,7 @@
 
 #define MDSS_MDP_HW_REV_100		0x10000000
 #define MDSS_MDP_HW_REV_102		0x10020000
+#define MDSS_MDP_HW_REV_103		0x10030000
 
 #define MDSS_REG_HW_VERSION				0x0
 #define MDSS_REG_HW_INTR_STATUS				0x10
@@ -57,15 +58,19 @@
 #define MDSS_MDP_INTR_PING_PONG_0_DONE			BIT(8)
 #define MDSS_MDP_INTR_PING_PONG_1_DONE			BIT(9)
 #define MDSS_MDP_INTR_PING_PONG_2_DONE			BIT(10)
+#define MDSS_MDP_INTR_PING_PONG_3_DONE			BIT(11)
 #define MDSS_MDP_INTR_PING_PONG_0_RD_PTR		BIT(12)
 #define MDSS_MDP_INTR_PING_PONG_1_RD_PTR		BIT(13)
 #define MDSS_MDP_INTR_PING_PONG_2_RD_PTR		BIT(14)
+#define MDSS_MDP_INTR_PING_PONG_3_RD_PTR		BIT(15)
 #define MDSS_MDP_INTR_PING_PONG_0_WR_PTR		BIT(16)
 #define MDSS_MDP_INTR_PING_PONG_1_WR_PTR		BIT(17)
 #define MDSS_MDP_INTR_PING_PONG_2_WR_PTR		BIT(18)
+#define MDSS_MDP_INTR_PING_PONG_3_WR_PTR		BIT(19)
 #define MDSS_MDP_INTR_PING_PONG_0_AUTOREFRESH_DONE	BIT(20)
 #define MDSS_MDP_INTR_PING_PONG_1_AUTOREFRESH_DONE	BIT(21)
 #define MDSS_MDP_INTR_PING_PONG_2_AUTOREFRESH_DONE	BIT(22)
+#define MDSS_MDP_INTR_PING_PONG_3_AUTOREFRESH_DONE	BIT(23)
 #define MDSS_MDP_INTR_INTF_0_UNDERRUN			BIT(24)
 #define MDSS_MDP_INTR_INTF_0_VSYNC			BIT(25)
 #define MDSS_MDP_INTR_INTF_1_UNDERRUN			BIT(26)
@@ -97,6 +102,7 @@
 	MDSS_MDP_CTL2,
 	MDSS_MDP_CTL3,
 	MDSS_MDP_CTL4,
+	MDSS_MDP_CTL5,
 	MDSS_MDP_MAX_CTL
 };
 
@@ -132,6 +138,8 @@
 	MDSS_MDP_SSPP_RGB2,
 	MDSS_MDP_SSPP_DMA0,
 	MDSS_MDP_SSPP_DMA1,
+	MDSS_MDP_SSPP_VIG3,
+	MDSS_MDP_SSPP_RGB3,
 	MDSS_MDP_MAX_SSPP
 };
 
@@ -232,6 +240,7 @@
 	MDSS_MDP_INTF_LAYERMIXER0,
 	MDSS_MDP_INTF_LAYERMIXER1,
 	MDSS_MDP_INTF_LAYERMIXER2,
+	MDSS_MDP_INTF_LAYERMIXER3,
 	MDSS_MDP_INTF_MAX_LAYERMIXER,
 };
 
@@ -248,17 +257,10 @@
 	MDSS_MDP_STAGE_1,
 	MDSS_MDP_STAGE_2,
 	MDSS_MDP_STAGE_3,
+	MDSS_MDP_STAGE_4,
 	MDSS_MDP_MAX_STAGE
 };
 
-enum mdss_mdp_blend_index {
-	MDSS_MDP_BLEND_STAGE0,
-	MDSS_MDP_BLEND_STAGE1,
-	MDSS_MDP_BLEND_STAGE2,
-	MDSS_MDP_BLEND_STAGE3,
-	MDSS_MDP_MAX_BLEND_STAGE,
-};
-
 #define MDSS_MDP_REG_LM_OFFSET(lm) (0x03200 + ((lm) * 0x400))
 
 #define MDSS_MDP_REG_LM_OP_MODE				0x000
@@ -391,6 +393,7 @@
 	MDSS_MDP_DSPP0,
 	MDSS_MDP_DSPP1,
 	MDSS_MDP_DSPP2,
+	MDSS_MDP_DSPP3,
 	MDSS_MDP_MAX_DSPP
 };
 
@@ -468,6 +471,7 @@
 	MDSS_MDP_PINGPONG0,
 	MDSS_MDP_PINGPONG1,
 	MDSS_MDP_PINGPONG2,
+	MDSS_MDP_PINGPONG3,
 	MDSS_MDP_MAX_PINGPONG
 };
 
@@ -494,28 +498,6 @@
 
 #define MDSS_MDP_SMP_MMB_BLOCKS			22
 
-enum mdss_mdp_smp_client_index {
-	MDSS_MDP_SMP_CLIENT_UNUSED,
-	MDSS_MDP_SMP_CLIENT_VIG0_FETCH_Y,
-	MDSS_MDP_SMP_CLIENT_VIG0_FETCH_CR,
-	MDSS_MDP_SMP_CLIENT_VIG0_FETCH_CB,
-	MDSS_MDP_SMP_CLIENT_VIG1_FETCH_Y,
-	MDSS_MDP_SMP_CLIENT_VIG1_FETCH_CR,
-	MDSS_MDP_SMP_CLIENT_VIG1_FETCH_CB,
-	MDSS_MDP_SMP_CLIENT_VIG2_FETCH_Y,
-	MDSS_MDP_SMP_CLIENT_VIG2_FETCH_CR,
-	MDSS_MDP_SMP_CLIENT_VIG2_FETCH_CB,
-	MDSS_MDP_SMP_CLIENT_DMA0_FETCH_Y,
-	MDSS_MDP_SMP_CLIENT_DMA0_FETCH_CR,
-	MDSS_MDP_SMP_CLIENT_DMA0_FETCH_CB,
-	MDSS_MDP_SMP_CLIENT_DMA1_FETCH_Y,
-	MDSS_MDP_SMP_CLIENT_DMA1_FETCH_CR,
-	MDSS_MDP_SMP_CLIENT_DMA1_FETCH_CB,
-	MDSS_MDP_SMP_CLIENT_RGB0_FETCH,
-	MDSS_MDP_SMP_CLIENT_RGB1_FETCH,
-	MDSS_MDP_SMP_CLIENT_RGB2_FETCH,
-};
-
 #define MDSS_MDP_LP_MISR_SEL			0x450
 #define MDSS_MDP_LP_MISR_CTRL_MDP		0x454
 #define MDSS_MDP_LP_MISR_CTRL_HDMI		0x458
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index 89e21d2..d0c1818 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -357,6 +357,24 @@
 	return 0;
 }
 
+int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl)
+{
+	struct mdss_panel_data *pdata;
+	int ret = 0;
+
+	pdata = ctl->panel_data;
+
+	pdata->panel_info.cont_splash_enabled = 0;
+
+	ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_FINISH,
+			NULL);
+
+	mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)0);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	return ret;
+}
+
 static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
 {
 	struct mdss_mdp_cmd_ctx *ctx;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index b7fe1bd..0a37573 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -219,7 +219,7 @@
 	if (!ctx)
 		return -ENODEV;
 
-	if (ctx->initialized) /* already set */
+	if (ctx->initialized && !ctl->shared_lock) /* already set */
 		return 0;
 
 	pr_debug("wfd setup ctl=%d\n", ctl->num);
@@ -347,6 +347,9 @@
 
 	rc = wait_for_completion_interruptible_timeout(&ctx->wb_comp,
 			KOFF_TIMEOUT);
+	mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
+		NULL, NULL);
+
 	if (rc <= 0) {
 		rc = -ENODEV;
 		WARN(1, "writeback kickoff timed out (%d) ctl=%d\n",
@@ -389,6 +392,9 @@
 		return ret;
 	}
 
+	mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
+		   mdss_mdp_writeback_intr_done, ctx);
+
 	ctx->callback_fnc = wb_args->callback_fnc;
 	ctx->callback_arg = wb_args->priv_data;
 
@@ -434,9 +440,6 @@
 	ctx->initialized = false;
 	init_completion(&ctx->wb_comp);
 
-	mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
-				   mdss_mdp_writeback_intr_done, ctx);
-
 	if (ctx->type == MDSS_MDP_WRITEBACK_TYPE_ROTATOR)
 		ctl->prepare_fnc = mdss_mdp_writeback_prepare_rot;
 	else /* wfd or line mode */
@@ -447,3 +450,21 @@
 
 	return ret;
 }
+
+int mdss_mdp_writeback_display_commit(struct mdss_mdp_ctl *ctl, void *arg)
+{
+	if (ctl->shared_lock && !mutex_is_locked(ctl->shared_lock)) {
+		pr_err("shared mutex is not locked before commit on ctl=%d\n",
+			ctl->num);
+		return -EINVAL;
+	}
+
+	if (ctl->mdata->mixer_switched) {
+		if (ctl->mixer_left)
+			ctl->mixer_left->params_changed++;
+		if (ctl->mixer_right)
+			ctl->mixer_right->params_changed++;
+	}
+
+	return mdss_mdp_display_commit(ctl, arg);
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 780ff94..24b27b4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -494,6 +494,7 @@
 	pipe->overfetch_disable = fmt->is_yuv &&
 			!(pipe->flags & MDP_SOURCE_ROTATED_90);
 
+	req->id = pipe->ndx;
 	pipe->req_data = *req;
 
 	if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) {
@@ -568,6 +569,10 @@
 	if (ret)
 		goto exit_fail;
 
+	if ((mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK) &&
+		!mdp5_data->mdata->has_wfd_blk)
+		mdss_mdp_smp_release(pipe);
+
 	ret = mdss_mdp_smp_reserve(pipe);
 	if (ret) {
 		pr_debug("mdss_mdp_smp_reserve failed. ret=%d\n", ret);
@@ -576,7 +581,6 @@
 
 	pipe->params_changed++;
 
-	req->id = pipe->ndx;
 	req->vert_deci = pipe->vert_deci;
 
 	*ppipe = pipe;
@@ -766,8 +770,12 @@
 	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
 	struct mdss_mdp_pipe *pipe, *next;
 	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+	struct mdss_mdp_ctl *tmp;
 	int ret;
 
+	if (ctl->shared_lock)
+		mutex_lock(ctl->shared_lock);
+
 	mutex_lock(&mdp5_data->ov_lock);
 	mutex_lock(&mfd->lock);
 
@@ -775,12 +783,44 @@
 	if (ret) {
 		mutex_unlock(&mfd->lock);
 		mutex_unlock(&mdp5_data->ov_lock);
+		if (ctl->shared_lock)
+			mutex_unlock(ctl->shared_lock);
 		return ret;
 	}
 
 	list_for_each_entry_safe(pipe, next, &mdp5_data->pipes_used,
 			used_list) {
 		struct mdss_mdp_data *buf;
+		/*
+		 * When external is connected and no dedicated wfd is present,
+		 * reprogram DMA pipe before kickoff to clear out any previous
+		 * block mode configuration.
+		 */
+		if ((pipe->type == MDSS_MDP_PIPE_TYPE_DMA) &&
+		    (ctl->shared_lock && !ctl->mdata->has_wfd_blk)) {
+			if (ctl->mdata->mixer_switched) {
+				ret = mdss_mdp_overlay_pipe_setup(mfd,
+						&pipe->req_data, &pipe);
+				pr_debug("reseting DMA pipe for ctl=%d",
+					 ctl->num);
+			}
+			if (ret) {
+				pr_err("can't reset DMA pipe ret=%d ctl=%d\n",
+					ret, ctl->num);
+				mutex_unlock(&mfd->lock);
+				goto commit_fail;
+			}
+
+			tmp = mdss_mdp_ctl_mixer_switch(ctl,
+					MDSS_MDP_WB_CTL_TYPE_LINE);
+			if (!tmp) {
+				mutex_unlock(&mfd->lock);
+				ret = -EINVAL;
+				goto commit_fail;
+			}
+			pipe->mixer = mdss_mdp_mixer_get(tmp,
+					MDSS_MDP_MIXER_MUX_DEFAULT);
+		}
 		if (pipe->back_buf.num_planes) {
 			buf = &pipe->back_buf;
 		} else if (ctl->play_cnt == 0) {
@@ -831,6 +871,8 @@
 	mdss_mdp_overlay_cleanup(mfd);
 
 	mutex_unlock(&mdp5_data->ov_lock);
+	if (ctl->shared_lock)
+		mutex_unlock(ctl->shared_lock);
 
 	return ret;
 }
@@ -1199,7 +1241,7 @@
 
 static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd)
 {
-	struct mdss_mdp_data data;
+	struct mdss_mdp_data *buf;
 	struct mdss_mdp_pipe *pipe;
 	struct fb_info *fbi;
 	struct mdss_overlay_private *mdp5_data;
@@ -1229,8 +1271,6 @@
 		return;
 	}
 
-	memset(&data, 0, sizeof(data));
-
 	bpp = fbi->var.bits_per_pixel / 8;
 	offset = fbi->var.xoffset * bpp +
 		 fbi->var.yoffset * fbi->fix.line_length;
@@ -1247,18 +1287,6 @@
 		goto pan_display_error;
 	}
 
-	if (is_mdss_iommu_attached()) {
-		if (!mfd->iova) {
-			pr_err("mfd iova is zero\n");
-			goto pan_display_error;
-		}
-		data.p[0].addr = mfd->iova;
-	} else
-		data.p[0].addr = fbi->fix.smem_start;
-
-	data.p[0].addr += offset;
-	data.p[0].len = fbi->fix.smem_len - offset;
-	data.num_planes = 1;
 
 	ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe, MDSS_MDP_MIXER_MUX_LEFT);
 	if (ret) {
@@ -1270,13 +1298,23 @@
 		pr_err("unable to map base pipe\n");
 		goto pan_display_error;
 	}
-	ret = mdss_mdp_pipe_queue_data(pipe, &data);
-	mdss_mdp_pipe_unmap(pipe);
-	if (ret) {
-		pr_err("unable to queue data\n");
-		goto pan_display_error;
+
+	buf = &pipe->back_buf;
+	if (is_mdss_iommu_attached()) {
+		if (!mfd->iova) {
+			pr_err("mfd iova is zero\n");
+			goto pan_display_error;
+		}
+		buf->p[0].addr = mfd->iova;
+	} else {
+		buf->p[0].addr = fbi->fix.smem_start;
 	}
 
+	buf->p[0].addr += offset;
+	buf->p[0].len = fbi->fix.smem_len - offset;
+	buf->num_planes = 1;
+	mdss_mdp_pipe_unmap(pipe);
+
 	if (fbi->var.xres > MAX_MIXER_WIDTH || mfd->split_display) {
 		ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe,
 						   MDSS_MDP_MIXER_MUX_RIGHT);
@@ -1288,12 +1326,8 @@
 			pr_err("unable to map right base pipe\n");
 			goto pan_display_error;
 		}
-		ret = mdss_mdp_pipe_queue_data(pipe, &data);
+		pipe->back_buf = *buf;
 		mdss_mdp_pipe_unmap(pipe);
-		if (ret) {
-			pr_err("unable to queue right data\n");
-			goto pan_display_error;
-		}
 	}
 	mutex_unlock(&mdp5_data->ov_lock);
 
@@ -1642,6 +1676,11 @@
 	case mdp_op_calib_mode:
 		ret = mdss_mdp_calib_mode(mfd, &mdp_pp.data.mdss_calib_cfg);
 		break;
+	case mdp_op_calib_buffer:
+		ret = mdss_mdp_calib_config_buffer(
+				(struct mdp_calib_config_buffer *)
+				 &mdp_pp.data.calib_buffer, &copyback);
+		break;
 	default:
 		pr_err("Unsupported request to MDP_PP IOCTL. %d = op\n",
 								mdp_pp.op);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 3b91ced..137da66 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -87,7 +87,7 @@
 {
 	if (!bitmap_empty(smp, SMP_MB_CNT)) {
 		if (write)
-			mdss_mdp_smp_mmb_set(MDSS_MDP_SMP_CLIENT_UNUSED, smp);
+			mdss_mdp_smp_mmb_set(0, smp);
 		bitmap_andnot(mdss_mdp_smp_mmb_pool, mdss_mdp_smp_mmb_pool,
 			      smp, SMP_MB_CNT);
 		bitmap_zero(smp, SMP_MB_CNT);
@@ -269,12 +269,13 @@
 }
 
 static struct mdss_mdp_pipe *mdss_mdp_pipe_init(struct mdss_mdp_mixer *mixer,
-						u32 type)
+						u32 type, u32 off)
 {
 	struct mdss_mdp_pipe *pipe;
 	struct mdss_data_type *mdata;
 	struct mdss_mdp_pipe *pipe_pool = NULL;
 	u32 npipes;
+	bool pipe_share = false;
 	u32 i;
 
 	if (!mixer || !mixer->ctl || !mixer->ctl->mdata)
@@ -296,6 +297,9 @@
 	case MDSS_MDP_PIPE_TYPE_DMA:
 		pipe_pool = mdata->dma_pipes;
 		npipes = mdata->ndma_pipes;
+		if (!mdata->has_wfd_blk &&
+		   (mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK))
+			pipe_share = true;
 		break;
 
 	default:
@@ -304,7 +308,7 @@
 		break;
 	}
 
-	for (i = 0; i < npipes; i++) {
+	for (i = off; i < npipes; i++) {
 		pipe = pipe_pool + i;
 		if (atomic_cmpxchg(&pipe->ref_cnt, 0, 1) == 0) {
 			pipe->mixer = mixer;
@@ -317,6 +321,14 @@
 		pr_debug("type=%x   pnum=%d\n", pipe->type, pipe->num);
 		mutex_init(&pipe->pp_res.hist.hist_mutex);
 		spin_lock_init(&pipe->pp_res.hist.hist_lock);
+	} else if (pipe_share) {
+		/*
+		 * when there is no dedicated wfd blk, DMA pipe can be
+		 * shared as long as its attached to a writeback mixer
+		 */
+		pipe = mdata->dma_pipes + mixer->num;
+		mdss_mdp_pipe_map(pipe);
+		pr_debug("pipe sharing for pipe=%d\n", pipe->num);
 	} else {
 		pr_err("no %d type pipes available\n", type);
 	}
@@ -328,20 +340,20 @@
 {
 	struct mdss_mdp_pipe *pipe = NULL;
 	struct mdss_data_type *mdata;
-	u32 pnum;
 
 	mutex_lock(&mdss_mdp_sspp_lock);
 	mdata = mixer->ctl->mdata;
-	pnum = mixer->num;
-
-	if (atomic_cmpxchg(&((mdata->dma_pipes[pnum]).ref_cnt), 0, 1) == 0) {
-		pipe = &mdata->dma_pipes[pnum];
-		pipe->mixer = mixer;
-
+	pipe = mdss_mdp_pipe_init(mixer, MDSS_MDP_PIPE_TYPE_DMA, mixer->num);
+	if (!pipe) {
+		pr_err("DMA pipes not available for mixer=%d\n", mixer->num);
+	} else if (pipe != &mdata->dma_pipes[mixer->num]) {
+		pr_err("Requested DMA pnum=%d not available\n",
+			mdata->dma_pipes[mixer->num].num);
+		mdss_mdp_pipe_unmap(pipe);
+		pipe = NULL;
 	} else {
-		pr_err("DMA pnum%d\t not available\n", pnum);
+		pipe->mixer = mixer;
 	}
-
 	mutex_unlock(&mdss_mdp_sspp_lock);
 	return pipe;
 }
@@ -351,7 +363,7 @@
 {
 	struct mdss_mdp_pipe *pipe;
 	mutex_lock(&mdss_mdp_sspp_lock);
-	pipe = mdss_mdp_pipe_init(mixer, type);
+	pipe = mdss_mdp_pipe_init(mixer, type, 0);
 	mutex_unlock(&mdss_mdp_sspp_lock);
 	return pipe;
 }
@@ -552,20 +564,15 @@
 	return 0;
 }
 
-int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata, u32 *offsets,
-				u32 *ftch_id, u32 type, u32 num_base, u32 len)
+int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata,
+	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_id, u32 type,
+	u32 num_base, u32 len)
 {
-	struct mdss_mdp_pipe *head;
 	u32 i;
-	int rc = 0;
 
-	head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_pipe) *
-			len, GFP_KERNEL);
-
-	if (!head) {
-		pr_err("unable to setup pipe type=%d :devm_kzalloc fail\n",
-			type);
-		return -ENOMEM;
+	if (!head || !mdata) {
+		pr_err("unable to setup pipe type=%d: invalid input\n", type);
+		return -EINVAL;
 	}
 
 	for (i = 0; i < len; i++) {
@@ -576,27 +583,7 @@
 		head[i].base = mdata->mdp_base + offsets[i];
 	}
 
-	switch (type) {
-
-	case MDSS_MDP_PIPE_TYPE_VIG:
-		mdata->vig_pipes = head;
-		break;
-
-	case MDSS_MDP_PIPE_TYPE_RGB:
-		mdata->rgb_pipes = head;
-		break;
-
-	case MDSS_MDP_PIPE_TYPE_DMA:
-		mdata->dma_pipes = head;
-		break;
-
-	default:
-		pr_err("Invalid pipe type=%d\n", type);
-		rc = -EINVAL;
-		break;
-	}
-
-	return rc;
+	return 0;
 }
 
 static int mdss_mdp_src_addr_setup(struct mdss_mdp_pipe *pipe,
@@ -658,13 +645,14 @@
 {
 	int ret = 0;
 	u32 params_changed, opmode;
+	struct mdss_mdp_ctl *ctl;
 
 	if (!pipe) {
 		pr_err("pipe not setup properly for queue\n");
 		return -ENODEV;
 	}
 
-	if (!pipe->mixer) {
+	if (!pipe->mixer || !pipe->mixer->ctl) {
 		pr_err("pipe mixer not setup properly for queue\n");
 		return -ENODEV;
 	}
@@ -673,8 +661,16 @@
 		 pipe->mixer->num, pipe->play_cnt);
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-
-	params_changed = pipe->params_changed;
+	ctl = pipe->mixer->ctl;
+	/*
+	 * Reprogram the pipe when there is no dedicated wfd blk and
+	 * virtual mixer is allocated for the DMA pipe during concurrent
+	 * line and block mode operations
+	 */
+	params_changed = (pipe->params_changed) ||
+			 ((pipe->type == MDSS_MDP_PIPE_TYPE_DMA) &&
+			 (pipe->mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK)
+			 && (ctl->mdata->mixer_switched));
 	if (src_data == NULL) {
 		mdss_mdp_pipe_solidfill_setup(pipe);
 		goto update_nobuf;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 75b6056..6cedd98 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -3329,6 +3329,14 @@
 				ret = 1;
 		else if (ptr >= 0x3200 || ptr == 0x100)
 				ret = 1;
+		else if (ptr == 0x104 || ptr == 0x614 || ptr == 0x714 ||
+			ptr == 0x814 || ptr == 0x914 || ptr == 0xa14)
+				ret = 1;
+		else if (ptr == 0x618 || ptr == 0x718 || ptr == 0x818 ||
+				 ptr == 0x918 || ptr == 0xa18)
+				ret = 1;
+		else if (ptr == 0x2234 || ptr == 0x1e34 || ptr == 0x2634)
+				ret = 1;
 	}
 end:
 	return ret;
@@ -3368,3 +3376,69 @@
 	mutex_unlock(&mdss_pp_mutex);
 	return 0;
 }
+
+int mdss_mdp_calib_config_buffer(struct mdp_calib_config_buffer *cfg,
+						u32 *copyback)
+{
+	int ret = -1;
+	int counter = cfg->size / (sizeof(uint32_t) * 2);
+	uint32_t *buff = NULL, *buff_org = NULL;
+	void *ptr;
+	int i = 0;
+
+	buff_org = buff = kzalloc(cfg->size, GFP_KERNEL);
+	if (buff == NULL) {
+		pr_err("Allocation failed");
+		return ret;
+	}
+
+	if (copy_from_user(buff, cfg->buffer, cfg->size)) {
+		kfree(buff);
+		pr_err("Copy failed");
+		return ret;
+	}
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+	if (cfg->ops & MDP_PP_OPS_READ) {
+		for (i = 0 ; i < counter ; i++) {
+			if (is_valid_calib_addr((void *) *buff)) {
+				ret = 0;
+			} else {
+				ret = -1;
+				pr_err("Address validation failed");
+				break;
+			}
+
+			ptr = (void *)(((unsigned int) *buff) +
+					 (mdss_res->mdp_base));
+			buff++;
+			*buff = readl_relaxed(ptr);
+			buff++;
+		}
+		if (!ret)
+			ret = copy_to_user(cfg->buffer, buff_org, cfg->size);
+		*copyback = 1;
+	} else if (cfg->ops & MDP_PP_OPS_WRITE) {
+		for (i = 0 ; i < counter ; i++) {
+			if (is_valid_calib_addr((void *) *buff)) {
+				ret = 0;
+			} else {
+				ret = -1;
+				pr_err("Address validation failed");
+				break;
+			}
+
+			ptr = (void *)(((unsigned int) *buff) +
+					 (mdss_res->mdp_base));
+			buff++;
+			writel_relaxed(*buff, ptr);
+			buff++;
+		}
+	}
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	kfree(buff_org);
+	return ret;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 8c45df8..fcd90e1 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -73,13 +73,16 @@
 	struct mdss_mdp_pipe *pipe = NULL;
 
 	mixer = mdss_mdp_wb_mixer_alloc(1);
-	if (!mixer)
+	if (!mixer) {
+		pr_err("wb mixer alloc failed\n");
 		return NULL;
+	}
 
 	pipe = mdss_mdp_pipe_alloc_dma(mixer);
-
-	if (!pipe)
+	if (!pipe) {
 		mdss_mdp_wb_mixer_destroy(mixer);
+		pr_err("dma pipe allocation failed\n");
+	}
 
 	return pipe;
 }
@@ -96,12 +99,12 @@
 	ctl = rot_pipe->mixer->ctl;
 	mutex_lock(&rot->lock);
 	if (rot->busy) {
-		pr_debug("waiting for rot=%d to complete\n", rot->pipe->num);
 		mdss_mdp_display_wait4comp(ctl);
 		rot->busy = false;
-		mdss_mdp_smp_release(rot->pipe);
-
+		if (ctl->shared_lock)
+			mutex_unlock(ctl->shared_lock);
 	}
+	mdss_mdp_smp_release(rot->pipe);
 	mutex_unlock(&rot->lock);
 
 	return 0;
@@ -120,7 +123,7 @@
 
 	mutex_lock(&rot->lock);
 	rot->busy = true;
-	ret = mdss_mdp_display_commit(ctl, &wb_args);
+	ret = mdss_mdp_writeback_display_commit(ctl, &wb_args);
 	if (ret) {
 		rot->busy = false;
 		pr_err("problem with kickoff rot pipe=%d", rot->pipe->num);
@@ -188,8 +191,19 @@
 	pr_debug("queue rotator pnum=%d\n", rot_pipe->num);
 
 	ctl = rot_pipe->mixer->ctl;
+	if (ctl->shared_lock)
+		mutex_lock(ctl->shared_lock);
 
-	if (rot->params_changed) {
+	ctl = mdss_mdp_ctl_mixer_switch(ctl,
+			MDSS_MDP_WB_CTL_TYPE_BLOCK);
+	if (!ctl) {
+		ret = -EINVAL;
+		goto error;
+	} else {
+		rot->pipe->mixer = ctl->mixer_left;
+	}
+
+	if (rot->params_changed || ctl->mdata->mixer_switched) {
 		rot->params_changed = 0;
 		rot_pipe->flags = rot->flags;
 		rot_pipe->src_fmt = mdss_mdp_get_format_params(rot->format);
@@ -205,19 +219,23 @@
 	ret = mdss_mdp_smp_reserve(rot->pipe);
 	if (ret) {
 		pr_err("unable to mdss_mdp_smp_reserve rot data\n");
-		return ret;
+		goto error;
 	}
 
 	ret = mdss_mdp_pipe_queue_data(rot->pipe, src_data);
 	if (ret) {
 		pr_err("unable to queue rot data\n");
 		mdss_mdp_smp_unreserve(rot->pipe);
-		return ret;
+		goto error;
 	}
 
 	ret = mdss_mdp_rotator_kickoff(ctl, rot, dst_data);
 
 	return ret;
+error:
+	if (ctl->shared_lock)
+		mutex_unlock(ctl->shared_lock);
+	return ret;
 }
 
 int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot,
@@ -342,6 +360,8 @@
 static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot)
 {
 	struct mdss_mdp_pipe *rot_pipe;
+	struct mdss_mdp_ctl *tmp;
+	int ret = 0;
 
 	if (!rot)
 		return -ENODEV;
@@ -359,11 +379,16 @@
 	memset(rot, 0, sizeof(*rot));
 	if (rot_pipe) {
 		struct mdss_mdp_mixer *mixer = rot_pipe->mixer;
-		mdss_mdp_pipe_destroy(rot_pipe);
+		mdss_mdp_pipe_unmap(rot_pipe);
+		tmp = mdss_mdp_ctl_mixer_switch(mixer->ctl,
+				MDSS_MDP_WB_CTL_TYPE_BLOCK);
+		if (!tmp)
+			return -EINVAL;
+		else
+			mixer = tmp->mixer_left;
 		mdss_mdp_wb_mixer_destroy(mixer);
 	}
-
-	return 0;
+	return ret;
 }
 
 int mdss_mdp_rotator_release(struct mdss_mdp_rotator_session *rot)
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index c7beb0e..b65d894 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -41,9 +41,11 @@
 	MDP_INTR_PING_PONG_0,
 	MDP_INTR_PING_PONG_1,
 	MDP_INTR_PING_PONG_2,
+	MDP_INTR_PING_PONG_3,
 	MDP_INTR_PING_PONG_0_RD_PTR,
 	MDP_INTR_PING_PONG_1_RD_PTR,
 	MDP_INTR_PING_PONG_2_RD_PTR,
+	MDP_INTR_PING_PONG_3_RD_PTR,
 	MDP_INTR_WB_0,
 	MDP_INTR_WB_1,
 	MDP_INTR_WB_2,
@@ -163,6 +165,9 @@
 	if (isr & MDSS_MDP_INTR_PING_PONG_2_DONE)
 		mdss_mdp_intr_done(MDP_INTR_PING_PONG_2);
 
+	if (isr & MDSS_MDP_INTR_PING_PONG_3_DONE)
+		mdss_mdp_intr_done(MDP_INTR_PING_PONG_3);
+
 	if (isr & MDSS_MDP_INTR_PING_PONG_0_RD_PTR)
 		mdss_mdp_intr_done(MDP_INTR_PING_PONG_0_RD_PTR);
 
@@ -172,6 +177,9 @@
 	if (isr & MDSS_MDP_INTR_PING_PONG_2_RD_PTR)
 		mdss_mdp_intr_done(MDP_INTR_PING_PONG_2_RD_PTR);
 
+	if (isr & MDSS_MDP_INTR_PING_PONG_3_RD_PTR)
+		mdss_mdp_intr_done(MDP_INTR_PING_PONG_3_RD_PTR);
+
 	if (isr & MDSS_MDP_INTR_INTF_0_VSYNC) {
 		mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_0);
 		mdss_misr_crc_collect(mdata, DISPLAY_MISR_EDP);
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index a9deef2..ff54067 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -527,7 +527,7 @@
 		goto kickoff_fail;
 	}
 
-	ret = mdss_mdp_display_commit(ctl, &wb_args);
+	ret = mdss_mdp_writeback_display_commit(ctl, &wb_args);
 	if (ret) {
 		pr_err("error on commit ctl=%d\n", ctl->num);
 		goto kickoff_fail;
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 2b4542a..130d0fd 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -152,6 +152,7 @@
 	__REQ_MIXED_MERGE,	/* merge of different types, fail separately */
 	__REQ_SANITIZE,		/* sanitize */
 	__REQ_URGENT,		/* urgent request */
+	__REQ_PM,		/* runtime pm request */
 	__REQ_NR_BITS,		/* stops here */
 };
 
@@ -196,5 +197,6 @@
 #define REQ_IO_STAT		(1 << __REQ_IO_STAT)
 #define REQ_MIXED_MERGE		(1 << __REQ_MIXED_MERGE)
 #define REQ_SECURE		(1 << __REQ_SECURE)
+#define REQ_PM                 (1 << __REQ_PM)
 
 #endif /* __LINUX_BLK_TYPES_H */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 6502841..651a0fc 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -340,6 +340,12 @@
 	 */
 	struct kobject kobj;
 
+#ifdef CONFIG_PM_RUNTIME
+	struct device		*dev;
+	int			rpm_status;
+	unsigned int		nr_pending;
+#endif
+
 	/*
 	 * queue settings
 	 */
@@ -883,6 +889,27 @@
 extern void blk_put_queue(struct request_queue *);
 
 /*
+ * block layer runtime pm functions
+ */
+#ifdef CONFIG_PM_RUNTIME
+extern void blk_pm_runtime_init(struct request_queue *q, struct device *dev);
+extern int blk_pre_runtime_suspend(struct request_queue *q);
+extern void blk_post_runtime_suspend(struct request_queue *q, int err);
+extern void blk_pre_runtime_resume(struct request_queue *q);
+extern void blk_post_runtime_resume(struct request_queue *q, int err);
+#else
+static inline void blk_pm_runtime_init(struct request_queue *q,
+	struct device *dev) {}
+static inline int blk_pre_runtime_suspend(struct request_queue *q)
+{
+	return -ENOSYS;
+}
+static inline void blk_post_runtime_suspend(struct request_queue *q, int err) {}
+static inline void blk_pre_runtime_resume(struct request_queue *q) {}
+static inline void blk_post_runtime_resume(struct request_queue *q, int err) {}
+#endif
+
+/*
  * blk_plug permits building a queue of related requests by holding the I/O
  * fragments for a short period. This allows merging of sequential requests
  * into single larger request. As the requests are moved from a per-task list to
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 384f37a..0739ece 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -27,7 +27,6 @@
 #define UART_MODE			4
 #define SOCKET_MODE			5
 #define CALLBACK_MODE			6
-#define MEMORY_DEVICE_MODE_NRT		7
 /* different values that go in for diag_data_type */
 #define DATA_TYPE_EVENT         	0
 #define DATA_TYPE_F3            	1
@@ -50,6 +49,8 @@
 #define DIAG_IOCTL_DCI_CLEAR_LOGS	28
 #define DIAG_IOCTL_DCI_CLEAR_EVENTS	29
 #define DIAG_IOCTL_REMOTE_DEV		32
+#define DIAG_IOCTL_VOTE_REAL_TIME	33
+#define DIAG_IOCTL_GET_REAL_TIME	34
 
 /* PC Tools IDs */
 #define APQ8060_TOOLS_ID	4062
@@ -118,10 +119,10 @@
 /* This needs to be modified manually now, when we add
  a new RANGE of SSIDs to the msg_mask_tbl */
 #define MSG_MASK_TBL_CNT		24
-#define EVENT_LAST_ID			0x09BE
+#define EVENT_LAST_ID			0x09CB
 
 #define MSG_SSID_0			0
-#define MSG_SSID_0_LAST			96
+#define MSG_SSID_0_LAST			97
 #define MSG_SSID_1			500
 #define MSG_SSID_1_LAST			506
 #define MSG_SSID_2			1000
@@ -135,7 +136,7 @@
 #define MSG_SSID_6			4500
 #define MSG_SSID_6_LAST			4526
 #define MSG_SSID_7			4600
-#define MSG_SSID_7_LAST			4613
+#define MSG_SSID_7_LAST			4614
 #define MSG_SSID_8			5000
 #define MSG_SSID_8_LAST			5030
 #define MSG_SSID_9			5500
@@ -270,7 +271,7 @@
 	MSG_LVL_LOW,
 	MSG_LVL_LOW,
 	MSG_LVL_LOW,
-	MSG_LVL_HIGH,
+	MSG_LVL_HIGH | MSG_MASK_21,
 	MSG_LVL_HIGH,
 	MSG_LVL_LOW,
 	MSG_LVL_LOW,
@@ -290,6 +291,7 @@
 	MSG_LVL_LOW,
 	MSG_LVL_LOW,
 	MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL,
+	MSG_LVL_MED,
 };
 
 static const uint32_t msg_bld_masks_1[] = {
@@ -402,6 +404,7 @@
 	MSG_LVL_MED,
 	MSG_LVL_MED,
 	MSG_LVL_LOW,
+	MSG_LVL_LOW,
 	MSG_LVL_LOW
 };
 
@@ -725,7 +728,7 @@
 /* LOG CODES */
 
 #define LOG_0	0x0
-#define LOG_1	0x1807
+#define LOG_1	0x1808
 #define LOG_2	0x0
 #define LOG_3	0x0
 #define LOG_4	0x4910
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index bd954ee..3ae83d6 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -570,6 +570,9 @@
 	/* Max bitrate from single memory input. Mbit/sec */
 	int memory_input_max_bitrate;
 
+	/* Max possible value of STC reported by demux, in 27MHz */
+	__u64 max_stc;
+
 	struct dmx_buffer_requirement section;
 
 	/* For PES not sent to decoder */
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index ae88807..f8b78a4 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -227,6 +227,7 @@
 #define KGSL_PERFCOUNTER_GROUP_VBIF_PWR 0xE
 
 #define KGSL_PERFCOUNTER_NOT_USED 0xFFFFFFFF
+#define KGSL_PERFCOUNTER_BROKEN 0xFFFFFFFE
 
 /* structure holds list of ibs */
 struct kgsl_ibdesc {
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 18921a0..c3ff9de 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -606,6 +606,12 @@
 	uint32_t data;
 };
 
+struct mdp_calib_config_buffer {
+	uint32_t ops;
+	uint32_t size;
+	uint32_t *buffer;
+};
+
 #define MDSS_MAX_BL_BRIGHTNESS 255
 #define AD_BL_LIN_LEN (MDSS_MAX_BL_BRIGHTNESS + 1)
 
@@ -697,6 +703,7 @@
 	mdp_op_ad_cfg,
 	mdp_op_ad_input,
 	mdp_op_calib_mode,
+	mdp_op_calib_buffer,
 	mdp_op_max,
 };
 
@@ -724,6 +731,7 @@
 		struct mdss_ad_init_cfg ad_init_cfg;
 		struct mdss_calib_cfg mdss_calib_cfg;
 		struct mdss_ad_input ad_input;
+		struct mdp_calib_config_buffer calib_buffer;
 	} data;
 };
 
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index c88d2a9..86e4c91 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -108,6 +108,7 @@
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 	PG_compound_lock,
 #endif
+	PG_readahead,		/* page in a readahead window */
 	__NR_PAGEFLAGS,
 
 	/* Filesystems */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 44c6d7f..2f18351 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -165,6 +165,7 @@
 	USB_ACA_C_CHARGER,
 	USB_ACA_DOCK_CHARGER,
 	USB_PROPRIETARY_CHARGER,
+	USB_FLOATED_CHARGER,
 };
 
 /**
@@ -457,6 +458,7 @@
 	bool disable_park_mode;
 	bool consider_ipa_handshake;
 	bool ahb_async_bridge_bypass;
+	bool disable_cerr;
 };
 
 struct msm_usb_host_platform_data {
@@ -464,6 +466,8 @@
 	int pmic_gpio_dp_irq;
 	unsigned int dock_connect_irq;
 	bool use_sec_phy;
+	bool no_selective_suspend;
+	int resume_gpio;
 };
 
 /**
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 5c7ae02..81187aa 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1836,12 +1836,6 @@
 	V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO,
 	V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP
 };
-#define V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO \
-		(V4L2_CID_MPEG_MSM_VIDC_BASE + 23)
-enum v4l2_mpeg_vidc_video_h264_vui_timing_info {
-	V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED = 0,
-	V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED = 1
-};
 
 #define V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL (V4L2_CID_MPEG_MSM_VIDC_BASE + 26)
 enum v4l2_mpeg_vidc_perf_level {
@@ -1851,9 +1845,17 @@
 };
 
 #define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_GOB		\
-		(V4L2_CID_MPEG_MSM_VIDC_BASE+27)
+		(V4L2_CID_MPEG_MSM_VIDC_BASE + 27)
+
 #define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_DELIVERY_MODE	\
-	(V4L2_CID_MPEG_MSM_VIDC_BASE+28)
+	(V4L2_CID_MPEG_MSM_VIDC_BASE + 28)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO \
+		(V4L2_CID_MPEG_MSM_VIDC_BASE + 29)
+enum v4l2_mpeg_vidc_video_h264_vui_timing_info {
+	V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED = 0,
+	V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED = 1
+};
 /*  Camera class control IDs */
 #define V4L2_CID_CAMERA_CLASS_BASE 	(V4L2_CTRL_CLASS_CAMERA | 0x900)
 #define V4L2_CID_CAMERA_CLASS 		(V4L2_CTRL_CLASS_CAMERA | 1)
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 31798d6..6358f8a 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -305,18 +305,19 @@
 	CFG_EEPROM_READ_CAL_DATA,
 	CFG_EEPROM_WRITE_DATA,
 };
+
 struct eeprom_get_t {
-	uint16_t num_bytes;
+	uint32_t num_bytes;
 };
 
 struct eeprom_read_t {
 	uint8_t *dbuffer;
-	uint16_t num_bytes;
+	uint32_t num_bytes;
 };
 
 struct eeprom_write_t {
 	uint8_t *dbuffer;
-	uint16_t num_bytes;
+	uint32_t num_bytes;
 };
 
 struct msm_eeprom_cfg_data {
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 4d36688..5ae852a 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -11,6 +11,7 @@
 #define ISP_NATIVE_BUF_BIT    0x10000
 #define ISP0_BIT              0x20000
 #define ISP1_BIT              0x40000
+#define ISP_META_CHANNEL_BIT  0x80000
 #define ISP_STATS_STREAM_BIT  0x80000000
 
 enum ISP_START_PIXEL_PATTERN {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index c68d427..60845de 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1,6 +1,7 @@
 /*
    BlueZ - Bluetooth protocol stack for Linux
-   Copyright (c) 2000-2001, 2010-2012, The Linux Foundation. All rights reserved.
+   Copyright (c) 2000-2001, The Linux Foundation. All rights reserved.
+   Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
 
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
@@ -354,6 +355,7 @@
 	void		*smp_conn;
 	struct timer_list smp_timer;
 	__u8		conn_valid;
+	__u8		hidp_session_valid;
 
 
 	void (*connect_cfm_cb)	(struct hci_conn *conn, u8 status);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 6efb2e1..7c6a558 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -383,10 +383,18 @@
 			int data_direction, void *buffer, unsigned bufflen,
 			unsigned char *sense, int timeout, int retries,
 			int flag, int *resid);
-extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
-			    int data_direction, void *buffer, unsigned bufflen,
-			    struct scsi_sense_hdr *, int timeout, int retries,
-			    int *resid);
+extern int scsi_execute_req_flags(struct scsi_device *sdev,
+	const unsigned char *cmd, int data_direction, void *buffer,
+	unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
+	int retries, int *resid, int flags);
+static inline int scsi_execute_req(struct scsi_device *sdev,
+	const unsigned char *cmd, int data_direction, void *buffer,
+	unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
+	int retries, int *resid)
+{
+	return scsi_execute_req_flags(sdev, cmd, data_direction, buffer,
+		bufflen, sshdr, timeout, retries, resid, 0);
+}
 
 #ifdef CONFIG_PM_RUNTIME
 extern int scsi_autopm_get_device(struct scsi_device *);
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 7e98ef3..364de9a 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -632,43 +632,44 @@
 
 /* Port ID. Update afe_get_port_index
  *	when a new port is added here. */
-#define PRIMARY_I2S_RX 0		/* index = 0 */
-#define PRIMARY_I2S_TX 1		/* index = 1 */
-#define SECONDARY_I2S_RX 4		/* index = 4 */
-#define SECONDARY_I2S_TX 5		/* index = 5 */
-#define MI2S_RX 6			/* index = 6 */
-#define MI2S_TX 7			/* index = 7 */
-#define HDMI_RX 8			/* index = 8 */
-#define RSVD_2 9			/* index = 9 */
-#define RSVD_3 10			/* index = 10 */
-#define DIGI_MIC_TX 11			/* index = 11 */
-#define VOICE_RECORD_RX 0x8003		/* index = 12 */
-#define VOICE_RECORD_TX 0x8004		/* index = 13 */
-#define VOICE_PLAYBACK_TX 0x8005	/* index = 14 */
+#define PRIMARY_I2S_RX 0
+#define PRIMARY_I2S_TX 1
+#define SECONDARY_I2S_RX 4
+#define SECONDARY_I2S_TX 5
+#define MI2S_RX 6
+#define MI2S_TX 7
+#define HDMI_RX 8
+#define RSVD_2 9
+#define RSVD_3 10
+#define DIGI_MIC_TX 11
+#define VOICE2_PLAYBACK_TX 0x8002
+#define VOICE_RECORD_RX 0x8003
+#define VOICE_RECORD_TX 0x8004
+#define VOICE_PLAYBACK_TX 0x8005
 
 /* Slimbus Multi channel port id pool  */
-#define SLIMBUS_0_RX		0x4000		/* index = 15 */
-#define SLIMBUS_0_TX		0x4001		/* index = 16 */
-#define SLIMBUS_1_RX		0x4002		/* index = 17 */
-#define SLIMBUS_1_TX		0x4003		/* index = 18 */
+#define SLIMBUS_0_RX		0x4000
+#define SLIMBUS_0_TX		0x4001
+#define SLIMBUS_1_RX		0x4002
+#define SLIMBUS_1_TX		0x4003
 #define SLIMBUS_2_RX		0x4004
 #define SLIMBUS_2_TX		0x4005
 #define SLIMBUS_3_RX		0x4006
 #define SLIMBUS_3_TX		0x4007
 #define SLIMBUS_4_RX		0x4008
-#define SLIMBUS_4_TX		0x4009		/* index = 24 */
+#define SLIMBUS_4_TX		0x4009
 #define SLIMBUS_5_RX		0x400a
 #define SLIMBUS_5_TX		0x400b
 #define SLIMBUS_6_RX		0x400c
 #define SLIMBUS_6_TX		0x400d
 #define SLIMBUS_PORT_LAST	SLIMBUS_6_TX
-#define INT_BT_SCO_RX 0x3000		/* index = 25 */
-#define INT_BT_SCO_TX 0x3001		/* index = 26 */
-#define INT_BT_A2DP_RX 0x3002		/* index = 27 */
-#define INT_FM_RX 0x3004		/* index = 28 */
-#define INT_FM_TX 0x3005		/* index = 29 */
-#define RT_PROXY_PORT_001_RX	0x2000    /* index = 30 */
-#define RT_PROXY_PORT_001_TX	0x2001    /* index = 31 */
+#define INT_BT_SCO_RX 0x3000
+#define INT_BT_SCO_TX 0x3001
+#define INT_BT_A2DP_RX 0x3002
+#define INT_FM_RX 0x3004
+#define INT_FM_TX 0x3005
+#define RT_PROXY_PORT_001_RX	0x2000
+#define RT_PROXY_PORT_001_TX	0x2001
 
 #define AFE_PORT_INVALID 0xFFFF
 #define SLIMBUS_INVALID AFE_PORT_INVALID
@@ -818,6 +819,7 @@
  * to this port from where the voice path delivers them on the
  * Rx path.
  */
+#define AFE_PORT_ID_VOICE2_PLAYBACK_TX  0x8002
 #define AFE_PORT_ID_VOICE_PLAYBACK_TX   0x8005
 #define AFE_PORT_ID_INVALID             0xFFFF
 
diff --git a/include/sound/msm-dai-q6-v2.h b/include/sound/msm-dai-q6-v2.h
index c34a397..e2f9399 100644
--- a/include/sound/msm-dai-q6-v2.h
+++ b/include/sound/msm-dai-q6-v2.h
@@ -40,7 +40,6 @@
 };
 
 struct msm_dai_auxpcm_pdata {
-	void *clk_cfg;
 	struct msm_dai_auxpcm_config mode_8k;
 	struct msm_dai_auxpcm_config mode_16k;
 };
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 2e4c7c1..12934aa 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -83,6 +83,7 @@
 	IDX_AFE_PORT_ID_PRIMARY_MI2S_TX = 41,
 	IDX_AFE_PORT_ID_SECONDARY_PCM_RX = 42,
 	IDX_AFE_PORT_ID_SECONDARY_PCM_TX = 43,
+	IDX_VOICE2_PLAYBACK_TX = 44,
 	IDX_GLOBAL_CFG,
 	AFE_MAX_PORTS
 };
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 2138689..4ad1ca9 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -191,6 +191,9 @@
 int q6asm_open_read(struct audio_client *ac, uint32_t format
 		/*, uint16_t bits_per_sample*/);
 
+int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
+			uint16_t bits_per_sample);
+
 int q6asm_open_write(struct audio_client *ac, uint32_t format
 		/*, uint16_t bits_per_sample*/);
 
@@ -252,6 +255,10 @@
 int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
 			uint32_t rate, uint32_t channels);
 
+int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac,
+			uint32_t rate, uint32_t channels,
+			uint16_t bits_per_sample);
+
 int q6asm_set_encdec_chan_map(struct audio_client *ac,
 		uint32_t num_channels);
 
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 5148c1a..9cc2f45 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -6093,6 +6093,7 @@
 #ifdef CONFIG_MEMORY_FAILURE
 	{1UL << PG_hwpoison,		"hwpoison"	},
 #endif
+	{1UL << PG_readahead,           "PG_readahead"  },
 	{-1UL,				NULL		},
 };
 
diff --git a/mm/readahead.c b/mm/readahead.c
index 728a7a3..56f8a24 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -184,6 +184,9 @@
 		if (!page)
 			break;
 		page->index = page_offset;
+
+		page->flags |= (1L << PG_readahead);
+
 		list_add(&page->lru, &page_pool);
 		if (page_idx == nr_to_read - lookahead_size)
 			SetPageReadahead(page);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 7ffcc1b..9ffd0f1 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1,6 +1,7 @@
 /*
    BlueZ - Bluetooth protocol stack for Linux
-   Copyright (c) 2000-2001, 2010-2012 The Linux Foundation.  All rights reserved.
+   Copyright (c) 2000-2001, The Linux Foundation. All rights reserved.
+   Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
 
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
@@ -659,6 +660,9 @@
 
 	hci_conn_put_device(conn);
 
+	if (conn->hidp_session_valid)
+		hci_conn_put_device(conn);
+
 	hci_dev_put(hdev);
 
 	return 0;
@@ -1267,8 +1271,10 @@
 
 void hci_conn_put_device(struct hci_conn *conn)
 {
-	if (atomic_dec_and_test(&conn->devref))
+	if (atomic_dec_and_test(&conn->devref)) {
+		conn->hidp_session_valid = false;
 		hci_conn_del_sysfs(conn);
+	}
 }
 EXPORT_SYMBOL(hci_conn_put_device);
 
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 2353e91..e214cb2 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -1,7 +1,7 @@
 /*
    HIDP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
-   Copyright (c) 2012 The Linux Foundation.  All rights reserved.
+   Copyright (c) 2012-2013 The Linux Foundation.  All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2 as
@@ -108,7 +108,7 @@
 	hdev = hci_get_route(dst, BDADDR_ANY);
 	if (hdev) {
 		session->conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
-		if (session->conn)
+		if (session->conn && session->conn->hidp_session_valid)
 			dev = &session->conn->dev;
 
 		hci_dev_put(hdev);
@@ -661,8 +661,10 @@
 
 	hci_dev_lock_bh(hdev);
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
-	if (conn)
+	if (conn) {
+		conn->hidp_session_valid = true;
 		hci_conn_hold_device(conn);
+	}
 	hci_dev_unlock_bh(hdev);
 
 	hci_dev_put(hdev);
diff --git a/net/ipv4/netfilter/ipt_NATTYPE.c b/net/ipv4/netfilter/ipt_NATTYPE.c
index f181be4..be405f7 100644
--- a/net/ipv4/netfilter/ipt_NATTYPE.c
+++ b/net/ipv4/netfilter/ipt_NATTYPE.c
@@ -59,7 +59,7 @@
 	struct list_head list;
 	struct timer_list timeout;
 	unsigned long timeout_value;
-	unsigned char is_valid;
+	unsigned int nattype_cookie;
 	unsigned short proto;		/* Protocol: TCP or UDP */
 	struct nf_nat_ipv4_range range;	/* LAN side source information */
 	unsigned short nat_port;	/* Routed NAT port */
@@ -67,6 +67,8 @@
 	unsigned short dest_port;/* Original egress packets destination port */
 };
 
+#define NATTYPE_COOKIE 0x11abcdef
+
 /*
  * TODO: It might be better to use a hash table for performance in
  * heavy traffic.
@@ -109,7 +111,7 @@
 	if (!nte)
 		return false;
 	spin_lock_bh(&nattype_lock);
-	if (!nte->is_valid) {
+	if (nte->nattype_cookie != NATTYPE_COOKIE) {
 		spin_unlock_bh(&nattype_lock);
 		return false;
 	}
@@ -483,7 +485,7 @@
 	add_timer(&nte->timeout);
 	list_add(&nte->list, &nattype_list);
 	ct->nattype_entry = (unsigned long)nte;
-	nte->is_valid = 1;
+	nte->nattype_cookie = NATTYPE_COOKIE;
 	spin_unlock_bh(&nattype_lock);
 	nattype_nte_debug_print(nte, "ADD");
 	return XT_CONTINUE;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index d7eafd5..eb535cc 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -716,6 +716,9 @@
 	/* Don't set timer yet: wait for confirmation */
 	setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct);
 	write_pnet(&ct->ct_net, net);
+#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
+	ct->nattype_entry = 0;
+#endif
 #ifdef CONFIG_NF_CONNTRACK_ZONES
 	if (zone) {
 		struct nf_conntrack_zone *nf_ct_zone;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2356791..d85cf09 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -648,6 +648,9 @@
 	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
 	int err;
 
+	if (addr_len < sizeof(struct sockaddr_nl))
+		return -EINVAL;
+
 	if (nladdr->nl_family != AF_NETLINK)
 		return -EINVAL;
 
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 1260e1c..53cfb3e 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -58,7 +58,7 @@
 
 #define MAX_MSM8X10_WCD_DEVICE	4
 #define CODEC_DT_MAX_PROP_SIZE	40
-#define MSM8X10_WCD_I2C_GSBI_SLAVE_ID "5-000d"
+#define MAX_ON_DEMAND_SUPPLY_NAME_LENGTH 64
 
 enum {
 	MSM8X10_WCD_I2C_TOP_LEVEL = 0,
@@ -117,6 +117,12 @@
 	MSM8X10_WCD_BANDGAP_MBHC_MODE,
 };
 
+enum {
+	ON_DEMAND_MICBIAS = 0,
+	ON_DEMAND_CP,
+	ON_DEMAND_SUPPLIES_MAX,
+};
+
 struct hpf_work {
 	struct msm8x10_wcd_priv *msm8x10_wcd;
 	u32 decimator;
@@ -126,6 +132,16 @@
 
 static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
 
+struct on_demand_supply {
+	struct regulator *supply;
+	atomic_t ref;
+};
+
+static char on_demand_supply_name[][MAX_ON_DEMAND_SUPPLY_NAME_LENGTH] = {
+	"cdc-vdd-mic-bias",
+	"cdc-vdda-cp",
+};
+
 struct msm8x10_wcd_priv {
 	struct snd_soc_codec *codec;
 	u32 adc_count;
@@ -136,6 +152,7 @@
 	bool clock_active;
 	bool config_mode_active;
 	bool mbhc_polling_active;
+	struct on_demand_supply on_demand_list[ON_DEMAND_SUPPLIES_MAX];
 	struct mutex codec_resource_lock;
 	/* resmgr module */
 	struct wcd9xxx_resmgr resmgr;
@@ -159,13 +176,9 @@
 	int mod_id;
 };
 
-static char *msm8x10_wcd_supplies[] = {
-	"cdc-vdda-cp", "cdc-vdda-h", "cdc-vdd-px", "cdc-vdd-1p2v",
-	"cdc-vdd-mic-bias",
-};
-
 static int msm8x10_wcd_dt_parse_vreg_info(struct device *dev,
-	struct msm8x10_wcd_regulator *vreg, const char *vreg_name);
+	struct msm8x10_wcd_regulator *vreg,
+	const char *vreg_name, bool ondemand);
 static int msm8x10_wcd_dt_parse_micbias_info(struct device *dev,
 	struct msm8x10_wcd_micbias_setting *micbias);
 static struct msm8x10_wcd_pdata *msm8x10_wcd_populate_dt_pdata(
@@ -449,7 +462,8 @@
 
 
 static int msm8x10_wcd_dt_parse_vreg_info(struct device *dev,
-	struct msm8x10_wcd_regulator *vreg, const char *vreg_name)
+	struct msm8x10_wcd_regulator *vreg, const char *vreg_name,
+	bool ondemand)
 {
 	int len, ret = 0;
 	const __be32 *prop;
@@ -471,6 +485,7 @@
 		prop_name, dev->of_node->full_name);
 
 	vreg->name = vreg_name;
+	vreg->ondemand = ondemand;
 
 	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
 		"qcom,%s-voltage", vreg_name);
@@ -479,7 +494,7 @@
 	if (!prop || (len != (2 * sizeof(__be32)))) {
 		dev_err(dev, "%s %s property\n",
 			prop ? "invalid format" : "no", prop_name);
-		return -ENODEV;
+		return -EINVAL;
 	} else {
 		vreg->min_uV = be32_to_cpup(&prop[0]);
 		vreg->max_uV = be32_to_cpup(&prop[1]);
@@ -492,12 +507,12 @@
 	if (ret) {
 		dev_err(dev, "Looking up %s property in node %s failed",
 			prop_name, dev->of_node->full_name);
-		return -ENODEV;
+		return -EFAULT;
 	}
 	vreg->optimum_uA = prop_val;
 
-	dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
-		 vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
+	dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n\n", vreg->name,
+		 vreg->min_uV, vreg->max_uV, vreg->optimum_uA, vreg->ondemand);
 	return 0;
 }
 
@@ -545,38 +560,72 @@
 						struct device *dev)
 {
 	struct msm8x10_wcd_pdata *pdata;
-	int ret = 0, i;
-	char **codec_supplies;
-	u32 num_of_supplies = 0;
+	int ret, static_cnt, ond_cnt, idx, i;
+	const char *name = NULL;
+	const char *static_prop_name = "qcom,cdc-static-supplies";
+	const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
 		dev_err(dev, "could not allocate memory for platform data\n");
 		return NULL;
 	}
-	if ((!strcmp(dev_name(dev), MSM8X10_WCD_I2C_GSBI_SLAVE_ID))) {
-		codec_supplies = msm8x10_wcd_supplies;
-		num_of_supplies = ARRAY_SIZE(msm8x10_wcd_supplies);
-	} else {
-		dev_err(dev, "%s unsupported device %s\n",
-			__func__, dev_name(dev));
+
+	static_cnt = of_property_count_strings(dev->of_node, static_prop_name);
+	if (IS_ERR_VALUE(static_cnt)) {
+		dev_err(dev, "%s: Failed to get static supplies %d\n", __func__,
+			static_cnt);
+		ret = -EINVAL;
 		goto err;
 	}
 
-	if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
+	/* On-demand supply list is an optional property */
+	ond_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
+	if (IS_ERR_VALUE(ond_cnt))
+		ond_cnt = 0;
+
+	BUG_ON(static_cnt <= 0 || ond_cnt < 0);
+	if ((static_cnt + ond_cnt) > ARRAY_SIZE(pdata->regulator)) {
 		dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
-			__func__, num_of_supplies,
-			ARRAY_SIZE(pdata->regulator));
-
+			__func__, static_cnt, ARRAY_SIZE(pdata->regulator));
+		ret = -EINVAL;
 		goto err;
 	}
 
-	for (i = 0; i < num_of_supplies; i++) {
-		ret = msm8x10_wcd_dt_parse_vreg_info(dev, &pdata->regulator[i],
-			codec_supplies[i]);
+	for (idx = 0; idx < static_cnt; idx++) {
+		ret = of_property_read_string_index(dev->of_node,
+						    static_prop_name, idx,
+						    &name);
+		if (ret) {
+			dev_err(dev, "%s: of read string %s idx %d error %d\n",
+				__func__, static_prop_name, idx, ret);
+			goto err;
+		}
+
+		dev_dbg(dev, "%s: Found static cdc supply %s\n", __func__,
+			name);
+		ret = msm8x10_wcd_dt_parse_vreg_info(dev,
+						&pdata->regulator[idx],
+						name, false);
 		if (ret)
 			goto err;
 	}
+
+	for (i = 0; i < ond_cnt; i++, idx++) {
+		ret = of_property_read_string_index(dev->of_node, ond_prop_name,
+						    i, &name);
+		if (ret)
+			goto err;
+
+		dev_dbg(dev, "%s: Found on-demand cdc supply %s\n", __func__,
+			name);
+		ret = msm8x10_wcd_dt_parse_vreg_info(dev,
+						&pdata->regulator[idx],
+						name, true);
+		if (ret)
+			goto err;
+	}
+
 	ret = msm8x10_wcd_dt_parse_micbias_info(dev, &pdata->micbias);
 	if (ret)
 		goto err;
@@ -588,12 +637,64 @@
 	return NULL;
 }
 
+static int msm8x10_wcd_codec_enable_on_demand_supply(
+		struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	int ret = 0;
+	struct snd_soc_codec *codec = w->codec;
+	struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
+	struct on_demand_supply *supply;
+
+	if (w->shift >= ON_DEMAND_SUPPLIES_MAX) {
+		ret = -EINVAL;
+		goto out;
+	}
+	dev_dbg(codec->dev, "%s: supply: %s event: %d ref: %d\n",
+		__func__, on_demand_supply_name[w->shift], event,
+		atomic_read(&msm8x10_wcd->on_demand_list[w->shift].ref));
+
+	supply = &msm8x10_wcd->on_demand_list[w->shift];
+	WARN_ONCE(!supply->supply, "%s isn't defined\n",
+		  on_demand_supply_name[w->shift]);
+	if (!supply->supply)
+		goto out;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (atomic_inc_return(&supply->ref) == 1)
+			ret = regulator_enable(supply->supply);
+		if (ret)
+			dev_err(codec->dev, "%s: Failed to enable %s\n",
+				__func__,
+				on_demand_supply_name[w->shift]);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (atomic_read(&supply->ref) == 0) {
+			dev_dbg(codec->dev, "%s: %s supply has been disabled.\n",
+				 __func__, on_demand_supply_name[w->shift]);
+			goto out;
+		}
+		if (atomic_dec_return(&supply->ref) == 0)
+			ret = regulator_disable(supply->supply);
+			if (ret)
+				dev_err(codec->dev, "%s: Failed to disable %s\n",
+					__func__,
+					on_demand_supply_name[w->shift]);
+		break;
+	default:
+		break;
+	}
+out:
+	return ret;
+}
+
 static int msm8x10_wcd_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
 		struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
-	dev_dbg(codec->dev, "%s: event = %d\n", __func__, event);
 
+	dev_dbg(codec->dev, "%s: event = %d\n", __func__, event);
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		/* Enable charge pump clock*/
@@ -625,6 +726,8 @@
 		snd_soc_update_bits(codec,
 				    MSM8X10_WCD_A_CP_STATIC, 0x08, 0x00);
 		break;
+	default:
+		break;
 	}
 	return 0;
 }
@@ -1728,6 +1831,7 @@
 	{"LINEOUT PA", NULL, "CP"},
 	{"LINEOUT PA", NULL, "LINEOUT DAC"},
 
+	{"CP", NULL, "CP_REGULATOR"},
 	{"CP", NULL, "RX_BIAS"},
 	{"SPK PA", NULL, "SPK DAC"},
 	{"SPK DAC", NULL, "RX3 CHAIN"},
@@ -1807,6 +1911,9 @@
 	{"MIC BIAS Internal1", NULL, "INT_LDO_H"},
 	{"MIC BIAS Internal2", NULL, "INT_LDO_H"},
 	{"MIC BIAS External", NULL, "INT_LDO_H"},
+	{"MIC BIAS Internal1", NULL, "MICBIAS_REGULATOR"},
+	{"MIC BIAS Internal2", NULL, "MICBIAS_REGULATOR"},
+	{"MIC BIAS External", NULL, "MICBIAS_REGULATOR"},
 };
 
 static int msm8x10_wcd_startup(struct snd_pcm_substream *substream,
@@ -2227,9 +2334,21 @@
 	SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
 		&rx2_mix2_inp1_mux),
 
+	SND_SOC_DAPM_SUPPLY("MICBIAS_REGULATOR", SND_SOC_NOPM,
+		ON_DEMAND_MICBIAS, 0,
+		msm8x10_wcd_codec_enable_on_demand_supply,
+		SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY("CP_REGULATOR", SND_SOC_NOPM,
+		ON_DEMAND_CP, 0,
+		msm8x10_wcd_codec_enable_on_demand_supply,
+		SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_SUPPLY("CP", MSM8X10_WCD_A_CP_EN, 0, 0,
-		msm8x10_wcd_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+		msm8x10_wcd_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
 
 	SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
 		msm8x10_wcd_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
@@ -2415,6 +2534,21 @@
 	return 0;
 }
 
+static struct regulator *wcd8x10_wcd_codec_find_regulator(
+				const struct msm8x10_wcd *msm8x10,
+				const char *name)
+{
+	int i;
+
+	for (i = 0; i < msm8x10->num_of_supplies; i++) {
+		if (msm8x10->supplies[i].supply &&
+		    !strncmp(msm8x10->supplies[i].supply, name, strlen(name)))
+			return msm8x10->supplies[i].consumer;
+	}
+
+	return NULL;
+}
+
 static int msm8x10_wcd_codec_probe(struct snd_soc_codec *codec)
 {
 	struct msm8x10_wcd_priv *msm8x10_wcd;
@@ -2440,20 +2574,33 @@
 	msm8x10_wcd_bringup(codec);
 	msm8x10_wcd_codec_init_reg(codec);
 	msm8x10_wcd_update_reg_defaults(codec);
-
+	msm8x10_wcd->on_demand_list[ON_DEMAND_CP].supply =
+				wcd8x10_wcd_codec_find_regulator(
+				codec->control_data,
+				on_demand_supply_name[ON_DEMAND_CP]);
+	atomic_set(&msm8x10_wcd->on_demand_list[ON_DEMAND_CP].ref, 0);
+	msm8x10_wcd->on_demand_list[ON_DEMAND_MICBIAS].supply =
+				wcd8x10_wcd_codec_find_regulator(
+				codec->control_data,
+				on_demand_supply_name[ON_DEMAND_MICBIAS]);
+	atomic_set(&msm8x10_wcd->on_demand_list[ON_DEMAND_MICBIAS].ref, 0);
 	msm8x10_wcd->mclk_enabled = false;
 	msm8x10_wcd->bandgap_type = MSM8X10_WCD_BANDGAP_OFF;
 	msm8x10_wcd->clock_active = false;
 	msm8x10_wcd->config_mode_active = false;
 	msm8x10_wcd->mbhc_polling_active = false;
 	mutex_init(&msm8x10_wcd->codec_resource_lock);
-	msm8x10_wcd->codec = codec;
 
 	return 0;
 }
 
 static int msm8x10_wcd_codec_remove(struct snd_soc_codec *codec)
 {
+	struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
+	msm8x10_wcd->on_demand_list[ON_DEMAND_CP].supply = NULL;
+	atomic_set(&msm8x10_wcd->on_demand_list[ON_DEMAND_CP].ref, 0);
+	msm8x10_wcd->on_demand_list[ON_DEMAND_MICBIAS].supply = NULL;
+	atomic_set(&msm8x10_wcd->on_demand_list[ON_DEMAND_MICBIAS].ref, 0);
 	return 0;
 }
 
@@ -2479,7 +2626,7 @@
 	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
-static int msm8x10_wcd_enable_supplies(struct msm8x10_wcd *msm8x10,
+static int msm8x10_wcd_init_supplies(struct msm8x10_wcd *msm8x10,
 				struct msm8x10_wcd_pdata *pdata)
 {
 	int ret;
@@ -2517,8 +2664,13 @@
 	}
 
 	for (i = 0; i < msm8x10->num_of_supplies; i++) {
+		if (regulator_count_voltages(msm8x10->supplies[i].consumer) <=
+			0)
+			continue;
+
 		ret = regulator_set_voltage(msm8x10->supplies[i].consumer,
-			pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
+			pdata->regulator[i].min_uV,
+			pdata->regulator[i].max_uV);
 		if (ret) {
 			dev_err(msm8x10->dev, "%s: Setting regulator voltage failed for regulator %s err = %d\n",
 				__func__, msm8x10->supplies[i].supply, ret);
@@ -2531,24 +2683,13 @@
 			dev_err(msm8x10->dev, "%s: Setting regulator optimum mode failed for regulator %s err = %d\n",
 				__func__, msm8x10->supplies[i].supply, ret);
 			goto err_get;
+		} else {
+			ret = 0;
 		}
 	}
 
-	ret = regulator_bulk_enable(msm8x10->num_of_supplies,
-				    msm8x10->supplies);
-	if (ret != 0) {
-		dev_err(msm8x10->dev, "Failed to enable supplies: err = %d\n",
-				ret);
-		goto err_configure;
-	}
 	return ret;
 
-err_configure:
-	for (i = 0; i < msm8x10->num_of_supplies; i++) {
-		regulator_set_voltage(msm8x10->supplies[i].consumer, 0,
-			pdata->regulator[i].max_uV);
-		regulator_set_optimum_mode(msm8x10->supplies[i].consumer, 0);
-	}
 err_get:
 	regulator_bulk_free(msm8x10->num_of_supplies, msm8x10->supplies);
 err_supplies:
@@ -2557,6 +2698,35 @@
 	return ret;
 }
 
+static int msm8x10_wcd_enable_static_supplies(struct msm8x10_wcd *msm8x10,
+					  struct msm8x10_wcd_pdata *pdata)
+{
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < msm8x10->num_of_supplies; i++) {
+		if (pdata->regulator[i].ondemand)
+			continue;
+		ret = regulator_enable(msm8x10->supplies[i].consumer);
+		if (ret) {
+			pr_err("%s: Failed to enable %s\n", __func__,
+			       msm8x10->supplies[i].supply);
+			break;
+		} else {
+			pr_debug("%s: Enabled regulator %s\n", __func__,
+				 msm8x10->supplies[i].supply);
+		}
+	}
+
+	while (ret && --i)
+		if (!pdata->regulator[i].ondemand)
+			regulator_disable(msm8x10->supplies[i].consumer);
+
+	return ret;
+}
+
+
+
 static void msm8x10_wcd_disable_supplies(struct msm8x10_wcd *msm8x10,
 				     struct msm8x10_wcd_pdata *pdata)
 {
@@ -2565,6 +2735,9 @@
 	regulator_bulk_disable(msm8x10->num_of_supplies,
 				    msm8x10->supplies);
 	for (i = 0; i < msm8x10->num_of_supplies; i++) {
+		if (regulator_count_voltages(msm8x10->supplies[i].consumer) <=
+			0)
+			continue;
 		regulator_set_voltage(msm8x10->supplies[i].consumer, 0,
 			pdata->regulator[i].max_uV);
 		regulator_set_optimum_mode(msm8x10->supplies[i].consumer, 0);
@@ -2677,12 +2850,21 @@
 	msm8x10->dev = &client->dev;
 	msm8x10->read_dev = msm8x10_wcd_reg_read;
 	msm8x10->write_dev = msm8x10_wcd_reg_write;
-	ret = msm8x10_wcd_enable_supplies(msm8x10, pdata);
+	ret = msm8x10_wcd_init_supplies(msm8x10, pdata);
 	if (ret) {
 		dev_err(&client->dev, "%s: Fail to enable Codec supplies\n",
 			__func__);
 		goto err_codec;
 	}
+
+	ret = msm8x10_wcd_enable_static_supplies(msm8x10, pdata);
+	if (ret) {
+		pr_err("%s: Fail to enable Codec pre-reset supplies\n",
+			   __func__);
+		goto err_codec;
+	}
+	usleep_range(5, 5);
+
 	ret = msm8x10_wcd_device_init(msm8x10);
 	if (ret) {
 		dev_err(&client->dev,
diff --git a/sound/soc/codecs/msm8x10-wcd.h b/sound/soc/codecs/msm8x10-wcd.h
index 08a2725..d8f6ace 100644
--- a/sound/soc/codecs/msm8x10-wcd.h
+++ b/sound/soc/codecs/msm8x10-wcd.h
@@ -147,6 +147,7 @@
 	int min_uV;
 	int max_uV;
 	int optimum_uA;
+	bool ondemand;
 	struct regulator *regulator;
 };
 
diff --git a/sound/soc/codecs/msm_stub.c b/sound/soc/codecs/msm_stub.c
index 0cbcaf3..bdf1eb4 100644
--- a/sound/soc/codecs/msm_stub.c
+++ b/sound/soc/codecs/msm_stub.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -36,7 +36,8 @@
 			.channels_min = 1,
 			.channels_max = 8,
 			.rates = SNDRV_PCM_RATE_8000_48000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				    SNDRV_PCM_FMTBIT_S24_LE),
 		},
 	},
 };
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index b31c7c9..7b896c2 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -4273,6 +4273,12 @@
 	 */
 	TAPAN_REG_VAL(TAPAN_A_MICB_2_MBHC, 0x41),
 
+	/*
+	 * Default register settings to support dynamic change of
+	 * vdd_buck between 1.8 volts and 2.15 volts.
+	 */
+	TAPAN_REG_VAL(TAPAN_A_BUCK_MODE_2, 0xAA),
+
 };
 
 static const struct tapan_reg_mask_val tapan_2_x_reg_reset_values[] = {
@@ -4589,6 +4595,30 @@
 	return 0;
 }
 
+static enum wcd9xxx_buck_volt tapan_codec_get_buck_mv(
+	struct snd_soc_codec *codec)
+{
+	int buck_volt = WCD9XXX_CDC_BUCK_UNSUPPORTED;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	struct wcd9xxx_pdata *pdata = tapan->resmgr.pdata;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+		if (!strncmp(pdata->regulator[i].name,
+					 WCD9XXX_SUPPLY_BUCK_NAME,
+					 sizeof(WCD9XXX_SUPPLY_BUCK_NAME))) {
+			if ((pdata->regulator[i].min_uV ==
+					WCD9XXX_CDC_BUCK_MV_1P8) ||
+				(pdata->regulator[i].min_uV ==
+					WCD9XXX_CDC_BUCK_MV_2P15))
+				buck_volt = pdata->regulator[i].min_uV;
+			break;
+		}
+	}
+	pr_debug("%s: S4 voltage requested is %d\n", __func__, buck_volt);
+	return buck_volt;
+}
+
 static int tapan_codec_probe(struct snd_soc_codec *codec)
 {
 	struct wcd9xxx *control;
@@ -4621,10 +4651,6 @@
 
 	snd_soc_codec_set_drvdata(codec, tapan);
 
-	/* TODO: Read buck voltage from DT property */
-	tapan->clsh_d.buck_mv = WCD9XXX_CDC_BUCK_MV_1P8;
-	wcd9xxx_clsh_init(&tapan->clsh_d, &tapan->resmgr);
-
 	/* codec resmgr module init */
 	wcd9xxx = codec->control_data;
 	pdata = dev_get_platdata(codec->dev->parent);
@@ -4635,6 +4661,16 @@
 		return ret;
 	}
 
+	tapan->clsh_d.buck_mv = tapan_codec_get_buck_mv(codec);
+	/*
+	 * If 1.8 volts is requested on the vdd_cp line, then
+	 * assume that S4 is in a dynamically switchable state
+	 * and can switch between 1.8 volts and 2.15 volts
+	 */
+	if (tapan->clsh_d.buck_mv == WCD9XXX_CDC_BUCK_MV_1P8)
+		tapan->clsh_d.is_dynamic_vdd_cp = true;
+	wcd9xxx_clsh_init(&tapan->clsh_d, &tapan->resmgr);
+
 	if (TAPAN_IS_1_0(control->version))
 		rco_clk_rate = TAPAN_MCLK_CLK_12P288MHZ;
 	else
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 516ac4f..4edcec6 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -1050,7 +1050,7 @@
 				    0x07, rate);
 		/* Set the static gain offset */
 		if (comp == COMPANDER_1
-			&& buck_mv == WCD9XXX_CDC_BUCK_MV_2P15) {
+			&& buck_mv == WCD9XXX_CDC_BUCK_MV_1P8) {
 			snd_soc_update_bits(codec,
 					TAIKO_A_CDC_COMP0_B4_CTL + (comp * 8),
 					0x80, 0x80);
@@ -6389,6 +6389,8 @@
 	}
 
 	taiko->clsh_d.buck_mv = taiko_codec_get_buck_mv(codec);
+	/* Taiko does not support dynamic switching of vdd_cp */
+	taiko->clsh_d.is_dynamic_vdd_cp = false;
 	wcd9xxx_clsh_init(&taiko->clsh_d, &taiko->resmgr);
 
 	if (TAIKO_IS_1_0(core->version))
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index 916ff1a..bfd66ea 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -221,20 +221,26 @@
 	usleep_range(BUCK_SETTLE_TIME_US, BUCK_SETTLE_TIME_US);
 }
 
-static void wcd9xxx_clsh_enable_post_pa(struct snd_soc_codec *codec)
+
+/* This will be called for all states except Lineout */
+static void wcd9xxx_clsh_enable_post_pa(struct snd_soc_codec *codec,
+	struct wcd9xxx_clsh_cdc_data *cdc_clsh_d)
 {
 	int i;
 	const struct wcd9xxx_reg_mask_val reg_set[] = {
 		{WCD9XXX_A_BUCK_MODE_5, 0x02, 0x00},
 		{WCD9XXX_A_NCP_STATIC, 0x20, 0x00},
 		{WCD9XXX_A_BUCK_MODE_3, 0x04, 0x04},
-		{WCD9XXX_A_BUCK_MODE_3, 0x08, 0x08},
 	};
 
 	for (i = 0; i < ARRAY_SIZE(reg_set); i++)
 		snd_soc_update_bits(codec, reg_set[i].reg,
 					reg_set[i].mask, reg_set[i].val);
 
+	if (!cdc_clsh_d->is_dynamic_vdd_cp)
+		snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_3,
+							0x08, 0x08);
+
 	dev_dbg(codec->dev, "%s: completed clsh mode settings after PA enable\n",
 		   __func__);
 
@@ -478,13 +484,17 @@
 			snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
 							0x20, 0x01);
 			wcd9xxx_enable_ncp(codec, true);
-			msleep(NCP_SETTLE_TIME_US);
+			/* NCP settle time recommended by codec specification */
+			usleep_range(NCP_SETTLE_TIME_US,
+				NCP_SETTLE_TIME_US + 10);
 
 		} else {
 			snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN,
 							0x40, 0x00);
 			wcd9xxx_enable_ncp(codec, true);
-			msleep(NCP_SETTLE_TIME_US);
+			/* NCP settle time recommended by codec specification */
+			usleep_range(NCP_SETTLE_TIME_US,
+				NCP_SETTLE_TIME_US + 10);
 			snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
 							0x01, 0x01);
 			snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
@@ -557,7 +567,7 @@
 
 
 		} else if (req_state != WCD9XXX_CLSH_STATE_LO) {
-			wcd9xxx_clsh_enable_post_pa(codec);
+			wcd9xxx_clsh_enable_post_pa(codec, cdc_clsh_d);
 		}
 
 		break;
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index 316742d..50381c9 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -52,6 +52,7 @@
 struct wcd9xxx_clsh_cdc_data {
 	u8 state;
 	int buck_mv;
+	bool is_dynamic_vdd_cp;
 	struct wcd9xxx_resmgr *resmgr;
 };
 
diff --git a/sound/soc/msm/apq8074.c b/sound/soc/msm/apq8074.c
index 9a2f83b..cb101bd 100644
--- a/sound/soc/msm/apq8074.c
+++ b/sound/soc/msm/apq8074.c
@@ -1922,7 +1922,7 @@
 	{
 		.name = LPASS_BE_AUXPCM_RX,
 		.stream_name = "AUX PCM Playback",
-		.cpu_dai_name = "msm-dai-q6.4106",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-rx",
@@ -1937,7 +1937,7 @@
 	{
 		.name = LPASS_BE_AUXPCM_TX,
 		.stream_name = "AUX PCM Capture",
-		.cpu_dai_name = "msm-dai-q6.4107",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-tx",
diff --git a/sound/soc/msm/mdm9625.c b/sound/soc/msm/mdm9625.c
index fd21c38..ad8d85a 100644
--- a/sound/soc/msm/mdm9625.c
+++ b/sound/soc/msm/mdm9625.c
@@ -928,7 +928,7 @@
 	{
 		.name = LPASS_BE_AUXPCM_RX,
 		.stream_name = "AUX PCM Playback",
-		.cpu_dai_name = "msm-dai-q6.4106",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-rx",
@@ -942,7 +942,7 @@
 	{
 		.name = LPASS_BE_AUXPCM_TX,
 		.stream_name = "AUX PCM Capture",
-		.cpu_dai_name = "msm-dai-q6.4107",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-tx",
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 1b51595..a0ed887 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -67,7 +67,8 @@
 			.aif_name = "MM_UL1",
 			.rates = (SNDRV_PCM_RATE_8000_48000|
 					SNDRV_PCM_RATE_KNOT),
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				    SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 4,
 			.rate_min =     8000,
@@ -713,6 +714,33 @@
 		.ops = &msm_fe_dai_ops,
 		.name = "VOICE2_STUB",
 	},
+	{
+		.playback = {
+			.stream_name = "Multimedia9 Playback",
+			.aif_name = "MM_DL9",
+			.rates = (SNDRV_PCM_RATE_8000_192000|
+				  SNDRV_PCM_RATE_KNOT),
+			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				    SNDRV_PCM_FMTBIT_S24_LE),
+			.channels_min = 1,
+			.channels_max = 8,
+			.rate_min =     8000,
+			.rate_max =	192000,
+		},
+		.capture = {
+			.stream_name = "Multimedia9 Capture",
+			.aif_name = "MM_UL9",
+			.rates = (SNDRV_PCM_RATE_8000_48000|
+				  SNDRV_PCM_RATE_KNOT),
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 8,
+			.rate_min =     8000,
+			.rate_max =	48000,
+		},
+		.ops = &msm_fe_Multimedia_dai_ops,
+		.name = "MultiMedia9",
+	},
 };
 
 static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 5dfd326..043a998 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -1025,6 +1025,21 @@
 		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
 	},
+	{
+		.name = "MSM8226 Media9",
+		.stream_name = "MultiMedia9",
+		.cpu_dai_name   = "MultiMedia9",
+		.platform_name  = "msm-pcm-dsp.0",
+		.dynamic = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* This dailink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA9,
+	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
@@ -1124,7 +1139,7 @@
 	{
 		.name = LPASS_BE_AUXPCM_RX,
 		.stream_name = "AUX PCM Playback",
-		.cpu_dai_name = "msm-dai-q6.4106",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-rx",
@@ -1139,7 +1154,7 @@
 	{
 		.name = LPASS_BE_AUXPCM_TX,
 		.stream_name = "AUX PCM Capture",
-		.cpu_dai_name = "msm-dai-q6.4107",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-tx",
@@ -1301,6 +1316,19 @@
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
 		.ignore_suspend = 1,
 	},
+	/* Incall Music 2 BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE2_PLAYBACK_TX,
+		.stream_name = "Voice2 Farend Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.32770",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
 };
 
 struct snd_soc_card snd_soc_card_msm8226 = {
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 0a86221..0b7e7f2 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -208,6 +208,7 @@
 static int msm_hdmi_rx_ch = 2;
 static int slim0_rx_sample_rate = SAMPLING_RATE_48KHZ;
 static int msm_proxy_rx_ch = 2;
+static int hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
 
 static struct mutex cdc_mclk_mutex;
 static struct clk *codec_clk;
@@ -481,13 +482,12 @@
 
 		pr_debug("%s Left and right speakers case spk = 0x%08x",
 				  __func__, spk);
-
+		msm8974_ext_spk_pamp &= ~spk;
 		if (!msm8974_ext_spk_pamp) {
 			if (ext_spk_amp_gpio >= 0 &&
 				msm8974_liquid_dock_dev != NULL &&
 				msm8974_liquid_dock_dev->dock_plug_det == 0)
 				msm8974_liquid_ext_spk_power_amp_enable(0);
-			msm8974_ext_spk_pamp = 0;
 		}
 
 	} else  {
@@ -721,6 +721,8 @@
 static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
 	"Five",	"Six", "Seven", "Eight"};
 
+static char const *hdmi_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
+					"KHZ_192"};
 static const char *const btsco_rate_text[] = {"8000", "16000"};
 static const struct soc_enum msm_btsco_enum[] = {
 	SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
@@ -941,6 +943,57 @@
 	return 1;
 }
 
+static int hdmi_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	int sample_rate_val = 0;
+
+	switch (hdmi_rx_sample_rate) {
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 2;
+		break;
+
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 1;
+		break;
+
+	case SAMPLING_RATE_48KHZ:
+	default:
+		sample_rate_val = 0;
+		break;
+	}
+
+	ucontrol->value.integer.value[0] = sample_rate_val;
+	pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
+				hdmi_rx_sample_rate);
+
+	return 0;
+}
+
+static int hdmi_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: ucontrol value = %ld\n", __func__,
+			ucontrol->value.integer.value[0]);
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 2:
+		hdmi_rx_sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 1:
+		hdmi_rx_sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
+	}
+
+	pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
+			hdmi_rx_sample_rate);
+
+	return 0;
+}
+
 static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					struct snd_pcm_hw_params *params)
 {
@@ -1056,7 +1109,7 @@
 				hdmi_rx_bit_format);
 	if (channels->max < 2)
 		channels->min = channels->max = 2;
-	rate->min = rate->max = 48000;
+	rate->min = rate->max = hdmi_rx_sample_rate;
 	channels->min = channels->max = msm_hdmi_rx_ch;
 
 	return 0;
@@ -1325,6 +1378,7 @@
 	SOC_ENUM_SINGLE_EXT(2, rx_bit_format_text),
 	SOC_ENUM_SINGLE_EXT(3, slim0_rx_sample_rate_text),
 	SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
+	SOC_ENUM_SINGLE_EXT(3, hdmi_rx_sample_rate_text),
 };
 
 static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -1348,6 +1402,8 @@
 			msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
 	SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
 		     msm_btsco_rate_get, msm_btsco_rate_put),
+	SOC_ENUM_EXT("HDMI_RX SampleRate", msm_snd_enum[7],
+			hdmi_rx_sample_rate_get, hdmi_rx_sample_rate_put),
 };
 
 static bool msm8974_swap_gnd_mic(struct snd_soc_codec *codec)
@@ -2230,7 +2286,7 @@
 	{
 		.name = LPASS_BE_AUXPCM_RX,
 		.stream_name = "AUX PCM Playback",
-		.cpu_dai_name = "msm-dai-q6.4106",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-rx",
@@ -2245,7 +2301,7 @@
 	{
 		.name = LPASS_BE_AUXPCM_TX,
 		.stream_name = "AUX PCM Capture",
-		.cpu_dai_name = "msm-dai-q6.4107",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-tx",
@@ -2259,7 +2315,7 @@
 	{
 		.name = LPASS_BE_SEC_AUXPCM_RX,
 		.stream_name = "Sec AUX PCM Playback",
-		.cpu_dai_name = "msm-dai-q6.4108",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.2",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-rx",
@@ -2274,7 +2330,7 @@
 	{
 		.name = LPASS_BE_SEC_AUXPCM_TX,
 		.stream_name = "Sec AUX PCM Capture",
-		.cpu_dai_name = "msm-dai-q6.4109",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.2",
 		.platform_name = "msm-pcm-routing",
 		.codec_name = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-tx",
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 60f4669..094c58b 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -2356,10 +2356,11 @@
 	}
 	if (common.ec_ref_ext == true) {
 		ret = voice_send_set_device_cmd_v2(v);
-		if (ret < 0)
+		if (ret < 0) {
 			pr_err("%s:  set device V2 failed rc =%x\n",
 			       __func__, ret);
 			goto fail;
+		}
 	}
 	/* send cvs cal */
 	ret = voice_send_cvs_map_memory_cmd(v);
@@ -3354,10 +3355,11 @@
 	if (v->voc_state == VOC_CHANGE) {
 		if (common.ec_ref_ext == true) {
 			ret = voice_send_set_device_cmd_v2(v);
-			if (ret < 0)
+			if (ret < 0) {
 				pr_err("%s: set device V2 failed\n"
 				       "rc =%x\n", __func__, ret);
 				goto fail;
+			}
 		} else {
 			ret = voice_send_set_device_cmd(v);
 			if (ret < 0) {
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 3b6a415..d6090cf 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -153,15 +153,18 @@
 	atomic_set(&acdb_data.valid_asm_custom_top, 1);
 }
 
-void get_adm_custom_topology(struct acdb_cal_block *cal_block)
+int get_adm_custom_topology(struct acdb_cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
+	/* Only return allow one access after memory registered */
 	if (atomic_read(&acdb_data.valid_adm_custom_top) == 0) {
 		cal_block->cal_size = 0;
 		goto done;
@@ -175,17 +178,19 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.adm_custom_topology.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_adm_custom_topology(struct cal_block *cal_block)
+int store_adm_custom_topology(struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -197,18 +202,21 @@
 		cal_block->cal_offset +
 		atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_asm_custom_topology(struct acdb_cal_block *cal_block)
+int get_asm_custom_topology(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
+	/* Only return allow one access after memory registered */
 	if (atomic_read(&acdb_data.valid_asm_custom_top) == 0) {
 		cal_block->cal_size = 0;
 		goto done;
@@ -222,17 +230,19 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.asm_custom_topology.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_asm_custom_topology(struct cal_block *cal_block)
+int store_asm_custom_topology(struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -244,24 +254,37 @@
 		cal_block->cal_offset +
 		atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_voice_cal_allocation(struct acdb_cal_block *cal_block)
+int get_voice_cal_allocation(struct acdb_cal_block *cal_block)
 {
+	int result = 0;
+	pr_debug("%s,\n", __func__);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
+		goto done;
+	}
+
 	cal_block->cal_size = ACDB_TOTAL_VOICE_ALLOCATION;
 	cal_block->cal_paddr =
 		atomic_read(&acdb_data.vocproc_cal.cal_paddr);
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.vocproc_cal.cal_kvaddr);
+done:
+	return result;
 }
 
-void get_aanc_cal(struct acdb_cal_block *cal_block)
+int get_aanc_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -272,18 +295,20 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.aanc_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_aanc_cal(struct cal_block *cal_block)
+int store_aanc_cal(struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 		 __func__, cal_block->cal_offset,
 		(long)atomic64_read(&acdb_data.mem_len));
-		 goto done;
+		result = -EINVAL;
+		goto done;
 	}
 
 	atomic_set(&acdb_data.aanc_cal.cal_size,
@@ -293,15 +318,17 @@
 	atomic_set(&acdb_data.aanc_cal.cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_lsm_cal(struct acdb_cal_block *cal_block)
+int get_lsm_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -312,17 +339,19 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.lsm_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_lsm_cal(struct cal_block *cal_block)
+int store_lsm_cal(struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -333,15 +362,17 @@
 	atomic_set(&acdb_data.lsm_cal.cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_anc_cal(struct acdb_cal_block *cal_block)
+int get_anc_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -352,17 +383,19 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.anc_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_anc_cal(struct cal_block *cal_block)
+int store_anc_cal(struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -373,22 +406,25 @@
 	atomic_set(&acdb_data.anc_cal.cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void store_afe_cal(int32_t path, struct cal_block *cal_block)
+int store_afe_cal(int32_t path, struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 	if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -399,20 +435,23 @@
 	atomic_set(&acdb_data.afe_cal[path].cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block)
+int get_afe_cal(int32_t path, struct acdb_cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 	if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -423,22 +462,25 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.afe_cal[path].cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_audproc_cal(int32_t path, struct cal_block *cal_block)
+int store_audproc_cal(int32_t path, struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -449,20 +491,23 @@
 	atomic_set(&acdb_data.audproc_cal[path].cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block)
+int get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -473,22 +518,25 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.audproc_cal[path].cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_audstrm_cal(int32_t path, struct cal_block *cal_block)
+int store_audstrm_cal(int32_t path, struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -499,20 +547,23 @@
 	atomic_set(&acdb_data.audstrm_cal[path].cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block)
+int get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -523,22 +574,25 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.audstrm_cal[path].cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_audvol_cal(int32_t path, struct cal_block *cal_block)
+int store_audvol_cal(int32_t path, struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -549,20 +603,23 @@
 	atomic_set(&acdb_data.audvol_cal[path].cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block)
+int get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES || path < 0) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -573,15 +630,19 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.audvol_cal[path].cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_voice_col_data(uint32_t vocproc_type, uint32_t cal_size,
+int store_voice_col_data(uint32_t vocproc_type, uint32_t cal_size,
 			  uint32_t *cal_block)
 {
+	int result = 0;
+	pr_debug("%s,\n", __func__);
+
 	if (cal_size > MAX_COL_SIZE) {
 		pr_err("%s: col size is to big %d\n", __func__,
 				cal_size);
+		result = -EINVAL;
 		goto done;
 	}
 	if (copy_from_user(acdb_data.col_data[vocproc_type],
@@ -589,19 +650,24 @@
 			cal_size)) {
 		pr_err("%s: fail to copy col size %d\n",
 			__func__, cal_size);
+		result = -EINVAL;
 		goto done;
 	}
 	atomic_set(&acdb_data.vocproc_col_cal[vocproc_type].cal_size,
 		cal_size);
 done:
-	return;
+	return result;
 }
 
-void get_voice_col_data(uint32_t vocproc_type,
+int get_voice_col_data(uint32_t vocproc_type,
 			struct acdb_cal_block *cal_block)
 {
+	int result = 0;
+	pr_debug("%s,\n", __func__);
+
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -612,12 +678,13 @@
 	cal_block->cal_kvaddr = atomic_read(&acdb_data.
 				vocproc_col_cal[vocproc_type].cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_vocproc_dev_cfg_cal(struct cal_block *cal_block)
+int store_vocproc_dev_cfg_cal(struct cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 
 	if (cal_block->cal_offset >
@@ -626,6 +693,7 @@
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
 		atomic_set(&acdb_data.vocproc_dev_cal.cal_size, 0);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -639,12 +707,19 @@
 			atomic64_read(&acdb_data.kvaddr));
 
 done:
-	return;
+	return result;
 }
 
-void get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block)
+int get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
+		goto done;
+	}
 
 	cal_block->cal_size =
 		atomic_read(&acdb_data.vocproc_dev_cal.cal_size);
@@ -652,13 +727,16 @@
 		atomic_read(&acdb_data.vocproc_dev_cal.cal_paddr);
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.vocproc_dev_cal.cal_kvaddr);
+done:
+	return result;
 }
 
 
 
-void store_vocproc_cal(struct cal_block *cal_block)
+int store_vocproc_cal(struct cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset >
 				atomic64_read(&acdb_data.mem_len)) {
@@ -666,6 +744,7 @@
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
 		atomic_set(&acdb_data.vocproc_cal.cal_size, 0);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -679,15 +758,17 @@
 		atomic64_read(&acdb_data.kvaddr));
 
 done:
-	return;
+	return result;
 }
 
-void get_vocproc_cal(struct acdb_cal_block *cal_block)
+int get_vocproc_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -698,12 +779,13 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.vocproc_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_vocstrm_cal(struct cal_block *cal_block)
+int store_vocstrm_cal(struct cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset >
 			atomic64_read(&acdb_data.mem_len)) {
@@ -711,6 +793,7 @@
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
 		atomic_set(&acdb_data.vocstrm_cal.cal_size, 0);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -724,15 +807,17 @@
 		atomic64_read(&acdb_data.kvaddr));
 
 done:
-	return;
+	return result;
 }
 
-void get_vocstrm_cal(struct acdb_cal_block *cal_block)
+int get_vocstrm_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -743,12 +828,13 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.vocstrm_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_vocvol_cal(struct cal_block *cal_block)
+int store_vocvol_cal(struct cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset >
 			atomic64_read(&acdb_data.mem_len)) {
@@ -756,6 +842,7 @@
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
 		atomic_set(&acdb_data.vocvol_cal.cal_size, 0);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -769,15 +856,17 @@
 		atomic64_read(&acdb_data.kvaddr));
 
 done:
-	return;
+	return result;
 }
 
-void get_vocvol_cal(struct acdb_cal_block *cal_block)
+int get_vocvol_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -788,47 +877,60 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.vocvol_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
 void store_sidetone_cal(struct sidetone_cal *cal_data)
 {
-	pr_debug("%s\n", __func__);
+	pr_debug("%s,\n", __func__);
 
 	atomic_set(&acdb_data.sidetone_cal.enable, cal_data->enable);
 	atomic_set(&acdb_data.sidetone_cal.gain, cal_data->gain);
 }
 
-
-void get_sidetone_cal(struct sidetone_cal *cal_data)
+int get_sidetone_cal(struct sidetone_cal *cal_data)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_data == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
 	cal_data->enable = atomic_read(&acdb_data.sidetone_cal.enable);
 	cal_data->gain = atomic_read(&acdb_data.sidetone_cal.gain);
 done:
-	return;
+	return result;
 }
-void get_spk_protection_cfg(struct msm_spk_prot_cfg *prot_cfg)
+
+int get_spk_protection_cfg(struct msm_spk_prot_cfg *prot_cfg)
 {
+	int result = 0;
+	pr_debug("%s,\n", __func__);
+
 	mutex_lock(&acdb_data.acdb_mutex);
 	if (prot_cfg) {
 		prot_cfg->mode = acdb_data.spk_prot_cfg.mode;
 		prot_cfg->r0 = acdb_data.spk_prot_cfg.r0;
 		prot_cfg->t0 = acdb_data.spk_prot_cfg.t0;
-	} else
+	} else {
 		pr_err("%s prot_cfg is NULL\n", __func__);
+		result = -EINVAL;
+	}
 	mutex_unlock(&acdb_data.acdb_mutex);
+
+	return result;
 }
-static void get_spk_protection_status(struct msm_spk_prot_status *status)
+
+static int get_spk_protection_status(struct msm_spk_prot_status *status)
 {
+	int					result = 0;
+	struct afe_spkr_prot_get_vi_calib	calib_resp;
+	pr_debug("%s,\n", __func__);
+
 	/*Call AFE function here to query the status*/
-	struct afe_spkr_prot_get_vi_calib calib_resp;
 	if (status) {
 		status->status = -EINVAL;
 		if (!afe_spk_prot_get_calib_data(&calib_resp)) {
@@ -839,8 +941,12 @@
 				status->r0 = calib_resp.res_cfg.r0_cali_q24;
 			}
 		 }
-	} else
+	} else {
 		pr_err("%s invalid params\n", __func__);
+		result =  -EINVAL;
+	}
+
+	return result;
 }
 
 static int acdb_open(struct inode *inode, struct file *f)
@@ -1054,13 +1160,16 @@
 
 	switch (cmd) {
 	case AUDIO_SET_VOCPROC_COL_CAL:
-		store_voice_col_data(VOCPROC_CAL, size, (uint32_t *)arg);
+		result = store_voice_col_data(VOCPROC_CAL,
+						size, (uint32_t *)arg);
 		goto done;
 	case AUDIO_SET_VOCSTRM_COL_CAL:
-		store_voice_col_data(VOCSTRM_CAL, size, (uint32_t *)arg);
+		result = store_voice_col_data(VOCSTRM_CAL,
+						size, (uint32_t *)arg);
 		goto done;
 	case AUDIO_SET_VOCVOL_COL_CAL:
-		store_voice_col_data(VOCVOL_CAL, size, (uint32_t *)arg);
+		result = store_voice_col_data(VOCVOL_CAL,
+						size, (uint32_t *)arg);
 		goto done;
 	}
 
@@ -1083,61 +1192,63 @@
 
 	switch (cmd) {
 	case AUDIO_SET_AUDPROC_TX_CAL:
-		store_audproc_cal(TX_CAL, (struct cal_block *)data);
+		result = store_audproc_cal(TX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AUDPROC_RX_CAL:
-		store_audproc_cal(RX_CAL, (struct cal_block *)data);
+		result = store_audproc_cal(RX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AUDPROC_TX_STREAM_CAL:
-		store_audstrm_cal(TX_CAL, (struct cal_block *)data);
+		result = store_audstrm_cal(TX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AUDPROC_RX_STREAM_CAL:
-		store_audstrm_cal(RX_CAL, (struct cal_block *)data);
+		result = store_audstrm_cal(RX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AUDPROC_TX_VOL_CAL:
-		store_audvol_cal(TX_CAL, (struct cal_block *)data);
+		result = store_audvol_cal(TX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AUDPROC_RX_VOL_CAL:
-		store_audvol_cal(RX_CAL, (struct cal_block *)data);
+		result = store_audvol_cal(RX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AFE_TX_CAL:
-		store_afe_cal(TX_CAL, (struct cal_block *)data);
+		result = store_afe_cal(TX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AFE_RX_CAL:
-		store_afe_cal(RX_CAL, (struct cal_block *)data);
+		result = store_afe_cal(RX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_VOCPROC_CAL:
-		store_vocproc_cal((struct cal_block *)data);
+		result = store_vocproc_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_VOCPROC_STREAM_CAL:
-		store_vocstrm_cal((struct cal_block *)data);
+		result = store_vocstrm_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_VOCPROC_VOL_CAL:
-		store_vocvol_cal((struct cal_block *)data);
+		result = store_vocvol_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_VOCPROC_DEV_CFG_CAL:
-		store_vocproc_dev_cfg_cal((struct cal_block *)data);
+		result = store_vocproc_dev_cfg_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_SIDETONE_CAL:
 		store_sidetone_cal((struct sidetone_cal *)data);
 		goto done;
 	case AUDIO_SET_ANC_CAL:
-		store_anc_cal((struct cal_block *)data);
+		result = store_anc_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_LSM_CAL:
-		store_lsm_cal((struct cal_block *)data);
+		result = store_lsm_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_ADM_CUSTOM_TOPOLOGY:
-		store_adm_custom_topology((struct cal_block *)data);
+		result = store_adm_custom_topology((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_ASM_CUSTOM_TOPOLOGY:
-		store_asm_custom_topology((struct cal_block *)data);
+		result = store_asm_custom_topology((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AANC_CAL:
-		store_aanc_cal((struct cal_block *)data);
+		result = store_aanc_cal((struct cal_block *)data);
 		goto done;
 	default:
 		pr_err("ACDB=> ACDB ioctl not found!\n");
+		result = -EFAULT;
+		goto done;
 	}
 
 done:
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.h b/sound/soc/msm/qdsp6v2/audio_acdb.h
index 3c644ed..1685894 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.h
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.h
@@ -48,23 +48,23 @@
 uint32_t get_adm_tx_topology(void);
 uint32_t get_asm_topology(void);
 void reset_custom_topology_flags(void);
-void get_adm_custom_topology(struct acdb_cal_block *cal_block);
-void get_asm_custom_topology(struct acdb_cal_block *cal_block);
-void get_voice_cal_allocation(struct acdb_cal_block *cal_block);
-void get_lsm_cal(struct acdb_cal_block *cal_block);
-void get_anc_cal(struct acdb_cal_block *cal_block);
-void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block);
-void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block);
-void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block);
-void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block);
-void get_voice_col_data(uint32_t vocproc_type,
+int get_adm_custom_topology(struct acdb_cal_block *cal_block);
+int get_asm_custom_topology(struct acdb_cal_block *cal_block);
+int get_voice_cal_allocation(struct acdb_cal_block *cal_block);
+int get_lsm_cal(struct acdb_cal_block *cal_block);
+int get_anc_cal(struct acdb_cal_block *cal_block);
+int get_afe_cal(int32_t path, struct acdb_cal_block *cal_block);
+int get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block);
+int get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block);
+int get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block);
+int get_voice_col_data(uint32_t vocproc_type,
 	struct acdb_cal_block *cal_block);
-void get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block);
-void get_vocproc_cal(struct acdb_cal_block *cal_block);
-void get_vocstrm_cal(struct acdb_cal_block *cal_block);
-void get_vocvol_cal(struct acdb_cal_block *cal_block);
-void get_sidetone_cal(struct sidetone_cal *cal_data);
-void get_spk_protection_cfg(struct msm_spk_prot_cfg *prot_cfg);
-void get_aanc_cal(struct acdb_cal_block *cal_block);
+int get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block);
+int get_vocproc_cal(struct acdb_cal_block *cal_block);
+int get_vocstrm_cal(struct acdb_cal_block *cal_block);
+int get_vocvol_cal(struct acdb_cal_block *cal_block);
+int get_sidetone_cal(struct sidetone_cal *cal_data);
+int get_spk_protection_cfg(struct msm_spk_prot_cfg *prot_cfg);
+int get_aanc_cal(struct acdb_cal_block *cal_block);
 
 #endif
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 4a20af1..687f10d 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -625,20 +625,26 @@
 {
 	int rc = 0;
 	int avg_vol = 0;
+	int lgain = (volume >> 16) & 0xFFFF;
+	int rgain = volume & 0xFFFF;
 	if (compressed_audio.prtd && compressed_audio.prtd->audio_client) {
-		if (compressed_audio.prtd->channel_mode > 2) {
-			avg_vol = (((volume >> 16) & 0xFFFF) +
-				   (volume & 0xFFFF)) / 2;
-			rc = q6asm_set_volume(
-				compressed_audio.prtd->audio_client, avg_vol);
-		} else {
+		pr_debug("%s: channels %d volume 0x%x\n", __func__,
+			compressed_audio.prtd->channel_mode, volume);
+		if ((compressed_audio.prtd->channel_mode <= 2) &&
+			(lgain != rgain)) {
+			pr_debug("%s: call q6asm_set_lrgain\n", __func__);
 			rc = q6asm_set_lrgain(
 				compressed_audio.prtd->audio_client,
-				(volume >> 16) & 0xFFFF, volume & 0xFFFF);
+				lgain, rgain);
+		} else {
+			avg_vol = (lgain + rgain)/2;
+			pr_debug("%s: call q6asm_set_volume\n", __func__);
+			rc = q6asm_set_volume(
+				compressed_audio.prtd->audio_client, avg_vol);
 		}
 		if (rc < 0) {
 			pr_err("%s: Send Volume command failed rc=%d\n",
-						__func__, rc);
+				__func__, rc);
 		}
 	}
 	compressed_audio.volume = volume;
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
index 16df886..0cf044c 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
@@ -264,11 +264,12 @@
 
 static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = {
 	.playback = {
-		.rates = SNDRV_PCM_RATE_48000,
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+		 SNDRV_PCM_RATE_192000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
 		.channels_min = 2,
 		.channels_max = 8,
-		.rate_max =     48000,
+		.rate_max =     192000,
 		.rate_min =	48000,
 	},
 	.ops = &msm_dai_q6_hdmi_ops,
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index b07e91e..1434970 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -28,6 +28,9 @@
 #include <sound/pcm_params.h>
 #include <mach/clk.h>
 
+#define MSM_DAI_PRI_AUXPCM_DT_DEV_ID 1
+#define MSM_DAI_SEC_AUXPCM_DT_DEV_ID 2
+
 static const struct afe_clk_cfg lpass_clk_cfg_default = {
 	AFE_API_VERSION_I2S_CONFIG,
 	Q6AFE_LPASS_OSR_CLK_2_P048_MHZ,
@@ -39,6 +42,10 @@
 };
 enum {
 	STATUS_PORT_STARTED, /* track if AFE port has started */
+	/* track AFE Tx port status for bi-directional transfers */
+	STATUS_TX_PORT,
+	/* track AFE Rx port status for bi-directional transfers */
+	STATUS_RX_PORT,
 	STATUS_MAX
 };
 
@@ -66,6 +73,16 @@
 	struct msm_dai_q6_mi2s_dai_config rx_dai;
 };
 
+struct msm_dai_q6_auxpcm_dai_data {
+	/* BITMAP to track Rx and Tx port usage count */
+	DECLARE_BITMAP(auxpcm_port_status, STATUS_MAX);
+	struct mutex rlock; /* auxpcm dev resource lock */
+	u16 rx_pid; /* AUXPCM RX AFE port ID */
+	u16 tx_pid; /* AUXPCM TX AFE port ID */
+	struct afe_clk_cfg clk_cfg; /* hold LPASS clock configuration */
+	struct msm_dai_q6_dai_data bdai_data; /* incoporate base DAI data */
+};
+
 /* MI2S format field for AFE_PORT_CMD_I2S_CONFIG command
  *  0: linear PCM
  *  1: non-linear PCM
@@ -83,27 +100,43 @@
 	SOC_ENUM_SINGLE_EXT(4, mi2s_format),
 };
 
-static DEFINE_MUTEX(aux_pcm_mutex);
-static int aux_pcm_count;
-
 static int msm_dai_q6_auxpcm_hw_params(
 				struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params,
 				struct snd_soc_dai *dai)
 {
-	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+	struct msm_dai_q6_auxpcm_dai_data *aux_dai_data =
+			dev_get_drvdata(dai->dev);
+	struct msm_dai_q6_dai_data *dai_data = &aux_dai_data->bdai_data;
 	struct msm_dai_auxpcm_pdata *auxpcm_pdata =
 			(struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
+	int rc = 0;
 
-	if (params_channels(params) != 1) {
-		dev_err(dai->dev, "AUX PCM supports only mono stream\n");
+	if (params_channels(params) != 1 || (params_rate(params) != 8000 &&
+	    params_rate(params) != 16000)) {
+		dev_err(dai->dev, "%s: invalid param chan %d rate %d\n",
+			__func__, params_channels(params), params_rate(params));
 		return -EINVAL;
 	}
+
+	mutex_lock(&aux_dai_data->rlock);
+
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+		/* AUXPCM DAI in use */
+		if (dai_data->rate != params_rate(params)) {
+			dev_err(dai->dev, "%s: rate mismatch of running DAI\n",
+			__func__);
+			rc = -EINVAL;
+		}
+		mutex_unlock(&aux_dai_data->rlock);
+		return rc;
+	}
+
 	dai_data->channels = params_channels(params);
 	dai_data->rate = params_rate(params);
 
-	switch (dai_data->rate) {
-	case 8000:
+	if (dai_data->rate == 8000) {
 		dai_data->port_config.pcm.pcm_cfg_minor_version =
 				AFE_API_VERSION_PCM_CONFIG;
 		dai_data->port_config.pcm.aux_mode = auxpcm_pdata->mode_8k.mode;
@@ -119,8 +152,7 @@
 		dai_data->port_config.pcm.bit_width = 16;
 		dai_data->port_config.pcm.slot_number_mapping[0] =
 					 auxpcm_pdata->mode_8k.slot;
-		break;
-	case 16000:
+	} else {
 		dai_data->port_config.pcm.pcm_cfg_minor_version =
 				AFE_API_VERSION_PCM_CONFIG;
 		dai_data->port_config.pcm.aux_mode =
@@ -138,12 +170,19 @@
 		dai_data->port_config.pcm.bit_width = 16;
 		dai_data->port_config.pcm.slot_number_mapping[0] =
 					auxpcm_pdata->mode_16k.slot;
-		break;
-	default:
-		dev_err(dai->dev, "AUX PCM supports only 8kHz and 16kHz sampling rate\n");
-		return -EINVAL;
 	}
-	return 0;
+
+	dev_dbg(dai->dev, "%s: aux_mode %x sync_src %x frame_setting %x\n",
+		__func__, dai_data->port_config.pcm.aux_mode,
+		dai_data->port_config.pcm.sync_src,
+		dai_data->port_config.pcm.frame_setting);
+	dev_dbg(dai->dev, "%s: qtype %x dout %x num_map %x\n",
+		__func__, dai_data->port_config.pcm.quantype,
+		dai_data->port_config.pcm.ctrl_data_out_enable,
+		dai_data->port_config.pcm.slot_number_mapping[0]);
+
+	mutex_unlock(&aux_dai_data->rlock);
+	return rc;
 }
 
 static void msm_dai_q6_auxpcm_shutdown(struct snd_pcm_substream *substream,
@@ -151,114 +190,115 @@
 {
 	int rc = 0;
 	struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
-	struct afe_clk_cfg lpass_pcm_oe_clk;
-	struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
-	unsigned int rx_port = 0;
-	unsigned int tx_port = 0;
+	struct msm_dai_q6_auxpcm_dai_data *aux_dai_data =
+		dev_get_drvdata(dai->dev);
 
-	mutex_lock(&aux_pcm_mutex);
+	mutex_lock(&aux_dai_data->rlock);
 
-	if (aux_pcm_count == 0) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just return\n",
+	if (!(test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	      test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status))) {
+		dev_dbg(dai->dev, "%s(): dai->id %d PCM ports already closed\n",
 				__func__, dai->id);
-		mutex_unlock(&aux_pcm_mutex);
-		return;
+		goto exit;
 	}
 
-	aux_pcm_count--;
-
-	if (aux_pcm_count > 0) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
-			__func__, dai->id, aux_pcm_count);
-		mutex_unlock(&aux_pcm_mutex);
-		return;
-	} else if (aux_pcm_count < 0) {
-		dev_err(dai->dev, "%s(): ERROR: dai->id %d aux_pcm_count = %d < 0\n",
-			__func__, dai->id, aux_pcm_count);
-		aux_pcm_count = 0;
-		mutex_unlock(&aux_pcm_mutex);
-		return;
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status))
+			clear_bit(STATUS_TX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+		else {
+			dev_dbg(dai->dev, "%s(): PCM_TX port already closed\n",
+				__func__);
+			goto exit;
+		}
+	} else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status))
+			clear_bit(STATUS_RX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+		else {
+			dev_dbg(dai->dev, "%s(): PCM_RX port already closed\n",
+				__func__);
+			goto exit;
+		}
+	}
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+		dev_dbg(dai->dev, "%s(): cannot shutdown PCM ports\n",
+			__func__);
+		goto exit;
 	}
 
-	pr_debug("%s: dai->id = %d aux_pcm_count = %d\n", __func__,
-			dai->id, aux_pcm_count);
+	dev_dbg(dai->dev, "%s: dai->id = %d closing PCM AFE ports\n",
+			__func__, dai->id);
 
-	auxpcm_pdata = (struct msm_dai_auxpcm_pdata *)dai->dev->platform_data;
-	lpass_pcm_src_clk = (struct afe_clk_cfg *)auxpcm_pdata->clk_cfg;
+	lpass_pcm_src_clk = (struct afe_clk_cfg *) &aux_dai_data->clk_cfg;
 
-	if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX
-			|| dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
-		rx_port = AFE_PORT_ID_PRIMARY_PCM_RX;
-		tx_port = AFE_PORT_ID_PRIMARY_PCM_TX;
-	} else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX
-			|| dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
-		rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
-		tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
-	}
-
-	rc = afe_close(rx_port); /* can block */
+	rc = afe_close(aux_dai_data->rx_pid); /* can block */
 	if (IS_ERR_VALUE(rc))
 		dev_err(dai->dev, "fail to close PCM_RX  AFE port\n");
 
-	rc = afe_close(tx_port);
+	rc = afe_close(aux_dai_data->tx_pid);
 	if (IS_ERR_VALUE(rc))
 		dev_err(dai->dev, "fail to close AUX PCM TX port\n");
 
 	lpass_pcm_src_clk->clk_val1 = 0;
-	afe_set_lpass_clock(tx_port, lpass_pcm_src_clk);
-	afe_set_lpass_clock(rx_port, lpass_pcm_src_clk);
+	afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
+	afe_set_lpass_clock(aux_dai_data->tx_pid, lpass_pcm_src_clk);
 
-	memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
-			 sizeof(struct afe_clk_cfg));
-	lpass_pcm_oe_clk.clk_val1 = 0;
-	afe_set_lpass_clock(rx_port, &lpass_pcm_oe_clk);
-
-	mutex_unlock(&aux_pcm_mutex);
+exit:
+	mutex_unlock(&aux_dai_data->rlock);
+	return;
 }
 
 static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
-	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+	struct msm_dai_q6_auxpcm_dai_data *aux_dai_data =
+		dev_get_drvdata(dai->dev);
+	struct msm_dai_q6_dai_data *dai_data = &aux_dai_data->bdai_data;
 	struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
 	int rc = 0;
 	unsigned long pcm_clk_rate;
-	struct afe_clk_cfg lpass_pcm_oe_clk;
 	struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
-	unsigned int rx_port = 0;
-	unsigned int tx_port = 0;
 
 	auxpcm_pdata = dai->dev->platform_data;
-	lpass_pcm_src_clk = (struct afe_clk_cfg *)auxpcm_pdata->clk_cfg;
+	lpass_pcm_src_clk = (struct afe_clk_cfg *) &aux_dai_data->clk_cfg;
 
-	mutex_lock(&aux_pcm_mutex);
+	mutex_lock(&aux_dai_data->rlock);
 
-	if (aux_pcm_count == 2) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just return.\n",
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (test_bit(STATUS_TX_PORT,
+				aux_dai_data->auxpcm_port_status)) {
+			dev_dbg(dai->dev, "%s(): PCM_TX port already ON\n",
+				__func__);
+			goto exit;
+		} else
+			set_bit(STATUS_TX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+	} else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (test_bit(STATUS_RX_PORT,
+				aux_dai_data->auxpcm_port_status)) {
+			dev_dbg(dai->dev, "%s(): PCM_RX port already ON\n",
+				__func__);
+			goto exit;
+		} else
+			set_bit(STATUS_RX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+	}
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) &&
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+		dev_dbg(dai->dev, "%s(): PCM ports already set\n", __func__);
+		goto exit;
+	}
+
+	dev_dbg(dai->dev, "%s: dai->id:%d  opening afe ports\n",
 			__func__, dai->id);
-		mutex_unlock(&aux_pcm_mutex);
-		return 0;
-	} else if (aux_pcm_count > 2) {
-		dev_err(dai->dev, "%s(): ERROR: dai->id %d aux_pcm_count = %d > 2\n",
-			__func__, dai->id, aux_pcm_count);
-		mutex_unlock(&aux_pcm_mutex);
-		return 0;
-	}
-
-	aux_pcm_count++;
-	if (aux_pcm_count == 2)  {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after increment\n",
-				__func__, dai->id, aux_pcm_count);
-		mutex_unlock(&aux_pcm_mutex);
-		return 0;
-	}
-
-	pr_debug("%s:dai->id:%d  aux_pcm_count = %d. opening afe\n",
-			__func__, dai->id, aux_pcm_count);
 
 	rc = afe_q6_interface_prepare();
-	if (IS_ERR_VALUE(rc))
+	if (IS_ERR_VALUE(rc)) {
 		dev_err(dai->dev, "fail to open AFE APR\n");
+		goto fail;
+	}
 
 	/*
 	 * For AUX PCM Interface the below sequence of clk
@@ -279,54 +319,42 @@
 	} else {
 		dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
 			dai_data->rate);
-		mutex_unlock(&aux_pcm_mutex);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto fail;
 	}
 
 	memcpy(lpass_pcm_src_clk, &lpass_clk_cfg_default,
 			sizeof(struct afe_clk_cfg));
 	lpass_pcm_src_clk->clk_val1 = pcm_clk_rate;
 
-	memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
-			sizeof(struct afe_clk_cfg));
-	lpass_pcm_oe_clk.clk_val1 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
-
-	if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX ||
-			dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
-		rx_port = AFE_PORT_ID_PRIMARY_PCM_RX;
-		tx_port = AFE_PORT_ID_PRIMARY_PCM_TX;
-	} else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX ||
-			dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
-		rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
-		tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
-	}
-
-	rc = afe_set_lpass_clock(rx_port, lpass_pcm_src_clk);
+	rc = afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
 	if (rc < 0) {
-		pr_err("%s:afe_set_lpass_clock on RX pcm_src_clk failed\n",
-							__func__);
+		dev_err(dai->dev,
+			"%s:afe_set_lpass_clock on RX pcm_src_clk failed\n",
+			__func__);
 		goto fail;
 	}
 
-	rc = afe_set_lpass_clock(tx_port, lpass_pcm_src_clk);
+	rc = afe_set_lpass_clock(aux_dai_data->tx_pid, lpass_pcm_src_clk);
 	if (rc < 0) {
-		pr_err("%s:afe_set_lpass_clock on TX pcm_src_clk failed\n",
-							__func__);
+		dev_err(dai->dev,
+			"%s:afe_set_lpass_clock on TX pcm_src_clk failed\n",
+			__func__);
 		goto fail;
 	}
 
-	rc = afe_set_lpass_clock(rx_port, &lpass_pcm_oe_clk);
-	if (rc < 0) {
-		pr_err("%s:afe_set_lpass_clock on pcm_oe_clk failed\n",
-							__func__);
-		goto fail;
-	}
-
-	afe_open(rx_port, &dai_data->port_config, dai_data->rate);
-	afe_open(tx_port, &dai_data->port_config, dai_data->rate);
+	afe_open(aux_dai_data->rx_pid, &dai_data->port_config, dai_data->rate);
+	afe_open(aux_dai_data->tx_pid, &dai_data->port_config, dai_data->rate);
+	goto exit;
 
 fail:
-	mutex_unlock(&aux_pcm_mutex);
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		clear_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status);
+	else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		clear_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status);
+
+exit:
+	mutex_unlock(&aux_dai_data->rlock);
 	return rc;
 }
 
@@ -335,8 +363,8 @@
 {
 	int rc = 0;
 
-	pr_debug("%s:port:%d  cmd:%d  aux_pcm_count= %d\n",
-		__func__, dai->id, cmd, aux_pcm_count);
+	pr_debug("%s:port:%d  cmd:%d\n",
+		__func__, dai->id, cmd);
 
 	switch (cmd) {
 
@@ -359,84 +387,33 @@
 
 }
 
-static int msm_dai_q6_dai_auxpcm_probe(struct snd_soc_dai *dai)
-{
-	struct msm_dai_q6_dai_data *dai_data;
-	int rc = 0;
-	struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
-
-	auxpcm_pdata = (struct msm_dai_auxpcm_pdata *)
-					dev_get_drvdata(dai->dev);
-	dai->dev->platform_data = auxpcm_pdata;
-	dai->id = dai->dev->id;
-
-
-	dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
-
-	if (!dai_data) {
-		dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
-		dai->id);
-		rc = -ENOMEM;
-	} else
-		dev_set_drvdata(dai->dev, dai_data);
-
-	pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
-	return rc;
-}
-
 static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
 {
-	struct msm_dai_q6_dai_data *dai_data;
+	struct msm_dai_q6_auxpcm_dai_data *aux_dai_data;
+	struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
 	int rc;
-	unsigned int rx_port = 0;
-	unsigned int tx_port = 0;
 
-	dai_data = dev_get_drvdata(dai->dev);
+	aux_dai_data = dev_get_drvdata(dai->dev);
 
-	mutex_lock(&aux_pcm_mutex);
+	dev_dbg(dai->dev, "%s(): dai->id %d closing afe\n",
+		__func__, dai->id);
 
-	if (aux_pcm_count == 0) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean up and return\n",
-					__func__, dai->id);
-		goto done;
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+		rc = afe_close(aux_dai_data->rx_pid); /* can block */
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to close AUXPCM RX AFE port\n");
+		rc = afe_close(aux_dai_data->tx_pid);
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to close AUXPCM TX AFE port\n");
+		clear_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status);
+		clear_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status);
 	}
 
-	aux_pcm_count--;
-
-	if (aux_pcm_count > 0) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
-			__func__, dai->id, aux_pcm_count);
-		goto done;
-	} else if (aux_pcm_count < 0) {
-		dev_err(dai->dev, "%s(): ERROR: dai->id %d aux_pcm_count = %d < 0\n",
-			__func__, dai->id, aux_pcm_count);
-		goto done;
-	}
-
-	dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d.closing afe\n",
-		__func__, dai->id, aux_pcm_count);
-
-	if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX ||
-			dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
-		rx_port = AFE_PORT_ID_PRIMARY_PCM_RX;
-		tx_port = AFE_PORT_ID_PRIMARY_PCM_TX;
-	} else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX ||
-			dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
-		rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
-		tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
-	}
-	rc = afe_close(rx_port); /* can block */
-	if (IS_ERR_VALUE(rc))
-		dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
-
-	rc = afe_close(tx_port);
-	if (IS_ERR_VALUE(rc))
-		dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
-done:
-	kfree(dai_data);
-	snd_soc_unregister_dai(dai->dev);
-
-	mutex_unlock(&aux_pcm_mutex);
+	lpass_pcm_src_clk = (struct afe_clk_cfg *) &aux_dai_data->clk_cfg;
+	lpass_pcm_src_clk->clk_val1 = 0;
+	afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
+	afe_set_lpass_clock(aux_dai_data->tx_pid, lpass_pcm_src_clk);
 
 	return 0;
 }
@@ -448,31 +425,24 @@
 	.shutdown	= msm_dai_q6_auxpcm_shutdown,
 };
 
-static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_rx_dai = {
+static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_dai = {
 	.playback = {
-		.rates = SNDRV_PCM_RATE_8000,
+		.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 		.channels_min = 1,
 		.channels_max = 1,
-		.rate_max = 8000,
+		.rate_max = 16000,
 		.rate_min = 8000,
 	},
-	.ops = &msm_dai_q6_auxpcm_ops,
-	.probe = msm_dai_q6_dai_auxpcm_probe,
-	.remove = msm_dai_q6_dai_auxpcm_remove,
-};
-
-static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_tx_dai = {
 	.capture = {
-		.rates = SNDRV_PCM_RATE_8000,
+		.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 		.channels_min = 1,
 		.channels_max = 1,
-		.rate_max = 8000,
+		.rate_max = 16000,
 		.rate_min = 8000,
 	},
 	.ops = &msm_dai_q6_auxpcm_ops,
-	.probe = msm_dai_q6_dai_auxpcm_probe,
 	.remove = msm_dai_q6_dai_auxpcm_remove,
 };
 
@@ -749,6 +719,7 @@
 		rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
 		break;
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 		rc = msm_dai_q6_psuedo_port_hw_params(params,
@@ -1090,72 +1061,38 @@
 
 static int __devinit msm_auxpcm_dev_probe(struct platform_device *pdev)
 {
-	int id;
-	void *plat_data;
-	int rc = 0;
-
-	if (pdev->dev.parent == NULL)
-		return -ENODEV;
-
-	plat_data = dev_get_drvdata(pdev->dev.parent);
-
-	rc = of_property_read_u32(pdev->dev.of_node,
-			"qcom,msm-auxpcm-dev-id", &id);
-	if (rc) {
-		dev_err(&pdev->dev, "%s: qcom,msm-auxpcm-dev-id missing in DT node\n",
-				__func__);
-		return rc;
-	}
-
-	pdev->id = id;
-	dev_set_name(&pdev->dev, "%s.%d", "msm-dai-q6", id);
-	dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
-
-	dev_set_drvdata(&pdev->dev, plat_data);
-	pdev->dev.id = id;
-
-	switch (id) {
-	case AFE_PORT_ID_PRIMARY_PCM_RX:
-	case AFE_PORT_ID_SECONDARY_PCM_RX:
-		rc = snd_soc_register_dai(&pdev->dev,
-					&msm_dai_q6_aux_pcm_rx_dai);
-		break;
-	case AFE_PORT_ID_PRIMARY_PCM_TX:
-	case AFE_PORT_ID_SECONDARY_PCM_TX:
-		rc = snd_soc_register_dai(&pdev->dev,
-					&msm_dai_q6_aux_pcm_tx_dai);
-		break;
-	default:
-		rc = -ENODEV;
-		break;
-	}
-
-	return rc;
-}
-
-static int __devinit msm_auxpcm_resource_probe(
-			struct platform_device *pdev)
-{
-	int rc = 0;
-	struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
-	struct afe_clk_cfg *clk_cfg = NULL;
+	struct msm_dai_q6_auxpcm_dai_data *dai_data;
+	struct msm_dai_auxpcm_pdata *auxpcm_pdata;
 	uint32_t val_array[RATE_MAX_NUM_OF_AUX_PCM_RATES];
+	const char *intf_name;
+	int rc = 0;
+
+	dai_data = kzalloc(sizeof(struct msm_dai_q6_auxpcm_dai_data),
+			   GFP_KERNEL);
+	if (!dai_data) {
+		dev_err(&pdev->dev,
+			"Failed to allocate memory for auxpcm DAI data\n");
+		return -ENOMEM;
+	}
 
 	auxpcm_pdata = kzalloc(sizeof(struct msm_dai_auxpcm_pdata),
 				GFP_KERNEL);
 
 	if (!auxpcm_pdata) {
 		dev_err(&pdev->dev, "Failed to allocate memory for platform data\n");
-		return -ENOMEM;
+		goto fail_pdata_nomem;
 	}
 
+	dev_dbg(&pdev->dev, "%s: dev %p, dai_data %p, auxpcm_pdata %p\n",
+		__func__, &pdev->dev, dai_data, auxpcm_pdata);
+
 	rc = of_property_read_u32_array(pdev->dev.of_node,
 			"qcom,msm-cpudai-auxpcm-mode",
 			val_array, RATE_MAX_NUM_OF_AUX_PCM_RATES);
 	if (rc) {
 		dev_err(&pdev->dev, "%s: qcom,msm-cpudai-auxpcm-mode missing in DT node\n",
 			__func__);
-		goto fail_free_plat;
+		goto fail_invalid_dt;
 	}
 	auxpcm_pdata->mode_8k.mode = (u16)val_array[RATE_8KHZ];
 	auxpcm_pdata->mode_16k.mode = (u16)val_array[RATE_16KHZ];
@@ -1166,7 +1103,7 @@
 	if (rc) {
 		dev_err(&pdev->dev, "%s: qcom,msm-cpudai-auxpcm-sync missing in DT node\n",
 			__func__);
-		goto fail_free_plat;
+		goto fail_invalid_dt;
 	}
 	auxpcm_pdata->mode_8k.sync = (u16)val_array[RATE_8KHZ];
 	auxpcm_pdata->mode_16k.sync = (u16)val_array[RATE_16KHZ];
@@ -1178,7 +1115,7 @@
 	if (rc) {
 		dev_err(&pdev->dev, "%s: qcom,msm-cpudai-auxpcm-frame missing in DT node\n",
 			__func__);
-		goto fail_free_plat;
+		goto fail_invalid_dt;
 	}
 	auxpcm_pdata->mode_8k.frame = (u16)val_array[RATE_8KHZ];
 	auxpcm_pdata->mode_16k.frame = (u16)val_array[RATE_16KHZ];
@@ -1189,7 +1126,7 @@
 	if (rc) {
 		dev_err(&pdev->dev, "%s: qcom,msm-cpudai-auxpcm-quant missing in DT node\n",
 			__func__);
-		goto fail_free_plat;
+		goto fail_invalid_dt;
 	}
 	auxpcm_pdata->mode_8k.quant = (u16)val_array[RATE_8KHZ];
 	auxpcm_pdata->mode_16k.quant = (u16)val_array[RATE_16KHZ];
@@ -1200,7 +1137,7 @@
 	if (rc) {
 		dev_err(&pdev->dev, "%s: qcom,msm-cpudai-auxpcm-slot missing in DT node\n",
 			__func__);
-		goto fail_free_plat;
+		goto fail_invalid_dt;
 	}
 	auxpcm_pdata->mode_8k.slot = (u16)val_array[RATE_8KHZ];
 	auxpcm_pdata->mode_16k.slot = (u16)val_array[RATE_16KHZ];
@@ -1211,7 +1148,7 @@
 	if (rc) {
 		dev_err(&pdev->dev, "%s: qcom,msm-cpudai-auxpcm-data missing in DT node\n",
 			__func__);
-		goto fail_free_plat;
+		goto fail_invalid_dt;
 	}
 	auxpcm_pdata->mode_8k.data = (u16)val_array[RATE_8KHZ];
 	auxpcm_pdata->mode_16k.data = (u16)val_array[RATE_16KHZ];
@@ -1219,60 +1156,79 @@
 	rc = of_property_read_u32_array(pdev->dev.of_node,
 			"qcom,msm-cpudai-auxpcm-pcm-clk-rate",
 			val_array, RATE_MAX_NUM_OF_AUX_PCM_RATES);
-
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: qcom,msm-cpudai-auxpcm-pcm-clk-rate missing in DT\n",
+			__func__);
+		goto fail_invalid_dt;
+	}
 	auxpcm_pdata->mode_8k.pcm_clk_rate = (int)val_array[RATE_8KHZ];
 	auxpcm_pdata->mode_16k.pcm_clk_rate = (int)val_array[RATE_16KHZ];
 
-	clk_cfg = kzalloc(sizeof(struct afe_clk_cfg), GFP_KERNEL);
-	if (clk_cfg == NULL) {
-		pr_err("%s: Failed to allocate memory for clk cfg\n", __func__);
-		goto fail_free_plat;
-	}
-	auxpcm_pdata->clk_cfg = clk_cfg;
-
-	platform_set_drvdata(pdev, auxpcm_pdata);
-
-	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	rc = of_property_read_string(pdev->dev.of_node,
+			"qcom,msm-auxpcm-interface", &intf_name);
 	if (rc) {
-		dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n",
+		dev_err(&pdev->dev,
+			"%s: qcom,msm-auxpcm-interface missing in DT node\n",
+			__func__);
+		goto fail_nodev_intf;
+	}
+
+	if (!strncmp(intf_name, "primary", sizeof("primary"))) {
+		dai_data->rx_pid = AFE_PORT_ID_PRIMARY_PCM_RX;
+		dai_data->tx_pid = AFE_PORT_ID_PRIMARY_PCM_TX;
+		pdev->id = MSM_DAI_PRI_AUXPCM_DT_DEV_ID;
+	} else if (!strncmp(intf_name, "secondary", sizeof("secondary"))) {
+		dai_data->rx_pid = AFE_PORT_ID_SECONDARY_PCM_RX;
+		dai_data->tx_pid = AFE_PORT_ID_SECONDARY_PCM_TX;
+		pdev->id = MSM_DAI_SEC_AUXPCM_DT_DEV_ID;
+	} else {
+		dev_err(&pdev->dev, "%s: invalid DT intf name %s\n",
+			__func__, intf_name);
+		goto fail_invalid_intf;
+	}
+
+	mutex_init(&dai_data->rlock);
+	dev_set_name(&pdev->dev, "%s.%d", "msm-dai-q6-auxpcm", pdev->id);
+	dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
+
+	dev_set_drvdata(&pdev->dev, dai_data);
+	pdev->dev.platform_data = (void *) auxpcm_pdata;
+
+	rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_aux_pcm_dai);
+	if (rc) {
+		dev_err(&pdev->dev, "%s: auxpcm dai reg failed, rc=%d\n",
 				__func__, rc);
-		goto fail_free_plat1;
+		goto fail_reg_dai;
 	}
 
 	return rc;
 
-fail_free_plat1:
-	kfree(clk_cfg);
-fail_free_plat:
+fail_reg_dai:
+fail_invalid_intf:
+fail_nodev_intf:
+fail_invalid_dt:
 	kfree(auxpcm_pdata);
+fail_pdata_nomem:
+	kfree(dai_data);
 	return rc;
 }
 
 static int __devexit msm_auxpcm_dev_remove(struct platform_device *pdev)
 {
+	struct msm_dai_q6_auxpcm_dai_data *dai_data;
+
+	dai_data = dev_get_drvdata(&pdev->dev);
+
 	snd_soc_unregister_dai(&pdev->dev);
-	return 0;
-}
 
-static int __devexit msm_auxpcm_resource_remove(
-				struct platform_device *pdev)
-{
-	struct msm_dai_auxpcm_pdata *auxpcm_pdata;
-	struct afe_clk_cfg *clk_cfg;
-
-	auxpcm_pdata = dev_get_drvdata(&pdev->dev);
-	clk_cfg = (struct afe_clk_cfg *)auxpcm_pdata->clk_cfg;
-	kfree(clk_cfg);
-	kfree(auxpcm_pdata);
+	mutex_destroy(&dai_data->rlock);
+	kfree(dai_data);
+	kfree(pdev->dev.platform_data);
 
 	return 0;
 }
 
-static struct of_device_id msm_auxpcm_resource_dt_match[] = {
-	{ .compatible = "qcom,msm-auxpcm-resource", },
-	{}
-};
-
 static struct of_device_id msm_auxpcm_dev_dt_match[] = {
 	{ .compatible = "qcom,msm-auxpcm-dev", },
 	{}
@@ -1289,16 +1245,6 @@
 	},
 };
 
-static struct platform_driver msm_auxpcm_resource_driver = {
-	.probe  = msm_auxpcm_resource_probe,
-	.remove  = __devexit_p(msm_auxpcm_resource_remove),
-	.driver = {
-		.name = "msm-auxpcm-resource",
-		.owner = THIS_MODULE,
-		.of_match_table = msm_auxpcm_resource_dt_match,
-	},
-};
-
 static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
 	.playback = {
 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
@@ -1638,8 +1584,21 @@
 		goto error_invalid_data;
 	}
 	dai_data->rate = params_rate(params);
-	dai_data->port_config.i2s.bit_width = 16;
-	dai_data->bitwidth = 16;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+	case SNDRV_PCM_FORMAT_SPECIAL:
+		dai_data->port_config.i2s.bit_width = 16;
+		dai_data->bitwidth = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		dai_data->port_config.i2s.bit_width = 24;
+		dai_data->bitwidth = 24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
 	dai_data->port_config.i2s.i2s_cfg_minor_version =
 			AFE_API_VERSION_I2S_CONFIG;
 	dai_data->port_config.i2s.sample_rate = dai_data->rate;
@@ -1759,7 +1718,7 @@
 	.capture = {
 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
 		SNDRV_PCM_RATE_16000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
 		.rate_min =     8000,
 		.rate_max =     48000,
 	},
@@ -2080,6 +2039,7 @@
 		rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
 		break;
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 		rc = snd_soc_register_dai(&pdev->dev,
 					&msm_dai_q6_voice_playback_tx_dai);
 		break;
@@ -2210,14 +2170,9 @@
 	int rc;
 
 	rc = platform_driver_register(&msm_auxpcm_dev_driver);
-	if (rc)
-		goto fail;
-
-	rc = platform_driver_register(&msm_auxpcm_resource_driver);
-
 	if (rc) {
-		pr_err("%s: fail to register cpu dai driver\n", __func__);
-		goto aux_pcm_resource_fail;
+		pr_err("%s: fail to register auxpcm dev driver", __func__);
+		goto fail;
 	}
 
 	rc = platform_driver_register(&msm_dai_q6);
@@ -2252,8 +2207,6 @@
 dai_q6_dev_fail:
 	platform_driver_unregister(&msm_dai_q6);
 dai_q6_fail:
-	platform_driver_unregister(&msm_auxpcm_resource_driver);
-aux_pcm_resource_fail:
 	platform_driver_unregister(&msm_auxpcm_dev_driver);
 fail:
 	return rc;
@@ -2265,7 +2218,6 @@
 	platform_driver_unregister(&msm_dai_q6_dev);
 	platform_driver_unregister(&msm_dai_q6);
 	platform_driver_unregister(&msm_auxpcm_dev_driver);
-	platform_driver_unregister(&msm_auxpcm_resource_driver);
 }
 module_exit(msm_dai_q6_exit);
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 77f3a07..49bc488 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -42,12 +42,6 @@
 	struct snd_pcm *pcm;
 };
 
-struct snd_msm_volume {
-	struct msm_audio *prtd;
-	unsigned volume;
-};
-static struct snd_msm_volume pcm_audio = {NULL, 0x2000};
-
 #define PLAYBACK_MIN_NUM_PERIODS    2
 #define PLAYBACK_MAX_NUM_PERIODS    8
 #define PLAYBACK_MAX_PERIOD_SIZE    12288
@@ -63,7 +57,8 @@
 				SNDRV_PCM_INFO_MMAP_VALID |
 				SNDRV_PCM_INFO_INTERLEAVED |
 				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
-	.formats =              SNDRV_PCM_FMTBIT_S16_LE,
+	.formats =              (SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S24_LE),
 	.rates =                SNDRV_PCM_RATE_8000_48000,
 	.rate_min =             8000,
 	.rate_max =             48000,
@@ -260,6 +255,8 @@
 	struct msm_audio *prtd = runtime->private_data;
 	int ret = 0;
 	int i = 0;
+	uint16_t bits_per_sample = 16;
+
 	pr_debug("%s\n", __func__);
 	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
 	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
@@ -272,10 +269,19 @@
 	if (prtd->enabled)
 		return 0;
 
+	switch (runtime->format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		bits_per_sample = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		bits_per_sample = 24;
+		break;
+	}
 	pr_debug("Samp_rate = %d\n", prtd->samp_rate);
 	pr_debug("Channel = %d\n", prtd->channel_mode);
-	ret = q6asm_enc_cfg_blk_pcm(prtd->audio_client, prtd->samp_rate,
-					prtd->channel_mode);
+	ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client,
+					prtd->samp_rate, prtd->channel_mode,
+					bits_per_sample);
 	if (ret < 0)
 		pr_debug("%s: cmd cfg pcm was block failed", __func__);
 
@@ -390,7 +396,6 @@
 	prtd->dsp_cnt = 0;
 	prtd->set_channel_map = false;
 	runtime->private_data = prtd;
-	pcm_audio.prtd = prtd;
 
 	return 0;
 }
@@ -479,7 +484,6 @@
 		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 		q6asm_audio_client_buf_free_contiguous(dir,
 					prtd->audio_client);
-		pcm_audio.prtd = NULL;
 		q6asm_audio_client_free(prtd->audio_client);
 	}
 	msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
@@ -702,10 +706,13 @@
 
 	/* Capture Path */
 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE)
+			bits_per_sample = 24;
 
 		pr_debug("%s Opening %d-ch PCM read stream\n",
 			__func__, params_channels(params));
-		ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
+		ret = q6asm_open_read_v2(prtd->audio_client, FORMAT_LINEAR_PCM,
+				bits_per_sample);
 		if (ret < 0) {
 			pr_err("%s: q6asm_open_read failed\n", __func__);
 			q6asm_audio_client_free(prtd->audio_client);
@@ -760,30 +767,71 @@
 	.mmap		= msm_pcm_mmap,
 };
 
-static int pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
+static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
 	int i;
-	char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
+	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	struct snd_pcm_substream *substream;
+	struct msm_audio *prtd;
 
 	pr_debug("%s", __func__);
-	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
-		channel_mapping[i] = (char)(ucontrol->value.integer.value[i]);
-	if (pcm_audio.prtd) {
-		pcm_audio.prtd->set_channel_map = true;
-		memcpy(pcm_audio.prtd->channel_map, channel_mapping,
-			PCM_FORMAT_MAX_NUM_CHANNEL);
+	substream = snd_pcm_chmap_substream(info, idx);
+	if (!substream)
+		return -ENODEV;
+	if (!substream->runtime)
+		return 0;
+
+	prtd = substream->runtime->private_data;
+	if (prtd) {
+		prtd->set_channel_map = true;
+			for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+				prtd->channel_map[i] =
+				(char)(ucontrol->value.integer.value[i]);
 	}
 	return 0;
 }
 
+static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int i;
+	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	struct snd_pcm_substream *substream;
+	struct msm_audio *prtd;
+
+	pr_debug("%s", __func__);
+	substream = snd_pcm_chmap_substream(info, idx);
+	if (!substream)
+		return -ENODEV;
+	memset(ucontrol->value.integer.value, 0,
+		sizeof(ucontrol->value.integer.value));
+	if (!substream->runtime)
+		return 0; /* no channels set */
+
+	prtd = substream->runtime->private_data;
+
+	if (prtd && prtd->set_channel_map == true) {
+		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+			ucontrol->value.integer.value[i] =
+					(int)prtd->channel_map[i];
+	} else {
+		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+			ucontrol->value.integer.value[i] = 0;
+	}
+
+	return 0;
+}
+
 static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_card *card = rtd->card->snd_card;
-	struct snd_pcm *pcm = rtd->pcm->streams[0].pcm;
+	struct snd_pcm *pcm = rtd->pcm;
 	struct snd_pcm_chmap *chmap_info;
 	struct snd_kcontrol *kctl;
-	char device_num[3];
+	char device_num[12];
 	int i, ret = 0;
 
 	if (!card->dev->coherent_dma_mask)
@@ -791,8 +839,9 @@
 
 	pr_debug("%s, Channel map cntrl add\n", __func__);
 	ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-					NULL, PCM_FORMAT_MAX_NUM_CHANNEL, 0,
-					&chmap_info);
+				     snd_pcm_std_chmaps,
+				     PCM_FORMAT_MAX_NUM_CHANNEL, 0,
+				     &chmap_info);
 	if (ret < 0)
 		return ret;
 	kctl = chmap_info->kctl;
@@ -802,7 +851,8 @@
 	strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
 	pr_debug("%s, Overwriting channel map control name to: %s",
 		__func__, kctl->id.name);
-	kctl->put = pcm_chmap_ctl_put;
+	kctl->put = msm_pcm_chmap_ctl_put;
+	kctl->get = msm_pcm_chmap_ctl_get;
 	return ret;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 97803b3..c1bc17b 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -40,7 +40,10 @@
 	u16 port_id; /* AFE port ID */
 	u8 active; /* track if this backend is enabled */
 	unsigned long fe_sessions; /* Front-end sessions */
-	unsigned long port_sessions; /* track Tx BE ports -> Rx BE */
+	u64 port_sessions; /* track Tx BE ports -> Rx BE
+			    * number of BE should not exceed
+			    * the size of this field
+			    */
 	unsigned int  sample_rate;
 	unsigned int  channel;
 	unsigned int  format;
@@ -217,6 +220,7 @@
 	{ AFE_PORT_ID_PRIMARY_PCM_RX, 0, 0, 0, 0, 0},
 	{ AFE_PORT_ID_PRIMARY_PCM_TX, 0, 0, 0, 0, 0},
 	{ VOICE_PLAYBACK_TX, 0, 0, 0, 0, 0},
+	{ VOICE2_PLAYBACK_TX, 0, 0, 0, 0, 0},
 	{ VOICE_RECORD_RX, 0, 0, 0, 0, 0},
 	{ VOICE_RECORD_TX, 0, 0, 0, 0, 0},
 	{ MI2S_RX, 0, 0, 0, 0, 0},
@@ -264,6 +268,8 @@
 	{INVALID_SESSION, INVALID_SESSION},
 	/* MULTIMEDIA8 */
 	{INVALID_SESSION, INVALID_SESSION},
+	/* MULTIMEDIA9 */
+	{INVALID_SESSION, INVALID_SESSION},
 };
 
 static uint8_t is_be_dai_extproc(int be_dai)
@@ -511,8 +517,9 @@
 	topology = get_topology(path_type);
 	if (set) {
 		if (!test_bit(val, &msm_bedais[reg].fe_sessions) &&
-			(msm_bedais[reg].port_id == VOICE_PLAYBACK_TX))
-			voc_start_playback(set);
+			((msm_bedais[reg].port_id == VOICE_PLAYBACK_TX) ||
+			(msm_bedais[reg].port_id == VOICE2_PLAYBACK_TX)))
+			voc_start_playback(set, msm_bedais[reg].port_id);
 		set_bit(val, &msm_bedais[reg].fe_sessions);
 		if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
 			INVALID_SESSION) {
@@ -555,8 +562,9 @@
 		}
 	} else {
 		if (test_bit(val, &msm_bedais[reg].fe_sessions) &&
-			(msm_bedais[reg].port_id == VOICE_PLAYBACK_TX))
-			voc_start_playback(set);
+			((msm_bedais[reg].port_id == VOICE_PLAYBACK_TX) ||
+			(msm_bedais[reg].port_id == VOICE2_PLAYBACK_TX)))
+			voc_start_playback(set, msm_bedais[reg].port_id);
 		clear_bit(val, &msm_bedais[reg].fe_sessions);
 		if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
 			INVALID_SESSION) {
@@ -970,7 +978,8 @@
 	struct soc_mixer_control *mc =
 	(struct soc_mixer_control *)kcontrol->private_value;
 
-	if (test_bit(mc->shift, &msm_bedais[mc->reg].port_sessions))
+	if (test_bit(mc->shift,
+		(unsigned long *)&msm_bedais[mc->reg].port_sessions))
 		ucontrol->value.integer.value[0] = 1;
 	else
 		ucontrol->value.integer.value[0] = 0;
@@ -987,19 +996,19 @@
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 
-	pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg,
+	pr_debug("%s: reg 0x%x shift 0x%x val %ld\n", __func__, mc->reg,
 		mc->shift, ucontrol->value.integer.value[0]);
 
 	if (ucontrol->value.integer.value[0]) {
 		afe_loopback(1, msm_bedais[mc->reg].port_id,
 			    msm_bedais[mc->shift].port_id);
 		set_bit(mc->shift,
-		&msm_bedais[mc->reg].port_sessions);
+		(unsigned long *)&msm_bedais[mc->reg].port_sessions);
 	} else {
 		afe_loopback(0, msm_bedais[mc->reg].port_id,
 			    msm_bedais[mc->shift].port_id);
 		clear_bit(mc->shift,
-		&msm_bedais[mc->reg].port_sessions);
+		(unsigned long *)&msm_bedais[mc->reg].port_sessions);
 	}
 
 	return 1;
@@ -1418,6 +1427,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = {
@@ -1445,6 +1457,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
@@ -1472,6 +1487,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = {
@@ -1499,6 +1517,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new quaternary_mi2s_rx_mixer_controls[] = {
@@ -1526,6 +1547,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new tertiary_mi2s_rx_mixer_controls[] = {
@@ -1568,6 +1592,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mi2s_hl_mixer_controls[] = {
@@ -1604,6 +1631,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_PRI_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
@@ -1631,6 +1661,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 	/* incall music delivery mixer */
 static const struct snd_kcontrol_new incall_music_delivery_mixer_controls[] = {
@@ -1640,6 +1673,21 @@
 	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
+static const struct snd_kcontrol_new incall_music2_delivery_mixer_controls[] = {
+	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_4_rx_mixer_controls[] = {
@@ -1676,6 +1724,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_INT_BT_SCO_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
@@ -1703,6 +1754,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_INT_FM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_INT_FM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
@@ -1730,6 +1784,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
@@ -1757,6 +1814,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
@@ -1784,6 +1844,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
@@ -2141,6 +2204,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_TX_Voice2", MSM_BACKEND_DAI_AUXPCM_TX,
 	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("PRI_MI2S_TX_Voice2", MSM_BACKEND_DAI_PRI_MI2S_TX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new tx_volte_mixer_controls[] = {
@@ -2763,11 +2829,13 @@
 	SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL9", "MultiMedia9 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL9", "MultiMedia9 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VOICE2_DL", "Voice2 Playback", 0, 0, 0, 0),
@@ -2862,6 +2930,8 @@
 	/* incall */
 	SND_SOC_DAPM_AIF_OUT("VOICE_PLAYBACK_TX", "Voice Farend Playback",
 				0, 0, 0 , 0),
+	SND_SOC_DAPM_AIF_OUT("VOICE2_PLAYBACK_TX", "Voice2 Farend Playback",
+				0, 0, 0 , 0),
 	SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_RX", "Slimbus4 Playback",
 				0, 0, 0 , 0),
 	SND_SOC_DAPM_AIF_IN("INCALL_RECORD_TX", "Voice Uplink Capture",
@@ -2945,11 +3015,14 @@
 	sec_auxpcm_rx_mixer_controls, ARRAY_SIZE(sec_auxpcm_rx_mixer_controls)),
 	/* incall */
 	SND_SOC_DAPM_MIXER("Incall_Music Audio Mixer", SND_SOC_NOPM, 0, 0,
-			incall_music_delivery_mixer_controls,
-			ARRAY_SIZE(incall_music_delivery_mixer_controls)),
+	incall_music_delivery_mixer_controls,
+	ARRAY_SIZE(incall_music_delivery_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Incall_Music_2 Audio Mixer", SND_SOC_NOPM, 0, 0,
+	incall_music2_delivery_mixer_controls,
+	ARRAY_SIZE(incall_music2_delivery_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SLIMBUS_4_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
-			slimbus_4_rx_mixer_controls,
-			ARRAY_SIZE(slimbus_4_rx_mixer_controls)),
+	slimbus_4_rx_mixer_controls,
+	ARRAY_SIZE(slimbus_4_rx_mixer_controls)),
 	/* Voice Mixer */
 	SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
 				SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
@@ -3066,6 +3139,7 @@
 	{"PRI_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"PRI_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"PRI_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"PRI_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
 
 	{"SEC_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3076,6 +3150,7 @@
 	{"SEC_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"SEC_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"SEC_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"SEC_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"SEC_I2S_RX", NULL, "SEC_RX Audio Mixer"},
 
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3086,6 +3161,7 @@
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
 
 	{"HDMI Mixer", "MultiMedia1", "MM_DL1"},
@@ -3096,12 +3172,18 @@
 	{"HDMI Mixer", "MultiMedia6", "MM_DL6"},
 	{"HDMI Mixer", "MultiMedia7", "MM_DL7"},
 	{"HDMI Mixer", "MultiMedia8", "MM_DL8"},
+	{"HDMI Mixer", "MultiMedia9", "MM_DL9"},
 	{"HDMI", NULL, "HDMI Mixer"},
 
 		/* incall */
 	{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"Incall_Music Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"VOICE_PLAYBACK_TX", NULL, "Incall_Music Audio Mixer"},
+	{"Incall_Music_2 Audio Mixer", "MultiMedia1", "MM_DL1"},
+	{"Incall_Music_2 Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"Incall_Music_2 Audio Mixer", "MultiMedia9", "MM_DL9"},
+	{"VOICE2_PLAYBACK_TX", NULL, "Incall_Music_2 Audio Mixer"},
 	{"SLIMBUS_4_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"SLIMBUS_4_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"SLIMBUS_4_RX", NULL, "SLIMBUS_4_RX Audio Mixer"},
@@ -3119,6 +3201,7 @@
 	{"MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"MI2S_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"MI2S_RX", NULL, "MI2S_RX Audio Mixer"},
 
 	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3174,6 +3257,7 @@
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
 
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3184,6 +3268,7 @@
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
 
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3194,6 +3279,7 @@
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"AFE_PCM_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
 
 	{"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
@@ -3217,6 +3303,7 @@
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"AUX_PCM_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
 
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3227,6 +3314,7 @@
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX Audio Mixer"},
 
 	{"MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3320,6 +3408,7 @@
 	{"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
 
 	{"Voice2_Tx Mixer", "PRI_TX_Voice2", "PRI_I2S_TX"},
+	{"Voice2_Tx Mixer", "PRI_MI2S_TX_Voice2", "PRI_MI2S_TX"},
 	{"Voice2_Tx Mixer", "MI2S_TX_Voice2", "MI2S_TX"},
 	{"Voice2_Tx Mixer", "SLIM_0_TX_Voice2", "SLIMBUS_0_TX"},
 	{"Voice2_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice2", "INT_BT_SCO_TX"},
@@ -3466,6 +3555,7 @@
 	{"BE_OUT", NULL, "AUX_PCM_RX"},
 	{"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
 	{"BE_OUT", NULL, "VOICE_PLAYBACK_TX"},
+	{"BE_OUT", NULL, "VOICE2_PLAYBACK_TX"},
 
 	{"PRI_I2S_TX", NULL, "BE_IN"},
 	{"MI2S_TX", NULL, "BE_IN"},
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 9750756..0d87735 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -29,6 +29,7 @@
 #define LPASS_BE_SEC_AUXPCM_RX "SEC_AUX_PCM_RX"
 #define LPASS_BE_SEC_AUXPCM_TX "SEC_AUX_PCM_TX"
 #define LPASS_BE_VOICE_PLAYBACK_TX "VOICE_PLAYBACK_TX"
+#define LPASS_BE_VOICE2_PLAYBACK_TX "VOICE2_PLAYBACK_TX"
 #define LPASS_BE_INCALL_RECORD_RX "INCALL_RECORD_TX"
 #define LPASS_BE_INCALL_RECORD_TX "INCALL_RECORD_RX"
 #define LPASS_BE_SEC_I2S_RX "SECONDARY_I2S_RX"
@@ -70,6 +71,7 @@
 	MSM_FRONTEND_DAI_MULTIMEDIA6,
 	MSM_FRONTEND_DAI_MULTIMEDIA7,
 	MSM_FRONTEND_DAI_MULTIMEDIA8,
+	MSM_FRONTEND_DAI_MULTIMEDIA9,
 	MSM_FRONTEND_DAI_CS_VOICE,
 	MSM_FRONTEND_DAI_VOIP,
 	MSM_FRONTEND_DAI_AFE_RX,
@@ -82,8 +84,8 @@
 	MSM_FRONTEND_DAI_MAX,
 };
 
-#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA8 + 1)
-#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA8
+#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA9 + 1)
+#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA9
 
 enum {
 	MSM_BACKEND_DAI_PRI_I2S_RX = 0,
@@ -100,6 +102,7 @@
 	MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_BACKEND_DAI_AUXPCM_TX,
 	MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+	MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
 	MSM_BACKEND_DAI_INCALL_RECORD_RX,
 	MSM_BACKEND_DAI_INCALL_RECORD_TX,
 	MSM_BACKEND_DAI_MI2S_RX,
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 9882ec7..0eb13d4 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -234,6 +234,7 @@
 	case INT_BT_A2DP_RX:
 	case INT_FM_RX:
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case RT_PROXY_PORT_001_RX:
 	case AUDIO_PORT_ID_I2S_RX:
 	case AFE_PORT_ID_PRIMARY_MI2S_RX:
@@ -303,6 +304,7 @@
 		ret_size = SIZEOF_CFG_CMD(afe_param_id_slimbus_cfg);
 		break;
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 		ret_size = SIZEOF_CFG_CMD(afe_param_id_pseudo_port_cfg);
@@ -1263,6 +1265,7 @@
 		cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
 		break;
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 		cfg_type = AFE_PARAM_ID_PSEUDO_PORT_CONFIG;
@@ -1356,6 +1359,7 @@
 	case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
 	case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
 	case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
+	case VOICE2_PLAYBACK_TX: return IDX_VOICE2_PLAYBACK_TX;
 	case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
 	case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
 	case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
@@ -2663,6 +2667,7 @@
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case SLIMBUS_0_RX:
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index c65222b..869d642 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1383,15 +1383,12 @@
 	hdr->pkt_size  = pkt_size;
 	return;
 }
-int q6asm_open_read(struct audio_client *ac,
-		uint32_t format)
+static int __q6asm_open_read(struct audio_client *ac,
+		uint32_t format, uint16_t bits_per_sample)
 {
 	int rc = 0x00;
 	struct asm_stream_cmd_open_read_v3 open;
 
-	uint16_t bits_per_sample = 16;
-
-
 	config_debug_fs_reset_index();
 
 	if ((ac == NULL) || (ac->apr == NULL)) {
@@ -1466,6 +1463,18 @@
 	return -EINVAL;
 }
 
+int q6asm_open_read(struct audio_client *ac,
+		uint32_t format)
+{
+	return __q6asm_open_read(ac, format, 16);
+}
+
+int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
+			uint16_t bits_per_sample)
+{
+	return __q6asm_open_read(ac, format, bits_per_sample);
+}
+
 static int __q6asm_open_write(struct audio_client *ac, uint32_t format,
 		uint16_t bits_per_sample)
 {
@@ -1820,8 +1829,8 @@
 		return rc;
 }
 
-int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
-			uint32_t rate, uint32_t channels)
+static int __q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
+		uint32_t rate, uint32_t channels, uint16_t bits_per_sample)
 {
 	struct asm_multi_channel_pcm_enc_cfg_v2  enc_cfg;
 	u8 *channel_mapping;
@@ -1842,7 +1851,7 @@
 					sizeof(struct asm_enc_cfg_blk_param_v2);
 
 	enc_cfg.num_channels = channels;
-	enc_cfg.bits_per_sample = 16;
+	enc_cfg.bits_per_sample = bits_per_sample;
 	enc_cfg.sample_rate = rate;
 	enc_cfg.is_signed = 1;
 	channel_mapping = enc_cfg.channel_mapping;
@@ -1869,6 +1878,18 @@
 	return -EINVAL;
 }
 
+int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
+			uint32_t rate, uint32_t channels)
+{
+	return __q6asm_enc_cfg_blk_pcm(ac, rate, channels, 16);
+}
+
+int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac,
+		uint32_t rate, uint32_t channels, uint16_t bits_per_sample)
+{
+	 return __q6asm_enc_cfg_blk_pcm(ac, rate, channels, bits_per_sample);
+}
+
 int q6asm_enc_cfg_blk_pcm_native(struct audio_client *ac,
 			uint32_t rate, uint32_t channels)
 {
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index bc7ad4d..57ea2a7 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -43,6 +43,7 @@
 	case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
 	case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
 	case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
+	case VOICE2_PLAYBACK_TX: return IDX_VOICE2_PLAYBACK_TX;
 	case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
 	case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
 	case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
@@ -103,6 +104,7 @@
 	case VOICE_RECORD_RX: return AFE_PORT_ID_VOICE_RECORD_RX;
 	case VOICE_RECORD_TX: return AFE_PORT_ID_VOICE_RECORD_TX;
 	case VOICE_PLAYBACK_TX: return AFE_PORT_ID_VOICE_PLAYBACK_TX;
+	case VOICE2_PLAYBACK_TX: return AFE_PORT_ID_VOICE2_PLAYBACK_TX;
 	case SLIMBUS_0_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX;
 	case SLIMBUS_0_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_TX;
 	case SLIMBUS_1_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX;
@@ -213,6 +215,7 @@
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case SLIMBUS_0_RX:
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 9f4cabe..0735b7a 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -3457,7 +3457,8 @@
 		cvs_start_playback.hdr.token = 0;
 		cvs_start_playback.hdr.opcode = VSS_IPLAYBACK_CMD_START;
 		cvs_start_playback.playback_mode.port_id =
-						VSS_IPLAYBACK_PORT_ID_DEFAULT;
+						v->music_info.port_id;
+
 		v->cvs_state = CMD_STATUS_FAIL;
 
 		ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_start_playback);
@@ -3555,17 +3556,21 @@
 	return ret;
 }
 
-int voc_start_playback(uint32_t set)
+int voc_start_playback(uint32_t set, uint16_t port_id)
 {
 	int ret = 0;
 	u16 cvs_handle;
-	int i;
 
+	struct voice_data *v = NULL;
 
-	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
-		struct voice_data *v = &common.voice[i];
+	if (port_id == VOICE_PLAYBACK_TX)
+		v = voice_get_session(voc_get_session_id(VOICE_SESSION_NAME));
+	else if (port_id == VOICE2_PLAYBACK_TX)
+		v = voice_get_session(voc_get_session_id(VOICE2_SESSION_NAME));
 
+	if (v != NULL) {
 		mutex_lock(&v->lock);
+		v->music_info.port_id = port_id;
 		v->music_info.play_enable = set;
 		if (set)
 			v->music_info.count++;
@@ -3583,6 +3588,8 @@
 		}
 
 		mutex_unlock(&v->lock);
+	} else {
+		pr_err("%s: Invalid port_id 0x%x", __func__, port_id);
 	}
 
 	return ret;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 5a16115..52cf940 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -486,6 +486,12 @@
 #define VSS_IPLAYBACK_PORT_ID_DEFAULT			0x0000FFFF
 /* Default AFE port ID. */
 
+#define VSS_IPLAYBACK_PORT_ID_VOICE			0x00008005
+/* AFE port ID for VOICE 1. */
+
+#define VSS_IPLAYBACK_PORT_ID_VOICE2			0x00008002
+/* AFE port ID for VOICE 2. */
+
 #define VSS_IRECORD_CMD_START				0x000112BE
 /* Start in-call conversation recording. */
 #define VSS_IRECORD_CMD_STOP				0x00011237
@@ -1209,6 +1215,7 @@
 	uint32_t playing;
 	int count;
 	int force;
+	uint16_t port_id;
 };
 
 struct share_memory_info {
@@ -1370,6 +1377,6 @@
 
 uint32_t voc_get_session_id(char *name);
 
-int voc_start_playback(uint32_t set);
+int voc_start_playback(uint32_t set, uint16_t port_id);
 int voc_start_record(uint32_t port_id, uint32_t set);
 #endif