Merge "arm/dt: apq8084: add ipc-spinlock entry"
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index 436dfc7..052feeb 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -72,6 +72,20 @@
 			   This is used to override faulty hardware readings.
 - qcom,strtstp-sleepwake:  Boolean. Enables use of GPU SLUMBER instead of SLEEP for power savings
 
+The following properties are optional as collecting data via coresight might
+not be supported for every chipset. The documentation for coresight
+properties can be found in:
+Documentation/devicetree/bindings/coresight/coresight.txt
+
+- coresight-id           Unique integer identifier for the bus.
+- coresight-name         Unique descriptive name of the bus.
+- coresight-nr-inports   Number of input ports on the bus.
+- coresight-outports     List of output port numbers on the bus.
+- coresight-child-list   List of phandles pointing to the children of this
+                         component.
+- coresight-child-ports  List of input port numbers of the children.
+
+
 Example of A330 GPU in MSM8974:
 
 / {
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 8ce31d9..b0d6b4d 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -40,6 +40,8 @@
   DATA GPIO PAD.
 - qcom,phy-sof-workaround : If present then HSIC PHY has h/w BUGs related to
   SOFs. Software workarounds are required for the same.
+- hsic,consider-ipa-handshake: If present then hsic low power mode is
+  depend on suitable handshake with the IPA peer.
 
 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
   below optional properties:
@@ -71,6 +73,7 @@
 		hsic,ignore-cal-pad-config;
 		hsic,strobe-pad-offset = <0x2050>;
 		hsic,data-pad-offset = <0x2054>;
+		hsic,consider-ipa-handshake;
 
 		qcom,msm-bus,name = "hsic";
 		qcom,msm-bus,num-cases = <2>;
diff --git a/arch/arm/boot/dts/apq8074-v1.dtsi b/arch/arm/boot/dts/apq8074-v1.dtsi
new file mode 100644
index 0000000..c4e7b7c
--- /dev/null
+++ b/arch/arm/boot/dts/apq8074-v1.dtsi
@@ -0,0 +1,48 @@
+/* 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-v1.dtsi"
+
+&soc {
+	qcom,qseecom@a700000 {
+		compatible = "qcom,qseecom";
+		reg = <0x0a700000 0x500000>;
+		reg-names = "secapp-region";
+		qcom,disk-encrypt-pipe-pair = <2>;
+		qcom,hlos-ce-hw-instance = <1>;
+		qcom,qsee-ce-hw-instance = <0>;
+		qcom,msm-bus,name = "qseecom-noc";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<55 512 0 0>,
+				<55 512 3936000 393600>,
+				<55 512 3936000 393600>,
+				<55 512 3936000 393600>;
+	};
+};
+
+&memory_hole {
+	qcom,memblock-remove = <0x0a700000 0x5800000>; /* Address and size of the hole */
+};
+
+&qseecom {
+	status = "disabled";
+};
+
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index 669097e..5172a5a 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -51,6 +51,14 @@
 		/* IOMMU Data */
 		iommu = <&kgsl_iommu>;
 
+		/* Trace bus */
+		coresight-id = <67>;
+		coresight-name = "coresight-gfx";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_mmss>;
+		coresight-child-ports = <7>;
+
 		qcom,gpu-pwrlevels {
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 6e258b5..ca09370 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -190,6 +190,7 @@
 				<85 512 40000 640000>;
 		qcom,pool-64-bit-align;
 		qcom,enable-hbm;
+		hsic,consider-ipa-handshake;
 	};
 
 	qcom,usbbam@f9a44000 {
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 07a15d9..7bf54ce 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -291,6 +291,10 @@
 CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_MSM8226=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_DEBUG_FS=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 4f4bfbc..fa3344d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -317,6 +317,7 @@
 obj-$(CONFIG_ARCH_MSM9625) += clock-local2.o clock-pll.o clock-9625.o clock-rpm.o clock-voter.o acpuclock-9625.o acpuclock-cortex.o
 obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o acpuclock-8930ab.o
 obj-$(CONFIG_ARCH_MPQ8092) += board-8092.o board-8092-gpiomux.o
+obj-$(CONFIG_ARCH_MPQ8092) += clock-8092.o
 obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8226) += clock-local2.o clock-pll.o clock-8226.o clock-rpm.o clock-voter.o clock-mdss-8226.o
 obj-$(CONFIG_ARCH_MSM8226) += acpuclock-8226.o acpuclock-cortex.o
diff --git a/arch/arm/mach-msm/board-8092.c b/arch/arm/mach-msm/board-8092.c
index cd95bf3..ab5cc3a 100644
--- a/arch/arm/mach-msm/board-8092.c
+++ b/arch/arm/mach-msm/board-8092.c
@@ -35,21 +35,6 @@
 #include "clock.h"
 #include "platsmp.h"
 
-static struct clk_lookup msm_clocks_dummy[] = {
-	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
-	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
-	CLK_DUMMY("core_clk",	SDC1_CLK,	"msm_sdcc.1", OFF),
-	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),
-
-};
-
-struct clock_init_data mpq8092_clock_init_data __initdata = {
-	.table = msm_clocks_dummy,
-	.size = ARRAY_SIZE(msm_clocks_dummy),
-};
-
 static struct memtype_reserve mpq8092_reserve_table[] __initdata = {
 	[MEMTYPE_SMI] = {
 	},
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index 424b694..b7f9fd7 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -325,7 +325,9 @@
 	CLK_DUMMY("",	mmss_mmssnoc_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mmss_mmssnoc_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	mmss_s0_axi_clk.c,	"", OFF),
-	CLK_DUMMY("",	ocmemcx_ocmemnoc_clk.c,	"", OFF),
+	CLK_DUMMY("core_clk",  ocmemgx_core_clk.c, "fdd00000.qcom,ocmem", OFF),
+	CLK_DUMMY("iface_clk",	ocmemcx_ocmemnoc_clk.c,
+						"fdd00000.qcom,ocmem", OFF),
 	CLK_DUMMY("",	oxili_ocmemgx_clk.c,	"", OFF),
 	CLK_DUMMY("",	oxili_gfx3d_clk.c,	"", OFF),
 	CLK_DUMMY("",	oxili_rbbmtimer_clk.c,	"", OFF),
diff --git a/arch/arm/mach-msm/clock-8092.c b/arch/arm/mach-msm/clock-8092.c
new file mode 100644
index 0000000..a8520e6
--- /dev/null
+++ b/arch/arm/mach-msm/clock-8092.c
@@ -0,0 +1,323 @@
+/* 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/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/rpm-regulator-smd.h>
+#include <mach/socinfo.h>
+#include <mach/rpm-smd.h>
+
+#include "clock-local2.h"
+#include "clock-pll.h"
+#include "clock-rpm.h"
+#include "clock-voter.h"
+#include "clock.h"
+
+/*
+ * Drivers need to fill in the clock names and device names for the clocks
+ * they need to control.
+ */
+static struct clk_lookup msm_clocks_8092[] = {
+	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
+	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
+	CLK_DUMMY("core_clk",	SDC1_CLK,	"msm_sdcc.1", OFF),
+	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("",	usb30_master_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	tsif_ref_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	ce1_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	ce2_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	ce3_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	geni_ser_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	gmac_125m_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	gmac_core_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	gmac_sys_25m_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	gp1_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	gp2_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	gp3_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	pcie_aux_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	pcie_pipe_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	pdm2_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	pwm_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	sata_asic0_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	sata_pmalive_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	sata_rx_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	sata_rx_oob_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	sdcc1_apps_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	sdcc2_apps_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	usb30_mock_utmi_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	usb_hs_system_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	usb_hs2_system_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	usb_hsic_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	usb_hsic_io_cal_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	usb_hsic_system_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	gcc_bam_dma_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_bcss_cfg_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_bimc_gfx_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_bimc_kpss_axi_mstr_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_bimc_sysnoc_axi_mstr_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup1_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup1_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup2_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup2_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup3_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup3_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup4_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup4_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup5_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup5_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup6_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_qup6_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_uart1_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_uart2_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_uart3_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_uart4_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_uart5_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp1_uart6_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup1_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup1_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup2_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup2_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup3_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup3_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup4_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup4_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup5_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup5_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup6_i2c_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_qup6_spi_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_uart1_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_uart2_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_uart3_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_uart4_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_uart5_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_blsp2_uart6_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_boot_rom_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_ce1_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_ce1_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_ce1_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_ce2_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_ce2_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_ce2_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_ce3_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_ce3_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_ce3_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_xo_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_xo_div4_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_geni_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_geni_ser_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_gmac_125m_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_gmac_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_gmac_cfg_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_gmac_core_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_gmac_rx_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_gmac_sys_25m_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_gmac_sys_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_gp1_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_gp2_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_gp3_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_klm_core_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_klm_s_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_lpass_q6_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sys_noc_lpass_mport_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sys_noc_lpass_sway_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_mmss_a5ss_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_mmss_bimc_gfx_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_pcie_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_pcie_axi_mstr_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_pcie_cfg_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_pcie_pipe_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_pcie_sleep_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_pdm2_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_pdm_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_prng_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_pwm_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_pwm_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sata_asic0_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sata_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sata_cfg_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sata_pmalive_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sata_rx_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sata_rx_oob_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sdcc1_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sdcc1_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sdcc2_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sdcc2_apps_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_spss_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_sys_noc_usb3_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb2a_phy_sleep_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb2b_phy_sleep_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb2c_phy_sleep_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb30_master_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb30_mock_utmi_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb30_sleep_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb_hs_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb_hs_system_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb_hs2_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb_hs2_system_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb_hsic_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb_hsic_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb_hsic_io_cal_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_usb_hsic_system_clk.c,	"", OFF),
+	/* MMSS Clock Dummy */
+	CLK_DUMMY("",	axi_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	mmpll0_pll_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	mmpll1_pll_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	mmpll2_pll_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	mmpll3_pll_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	mmpll6_pll_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	vcodec0_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	extpclk_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	lvds_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	mdp_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	vbyone_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	gfx3d_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	vp_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	jpeg2_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	hdmi_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	vbyone_symbol_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	mmss_spdm_axi_div_clk.c,	"", OFF),
+	CLK_DUMMY("",	mmss_spdm_gfx3d_div_clk.c,	"", OFF),
+	CLK_DUMMY("",	mmss_spdm_jpeg2_div_clk.c,	"", OFF),
+	CLK_DUMMY("",	mmss_spdm_mdp_div_clk.c,	"", OFF),
+	CLK_DUMMY("",	mmss_spdm_vcodec0_div_clk.c,	"", OFF),
+	CLK_DUMMY("",	afe_pixel_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	cfg_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	hdmi_bus_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	hdmi_rx_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	md_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	ttl_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	vafe_ext_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	vcap_vp_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	gproc_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	hdmc_frcf_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	kproc_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	maple_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	preproc_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	sdmc_frcs_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	sdme_frcf_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	sdme_vproc_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	vdp_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	vpu_bus_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	vpu_frc_xin_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	vpu_vdp_xin_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	avsync_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	avsync_extpclk_clk.c,	"", OFF),
+	CLK_DUMMY("",	avsync_lvds_clk.c,	"", OFF),
+	CLK_DUMMY("",	avsync_vbyone_clk.c,	"", OFF),
+	CLK_DUMMY("",	avsync_vp_clk.c,	"", OFF),
+	CLK_DUMMY("",	camss_jpeg_jpeg2_clk.c,	"", OFF),
+	CLK_DUMMY("",	camss_jpeg_jpeg_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	camss_jpeg_jpeg_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	camss_micro_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	camss_top_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	mdss_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	mdss_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	mdss_extpclk_clk.c,	"", OFF),
+	CLK_DUMMY("",	mdss_hdmi_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	mdss_hdmi_clk.c,	"", OFF),
+	CLK_DUMMY("",	mdss_lvds_clk.c,	"", OFF),
+	CLK_DUMMY("",	mdss_mdp_clk.c,	"", OFF),
+	CLK_DUMMY("",	mdss_mdp_lut_clk.c,	"", OFF),
+	CLK_DUMMY("",	mdss_vbyone_clk.c,	"", OFF),
+	CLK_DUMMY("",	mdss_vbyone_symbol_clk.c,	"", 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),
+	CLK_DUMMY("",	mmss_s0_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	ocmemcx_ocmemnoc_clk.c,	"", OFF),
+	CLK_DUMMY("",	oxili_ocmemgx_clk.c,	"", OFF),
+	CLK_DUMMY("",	oxili_gfx3d_clk.c,	"", OFF),
+	CLK_DUMMY("",	oxilicx_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcss_mmss_ifdemod_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_afe_pixel_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_audio_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_cfg_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_hdmi_bus_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_hdmi_rx_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_md_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_ttl_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_ttl_debug_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_vafe_ext_clk.c,	"", OFF),
+	CLK_DUMMY("",	vcap_vp_clk.c,	"", OFF),
+	CLK_DUMMY("",	venus0_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	venus0_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	venus0_core0_vcodec_clk.c,	"", OFF),
+	CLK_DUMMY("",	venus0_core1_vcodec_clk.c,	"", OFF),
+	CLK_DUMMY("",	venus0_ocmemnoc_clk.c,	"", OFF),
+	CLK_DUMMY("",	venus0_vcodec0_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_bus_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_cxo_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_frc_xin_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_gproc_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_hdmc_frcf_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_kproc_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_maple_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_preproc_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_sdmc_frcs_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_sdme_frcf_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_sdme_frcs_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_sdme_vproc_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_sleep_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_vdp_clk.c,	"", OFF),
+	CLK_DUMMY("",	vpu_vdp_xin_clk.c,	"", OFF),
+	/* BCSS broadcast */
+	CLK_DUMMY("",	bcc_dem_core_b_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	adc_01_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	bcc_adc_0_in_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_dem_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_klm_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_lnb_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_tsc_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_tspp2_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_vbif_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_bcss_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_dem_atv_rxfe_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_dem_atv_rxfe_resamp_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_dem_core_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	bcc_dem_core_div2_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	bcc_dem_core_x2_b_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	bcc_dem_core_x2_pre_cgf_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_tsc_ci_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_tsc_cicam_ts_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	bcc_tsc_par_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_tsc_ser_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	bcc_tspp2_clk_src.c,	"", OFF),
+	CLK_DUMMY("",	dig_dem_core_b_div2_clk.c,	"", OFF),
+	CLK_DUMMY("",	atv_x5_pre_cgc_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_albacore_cvbs_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_atv_x1_clk.c,	"", OFF),
+	CLK_DUMMY("",	nidaq_out_clk.c,	"", OFF),
+	CLK_DUMMY("",	gcc_bcss_axi_clk.c,	"", OFF),
+	CLK_DUMMY("",	bcc_lnb_core_clk.c,	"", OFF),
+};
+
+struct clock_init_data mpq8092_clock_init_data __initdata = {
+	.table = msm_clocks_8092,
+	.size = ARRAY_SIZE(msm_clocks_8092),
+};
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 340f1ef..1034516 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -509,7 +509,6 @@
 
 static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(pnoc_iommu_clk, &pnoc_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(pnoc_qseecom_clk, &pnoc_clk.c, LONG_MAX);
 
 static DEFINE_CLK_MEASURE(apc0_m_clk);
 static DEFINE_CLK_MEASURE(apc1_m_clk);
@@ -1546,6 +1545,7 @@
 	F_END,
 };
 
+static struct branch_clk mmss_mmssnoc_axi_clk;
 static struct rcg_clk axi_clk_src = {
 	.cmd_rcgr_reg = AXI_CMD_RCGR,
 	.set_rate = set_rate_hid,
@@ -1557,6 +1557,7 @@
 		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
 		CLK_INIT(axi_clk_src.c),
+		.depends = &mmss_mmssnoc_axi_clk.c
 	},
 };
 
@@ -2320,7 +2321,6 @@
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
-		.parent = &axi_clk_src.c,
 		.dbg_name = "mmss_mmssnoc_axi_clk",
 		.ops = &clk_ops_branch,
 		CLK_INIT(mmss_mmssnoc_axi_clk.c),
@@ -2336,7 +2336,6 @@
 		.dbg_name = "mmss_s0_axi_clk",
 		.ops = &clk_ops_branch,
 		CLK_INIT(mmss_s0_axi_clk.c),
-		.depends = &mmss_mmssnoc_axi_clk.c,
 	},
 };
 
@@ -2764,7 +2763,6 @@
 	CLK_LOOKUP("core_clk",  gcc_blsp1_uart2_apps_clk.c, "f991e000.serial"),
 
 	CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
-	CLK_LOOKUP("bus_clk",  pnoc_qseecom_clk.c, "qseecom"),
 
 	CLK_LOOKUP("bus_clk", snoc_clk.c, ""),
 	CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),
@@ -3232,10 +3230,6 @@
 	/* Maintain the max nominal frequency on the MMSSNOC AHB bus. */
 	clk_set_rate(&mmssnoc_ahb_a_clk.c,  40000000);
 	clk_prepare_enable(&mmssnoc_ahb_a_clk.c);
-
-	/* TODO: Remove this once the bus driver is in place */
-	clk_set_rate(&axi_clk_src.c, 200000000);
-	clk_prepare_enable(&mmss_s0_axi_clk.c);
 }
 
 struct clock_init_data msm8610_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 674ef77..2a65d2f 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -54,6 +54,7 @@
 extern struct clock_init_data msm8226_clock_init_data;
 extern struct clock_init_data msm8226_rumi_clock_init_data;
 extern struct clock_init_data msm8084_clock_init_data;
+extern struct clock_init_data mpq8092_clock_init_data;
 
 int msm_clock_init(struct clock_init_data *data);
 int find_vdd_level(struct clk *clk, unsigned long rate);
diff --git a/arch/arm/mach-msm/include/mach/kgsl.h b/arch/arm/mach-msm/include/mach/kgsl.h
index 349dbe7..2216183 100644
--- a/arch/arm/mach-msm/include/mach/kgsl.h
+++ b/arch/arm/mach-msm/include/mach/kgsl.h
@@ -89,6 +89,8 @@
 	struct kgsl_device_iommu_data *iommu_data;
 	int iommu_count;
 	struct msm_dcvs_core_info *core_info;
+	struct coresight_device *csdev;
+	struct coresight_platform_data *coresight_pdata;
 	unsigned int chipid;
 };
 
diff --git a/arch/arm/mach-msm/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
index 5ecc63b..bc76f56 100644
--- a/arch/arm/mach-msm/include/mach/usb_bam.h
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -126,6 +126,7 @@
 	struct sps_mem_buffer desc_mem_buf;
 	struct usb_bam_event_info event;
 	bool enabled;
+	bool suspended;
 	int ipa_clnt_hdl;
 	void *priv;
 	int (*activity_notify)(void *priv);
diff --git a/arch/arm/mach-msm/ipc_logging.c b/arch/arm/mach-msm/ipc_logging.c
index 1260a1a..280f237 100644
--- a/arch/arm/mach-msm/ipc_logging.c
+++ b/arch/arm/mach-msm/ipc_logging.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
@@ -32,7 +32,7 @@
 #include "ipc_logging.h"
 
 static LIST_HEAD(ipc_log_context_list);
-DEFINE_SPINLOCK(ipc_log_context_list_lock);
+DEFINE_RWLOCK(ipc_log_context_list_lock);
 static atomic_t next_log_id = ATOMIC_INIT(0);
 
 static struct ipc_log_page *get_first_page(struct ipc_log_context *ilctxt)
@@ -140,7 +140,7 @@
 		return;
 	}
 
-	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	read_lock_irqsave(&ipc_log_context_list_lock, flags);
 	spin_lock(&ilctxt->ipc_log_context_lock);
 	while (ilctxt->write_avail < ectxt->offset)
 		msg_read(ilctxt, NULL);
@@ -165,7 +165,7 @@
 	ilctxt->write_avail -= ectxt->offset;
 	complete(&ilctxt->read_avail);
 	spin_unlock(&ilctxt->ipc_log_context_lock);
-	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
 }
 EXPORT_SYMBOL(ipc_log_write);
 
@@ -471,13 +471,13 @@
 	if (!df_info)
 		return -ENOSPC;
 
-	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	read_lock_irqsave(&ipc_log_context_list_lock, flags);
 	spin_lock(&ilctxt->ipc_log_context_lock);
 	df_info->type = type;
 	df_info->dfunc = dfunc;
 	list_add_tail(&df_info->list, &ilctxt->dfunc_info_list);
 	spin_unlock(&ilctxt->ipc_log_context_lock);
-	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
 	return 0;
 }
 EXPORT_SYMBOL(add_deserialization_func);
@@ -528,9 +528,9 @@
 
 	create_ctx_debugfs(ctxt, mod_name);
 
-	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	write_lock_irqsave(&ipc_log_context_list_lock, flags);
 	list_add_tail(&ctxt->list, &ipc_log_context_list);
-	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	write_unlock_irqrestore(&ipc_log_context_list_lock, flags);
 	return (void *)ctxt;
 
 release_ipc_log_context:
diff --git a/arch/arm/mach-msm/ipc_logging.h b/arch/arm/mach-msm/ipc_logging.h
index 0eb82a5..36b4171 100644
--- a/arch/arm/mach-msm/ipc_logging.h
+++ b/arch/arm/mach-msm/ipc_logging.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
@@ -65,7 +65,7 @@
 #define IS_MSG_TYPE(x) (((x) > TSV_TYPE_MSG_START) && \
 			((x) < TSV_TYPE_MSG_END))
 
-extern spinlock_t ipc_log_context_list_lock;
+extern rwlock_t ipc_log_context_list_lock;
 
 extern int msg_read(struct ipc_log_context *ilctxt,
 		    struct encode_context *ectxt);
diff --git a/arch/arm/mach-msm/ipc_logging_debug.c b/arch/arm/mach-msm/ipc_logging_debug.c
index ff947ef..246fb99 100644
--- a/arch/arm/mach-msm/ipc_logging_debug.c
+++ b/arch/arm/mach-msm/ipc_logging_debug.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
@@ -62,7 +62,7 @@
 	dctxt.output_format = OUTPUT_DEBUGFS;
 	dctxt.buff = buff;
 	dctxt.size = size;
-	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	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)) {
@@ -70,19 +70,19 @@
 		deserialize_func = get_deserialization_func(ilctxt,
 							ectxt.hdr.type);
 		spin_unlock(&ilctxt->ipc_log_context_lock);
-		spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+		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);
-		spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+		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);
-	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
 	return size - dctxt.size;
 }
 
diff --git a/arch/arm/mach-msm/spm-regulator.c b/arch/arm/mach-msm/spm-regulator.c
index 00817c0..244a779 100644
--- a/arch/arm/mach-msm/spm-regulator.c
+++ b/arch/arm/mach-msm/spm-regulator.c
@@ -42,17 +42,40 @@
 static const struct voltage_range fts2_range0 = {0, 350000, 1275000,  5000};
 static const struct voltage_range fts2_range1 = {0, 700000, 2040000, 10000};
 
-/* Specifies the PMIC internal slew rate in uV/us. */
-#define QPNP_FTS2_SLEW_RATE		6000
-
 #define QPNP_FTS2_REG_TYPE		0x04
 #define QPNP_FTS2_REG_SUBTYPE		0x05
 #define QPNP_FTS2_REG_VOLTAGE_RANGE	0x40
 #define QPNP_FTS2_REG_VOLTAGE_SETPOINT	0x41
+#define QPNP_FTS2_REG_MODE		0x45
+#define QPNP_FTS2_REG_STEP_CTRL		0x61
 
 #define QPNP_FTS2_TYPE			0x1C
 #define QPNP_FTS2_SUBTYPE		0x08
 
+#define QPNP_FTS2_MODE_PWM		0x80
+#define QPNP_FTS2_MODE_AUTO		0x40
+
+#define QPNP_FTS2_STEP_CTRL_STEP_MASK	0x18
+#define QPNP_FTS2_STEP_CTRL_STEP_SHIFT	3
+#define QPNP_FTS2_STEP_CTRL_DELAY_MASK	0x07
+#define QPNP_FTS2_STEP_CTRL_DELAY_SHIFT	0
+
+/* Clock rate in kHz of the FTS2 regulator reference clock. */
+#define QPNP_FTS2_CLOCK_RATE		19200
+
+/* Time to delay in us to ensure that a mode change has completed. */
+#define QPNP_FTS2_MODE_CHANGE_DELAY	50
+
+/* Minimum time in us that it takes to complete a single SPMI write. */
+#define QPNP_SPMI_WRITE_MIN_DELAY	8
+
+/*
+ * The ratio QPNP_FTS2_STEP_MARGIN_NUM/QPNP_FTS2_STEP_MARGIN_DEN is use to
+ * adjust the step rate in order to account for oscillator variance.
+ */
+#define QPNP_FTS2_STEP_MARGIN_NUM	4
+#define QPNP_FTS2_STEP_MARGIN_DEN	5
+
 struct spm_vreg {
 	struct regulator_desc		rdesc;
 	struct regulator_dev		*rdev;
@@ -64,8 +87,23 @@
 	unsigned			last_set_vlevel;
 	bool				online;
 	u16				spmi_base_addr;
+	u8				init_mode;
+	int				step_rate;
 };
 
+static int qpnp_fts2_set_mode(struct spm_vreg *vreg, u8 mode)
+{
+	int rc;
+
+	rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+		vreg->spmi_base_addr + QPNP_FTS2_REG_MODE, &mode, 1);
+	if (rc)
+		dev_err(&vreg->spmi_dev->dev, "%s: could not write to mode register, rc=%d\n",
+			__func__, rc);
+
+	return rc;
+}
+
 static int _spm_regulator_set_voltage(struct regulator_dev *rdev)
 {
 	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
@@ -74,6 +112,14 @@
 	if (vreg->vlevel == vreg->last_set_vlevel)
 		return 0;
 
+	if (!(vreg->init_mode & QPNP_FTS2_MODE_PWM)
+	    && vreg->uV > vreg->last_set_uV) {
+		/* Switch to PWM mode so that voltage ramping is fast. */
+		rc = qpnp_fts2_set_mode(vreg, QPNP_FTS2_MODE_PWM);
+		if (rc)
+			return rc;
+	}
+
 	rc = msm_spm_apcs_set_vdd(vreg->vlevel);
 	if (rc) {
 		pr_err("%s: msm_spm_set_vdd failed %d\n", vreg->rdesc.name, rc);
@@ -81,10 +127,21 @@
 	}
 
 	if (vreg->uV > vreg->last_set_uV) {
-		/* Wait for voltage to stabalize. */
+		/* Wait for voltage stepping to complete. */
 		udelay(DIV_ROUND_UP(vreg->uV - vreg->last_set_uV,
-					QPNP_FTS2_SLEW_RATE));
+					vreg->step_rate));
 	}
+
+	if (!(vreg->init_mode & QPNP_FTS2_MODE_PWM)
+	    && vreg->uV > vreg->last_set_uV) {
+		/* Wait for mode transition to complete. */
+		udelay(QPNP_FTS2_MODE_CHANGE_DELAY - QPNP_SPMI_WRITE_MIN_DELAY);
+		/* Switch to AUTO mode so that power consumption is lowered. */
+		rc = qpnp_fts2_set_mode(vreg, QPNP_FTS2_MODE_AUTO);
+		if (rc)
+			return rc;
+	}
+
 	vreg->last_set_uV = vreg->uV;
 	vreg->last_set_vlevel = vreg->vlevel;
 
@@ -254,6 +311,51 @@
 	return rc;
 }
 
+static int qpnp_fts2_init_mode(struct spm_vreg *vreg)
+{
+	int rc;
+
+	rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+		vreg->spmi_base_addr + QPNP_FTS2_REG_MODE, &vreg->init_mode, 1);
+	if (rc)
+		dev_err(&vreg->spmi_dev->dev, "%s: could not read mode register, rc=%d\n",
+			__func__, rc);
+
+	return rc;
+}
+
+static int qpnp_fts2_init_step_rate(struct spm_vreg *vreg)
+{
+	int rc;
+	u8 reg = 0;
+	int step, delay;
+
+	rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+		vreg->spmi_base_addr + QPNP_FTS2_REG_STEP_CTRL, &reg, 1);
+	if (rc) {
+		dev_err(&vreg->spmi_dev->dev, "%s: could not read stepping control register, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	step = (reg & QPNP_FTS2_STEP_CTRL_STEP_MASK)
+		>> QPNP_FTS2_STEP_CTRL_STEP_SHIFT;
+	delay = (reg & QPNP_FTS2_STEP_CTRL_DELAY_MASK)
+		>> QPNP_FTS2_STEP_CTRL_DELAY_SHIFT;
+
+	/* step_rate has units of uV/us. */
+	vreg->step_rate = QPNP_FTS2_CLOCK_RATE * vreg->range->step_uV
+				* (1 << step);
+	vreg->step_rate /= 1000 * (8 << delay);
+	vreg->step_rate = vreg->step_rate * QPNP_FTS2_STEP_MARGIN_NUM
+				/ QPNP_FTS2_STEP_MARGIN_DEN;
+
+	/* Ensure that the stepping rate is greater than 0. */
+	vreg->step_rate = max(vreg->step_rate, 1);
+
+	return rc;
+}
+
 static int __devinit spm_regulator_probe(struct spmi_device *spmi)
 {
 	struct device_node *node = spmi->dev.of_node;
@@ -299,6 +401,14 @@
 	if (rc)
 		return rc;
 
+	rc = qpnp_fts2_init_mode(vreg);
+	if (rc)
+		return rc;
+
+	rc = qpnp_fts2_init_step_rate(vreg);
+	if (rc)
+		return rc;
+
 	init_data = of_get_regulator_init_data(&spmi->dev, node);
 	if (!init_data) {
 		dev_err(&spmi->dev, "%s: unable to allocate memory\n",
@@ -334,8 +444,12 @@
 
 	dev_set_drvdata(&spmi->dev, vreg);
 
-	pr_info("name=%s, range=%d\n", vreg->rdesc.name,
-		(vreg->range == &fts2_range0) ? 0 : 1);
+	pr_info("name=%s, range=%s, voltage=%d uV, mode=%s, step rate=%d uV/us\n",
+		vreg->rdesc.name, vreg->range == &fts2_range0 ? "LV" : "MV",
+		vreg->uV,
+		vreg->init_mode & QPNP_FTS2_MODE_PWM ? "PWM" :
+		    (vreg->init_mode & QPNP_FTS2_MODE_AUTO ? "AUTO" : "PFM"),
+		vreg->step_rate);
 
 	return rc;
 }
diff --git a/block/blk-core.c b/block/blk-core.c
index 2b6595c..153240e 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1086,7 +1086,7 @@
 		 * urgent requests. We want to be able to track this
 		 * down.
 		 */
-		pr_err("%s(): requeueing an URGENT request", __func__);
+		pr_debug("%s(): requeueing an URGENT request", __func__);
 		WARN_ON(!q->dispatched_urgent);
 		q->dispatched_urgent = false;
 	}
@@ -1123,7 +1123,7 @@
 		 * urgent requests. We want to be able to track this
 		 * down.
 		 */
-		pr_err("%s(): reinserting an URGENT request", __func__);
+		pr_debug("%s(): reinserting an URGENT request", __func__);
 		WARN_ON(!q->dispatched_urgent);
 		q->dispatched_urgent = false;
 	}
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index f76d41a..9c2c8b1 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -689,9 +689,15 @@
 					 int len, int type)
 {
 	driver->pkt_length = len;
-	if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
-		diag_update_pkt_buffer(buf);
-		diag_update_sleeping_process(entry.process_id, PKT_TYPE);
+
+	/* If the process_id corresponds to an apps process */
+	if (entry.process_id != NON_APPS_PROC) {
+		/* If the message is to be sent to the apps process */
+		if (type != MODEM_DATA) {
+			diag_update_pkt_buffer(buf);
+			diag_update_sleeping_process(entry.process_id,
+							PKT_TYPE);
+		}
 	} else {
 		if (len > 0) {
 			if (entry.client_id < NUM_SMD_DATA_CHANNELS) {
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index 3441afa..fc66328 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -25,6 +25,7 @@
 	adreno_drawctxt.o \
 	adreno_postmortem.o \
 	adreno_snapshot.o \
+	adreno_coresight.o \
 	adreno_a2xx.o \
 	adreno_a2xx_trace.o \
 	adreno_a2xx_snapshot.o \
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 5f435f3..0c398c4 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -165,8 +165,16 @@
 #define A3XX_RBBM_PERFCTR_PWR_0_HI 0x0EB
 #define A3XX_RBBM_PERFCTR_PWR_1_LO 0x0EC
 #define A3XX_RBBM_PERFCTR_PWR_1_HI 0x0ED
-#define A3XX_RBBM_DEBUG_BUS_CTL             0x111
-#define A3XX_RBBM_DEBUG_BUS_DATA_STATUS     0x112
+#define A3XX_RBBM_DEBUG_BUS_CTL 0x111
+#define A3XX_RBBM_DEBUG_BUS_DATA_STATUS 0x112
+#define A3XX_RBBM_DEBUG_BUS_STB_CTL0 0x11B
+#define A3XX_RBBM_DEBUG_BUS_STB_CTL1 0x11C
+#define A3XX_RBBM_INT_TRACE_BUS_CTL 0x11D
+#define A3XX_RBBM_EXT_TRACE_BUS_CTL 0x11E
+#define A3XX_RBBM_EXT_TRACE_STOP_CNT 0x11F
+#define A3XX_RBBM_EXT_TRACE_START_CNT 0x120
+#define A3XX_RBBM_EXT_TRACE_PERIOD_CNT 0x121
+#define A3XX_RBBM_EXT_TRACE_CMD 0x122
 
 /* Following two are same as on A2XX, just in a different place */
 #define A3XX_CP_PFP_UCODE_ADDR 0x1C9
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index a4f60f9..aad2882 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -18,6 +18,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/delay.h>
+#include <linux/of_coresight.h>
 
 #include <mach/socinfo.h>
 #include <mach/msm_bus_board.h>
@@ -1522,6 +1523,9 @@
 	if (ret)
 		goto err;
 
+	pdata->coresight_pdata = of_get_coresight_platform_data(&pdev->dev,
+			pdev->dev.of_node);
+
 	pdev->dev.platform_data = pdata;
 	return 0;
 
@@ -1595,6 +1599,7 @@
 adreno_probe(struct platform_device *pdev)
 {
 	struct kgsl_device *device;
+	struct kgsl_device_platform_data *pdata = NULL;
 	struct adreno_device *adreno_dev;
 	int status = -EINVAL;
 	bool is_dt;
@@ -1625,6 +1630,10 @@
 	kgsl_pwrscale_attach_policy(device, ADRENO_DEFAULT_PWRSCALE_POLICY);
 
 	device->flags &= ~KGSL_FLAGS_SOFT_RESET;
+	pdata = kgsl_device_get_drvdata(device);
+
+	adreno_coresight_init(pdev);
+
 	return 0;
 
 error_close_rb:
@@ -1643,6 +1652,8 @@
 	device = (struct kgsl_device *)pdev->id_entry->driver_data;
 	adreno_dev = ADRENO_DEVICE(device);
 
+	adreno_coresight_remove(pdev);
+
 	kgsl_pwrscale_detach_policy(device);
 	kgsl_pwrscale_close(device);
 
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index fa892b9..77b654b 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -80,6 +80,15 @@
 	ADRENO_REV_A305B = 335,
 };
 
+enum coresight_debug_reg {
+	DEBUG_BUS_CTL,
+	TRACE_STOP_CNT,
+	TRACE_START_CNT,
+	TRACE_PERIOD_CNT,
+	TRACE_CMD,
+	TRACE_BUS_CTL,
+};
+
 struct adreno_gpudev;
 
 struct adreno_device {
@@ -187,6 +196,10 @@
 	uint64_t (*perfcounter_read)(struct adreno_device *adreno_dev,
 		unsigned int group, unsigned int counter,
 		unsigned int offset);
+	int (*coresight_enable) (struct kgsl_device *device);
+	void (*coresight_disable) (struct kgsl_device *device);
+	void (*coresight_config_debug_reg) (struct kgsl_device *device,
+			int debug_reg, unsigned int val);
 };
 
 /*
@@ -269,6 +282,10 @@
 extern unsigned int ft_detect_regs[];
 extern const unsigned int ft_detect_regs_count;
 
+int adreno_coresight_enable(struct coresight_device *csdev);
+void adreno_coresight_disable(struct coresight_device *csdev);
+void adreno_coresight_remove(struct platform_device *pdev);
+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,
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index a4b3121..1cdc87a 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -3235,6 +3235,108 @@
 	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
@@ -3381,4 +3483,7 @@
 	.snapshot = a3xx_snapshot,
 	.perfcounter_enable = a3xx_perfcounter_enable,
 	.perfcounter_read = a3xx_perfcounter_read,
+	.coresight_enable = a3xx_coresight_enable,
+	.coresight_disable = a3xx_coresight_disable,
+	.coresight_config_debug_reg = a3xx_coresight_config_debug_reg,
 };
diff --git a/drivers/gpu/msm/adreno_coresight.c b/drivers/gpu/msm/adreno_coresight.c
new file mode 100644
index 0000000..e18568d
--- /dev/null
+++ b/drivers/gpu/msm/adreno_coresight.c
@@ -0,0 +1,219 @@
+/* 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/clk.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+#include <linux/memory_alloc.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include "kgsl.h"
+#include "kgsl_device.h"
+#include "adreno.h"
+
+struct coresight_attr {
+	struct device_attribute attr;
+	int regname;
+};
+
+#define CORESIGHT_CREATE_REG_ATTR(_attrname, _regname) \
+	struct coresight_attr coresight_attr_##_attrname = \
+	{ __ATTR(_attrname, S_IRUGO | S_IWUSR, gfx_show_reg, gfx_store_reg),\
+		_regname}
+
+/**
+ * adreno_coresight_enable() - Generic function to enable coresight debugging
+ * @csdev: Pointer to coresight's device struct
+ *
+ * This is a generic function to enable coresight debug bus on adreno
+ * devices. This should be used in all cases of enabling
+ * coresight debug bus for adreno devices. This function in turn calls
+ * the adreno device specific function through gpudev hook.
+ * This function is registered as the coresight enable function
+ * with coresight driver. It should only be called through coresight driver
+ * as that would ensure that the necessary setup required to be done
+ * on coresight driver's part is also done.
+ */
+int adreno_coresight_enable(struct coresight_device *csdev)
+{
+	struct kgsl_device *device = dev_get_drvdata(csdev->dev.parent);
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+	/* Check if coresight compatible device, return error otherwise */
+	if (adreno_dev->gpudev->coresight_enable)
+		return adreno_dev->gpudev->coresight_enable(device);
+	else
+		return -ENODEV;
+}
+
+/**
+ * adreno_coresight_disable() - Generic function to disable coresight debugging
+ * @csdev: Pointer to coresight's device struct
+ *
+ * This is a generic function to disable coresight debug bus on adreno
+ * devices. This should be used in all cases of disabling
+ * coresight debug bus for adreno devices. This function in turn calls
+ * the adreno device specific function through the gpudev hook.
+ * This function is registered as the coresight disable function
+ * with coresight driver. It should only be called through coresight driver
+ * as that would ensure that the necessary setup required to be done on
+ * coresight driver's part is also done.
+ */
+void adreno_coresight_disable(struct coresight_device *csdev)
+{
+	struct kgsl_device *device = dev_get_drvdata(csdev->dev.parent);
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+	/* Check if coresight compatible device, bail otherwise */
+	if (adreno_dev->gpudev->coresight_disable)
+		return adreno_dev->gpudev->coresight_disable(device);
+}
+
+static const struct coresight_ops_source adreno_coresight_ops_source = {
+	.enable = adreno_coresight_enable,
+	.disable = adreno_coresight_disable,
+};
+
+static const struct coresight_ops adreno_coresight_cs_ops = {
+	.source_ops = &adreno_coresight_ops_source,
+};
+
+void adreno_coresight_remove(struct platform_device *pdev)
+{
+	struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
+	coresight_unregister(pdata->csdev);
+}
+
+static ssize_t coresight_read_reg(struct kgsl_device *device,
+		unsigned int offset, char *buf)
+{
+	unsigned int regval = 0;
+
+	mutex_lock(&device->mutex);
+	if (!kgsl_active_count_get(device)) {
+		adreno_regread(device, offset, &regval);
+		kgsl_active_count_put(device);
+	}
+	mutex_unlock(&device->mutex);
+	return snprintf(buf, PAGE_SIZE, "0x%X", regval);
+}
+
+static inline unsigned int coresight_convert_reg(const char *buf)
+{
+	long regval = 0;
+	int rv = 0;
+
+	rv = kstrtoul(buf, 16, &regval);
+	if (!rv)
+		return (unsigned int)regval;
+	else
+		return rv;
+}
+
+static ssize_t gfx_show_reg(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kgsl_device *device = dev_get_drvdata(dev->parent);
+	struct coresight_attr *csight_attr = container_of(attr,
+			struct coresight_attr, attr);
+	return coresight_read_reg(device, csight_attr->regname, buf);
+}
+
+static ssize_t gfx_store_reg(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t size)
+{
+	struct kgsl_device *device = dev_get_drvdata(dev->parent);
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct coresight_attr *csight_attr = container_of(attr,
+			struct coresight_attr, attr);
+	unsigned int regval = 0;
+
+	regval = coresight_convert_reg(buf);
+
+	if (adreno_dev->gpudev->coresight_config_debug_reg)
+		adreno_dev->gpudev->coresight_config_debug_reg(device,
+				csight_attr->regname, regval);
+	return size;
+}
+
+CORESIGHT_CREATE_REG_ATTR(config_debug_bus, DEBUG_BUS_CTL);
+CORESIGHT_CREATE_REG_ATTR(config_trace_stop_cnt, TRACE_STOP_CNT);
+CORESIGHT_CREATE_REG_ATTR(config_trace_start_cnt, TRACE_START_CNT);
+CORESIGHT_CREATE_REG_ATTR(config_trace_period_cnt, TRACE_PERIOD_CNT);
+CORESIGHT_CREATE_REG_ATTR(config_trace_cmd, TRACE_CMD);
+CORESIGHT_CREATE_REG_ATTR(config_trace_bus_ctl, TRACE_BUS_CTL);
+
+static struct attribute *gfx_attrs[] = {
+	&coresight_attr_config_debug_bus.attr.attr,
+	&coresight_attr_config_trace_start_cnt.attr.attr,
+	&coresight_attr_config_trace_stop_cnt.attr.attr,
+	&coresight_attr_config_trace_period_cnt.attr.attr,
+	&coresight_attr_config_trace_cmd.attr.attr,
+	&coresight_attr_config_trace_bus_ctl.attr.attr,
+	NULL,
+};
+
+static struct attribute_group gfx_attr_grp = {
+	.attrs = gfx_attrs,
+};
+
+static const struct attribute_group *gfx_attr_grps[] = {
+	&gfx_attr_grp,
+	NULL,
+};
+
+int adreno_coresight_init(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct coresight_desc *desc;
+
+	if (IS_ERR_OR_NULL(pdata->coresight_pdata))
+		return -ENODATA;
+
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+
+
+	desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+	desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS;
+	desc->ops = &adreno_coresight_cs_ops;
+	desc->pdata = pdata->coresight_pdata;
+	desc->dev = &pdev->dev;
+	desc->owner = THIS_MODULE;
+	desc->groups = gfx_attr_grps;
+	pdata->csdev = coresight_register(desc);
+	if (IS_ERR(pdata->csdev)) {
+		ret = PTR_ERR(pdata->csdev);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	devm_kfree(dev, desc);
+	return ret;
+}
+
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index 4579cee..08fa7dd 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -539,7 +539,6 @@
 		rc = msm_create_session(pvdev->vdev->num, pvdev->vdev);
 		if (rc < 0)
 			goto session_fail;
-
 		rc = msm_create_command_ack_q(pvdev->vdev->num, 0);
 		if (rc < 0)
 			goto command_ack_q_fail;
@@ -611,6 +610,7 @@
 
 		/* Donot wait, imaging server may have crashed */
 		msm_post_event(&event, -1);
+		msm_delete_command_ack_q(pvdev->vdev->num, 0);
 
 		/* This should take care of both normal close
 		 * and application crashes */
@@ -622,7 +622,6 @@
 
 		/* Donot wait, imaging server may have crashed */
 		msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
-
 		msm_delete_command_ack_q(pvdev->vdev->num,
 			sp->stream_id);
 
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 8a691c5..5581723 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -413,6 +413,7 @@
 
 	spin_lock_irqsave(&(session->command_ack_q.lock), flags);
 	list_del_init(&cmd_ack->list);
+	kzfree(cmd_ack);
 	session->command_ack_q.len--;
 	spin_unlock_irqrestore(&(session->command_ack_q.lock), flags);
 }
diff --git a/drivers/platform/msm/qpnp-pwm.c b/drivers/platform/msm/qpnp-pwm.c
index 442d18f..be62408 100644
--- a/drivers/platform/msm/qpnp-pwm.c
+++ b/drivers/platform/msm/qpnp-pwm.c
@@ -914,7 +914,7 @@
 
 static inline int qpnp_enable_pwm_mode(struct qpnp_pwm_config *pwm_conf)
 {
-	if (pwm_conf->channel_id >= QPNP_GPLED_LPG_CHANNEL_RANGE_START ||
+	if (pwm_conf->channel_id >= QPNP_GPLED_LPG_CHANNEL_RANGE_START &&
 		pwm_conf->channel_id <= QPNP_GPLED_LPG_CHANNEL_RANGE_END)
 		return QPNP_ENABLE_PWM_MODE_GPLED_CHANNEL;
 	return QPNP_ENABLE_PWM_MODE;
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index e4affc1..af5442a 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -133,11 +133,11 @@
 	enum ipa_rm_event cur_prod_state[MAX_BAMS];
 	enum ipa_rm_event cur_cons_state[MAX_BAMS];
 
-	int lpm_wait_handshake;
+	bool lpm_wait_handshake[MAX_BAMS];
 	int connect_complete;
 	bool lpm_wait_pipes;
 	int bus_suspend;
-	bool in_lpm;
+	bool in_lpm[MAX_BAMS];
 
 	int (*wake_cb)(void *);
 	void *wake_param;
@@ -169,8 +169,31 @@
 static struct usb_bam_pipe_connect *usb_bam_connections;
 static struct usb_bam_ctx_type ctx;
 
+static struct device *hsic_host_dev;
+
 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)
+{
+	if (dev) {
+		/* Hold the device until allowing lpm */
+		info.in_lpm[HSIC_BAM] = false;
+		pr_debug("%s: Getting hsic device %x\n", __func__,
+			(int)dev);
+		pm_runtime_get(dev);
+	} else if (hsic_host_dev) {
+		pr_debug("%s: Putting hsic device %x\n", __func__,
+			(int)hsic_host_dev);
+		/* Just free previous device*/
+		info.in_lpm[HSIC_BAM] = true;
+		pm_runtime_put(hsic_host_dev);
+	}
+
+	hsic_host_dev = dev;
+}
 
 static int get_bam_type_from_core_name(const char *name)
 {
@@ -209,6 +232,8 @@
 	struct sps_pipe *pipe = NULL;
 	int i;
 
+	pr_debug("%s: enter\n", __func__);
+
 	/*
 	 * Since we configure global incativity timer for all pipes
 	 * and not per each pipe, it is enough to use some pipe
@@ -217,14 +242,15 @@
 	 */
 	for (i = 0; i < ctx.max_connections; i++) {
 		pipe_connect = &usb_bam_connections[i];
-		if (pipe_connect->bam_type == bam) {
+		if (pipe_connect->bam_type == bam &&
+		    pipe_connect->enabled) {
 			pipe = ctx.usb_bam_sps.sps_pipes[i];
 			break;
 		}
 	}
 
 	if (!pipe) {
-		pr_err("%s: Bam %s has no pipes\n", __func__,
+		pr_warning("%s: Bam %s has no connected pipes\n", __func__,
 			bam_enable_strings[bam]);
 		return;
 	}
@@ -540,16 +566,6 @@
 		goto error;
 	}
 
-	spin_lock(&usb_bam_lock);
-
-	/* Set global inactivity timer upon first pipe connection */
-	if (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0 &&
-		ctx.inactivity_timer_ms[pipe_connect->bam_type] &&
-		pipe_connect->inactivity_notify)
-		usb_bam_set_inactivity_timer(pipe_connect->bam_type);
-
-	spin_unlock(&usb_bam_lock);
-
 	return 0;
 
 error:
@@ -622,7 +638,7 @@
 	BUG_ON(trans == NULL);
 		pr_debug("%s: Going to LPM\n", __func__);
 	spin_lock(&usb_bam_ipa_handshake_info_lock);
-	info.lpm_wait_handshake = false;
+	info.lpm_wait_handshake[HSUSB_BAM] = false;
 		info.lpm_wait_pipes = 0;
 	if (disconnect)
 		pm_runtime_put_noidle(trans->dev);
@@ -813,8 +829,40 @@
 	return;
 }
 
+static void usb_bam_resume_hsic_host(void)
+{
+	int i;
+	struct usb_bam_pipe_connect *pipe_iter;
+
+	spin_lock(&usb_bam_lock);
+
+	/* Exit from "full suspend" in case of hsic host */
+	if (hsic_host_dev && info.in_lpm[HSIC_BAM]) {
+		pr_debug("%s: Getting hsic device %x\n", __func__,
+			(int)hsic_host_dev);
+		pm_runtime_get(hsic_host_dev);
+		info.in_lpm[HSIC_BAM] = false;
+
+		for (i = 0; i < ctx.max_connections; i++) {
+			pipe_iter = &usb_bam_connections[i];
+			if (pipe_iter->bam_type == HSIC_BAM &&
+			    pipe_iter->enabled &&
+			    pipe_iter->suspended) {
+				spin_unlock(&usb_bam_lock);
+				ipa_resume(pipe_iter->ipa_clnt_hdl);
+				pipe_iter->suspended = false;
+				spin_lock(&usb_bam_lock);
+			}
+		}
+	}
+
+	spin_unlock(&usb_bam_lock);
+}
+
 static int cons_request_resource(enum usb_bam cur_bam)
 {
+	int ret = -EINPROGRESS;
+
 	pr_debug("%s: Request %s_CONS resource\n",
 			__func__, bam_enable_strings[cur_bam]);
 
@@ -823,29 +871,44 @@
 	complete_all(&info.cons_avail[cur_bam]);
 
 	spin_lock(&usb_bam_lock);
-	if (ctx.pipes_enabled_per_bam[cur_bam] && info.connect_complete &&
-				!info.bus_suspend && !info.prod_stopped) {
-		spin_unlock(&usb_bam_lock);
-		spin_unlock(&usb_bam_ipa_handshake_info_lock);
-		pr_debug("%s: ACK on cons_request", __func__);
-		return 0;
+
+	switch (cur_bam) {
+	case HSUSB_BAM:
+		if (ctx.pipes_enabled_per_bam[HSUSB_BAM] &&
+		    info.connect_complete &&
+			!info.cons_stopped && !info.prod_stopped) {
+			pr_debug("%s: ACK on cons_request", __func__);
+			ret = 0;
+		} else if (ctx.pipes_enabled_per_bam[HSUSB_BAM] &&
+				   info.connect_complete && info.bus_suspend) {
+			info.bus_suspend = 0;
+			if (info.wake_cb)
+				info.wake_cb(info.wake_param);
+		}
+
+		break;
+	case HSIC_BAM:
+			usb_bam_resume_hsic_host();
+
+			/*
+			 * Return sucess if there are pipes connected
+			 * and not in lpm
+			 */
+			if (ctx.pipes_enabled_per_bam[cur_bam] &&
+			    !info.in_lpm[cur_bam])
+				ret = 0;
+		break;
+	case SSUSB_BAM:
+	default:
+		break;
 	}
 
-	/* A2 wakeup from LPM */
-	if (cur_bam == HSUSB_BAM && ctx.pipes_enabled_per_bam[cur_bam] &&
-		info.connect_complete && info.bus_suspend) {
-		info.bus_suspend = 0;
-		spin_unlock(&usb_bam_lock);
-		spin_unlock(&usb_bam_ipa_handshake_info_lock);
-		if (info.wake_cb)
-			info.wake_cb(info.wake_param);
-	} else {
-		spin_unlock(&usb_bam_lock);
-		spin_unlock(&usb_bam_ipa_handshake_info_lock);
-	}
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	spin_unlock(&usb_bam_lock);
 
-	pr_debug("%s: EINPROGRESS on cons_request", __func__);
-	return -EINPROGRESS;
+	if (ret == -EINPROGRESS)
+		pr_debug("%s: EINPROGRESS on cons_request", __func__);
+	return ret;
 }
 
 static int usb_cons_request_resource(void)
@@ -934,7 +997,7 @@
 	}
 }
 
-static void wait_for_prod_granted(enum usb_bam cur_bam)
+static void wait_for_prod_granted(enum usb_bam cur_bam, bool start_cons)
 {
 	int ret;
 
@@ -948,7 +1011,8 @@
 			__func__);
 
 	init_completion(&info.prod_avail[cur_bam]);
-	init_completion(&info.cons_avail[cur_bam]);
+	if (start_cons)
+		init_completion(&info.cons_avail[cur_bam]);
 
 	ret = ipa_rm_request_resource(ipa_rm_resource_prod[cur_bam]);
 	if (!ret) {
@@ -1129,7 +1193,7 @@
 	}
 
 	spin_lock(&usb_bam_ipa_handshake_info_lock);
-	info.lpm_wait_handshake = true;
+	info.lpm_wait_handshake[HSUSB_BAM] = true;
 	spin_unlock(&usb_bam_ipa_handshake_info_lock);
 
 	wait_for_prod_release(HSUSB_BAM);
@@ -1156,10 +1220,10 @@
 		mutex_unlock(&info.suspend_resume_mutex);
 		return;
 	}
-	info.lpm_wait_handshake = true;
+	info.lpm_wait_handshake[HSUSB_BAM] = true;
 	spin_unlock(&usb_bam_ipa_handshake_info_lock);
 
-	wait_for_prod_granted(HSUSB_BAM);
+	wait_for_prod_granted(HSUSB_BAM, true);
 	wait_for_cons_granted(HSUSB_BAM);
 	if (info.cons_stopped) {
 		ipa_resume_pipes();
@@ -1213,13 +1277,115 @@
 	if (cur_bam != HSUSB_BAM)
 		return;
 
-	info.in_lpm = false;
+	info.in_lpm[HSUSB_BAM] = false;
 	spin_lock(&usb_bam_ipa_handshake_info_lock);
 	info.bus_suspend = 0;
 	spin_unlock(&usb_bam_ipa_handshake_info_lock);
 	queue_work(ctx.usb_bam_wq, &info.resume_work);
 }
 
+void msm_bam_wait_for_hsic_prod_granted(void)
+{
+	ctx.is_bam_inactivity[HSIC_BAM] = false;
+
+	/* Get back to resume state including wakeup ipa */
+	usb_bam_resume_hsic_host();
+
+	/* Ensure getting the producer resource */
+	wait_for_prod_granted(HSIC_BAM, false);
+}
+
+void msm_bam_hsic_notify_on_resume(void)
+{
+	/*
+	 * This function is called to notify the usb bam driver
+	 * that the hsic core and hsic bam hw are fully resumed
+	 * and clocked on. Therefore we can now set the inactivity
+	 * timer to the hsic bam hw.
+	 */
+	if (ctx.inactivity_timer_ms[HSIC_BAM])
+		usb_bam_set_inactivity_timer(HSIC_BAM);
+}
+
+bool msm_bam_hsic_lpm_ok(void)
+{
+	int i;
+	struct usb_bam_pipe_connect *pipe_iter;
+
+	if (hsic_host_dev) {
+
+		pr_debug("%s: Starting hsic full suspend sequence\n",
+			__func__);
+
+		info.lpm_wait_handshake[HSIC_BAM] = true;
+
+		wait_for_prod_release(HSIC_BAM);
+		pr_debug("%s: complete wait on hsic producer s=%d\n",
+			__func__, info.cur_prod_state[HSIC_BAM]);
+
+		wait_for_cons_release(HSIC_BAM);
+		pr_debug("%s: complete wait on hsic consumer s=%d\n",
+			__func__, info.cur_cons_state[HSIC_BAM]);
+
+		info.lpm_wait_handshake[HSIC_BAM] = false;
+
+		/*
+		 * Start low power mode by releasing the device
+		 * only in case that indeed the resources were released
+		 * and we are still in inactivity state (wake event
+		 * have not been occured while we were waiting to the
+		 * resources release)
+		 */
+		spin_lock(&usb_bam_lock);
+
+		pr_debug("%s: goto lpm?, inactivity=%d\n",
+			__func__, ctx.is_bam_inactivity[HSIC_BAM]);
+
+		if (info.cur_cons_state[HSIC_BAM] ==
+			IPA_RM_RESOURCE_RELEASED &&
+		    info.cur_prod_state[HSIC_BAM] ==
+			IPA_RM_RESOURCE_RELEASED &&
+		    ctx.is_bam_inactivity[HSIC_BAM] && info.in_lpm[HSIC_BAM]) {
+
+			/* HSIC host will go now to lpm */
+			pr_debug("%s: vote for suspend hsic %x\n",
+				__func__, (int)hsic_host_dev);
+
+			for (i = 0; i < ctx.max_connections; i++) {
+				pipe_iter =
+					&usb_bam_connections[i];
+				if (pipe_iter->bam_type == HSIC_BAM &&
+				    pipe_iter->enabled &&
+				    !pipe_iter->suspended) {
+					spin_unlock(&usb_bam_lock);
+					ipa_suspend(
+					   pipe_iter->ipa_clnt_hdl);
+					pipe_iter->suspended = true;
+					spin_lock(&usb_bam_lock);
+				}
+			}
+
+			spin_unlock(&usb_bam_lock);
+			return true;
+		}
+
+		/* We not allow lpm, therefore renew our vote here */
+		if (info.in_lpm[HSIC_BAM]) {
+			pr_debug("%s: Getting hsic device %x\n", __func__,
+			(int)hsic_host_dev);
+			pm_runtime_get(hsic_host_dev);
+			info.in_lpm[HSIC_BAM] = false;
+			spin_unlock(&usb_bam_lock);
+			wait_for_prod_granted(HSIC_BAM, false);
+		} else
+			spin_unlock(&usb_bam_lock);
+
+		return false;
+	}
+
+	return true;
+}
+
 int usb_bam_connect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
 {
 	u8 idx;
@@ -1255,52 +1421,77 @@
 	}
 
 	pr_debug("%s: enter", __func__);
-	mutex_lock(&info.suspend_resume_mutex);
 
-	spin_lock(&usb_bam_lock);
-	if (ctx.pipes_enabled_per_bam[cur_bam] == 0) {
-		spin_unlock(&usb_bam_lock);
-		if (cur_bam == HSUSB_BAM) {
+	if (cur_bam == HSUSB_BAM) {
+		mutex_lock(&info.suspend_resume_mutex);
+
+		spin_lock(&usb_bam_lock);
+		if (ctx.pipes_enabled_per_bam[HSUSB_BAM] == 0) {
+			spin_unlock(&usb_bam_lock);
 			spin_lock(&usb_bam_ipa_handshake_info_lock);
-			info.lpm_wait_handshake = 1;
+			info.lpm_wait_handshake[HSUSB_BAM] = true;
 			info.connect_complete = 0;
 			info.lpm_wait_pipes = 1;
 			info.bus_suspend = 0;
 			info.cons_stopped = 0;
 			info.prod_stopped = 0;
 			spin_unlock(&usb_bam_ipa_handshake_info_lock);
-		}
-		usb_bam_resume_core(cur_bam);
-	} else
-		spin_unlock(&usb_bam_lock);
+			usb_bam_resume_core(cur_bam);
+		} else
+			spin_unlock(&usb_bam_lock);
+	}
 
 	 /* Check if BAM requires RESET before connect and reset first pipe */
 	 spin_lock(&usb_bam_lock);
 	 if ((pdata->reset_on_connect[cur_bam] == true) &&
-		 (ctx.pipes_enabled_per_bam[cur_bam] == 0))
-			sps_device_reset(ctx.h_bam[cur_bam]);
+	     (ctx.pipes_enabled_per_bam[cur_bam] == 0)) {
+		spin_unlock(&usb_bam_lock);
+		sps_device_reset(ctx.h_bam[cur_bam]);
+
+		/* On re-connect assume out from lpm for HSIC BAM */
+		if (cur_bam == HSIC_BAM && hsic_host_dev &&
+		    info.in_lpm[HSIC_BAM]) {
+			pr_debug("%s: Getting hsic device %x\n",
+					__func__, (int)hsic_host_dev);
+			pm_runtime_get(hsic_host_dev);
+		}
+
+		/* On re-connect assume out from lpm for all BAMs */
+		info.in_lpm[cur_bam] = false;
+	 } else
 		spin_unlock(&usb_bam_lock);
 
 	if (ipa_params->dir == USB_TO_PEER_PERIPHERAL) {
 		pr_debug("%s: Starting connect sequence\n", __func__);
-		wait_for_prod_granted(cur_bam);
+		wait_for_prod_granted(cur_bam, true);
 	}
 
 	ret = connect_pipe_ipa(idx, ipa_params);
 	if (ret) {
 		pr_err("%s: pipe connection failure\n", __func__);
-		mutex_unlock(&info.suspend_resume_mutex);
+		if (cur_bam == HSUSB_BAM)
+			mutex_unlock(&info.suspend_resume_mutex);
 		return ret;
 	}
 
 	spin_lock(&usb_bam_lock);
 	pipe_connect->enabled = 1;
+	pipe_connect->suspended = 0;
+
+	/* Set global inactivity timer upon first pipe connection */
+	if (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0 &&
+		ctx.inactivity_timer_ms[pipe_connect->bam_type] &&
+		pipe_connect->inactivity_notify)
+		usb_bam_set_inactivity_timer(pipe_connect->bam_type);
+
 	ctx.pipes_enabled_per_bam[cur_bam] += 1;
 	spin_unlock(&usb_bam_lock);
 	if (ipa_params->dir == PEER_PERIPHERAL_TO_USB && cur_bam == HSUSB_BAM)
 		wait_for_cons_granted(cur_bam);
 
-	mutex_unlock(&info.suspend_resume_mutex);
+	if (cur_bam == HSUSB_BAM)
+		mutex_unlock(&info.suspend_resume_mutex);
+
 	pr_debug("%s: done", __func__);
 
 	return 0;
@@ -1337,7 +1528,7 @@
 		container_of(w, struct usb_bam_event_info, event_w);
 	struct usb_bam_pipe_connect *pipe_connect =
 		container_of(event_info, struct usb_bam_pipe_connect, event);
-	struct usb_bam_pipe_connect *pipe_connect_iter;
+	struct usb_bam_pipe_connect *pipe_iter;
 	int (*callback)(void *priv);
 	void *param = NULL;
 
@@ -1347,8 +1538,33 @@
 
 		pr_debug("%s recieved USB_BAM_EVENT_WAKEUP\n", __func__);
 
+		/*
+		 * Make sure the PROD resource is granted before
+		 * wakeup hsic host class driver (done by the callback below)
+		 */
+		if (pipe_connect->peer_bam == IPA_P_BAM &&
+		    pipe_connect->bam_type == HSIC_BAM &&
+		    info.cur_prod_state[HSIC_BAM] != IPA_RM_RESOURCE_GRANTED) {
+			wait_for_prod_granted(HSIC_BAM, false);
+		}
+
+		/*
+		 * Check if need to resume the hsic host.
+		 * On one hand, since we got the wakeup interrupt
+		 * the hsic bam clocks are already enabled, so no need
+		 * to actualluy resume the hardware... However, we still need
+		 * to update the usb bam driver state (to set in_lpm=false),
+		 * and to wake ipa (ipa_resume) and to hold again the hsic host
+		 * device again to avoid it going to low poer mode next time
+		 * until we complete releasing the hsic consumer and producer
+		 * resources against the ipa resource manager.
+		 */
+		if (pipe_connect->bam_type == HSIC_BAM)
+			usb_bam_resume_hsic_host();
+
 		/* Notify about wakeup / activity of the bam */
-		event_info->callback(event_info->param);
+		if (event_info->callback)
+			event_info->callback(event_info->param);
 
 		/*
 		 * Reset inactivity timer counter if this pipe's bam
@@ -1359,12 +1575,14 @@
 			usb_bam_set_inactivity_timer(pipe_connect->bam_type);
 		spin_unlock(&usb_bam_lock);
 
-		/* A2 wakeup not from LPM (CONS was up) */
-		wait_for_prod_granted(pipe_connect->bam_type);
-		if (info.start) {
-			pr_debug("%s: Enqueue PROD transfer", __func__);
-			info.start(info.start_stop_param,
-					USB_TO_PEER_PERIPHERAL);
+		if (pipe_connect->bam_type == HSUSB_BAM) {
+			/* A2 wakeup not from LPM (CONS was up) */
+			wait_for_prod_granted(pipe_connect->bam_type, true);
+			if (info.start) {
+				pr_debug("%s: Enqueue PROD transfer", __func__);
+				info.start(info.start_stop_param,
+						USB_TO_PEER_PERIPHERAL);
+			}
 		}
 
 		break;
@@ -1389,21 +1607,34 @@
 		 */
 		spin_lock(&usb_bam_lock);
 		for (i = 0; i < ctx.max_connections; i++) {
-			pipe_connect_iter = &usb_bam_connections[i];
-			if (pipe_connect_iter->bam_type ==
+			pipe_iter = &usb_bam_connections[i];
+			if (pipe_iter->bam_type ==
 				pipe_connect->bam_type &&
-			    pipe_connect_iter->dir ==
+			    pipe_iter->dir ==
 				PEER_PERIPHERAL_TO_USB &&
-				pipe_connect_iter->enabled) {
+				pipe_iter->enabled) {
+				pr_debug("%s: Register wakeup on pipe %x\n",
+					__func__, (int)pipe_iter);
 				__usb_bam_register_wake_cb(i,
-					pipe_connect_iter->activity_notify,
-					pipe_connect_iter->priv,
+					pipe_iter->activity_notify,
+					pipe_iter->priv,
 					false);
 			}
 		}
 		spin_unlock(&usb_bam_lock);
 
-		/* Notify about the inactivity */
+		/*
+		 * Allow to go to lpm for now. Actual state will be checked
+		 * in msm_bam_hsic_lpm_ok() just before going to lpm.
+		 */
+		if (hsic_host_dev) {
+			pr_debug("%s: Putting hsic device %x\n", __func__,
+			(int)hsic_host_dev);
+			pm_runtime_put(hsic_host_dev);
+			info.in_lpm[HSIC_BAM] = true;
+		}
+
+		/* Notify about the inactivity to the USB class driver */
 		if (callback)
 			callback(param);
 
@@ -1422,13 +1653,14 @@
 		container_of(event_info,
 			     struct usb_bam_pipe_connect,
 			     event);
+	enum usb_bam bam = pipe_connect->bam_type;
 
 	spin_lock(&usb_bam_lock);
 
 	if (event_info->type == USB_BAM_EVENT_WAKEUP_PIPE)
 		queue_work(ctx.usb_bam_wq, &event_info->event_w);
 	else if (event_info->type == USB_BAM_EVENT_WAKEUP &&
-			ctx.is_bam_inactivity[pipe_connect->bam_type]) {
+			ctx.is_bam_inactivity[bam]) {
 
 		/*
 		 * Sps wake event is per pipe, so usb_bam_wake_cb is
@@ -1437,7 +1669,23 @@
 		 * Therefore, the first pipe that awaked will be considered
 		 * as global bam wake event.
 		 */
-		ctx.is_bam_inactivity[pipe_connect->bam_type] = false;
+		ctx.is_bam_inactivity[bam] = false;
+
+		/*
+		 * In case that this wakeup event occured while we are
+		 * waiting to release of the resurces in order to get into
+		 * low power mode, just cancle the waiting.
+		 */
+		if (info.lpm_wait_handshake[bam]) {
+			pr_debug("%s: cancel waiting for lpm\n", __func__);
+			if (info.cur_prod_state[bam] !=
+			    IPA_RM_RESOURCE_RELEASED)
+				complete_all(&info.prod_released[bam]);
+			if (info.cur_cons_state[bam] !=
+			    IPA_RM_RESOURCE_RELEASED)
+				complete_all(&info.cons_released[bam]);
+		}
+
 		queue_work(ctx.usb_bam_wq, &event_info->event_w);
 	}
 
@@ -1687,6 +1935,10 @@
 		idx = ipa_params->dst_idx;
 		pipe_connect = &usb_bam_connections[idx];
 
+		pipe_connect->activity_notify = NULL;
+		pipe_connect->inactivity_notify = NULL;
+		pipe_connect->priv = NULL;
+
 		/* Do the release handshake with the A2 via RM */
 		cur_bam = pipe_connect->bam_type;
 		info.lpm_wait_pipes = 1;
@@ -1716,6 +1968,11 @@
 	if (ipa_params->cons_clnt_hdl) {
 		idx = ipa_params->src_idx;
 		pipe_connect = &usb_bam_connections[idx];
+
+		pipe_connect->activity_notify = NULL;
+		pipe_connect->inactivity_notify = NULL;
+		pipe_connect->priv = NULL;
+
 		cur_bam = pipe_connect->bam_type;
 		wait_for_cons_release(cur_bam);
 		/* close IPA -> USB pipe */
@@ -1839,9 +2096,11 @@
 
 			/*
 			 * Notify inactivity once, Since it is global
-			 * for all pipes on bam.
+			 * for all pipes on bam. Notify only if we have
+			 * connected pipes.
 			 */
-			if (pipe_connect->bam_type == bam) {
+			if (pipe_connect->bam_type == bam &&
+			    pipe_connect->enabled) {
 				event_info = &pipe_connect->event;
 				event_info->type = USB_BAM_EVENT_INACTIVITY;
 				event_info->param = pipe_connect->priv;
@@ -2191,7 +2450,8 @@
 			/* Apply new timer setting if bam has running pipes */
 			if (ctx.inactivity_timer_ms[bam] != timer_d) {
 				ctx.inactivity_timer_ms[bam] = timer_d;
-				if (ctx.pipes_enabled_per_bam[bam] > 0)
+				if (ctx.pipes_enabled_per_bam[bam] > 0 &&
+				    !info.in_lpm[bam])
 					usb_bam_set_inactivity_timer(bam);
 			}
 
@@ -2264,6 +2524,7 @@
 		complete(&info.prod_released[i]);
 		info.cur_prod_state[i] = IPA_RM_RESOURCE_RELEASED;
 		info.cur_cons_state[i] = IPA_RM_RESOURCE_RELEASED;
+		info.lpm_wait_handshake[i] = false;
 	}
 
 	INIT_WORK(&info.resume_work, usb_bam_finish_resume);
@@ -2361,12 +2622,12 @@
 bool msm_bam_lpm_ok(void)
 {
 	spin_lock(&usb_bam_ipa_handshake_info_lock);
-	if (info.lpm_wait_handshake || info.lpm_wait_pipes) {
+	if (info.lpm_wait_handshake[HSUSB_BAM] || info.lpm_wait_pipes) {
 		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Scheduling LPM for later\n", __func__);
 		return 0;
 	} else {
-		info.in_lpm = 1;
+		info.in_lpm[HSUSB_BAM] = true;
 		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Going to LPM now\n", __func__);
 		return 1;
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index d1d0f91..0ea9778 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -752,6 +752,19 @@
 		return -EBUSY;
 	}
 
+	if (pdata->consider_ipa_handshake) {
+		dev_dbg(mehci->dev, "%s:Wait for resources release\n",
+			__func__);
+		if (!msm_bam_hsic_lpm_ok()) {
+			dev_dbg(mehci->dev, "%s:Prod+Cons not released\n",
+			__func__);
+			enable_irq(hcd->irq);
+			return -EBUSY;
+		}
+		dev_dbg(mehci->dev, "%s:Prod+Cons resources released\n",
+			__func__);
+	}
+
 	/*
 	 * 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
@@ -829,7 +842,7 @@
 
 	wake_unlock(&mehci->wlock);
 
-	dev_dbg(mehci->dev, "HSIC-USB in low power mode\n");
+	dev_info(mehci->dev, "HSIC-USB in low power mode\n");
 
 	return 0;
 }
@@ -848,6 +861,14 @@
 		return 0;
 	}
 
+	if (pdata->consider_ipa_handshake) {
+		dev_dbg(mehci->dev, "%s:Wait for producer resource\n",
+			__func__);
+		msm_bam_wait_for_hsic_prod_granted();
+		dev_dbg(mehci->dev, "%s:Producer resource obtained\n",
+			__func__);
+	}
+
 	/* Handles race with Async interrupt */
 	disable_irq(hcd->irq);
 
@@ -933,7 +954,13 @@
 	}
 
 	enable_irq(hcd->irq);
-	dev_dbg(mehci->dev, "HSIC-USB exited from low power mode\n");
+	dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
+
+	if (pdata->consider_ipa_handshake) {
+		dev_dbg(mehci->dev, "%s:Notify usb bam on resume complete\n",
+			__func__);
+		msm_bam_hsic_notify_on_resume();
+	}
 
 	return 0;
 }
@@ -1853,6 +1880,8 @@
 				"qcom,enable-hbm");
 	pdata->disable_park_mode = (of_property_read_bool(node,
 				"qcom,disable-park-mode"));
+	pdata->consider_ipa_handshake = (of_property_read_bool(node,
+				"hsic,consider-ipa-handshake"));
 
 	return pdata;
 }
@@ -2092,6 +2121,8 @@
 	if (mehci->enable_hbm)
 		hbm_init(hcd, pdata->disable_park_mode);
 
+	msm_bam_set_hsic_host_dev(&pdev->dev);
+
 	return 0;
 
 destroy_wq:
@@ -2115,6 +2146,8 @@
 	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
 	struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
 
+	msm_bam_set_hsic_host_dev(NULL);
+
 	/* If the device was removed no need to call pm_runtime_disable */
 	if (pdev->dev.power.power_state.event != PM_EVENT_INVALID)
 		pm_runtime_disable(&pdev->dev);
diff --git a/drivers/video/msm/mdss/mhl_msc.c b/drivers/video/msm/mdss/mhl_msc.c
index 08d0693..15811bb 100644
--- a/drivers/video/msm/mdss/mhl_msc.c
+++ b/drivers/video/msm/mdss/mhl_msc.c
@@ -201,6 +201,22 @@
 	return 0;
 }
 
+int mhl_msc_clear(struct mhl_tx_ctrl *mhl_ctrl)
+{
+	if (!mhl_ctrl)
+		return -EFAULT;
+
+	memset(mhl_ctrl->devcap, 0, 16);
+	mhl_ctrl->devcap_state = 0;
+	mhl_ctrl->path_en_state = 0;
+	mhl_ctrl->status[0] = 0;
+	mhl_ctrl->status[1] = 0;
+	mhl_ctrl->scrpd_busy = 0;
+	mhl_ctrl->wr_burst_pending = 0;
+
+	return 0;
+}
+
 int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl,
 			 struct msc_command_struct *req)
 {
@@ -541,7 +557,7 @@
 		 * connected device bits
 		 * changed and DEVCAP READY
 		 */
-		if (((value ^ mhl_ctrl->devcap_state) &
+		if (((value ^ mhl_ctrl->status[offset]) &
 		     MHL_STATUS_DCAP_RDY)) {
 			if (value & MHL_STATUS_DCAP_RDY) {
 				mhl_ctrl->devcap_state = 0;
@@ -563,7 +579,7 @@
 		 * bit set
 		 */
 		tmds_en = mhl_check_tmds_enabled(mhl_ctrl);
-		if ((value ^ mhl_ctrl->path_en_state)
+		if ((value ^ mhl_ctrl->status[offset])
 		    & MHL_STATUS_PATH_ENABLED) {
 			if (value & MHL_STATUS_PATH_ENABLED) {
 				if (tmds_en &&
@@ -593,7 +609,7 @@
 		}
 		break;
 	}
-	mhl_ctrl->path_en_state = value;
+	mhl_ctrl->status[offset] = value;
 	return 0;
 }
 
diff --git a/drivers/video/msm/mdss/mhl_msc.h b/drivers/video/msm/mdss/mhl_msc.h
index 8a1fd39..3137f17 100644
--- a/drivers/video/msm/mdss/mhl_msc.h
+++ b/drivers/video/msm/mdss/mhl_msc.h
@@ -25,6 +25,8 @@
 
 /******************************************************************/
 /* the below APIs are implemented by the MSC functionality */
+int mhl_msc_clear(struct mhl_tx_ctrl *mhl_ctrl);
+
 int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl,
 			 struct msc_command_struct *req);
 
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 3c11317..a1053fb 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -867,6 +867,7 @@
 	/* disabling Tx termination */
 	MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0xD0);
 	switch_mode(mhl_ctrl, POWER_STATE_D3, true);
+	mhl_msc_clear(mhl_ctrl);
 }
 
 static int  mhl_msm_read_rgnd_int(struct mhl_tx_ctrl *mhl_ctrl)
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index a66a411..f04bf80 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -146,6 +146,7 @@
 	struct completion msc_cmd_done;
 	uint8_t devcap[16];
 	uint8_t devcap_state;
+	uint8_t status[2];
 	uint8_t path_en_state;
 	void *hdmi_mhl_ops;
 	struct work_struct mhl_msc_send_work;
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 4ae3b79..209062b 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -424,6 +424,7 @@
 	bool pool_64_bit_align;
 	bool enable_hbm;
 	bool disable_park_mode;
+	bool consider_ipa_handshake;
 };
 
 struct msm_usb_host_platform_data {
@@ -465,8 +466,16 @@
 };
 #ifdef CONFIG_USB_BAM
 bool msm_bam_lpm_ok(void);
+void msm_bam_set_hsic_host_dev(struct device *dev);
+void msm_bam_wait_for_hsic_prod_granted(void);
+bool msm_bam_hsic_lpm_ok(void);
+void msm_bam_hsic_notify_on_resume(void);
 #else
 static inline bool msm_bam_lpm_ok(void) { return true; }
+static inline void msm_bam_set_hsic_host_dev(struct device *dev) {}
+static inline void msm_bam_wait_for_hsic_prod_granted(void) {}
+static inline bool msm_bam_hsic_lpm_ok(void) { return true; }
+static inline void msm_bam_hsic_notify_on_resume(void) {}
 #endif
 #ifdef CONFIG_USB_CI13XXX_MSM
 void msm_hw_bam_disable(bool bam_disable);
diff --git a/include/sound/Kbuild b/include/sound/Kbuild
index edadaa9..60847b0 100644
--- a/include/sound/Kbuild
+++ b/include/sound/Kbuild
@@ -12,3 +12,4 @@
 header-y += compress_params.h
 header-y += compress_offload.h
 header-y += lsm_params.h
+header-y += voice_params.h
diff --git a/include/sound/voice_params.h b/include/sound/voice_params.h
new file mode 100644
index 0000000..43e3b9d
--- /dev/null
+++ b/include/sound/voice_params.h
@@ -0,0 +1,14 @@
+#ifndef __VOICE_PARAMS_H__
+#define __VOICE_PARAMS_H__
+
+#include <linux/types.h>
+#include <sound/asound.h>
+
+enum voice_lch_mode {
+	VOICE_LCH_START = 1,
+	VOICE_LCH_STOP
+};
+
+#define SNDRV_VOICE_IOCTL_LCH _IOW('U', 0x00, enum voice_lch_mode)
+
+#endif
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 25bb72f..506eae8 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -281,6 +281,58 @@
 	return ret;
 }
 
+static int msm_pcm_ioctl(struct snd_pcm_substream *substream,
+			 unsigned int cmd, void *arg)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_voice *prtd = runtime->private_data;
+	uint16_t session_id = get_session_id(prtd);
+	enum voice_lch_mode lch_mode;
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_VOICE_IOCTL_LCH:
+		if (copy_from_user(&lch_mode, (void *)arg,
+				   sizeof(enum voice_lch_mode))) {
+			pr_err("%s: Copy from user failed, size %d\n", __func__,
+			       sizeof(enum voice_lch_mode));
+
+			ret = -EFAULT;
+			break;
+		}
+
+		pr_debug("%s: %s lch_mode:%d\n",
+			 __func__, substream->pcm->id, lch_mode);
+
+		switch (lch_mode) {
+		case VOICE_LCH_START:
+		case VOICE_LCH_STOP:
+			ret = voc_set_lch(session_id, lch_mode);
+			break;
+
+		default:
+			pr_err("%s: Invalid LCH MODE %d\n", __func__, lch_mode);
+
+			ret = -EFAULT;
+		}
+
+		break;
+	default:
+		pr_debug("%s: Falling into default snd_lib_ioctl cmd 0x%x\n",
+			 __func__, cmd);
+
+		ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+		break;
+	}
+
+	if (!ret)
+		pr_debug("%s: ret %d\n", __func__, ret);
+	else
+		pr_err("%s: cmd 0x%x failed %d\n", __func__, cmd, ret);
+
+	return ret;
+}
+
 static int msm_voice_volume_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -581,11 +633,12 @@
 };
 
 static struct snd_pcm_ops msm_pcm_ops = {
-	.open           = msm_pcm_open,
-	.hw_params	= msm_pcm_hw_params,
-	.close          = msm_pcm_close,
-	.prepare        = msm_pcm_prepare,
-	.trigger	= msm_pcm_trigger,
+	.open			= msm_pcm_open,
+	.hw_params		= msm_pcm_hw_params,
+	.close			= msm_pcm_close,
+	.prepare		= msm_pcm_prepare,
+	.trigger		= msm_pcm_trigger,
+	.ioctl			= msm_pcm_ioctl,
 };
 
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 5f89e4a..d7e1ef0 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -1444,6 +1444,34 @@
 	return -EINVAL;
 }
 
+static void voc_get_tx_rx_topology(struct voice_data *v,
+				   uint32_t *tx_topology_id,
+				   uint32_t *rx_topology_id)
+{
+	uint32_t tx_id = 0;
+	uint32_t rx_id = 0;
+
+	if (v->lch_mode == VOICE_LCH_START) {
+		pr_debug("%s: Setting TX and RX topology to NONE for LCH\n",
+			 __func__);
+
+		tx_id = VSS_IVOCPROC_TOPOLOGY_ID_NONE;
+		rx_id = VSS_IVOCPROC_TOPOLOGY_ID_NONE;
+	} else {
+		/* Use default topology if invalid value in ACDB */
+		tx_id = get_voice_tx_topology();
+		if (tx_id == 0)
+			tx_id = VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS;
+
+		rx_id = get_voice_rx_topology();
+		if (rx_id == 0)
+			rx_id = VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
+	}
+
+	*tx_topology_id = tx_id;
+	*rx_topology_id = rx_id;
+}
+
 static int voice_send_set_device_cmd(struct voice_data *v)
 {
 	struct cvp_set_device_cmd  cvp_setdev_cmd;
@@ -1474,26 +1502,22 @@
 	cvp_setdev_cmd.hdr.src_port = v->session_id;
 	cvp_setdev_cmd.hdr.dest_port = cvp_handle;
 	cvp_setdev_cmd.hdr.token = 0;
-	cvp_setdev_cmd.hdr.opcode = VSS_IVOCPROC_CMD_SET_DEVICE;
+	cvp_setdev_cmd.hdr.opcode = VSS_IVOCPROC_CMD_SET_DEVICE_V2;
 
-	/* Use default topology if invalid value in ACDB */
-	cvp_setdev_cmd.cvp_set_device.tx_topology_id =
-				get_voice_tx_topology();
-	if (cvp_setdev_cmd.cvp_set_device.tx_topology_id == 0)
-		cvp_setdev_cmd.cvp_set_device.tx_topology_id =
-				VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS;
+	voc_get_tx_rx_topology(v,
+			&cvp_setdev_cmd.cvp_set_device_v2.tx_topology_id,
+			&cvp_setdev_cmd.cvp_set_device_v2.rx_topology_id);
 
-	cvp_setdev_cmd.cvp_set_device.rx_topology_id =
-				get_voice_rx_topology();
-	if (cvp_setdev_cmd.cvp_set_device.rx_topology_id == 0)
-		cvp_setdev_cmd.cvp_set_device.rx_topology_id =
-				VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
-	cvp_setdev_cmd.cvp_set_device.tx_port_id = v->dev_tx.port_id;
-	cvp_setdev_cmd.cvp_set_device.rx_port_id = v->dev_rx.port_id;
+	cvp_setdev_cmd.cvp_set_device_v2.tx_port_id = v->dev_tx.port_id;
+	cvp_setdev_cmd.cvp_set_device_v2.rx_port_id = v->dev_rx.port_id;
+	cvp_setdev_cmd.cvp_set_device_v2.vocproc_mode =
+				    VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING;
+	cvp_setdev_cmd.cvp_set_device_v2.ec_ref_port_id =
+				    VSS_IVOCPROC_PORT_ID_NONE;
 	pr_debug("topology=%d , tx_port_id=%d, rx_port_id=%d\n",
-		cvp_setdev_cmd.cvp_set_device.tx_topology_id,
-		cvp_setdev_cmd.cvp_set_device.tx_port_id,
-		cvp_setdev_cmd.cvp_set_device.rx_port_id);
+		cvp_setdev_cmd.cvp_set_device_v2.tx_topology_id,
+		cvp_setdev_cmd.cvp_set_device_v2.tx_port_id,
+		cvp_setdev_cmd.cvp_set_device_v2.rx_port_id);
 
 	v->cvp_state = CMD_STATUS_FAIL;
 	ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_setdev_cmd);
@@ -2249,18 +2273,9 @@
 	cvp_session_cmd.hdr.opcode =
 			VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2;
 
-	/* Use default topology if invalid value in ACDB */
-	cvp_session_cmd.cvp_session.tx_topology_id =
-				get_voice_tx_topology();
-	if (cvp_session_cmd.cvp_session.tx_topology_id == 0)
-		cvp_session_cmd.cvp_session.tx_topology_id =
-			VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS;
-
-	cvp_session_cmd.cvp_session.rx_topology_id =
-				get_voice_rx_topology();
-	if (cvp_session_cmd.cvp_session.rx_topology_id == 0)
-		cvp_session_cmd.cvp_session.rx_topology_id =
-			VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
+	voc_get_tx_rx_topology(v,
+			&cvp_session_cmd.cvp_session.tx_topology_id,
+			&cvp_session_cmd.cvp_session.rx_topology_id);
 
 	cvp_session_cmd.cvp_session.direction = 2; /*tx and rx*/
 	cvp_session_cmd.cvp_session.tx_port_id = v->dev_tx.port_id;
@@ -2645,6 +2660,9 @@
 	if (v->dtmf_rx_detect_en)
 		voice_send_dtmf_rx_detection_cmd(v, 0);
 
+	/* reset LCH mode */
+	v->lch_mode = 0;
+
 	/* detach VOCPROC and wait for response from mvm */
 	mvm_d_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
@@ -2884,7 +2902,7 @@
 	return -EINVAL;
 }
 
-static int voice_send_mute_cmd(struct voice_data *v)
+static int voice_send_stream_mute_cmd(struct voice_data *v)
 {
 	struct cvs_set_mute_cmd cvs_mute_cmd;
 	int ret = 0;
@@ -2912,7 +2930,7 @@
 	cvs_mute_cmd.hdr.token = 0;
 	cvs_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
 	cvs_mute_cmd.cvs_set_mute.direction = VSS_IVOLUME_DIRECTION_TX;
-	cvs_mute_cmd.cvs_set_mute.mute_flag = v->dev_tx.mute;
+	cvs_mute_cmd.cvs_set_mute.mute_flag = v->stream_tx.stream_mute;
 	cvs_mute_cmd.cvs_set_mute.ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
 
 	v->cvs_state = CMD_STATUS_FAIL;
@@ -2937,7 +2955,8 @@
 	return -EINVAL;
 }
 
-static int voice_send_rx_device_mute_cmd(struct voice_data *v)
+static int voice_send_device_mute_cmd(struct voice_data *v, uint16_t direction,
+				      uint16_t mute_flag)
 {
 	struct cvp_set_mute_cmd cvp_mute_cmd;
 	int ret = 0;
@@ -2963,8 +2982,8 @@
 	cvp_mute_cmd.hdr.dest_port = voice_get_cvp_handle(v);
 	cvp_mute_cmd.hdr.token = 0;
 	cvp_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
-	cvp_mute_cmd.cvp_set_mute.direction = VSS_IVOLUME_DIRECTION_RX;
-	cvp_mute_cmd.cvp_set_mute.mute_flag = v->dev_rx.mute;
+	cvp_mute_cmd.cvp_set_mute.direction = direction;
+	cvp_mute_cmd.cvp_set_mute.mute_flag = mute_flag;
 	cvp_mute_cmd.cvp_set_mute.ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
 
 	v->cvp_state = CMD_STATUS_FAIL;
@@ -3493,7 +3512,7 @@
 	int ret = 0;
 
 	if (v == NULL) {
-		pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+		pr_err("%s: Invalid session_id 0x%x\n", __func__, session_id);
 
 		return -EINVAL;
 	}
@@ -3503,7 +3522,7 @@
 	if (v->voc_state == VOC_CHANGE) {
 		ret = voice_send_set_device_cmd(v);
 		if (ret < 0) {
-			pr_err("%s:  set device failed\n", __func__);
+			pr_err("%s:  Set device failed\n", __func__);
 			goto fail;
 		}
 
@@ -3511,9 +3530,35 @@
 		voice_send_cvp_register_cal_cmd(v);
 		voice_send_cvp_register_vol_cal_cmd(v);
 
+		if (v->lch_mode == VOICE_LCH_START) {
+			pr_debug("%s: TX and RX mute ON\n", __func__);
+
+			voice_send_device_mute_cmd(v,
+						   VSS_IVOLUME_DIRECTION_TX,
+						   VSS_IVOLUME_MUTE_ON);
+			voice_send_device_mute_cmd(v,
+						   VSS_IVOLUME_DIRECTION_RX,
+						   VSS_IVOLUME_MUTE_ON);
+		} else if (v->lch_mode == VOICE_LCH_STOP) {
+			pr_debug("%s: TX and RX mute OFF\n", __func__);
+
+			voice_send_device_mute_cmd(v,
+						   VSS_IVOLUME_DIRECTION_TX,
+						   VSS_IVOLUME_MUTE_OFF);
+			voice_send_device_mute_cmd(v,
+						   VSS_IVOLUME_DIRECTION_RX,
+						   VSS_IVOLUME_MUTE_OFF);
+			/* Reset lch mode when VOICE_LCH_STOP is recieved */
+			v->lch_mode = 0;
+		} else {
+			pr_debug("%s: Mute commands not sent for lch_mode=%d\n",
+				 __func__, v->lch_mode);
+		}
+
 		ret = voice_send_enable_vocproc_cmd(v);
 		if (ret < 0) {
-			pr_err("%s: enable vocproc failed %d\n", __func__, ret);
+			pr_err("%s: Enable vocproc failed %d\n", __func__, ret);
+
 			goto fail;
 		}
 
@@ -3593,12 +3638,12 @@
 
 	mutex_lock(&v->lock);
 
-	v->dev_tx.mute = mute;
+	v->stream_tx.stream_mute = mute;
 
 	if ((v->voc_state == VOC_RUN) ||
 	    (v->voc_state == VOC_CHANGE) ||
 	    (v->voc_state == VOC_STANDBY))
-		ret = voice_send_mute_cmd(v);
+		ret = voice_send_stream_mute_cmd(v);
 
 	mutex_unlock(&v->lock);
 
@@ -3618,10 +3663,12 @@
 
 	mutex_lock(&v->lock);
 
-	v->dev_rx.mute = mute;
+	v->dev_rx.dev_mute = mute;
 
 	if (v->voc_state == VOC_RUN)
-		ret = voice_send_rx_device_mute_cmd(v);
+		ret = voice_send_device_mute_cmd(v,
+						 VSS_IVOLUME_DIRECTION_RX,
+						 v->dev_rx.dev_mute);
 
 	mutex_unlock(&v->lock);
 
@@ -3641,7 +3688,7 @@
 
 	mutex_lock(&v->lock);
 
-	ret = v->dev_rx.mute;
+	ret = v->dev_rx.dev_mute;
 
 	mutex_unlock(&v->lock);
 
@@ -3960,6 +4007,49 @@
 	return ret;
 }
 
+int voc_set_lch(uint16_t session_id, enum voice_lch_mode lch_mode)
+{
+	struct voice_data *v = voice_get_session(session_id);
+	int ret = 0;
+
+	if (v == NULL) {
+		pr_err("%s: Invalid session_id 0x%x\n", __func__, session_id);
+
+		ret = -EINVAL;
+		goto done;
+	}
+
+	mutex_lock(&v->lock);
+	if (v->lch_mode == lch_mode) {
+		pr_debug("%s: Session %d already in LCH mode %d\n",
+				 __func__, session_id, lch_mode);
+
+		mutex_unlock(&v->lock);
+		goto done;
+	}
+
+	v->lch_mode = lch_mode;
+	mutex_unlock(&v->lock);
+
+	ret = voc_disable_cvp(session_id);
+	if (ret < 0) {
+		pr_err("%s: voc_disable_cvp failed ret=%d\n", __func__, ret);
+
+		goto done;
+	}
+
+	/* Mute and topology_none will be set as part of voc_enable_cvp() */
+	ret = voc_enable_cvp(session_id);
+	if (ret < 0) {
+		pr_err("%s: voc_enable_cvp failed ret=%d\n", __func__, ret);
+
+		goto done;
+	}
+
+done:
+	return ret;
+}
+
 int voc_resume_voice_call(uint16_t session_id)
 {
 	struct voice_data *v = voice_get_session(session_id);
@@ -4580,7 +4670,7 @@
 				v->cvp_state = CMD_STATUS_SUCCESS;
 				wake_up(&v->cvp_wait);
 				break;
-			case VSS_IVOCPROC_CMD_SET_DEVICE:
+			case VSS_IVOCPROC_CMD_SET_DEVICE_V2:
 			case VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX:
 			case VSS_IVOCPROC_CMD_ENABLE:
 			case VSS_IVOCPROC_CMD_DISABLE:
@@ -4769,13 +4859,16 @@
 
 		/* initialize dev_rx and dev_tx */
 		common.voice[i].dev_rx.volume = common.default_vol_val;
-		common.voice[i].dev_rx.mute =  0;
-		common.voice[i].dev_tx.mute = common.default_mute_val;
+		common.voice[i].dev_rx.dev_mute =  0;
+		common.voice[i].dev_tx.dev_mute =  0;
+		common.voice[i].stream_rx.stream_mute = common.default_mute_val;
+		common.voice[i].stream_tx.stream_mute = common.default_mute_val;
 
 		common.voice[i].dev_tx.port_id = 0x100B;
 		common.voice[i].dev_rx.port_id = 0x100A;
 		common.voice[i].sidetone_gain = 0x512;
 		common.voice[i].dtmf_rx_detect_en = 0;
+		common.voice[i].lch_mode = 0;
 
 		common.voice[i].voc_state = VOC_INIT;
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index ef5c6e3..c85e0b3 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -14,6 +14,7 @@
 
 #include <mach/qdsp6v2/apr.h>
 #include <linux/msm_ion.h>
+#include <sound/voice_params.h>
 
 #define MAX_VOC_PKT_SIZE 642
 #define SESSION_NAME_LEN 20
@@ -41,11 +42,15 @@
 	void *cb_handle;
 };
 
-/* Device information payload structure */
+/* Stream information payload structure */
+struct stream_data {
+	uint32_t stream_mute;
+};
 
+/* Device information payload structure */
 struct device_data {
 	uint32_t volume; /* in index */
-	uint32_t mute;
+	uint32_t dev_mute;
 	uint32_t sample;
 	uint32_t enabled;
 	uint32_t dev_id;
@@ -904,7 +909,7 @@
 
 #define APRV2_IBASIC_CMD_DESTROY_SESSION		0x0001003C
 
-#define VSS_IVOCPROC_CMD_SET_DEVICE			0x000100C4
+#define VSS_IVOCPROC_CMD_SET_DEVICE_V2			0x000112C6
 
 #define VSS_IVOCPROC_CMD_SET_VP3_DATA			0x000110EB
 
@@ -1042,8 +1047,8 @@
 	 */
 } __packed;
 
-struct vss_ivocproc_cmd_set_device_t {
-	uint32_t tx_port_id;
+struct vss_ivocproc_cmd_set_device_v2_t {
+	uint16_t tx_port_id;
 	/*
 	 * TX device port ID which vocproc will connect to.
 	 * VSS_IVOCPROC_PORT_ID_NONE means vocproc will not connect to any port.
@@ -1054,7 +1059,7 @@
 	 * VSS_IVOCPROC_TOPOLOGY_ID_NONE means vocproc does not contain any
 	 * pre/post-processing blocks and is pass-through.
 	 */
-	int32_t rx_port_id;
+	uint16_t rx_port_id;
 	/*
 	 * RX device port ID which vocproc will connect to.
 	 * VSS_IVOCPROC_PORT_ID_NONE means vocproc will not connect to any port.
@@ -1065,6 +1070,15 @@
 	 * VSS_IVOCPROC_TOPOLOGY_ID_NONE means vocproc does not contain any
 	 * pre/post-processing blocks and is pass-through.
 	 */
+	uint32_t vocproc_mode;
+	/* Vocproc mode. The supported values:
+	 * VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING - 0x00010F7C
+	 * VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING - 0x00010F7D
+	 */
+	uint16_t ec_ref_port_id;
+	/* Port ID to which the vocproc connects for receiving
+	 * echo
+	 */
 } __packed;
 
 struct vss_ivocproc_cmd_register_device_config_t {
@@ -1128,7 +1142,7 @@
 
 struct cvp_set_device_cmd {
 	struct apr_hdr hdr;
-	struct vss_ivocproc_cmd_set_device_t cvp_set_device;
+	struct vss_ivocproc_cmd_set_device_v2_t cvp_set_device_v2;
 } __packed;
 
 struct cvp_set_vp3_data_cmd {
@@ -1230,10 +1244,14 @@
 	wait_queue_head_t cvs_wait;
 	wait_queue_head_t cvp_wait;
 
-	/* cache the values related to Rx and Tx */
+	/* Cache the values related to Rx and Tx devices */
 	struct device_data dev_rx;
 	struct device_data dev_tx;
 
+	/* Cache the values related to Rx and Tx streams */
+	struct stream_data stream_rx;
+	struct stream_data stream_tx;
+
 	u32 mvm_state;
 	u32 cvs_state;
 	u32 cvp_state;
@@ -1257,6 +1275,8 @@
 	uint32_t fens_enable;
 
 	uint32_t dtmf_rx_detect_en;
+	/* Local Call Hold mode */
+	uint8_t lch_mode;
 
 	struct voice_dev_route_state voc_route_state;
 
@@ -1353,6 +1373,7 @@
 int voc_end_voice_call(uint16_t session_id);
 int voc_standby_voice_call(uint16_t session_id);
 int voc_resume_voice_call(uint16_t session_id);
+int voc_set_lch(uint16_t session_id, enum voice_lch_mode lch_mode);
 int voc_set_rxtx_port(uint16_t session_id,
 		      uint32_t dev_port_id,
 		      uint32_t dev_type);