Merge "msm: iomap: Add static iomap for PS hold register on 8910."
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 0a349f7..7b01020 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -241,6 +241,7 @@
 		compatible = "qcom,bam_dmux";
 		reg = <0xfc834000 0x7000>;
 		interrupts = <0 29 1>;
+		qcom,satellite-mode;
 	};
 
 	qcom,acpuclk@f9010000 {
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 5c5b51e..5a9799a 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -607,7 +607,7 @@
 	},
 	.c = {
 		.dbg_name = "smi_2x_axi_clk",
-		.ops = &clk_ops_branch,
+		.ops = &clk_ops_smi_2x,
 		CLK_INIT(smi_2x_axi_clk.c),
 	},
 };
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index d2260cb..c43ca46 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -839,6 +839,14 @@
 	.set_flags = branch_clk_set_flags,
 };
 
+struct clk_ops clk_ops_smi_2x = {
+	.prepare = branch_clk_enable,
+	.unprepare = branch_clk_disable,
+	.is_enabled = branch_clk_is_enabled,
+	.get_parent = branch_clk_get_parent,
+	.handoff = branch_clk_handoff,
+};
+
 struct clk_ops clk_ops_reset = {
 	.reset = branch_clk_reset,
 };
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 1873343..fca6486 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -153,6 +153,7 @@
 };
 
 extern struct clk_ops clk_ops_branch;
+extern struct clk_ops clk_ops_smi_2x;
 extern struct clk_ops clk_ops_reset;
 
 int branch_reset(struct branch *b, enum clk_reset_action action);
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 9aa771a..ddb98b4 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1643,6 +1643,7 @@
 	case 0x771:
 	case 0x77C:
 	case 0x780:
+	case 0x785: /* Edge-only MSM8125-0 */
 	case 0x8D0:
 		cpu = MSM8625;
 		break;
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index 55ae2f8..e248917 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -24,6 +24,7 @@
 #include "scm-pas.h"
 
 #define PAS_INIT_IMAGE_CMD	1
+#define PAS_MEM_SETUP_CMD	2
 #define PAS_AUTH_AND_RESET_CMD	5
 #define PAS_SHUTDOWN_CMD	6
 #define PAS_IS_SUPPORTED_CMD	7
@@ -55,6 +56,28 @@
 }
 EXPORT_SYMBOL(pas_init_image);
 
+int pas_mem_setup(enum pas_id id, u32 start_addr, u32 len)
+{
+	int ret;
+	struct pas_init_image_req {
+		u32	proc;
+		u32	start_addr;
+		u32	len;
+	} request;
+	u32 scm_ret = 0;
+
+	request.proc = id;
+	request.start_addr = start_addr;
+	request.len = len;
+
+	ret = scm_call(SCM_SVC_PIL, PAS_MEM_SETUP_CMD, &request,
+			sizeof(request), &scm_ret, sizeof(scm_ret));
+	if (ret)
+		return ret;
+	return scm_ret;
+}
+EXPORT_SYMBOL(pas_mem_setup);
+
 static struct msm_bus_paths scm_pas_bw_tbl[] = {
 	{
 		.vectors = (struct msm_bus_vectors[]){
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index 8da1d75..6441a18 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -27,6 +27,7 @@
 
 #ifdef CONFIG_MSM_PIL
 extern int pas_init_image(enum pas_id id, const u8 *metadata, size_t size);
+extern int pas_mem_setup(enum pas_id id, u32 start_addr, u32 len);
 extern int pas_auth_and_reset(enum pas_id id);
 extern int pas_shutdown(enum pas_id id);
 extern int pas_supported(enum pas_id id);
@@ -36,6 +37,10 @@
 {
 	return 0;
 }
+static inline int pas_mem_setup(enum pas_id id, u32 start_addr, u32 len)
+{
+	return 0;
+}
 static inline int pas_auth_and_reset(enum pas_id id)
 {
 	return 0;
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index ecdc951..73ebdf6 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -41,7 +41,7 @@
 #ifdef CONFIG_ARCH_FSM9XXX
 #define NUM_SMD_PKT_PORTS 4
 #else
-#define NUM_SMD_PKT_PORTS 15
+#define NUM_SMD_PKT_PORTS 24
 #endif
 
 #define PDRIVER_NAME_MAX_SIZE 32
@@ -711,6 +711,15 @@
 	"smdcntl6",
 	"smdcntl7",
 	"smd22",
+	"smdcnt_rev0",
+	"smdcnt_rev1",
+	"smdcnt_rev2",
+	"smdcnt_rev3",
+	"smdcnt_rev4",
+	"smdcnt_rev5",
+	"smdcnt_rev6",
+	"smdcnt_rev7",
+	"smdcnt_rev8",
 	"smd_sns_dsps",
 	"apr_apps2",
 	"smdcntl8",
@@ -729,6 +738,15 @@
 	"DATA13_CNTL",
 	"DATA14_CNTL",
 	"DATA22",
+	"DATA23_CNTL",
+	"DATA24_CNTL",
+	"DATA25_CNTL",
+	"DATA26_CNTL",
+	"DATA27_CNTL",
+	"DATA28_CNTL",
+	"DATA29_CNTL",
+	"DATA30_CNTL",
+	"DATA31_CNTL",
 	"SENSOR",
 	"apr_apps2",
 	"DATA40_CNTL",
@@ -747,6 +765,15 @@
 	SMD_APPS_MODEM,
 	SMD_APPS_MODEM,
 	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
+	SMD_APPS_MODEM,
 	SMD_APPS_DSPS,
 	SMD_APPS_QDSP,
 	SMD_APPS_MODEM,
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 62085f6..6cb9339 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -260,6 +260,7 @@
 	[128] = MSM_CPU_8625,
 	[129] = MSM_CPU_8625,
 	[137] = MSM_CPU_8625,
+	[167] = MSM_CPU_8625,
 
 	/* 8064 MPQ ID */
 	[130] = MSM_CPU_8064,
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 50bae55..2c0c2a0 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -25,8 +25,9 @@
 #include <linux/wakelock.h>
 #include <linux/sysfs.h>
 #include <linux/stat.h>
-#include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <linux/clk.h>
+#include <linux/cpu.h>
 #include <linux/of_coresight.h>
 #include <linux/coresight.h>
 #include <asm/sections.h>
@@ -191,10 +192,11 @@
 	struct device			*dev;
 	struct coresight_device		*csdev;
 	struct clk			*clk;
-	struct mutex			mutex;
+	spinlock_t			spinlock;
 	struct wake_lock		wake_lock;
 	int				cpu;
 	uint8_t				arch;
+	bool				enable;
 	uint8_t				nr_addr_cmp;
 	uint8_t				nr_cntr;
 	uint8_t				nr_ext_inp;
@@ -203,7 +205,6 @@
 	uint8_t				reset;
 	uint32_t			mode;
 	uint32_t			ctrl;
-	uint8_t				ctrl_pwrdwn;
 	uint32_t			trigger_event;
 	uint32_t			startstop_ctrl;
 	uint32_t			enable_event;
@@ -230,7 +231,6 @@
 	uint32_t			ctxid_mask;
 	uint32_t			sync_freq;
 	uint32_t			timestamp_event;
-	uint8_t				pdcr_pwrup;
 	bool				pcsave_impl;
 	bool				pcsave_enable;
 };
@@ -339,48 +339,18 @@
 	     etm_readl(drvdata, ETMSR));
 }
 
-static void etm_save_pwrdwn(struct etm_drvdata *drvdata)
-{
-	drvdata->ctrl_pwrdwn = BVAL(etm_readl(drvdata, ETMCR), 0);
-}
-
-static void etm_restore_pwrdwn(struct etm_drvdata *drvdata)
-{
-	uint32_t etmcr;
-
-	etmcr = etm_readl(drvdata, ETMCR);
-	etmcr = (etmcr & ~BIT(0)) | drvdata->ctrl_pwrdwn;
-	etm_writel(drvdata, etmcr, ETMCR);
-}
-
-static void etm_save_pwrup(struct etm_drvdata *drvdata)
-{
-	drvdata->pdcr_pwrup = BVAL(etm_readl_mm(drvdata, ETMPDCR), 3);
-}
-
-static void etm_restore_pwrup(struct etm_drvdata *drvdata)
-{
-	uint32_t etmpdcr;
-
-	etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
-	etmpdcr = (etmpdcr & ~BIT(3)) | (drvdata->pdcr_pwrup << 3);
-	etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
-}
-
 static void etm_enable_pcsave(void *info)
 {
 	struct etm_drvdata *drvdata = info;
 
 	ETM_UNLOCK(drvdata);
 
-	etm_save_pwrup(drvdata);
 	/*
 	 * ETMPDCR is only accessible via memory mapped interface and so use
 	 * it first to enable power/clock to allow subsequent cp14 accesses.
 	 */
 	etm_set_pwrup(drvdata);
 	etm_clr_pwrdwn(drvdata);
-	etm_restore_pwrup(drvdata);
 
 	ETM_LOCK(drvdata);
 }
@@ -391,14 +361,10 @@
 
 	ETM_UNLOCK(drvdata);
 
-	etm_save_pwrup(drvdata);
-	/*
-	 * ETMPDCR is only accessible via memory mapped interface and so use
-	 * it first to enable power/clock to allow subsequent cp14 accesses.
-	 */
-	etm_set_pwrup(drvdata);
-	etm_set_pwrdwn(drvdata);
-	etm_restore_pwrup(drvdata);
+	if (!drvdata->enable) {
+		etm_set_pwrdwn(drvdata);
+		etm_clr_pwrup(drvdata);
+	}
 
 	ETM_LOCK(drvdata);
 }
@@ -416,10 +382,10 @@
 	 * to allow subsequent cp14 accesses.
 	 */
 	etm_set_pwrup(drvdata);
-	etm_save_pwrdwn(drvdata);
 	/*
 	 * Clear power down bit since when this bit is set writes to
-	 * certain registers might be ignored.
+	 * certain registers might be ignored. This is also a pre-requisite
+	 * for trace enable.
 	 */
 	etm_clr_pwrdwn(drvdata);
 	etm_set_prog(drvdata);
@@ -463,7 +429,6 @@
 	etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
 
 	etm_clr_prog(drvdata);
-	etm_restore_pwrdwn(drvdata);
 	ETM_LOCK(drvdata);
 
 	dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
@@ -480,12 +445,16 @@
 	if (ret)
 		goto err_clk;
 
-	mutex_lock(&drvdata->mutex);
-	/* executing __etm_enable on the cpu whose ETM is being enabled
+	spin_lock(&drvdata->spinlock);
+
+	/*
+	 * Executing __etm_enable on the cpu whose ETM is being enabled
 	 * ensures that register writes occur when cpu is powered.
 	 */
 	smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
-	mutex_unlock(&drvdata->mutex);
+	drvdata->enable = true;
+
+	spin_unlock(&drvdata->spinlock);
 
 	wake_unlock(&drvdata->wake_lock);
 
@@ -501,20 +470,15 @@
 	struct etm_drvdata *drvdata = info;
 
 	ETM_UNLOCK(drvdata);
-	etm_save_pwrdwn(drvdata);
-	/*
-	 * Clear power down bit since when this bit is set writes to
-	 * certain registers might be ignored.
-	 */
-	etm_clr_pwrdwn(drvdata);
 	etm_set_prog(drvdata);
 
 	/* program trace enable to low by using always false event */
 	etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
 
-	etm_restore_pwrdwn(drvdata);
-	/* Vote for ETM power/clock disable */
-	etm_clr_pwrup(drvdata);
+	if (!drvdata->pcsave_enable) {
+		etm_set_pwrdwn(drvdata);
+		etm_clr_pwrup(drvdata);
+	}
 	ETM_LOCK(drvdata);
 
 	dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
@@ -526,12 +490,16 @@
 
 	wake_lock(&drvdata->wake_lock);
 
-	mutex_lock(&drvdata->mutex);
-	/* executing __etm_disable on the cpu whose ETM is being disabled
+	spin_lock(&drvdata->spinlock);
+
+	/*
+	 * Executing __etm_disable on the cpu whose ETM is being disabled
 	 * ensures that register writes occur when cpu is powered.
 	 */
 	smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
-	mutex_unlock(&drvdata->mutex);
+	drvdata->enable = false;
+
+	spin_unlock(&drvdata->spinlock);
 
 	clk_disable_unprepare(drvdata->clk);
 
@@ -600,7 +568,7 @@
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	if (val) {
 		drvdata->mode = ETM_MODE_EXCLUDE;
 		drvdata->ctrl = 0x0;
@@ -644,7 +612,7 @@
 			drvdata->sync_freq = 0x80;
 		drvdata->timestamp_event = 0x406F;
 	}
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
@@ -667,7 +635,7 @@
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	drvdata->mode = val & ETM_MODE_ALL;
 
 	if (drvdata->mode & ETM_MODE_EXCLUDE)
@@ -694,7 +662,7 @@
 		drvdata->ctrl |= (BIT(14) | BIT(15));
 	else
 		drvdata->ctrl &= ~(BIT(14) | BIT(15));
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 
 	return size;
 }
@@ -796,12 +764,13 @@
 	if (val >= drvdata->nr_addr_cmp)
 		return -EINVAL;
 
-	/* Use mutex to ensure index doesn't change while it gets dereferenced
-	 * multiple times within a mutex block elsewhere.
+	/*
+	 * Use spinlock to ensure index doesn't change while it gets
+	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	drvdata->addr_idx = val;
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
@@ -814,16 +783,16 @@
 	unsigned long val;
 	uint8_t idx;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	idx = drvdata->addr_idx;
 	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
-		mutex_unlock(&drvdata->mutex);
+		spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	val = drvdata->addr_val[idx];
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -838,17 +807,17 @@
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	idx = drvdata->addr_idx;
 	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
-		mutex_unlock(&drvdata->mutex);
+		spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	drvdata->addr_val[idx] = val;
 	drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
@@ -861,23 +830,23 @@
 	unsigned long val1, val2;
 	uint8_t idx;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	idx = drvdata->addr_idx;
 	if (idx % 2 != 0) {
-		mutex_unlock(&drvdata->mutex);
+		spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 	if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
 	       drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
 	      (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
 	       drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
-		mutex_unlock(&drvdata->mutex);
+		spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	val1 = drvdata->addr_val[idx];
 	val2 = drvdata->addr_val[idx + 1];
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
 }
 
@@ -895,17 +864,17 @@
 	if (val1 > val2)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	idx = drvdata->addr_idx;
 	if (idx % 2 != 0) {
-		mutex_unlock(&drvdata->mutex);
+		spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 	if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
 	       drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
 	      (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
 	       drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
-		mutex_unlock(&drvdata->mutex);
+		spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
@@ -914,7 +883,7 @@
 	drvdata->addr_val[idx + 1] = val2;
 	drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
 	drvdata->enable_ctrl1 |= (1 << (idx/2));
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
@@ -927,16 +896,16 @@
 	unsigned long val;
 	uint8_t idx;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	idx = drvdata->addr_idx;
 	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
-		mutex_unlock(&drvdata->mutex);
+		spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	val = drvdata->addr_val[idx];
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -951,11 +920,11 @@
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	idx = drvdata->addr_idx;
 	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
-		mutex_unlock(&drvdata->mutex);
+		spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
@@ -963,7 +932,7 @@
 	drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
 	drvdata->startstop_ctrl |= (1 << idx);
 	drvdata->enable_ctrl1 |= BIT(25);
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
@@ -976,16 +945,16 @@
 	unsigned long val;
 	uint8_t idx;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	idx = drvdata->addr_idx;
 	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
-		mutex_unlock(&drvdata->mutex);
+		spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
 	val = drvdata->addr_val[idx];
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1000,11 +969,11 @@
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	idx = drvdata->addr_idx;
 	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
 	      drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
-		mutex_unlock(&drvdata->mutex);
+		spin_unlock(&drvdata->spinlock);
 		return -EPERM;
 	}
 
@@ -1012,7 +981,7 @@
 	drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
 	drvdata->startstop_ctrl |= (1 << (idx + 16));
 	drvdata->enable_ctrl1 |= BIT(25);
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
@@ -1024,9 +993,9 @@
 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	val = drvdata->addr_acctype[drvdata->addr_idx];
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1040,9 +1009,9 @@
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	drvdata->addr_acctype[drvdata->addr_idx] = val;
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
@@ -1069,12 +1038,13 @@
 	if (val >= drvdata->nr_cntr)
 		return -EINVAL;
 
-	/* Use mutex to ensure index doesn't change while it gets dereferenced
-	 * multiple times within a mutex block elsewhere.
+	/*
+	 * Use spinlock to ensure index doesn't change while it gets
+	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	drvdata->cntr_idx = val;
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
@@ -1086,9 +1056,9 @@
 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	val = drvdata->cntr_rld_val[drvdata->cntr_idx];
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1102,9 +1072,9 @@
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
@@ -1116,9 +1086,9 @@
 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	val = drvdata->cntr_event[drvdata->cntr_idx];
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1132,9 +1102,9 @@
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
@@ -1146,9 +1116,9 @@
 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	val = drvdata->cntr_rld_event[drvdata->cntr_idx];
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1162,9 +1132,9 @@
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
@@ -1176,9 +1146,9 @@
 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	val = drvdata->cntr_val[drvdata->cntr_idx];
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1192,9 +1162,9 @@
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	drvdata->cntr_val[drvdata->cntr_idx] = val;
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
@@ -1398,12 +1368,13 @@
 	if (val >= drvdata->nr_ctxid_cmp)
 		return -EINVAL;
 
-	/* Use mutex to ensure index doesn't change while it gets dereferenced
-	 * multiple times within a mutex block elsewhere.
+	/*
+	 * Use spinlock to ensure index doesn't change while it gets
+	 * dereferenced multiple times within a spinlock block elsewhere.
 	 */
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	drvdata->ctxid_idx = val;
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
@@ -1415,9 +1386,9 @@
 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	val = drvdata->ctxid_val[drvdata->ctxid_idx];
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1431,9 +1402,9 @@
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
-	mutex_lock(&drvdata->mutex);
+	spin_lock(&drvdata->spinlock);
 	drvdata->ctxid_val[drvdata->ctxid_idx] = val;
-	mutex_unlock(&drvdata->mutex);
+	spin_unlock(&drvdata->spinlock);
 	return size;
 }
 static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
@@ -1527,26 +1498,43 @@
 
 static int __etm_store_pcsave(struct etm_drvdata *drvdata, unsigned long val)
 {
-	int ret;
+	int ret = 0;
 
 	ret = clk_prepare_enable(drvdata->clk);
 	if (ret)
 		return ret;
 
-	mutex_lock(&drvdata->mutex);
+	get_online_cpus();
+	spin_lock(&drvdata->spinlock);
 	if (val) {
-		smp_call_function_single(drvdata->cpu, etm_enable_pcsave,
-					 drvdata, 1);
+		if (drvdata->pcsave_enable)
+			goto out;
+
+		ret = smp_call_function_single(drvdata->cpu, etm_enable_pcsave,
+					       drvdata, 1);
+		if (ret)
+			goto out;
 		drvdata->pcsave_enable = true;
+
+		dev_info(drvdata->dev, "PC save enabled\n");
 	} else {
-		smp_call_function_single(drvdata->cpu, etm_disable_pcsave,
-					 drvdata, 1);
+		if (!drvdata->pcsave_enable)
+			goto out;
+
+		ret = smp_call_function_single(drvdata->cpu, etm_disable_pcsave,
+					       drvdata, 1);
+		if (ret)
+			goto out;
 		drvdata->pcsave_enable = false;
+
+		dev_info(drvdata->dev, "PC save disabled\n");
 	}
-	mutex_unlock(&drvdata->mutex);
+out:
+	spin_unlock(&drvdata->spinlock);
+	put_online_cpus();
 
 	clk_disable_unprepare(drvdata->clk);
-	return 0;
+	return ret;
 }
 
 static ssize_t etm_store_pcsave(struct device *dev,
@@ -1677,7 +1665,6 @@
 	drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
 
 	etm_set_pwrdwn(drvdata);
-	/* Vote for ETM power/clock disable */
 	etm_clr_pwrup(drvdata);
 	ETM_LOCK(drvdata);
 }
@@ -1774,7 +1761,7 @@
 	if (!drvdata->base)
 		return -ENOMEM;
 
-	mutex_init(&drvdata->mutex);
+	spin_lock_init(&drvdata->spinlock);
 	wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
 
 	drvdata->clk = devm_clk_get(dev, "core_clk");
@@ -1868,7 +1855,6 @@
 	clk_disable_unprepare(drvdata->clk);
 err0:
 	wake_lock_destroy(&drvdata->wake_lock);
-	mutex_destroy(&drvdata->mutex);
 	return ret;
 }
 
@@ -1879,7 +1865,6 @@
 	device_remove_file(&drvdata->csdev->dev, &dev_attr_pcsave);
 	coresight_unregister(drvdata->csdev);
 	wake_lock_destroy(&drvdata->wake_lock);
-	mutex_destroy(&drvdata->mutex);
 	return 0;
 }
 
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 785ba6c..4b03cfd 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -115,7 +115,12 @@
 
 static struct workqueue_struct *input_wq;
 
-static DEFINE_PER_CPU(struct work_struct, dbs_refresh_work);
+struct dbs_work_struct {
+	struct work_struct work;
+	unsigned int cpu;
+};
+
+static DEFINE_PER_CPU(struct dbs_work_struct, dbs_refresh_work);
 
 static struct dbs_tuners {
 	unsigned int sampling_rate;
@@ -831,11 +836,15 @@
 	return 0;
 }
 
-static void dbs_refresh_callback(struct work_struct *unused)
+static void dbs_refresh_callback(struct work_struct *work)
 {
 	struct cpufreq_policy *policy;
 	struct cpu_dbs_info_s *this_dbs_info;
-	unsigned int cpu = smp_processor_id();
+	struct dbs_work_struct *dbs_work;
+	unsigned int cpu;
+
+	dbs_work = container_of(work, struct dbs_work_struct, work);
+	cpu = dbs_work->cpu;
 
 	get_online_cpus();
 
@@ -877,9 +886,8 @@
 		return;
 	}
 
-	for_each_online_cpu(i) {
-		queue_work_on(i, input_wq, &per_cpu(dbs_refresh_work, i));
-	}
+	for_each_online_cpu(i)
+		queue_work_on(i, input_wq, &per_cpu(dbs_refresh_work, i).work);
 }
 
 static int dbs_input_connect(struct input_handler *handler,
@@ -1072,8 +1080,12 @@
 	for_each_possible_cpu(i) {
 		struct cpu_dbs_info_s *this_dbs_info =
 			&per_cpu(od_cpu_dbs_info, i);
+		struct dbs_work_struct *dbs_work =
+			&per_cpu(dbs_refresh_work, i);
+
 		mutex_init(&this_dbs_info->timer_mutex);
-		INIT_WORK(&per_cpu(dbs_refresh_work, i), dbs_refresh_callback);
+		INIT_WORK(&dbs_work->work, dbs_refresh_callback);
+		dbs_work->cpu = i;
 	}
 
 	return cpufreq_register_governor(&cpufreq_gov_ondemand);
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 2003098..119e25d 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -17,6 +17,7 @@
 #include "drmP.h"
 #include "drm.h"
 #include <linux/android_pmem.h>
+#include <linux/msm_ion.h>
 
 #include "kgsl.h"
 #include "kgsl_device.h"
@@ -106,6 +107,7 @@
 	uint32_t type;
 	struct kgsl_memdesc memdesc;
 	struct kgsl_pagetable *pagetable;
+	struct ion_handle *ion_handle;
 	uint64_t mmap_offset;
 	int bufcount;
 	int flags;
@@ -129,6 +131,8 @@
 	struct list_head wait_list;
 };
 
+static struct ion_client *kgsl_drm_ion_phys_client;
+
 static int kgsl_drm_inited = DRM_KGSL_NOT_INITED;
 
 /* This is a global list of all the memory currently mapped in the MMU */
@@ -243,15 +247,50 @@
 	if (TYPE_IS_PMEM(priv->type)) {
 		if (priv->type == DRM_KGSL_GEM_TYPE_EBI ||
 		    priv->type & DRM_KGSL_GEM_PMEM_EBI) {
-				result = kgsl_sharedmem_ebimem_user(
-						&priv->memdesc,
-						priv->pagetable,
-						obj->size * priv->bufcount);
-				if (result) {
-					DRM_ERROR(
-					"Unable to allocate PMEM memory\n");
-					return result;
-				}
+			priv->ion_handle = ion_alloc(kgsl_drm_ion_phys_client,
+				obj->size * priv->bufcount, PAGE_SIZE,
+				ION_HEAP(ION_SF_HEAP_ID), 0);
+			if (IS_ERR_OR_NULL(priv->ion_handle)) {
+				DRM_ERROR(
+				"Unable to allocate ION Phys memory handle\n");
+				return -ENOMEM;
+			}
+
+			priv->memdesc.pagetable = priv->pagetable;
+
+			result = ion_phys(kgsl_drm_ion_phys_client,
+				priv->ion_handle, (ion_phys_addr_t *)
+				&priv->memdesc.physaddr, &priv->memdesc.size);
+			if (result) {
+				DRM_ERROR(
+				"Unable to get ION Physical memory address\n");
+				ion_free(kgsl_drm_ion_phys_client,
+					priv->ion_handle);
+				priv->ion_handle = NULL;
+				return result;
+			}
+
+			result = memdesc_sg_phys(&priv->memdesc,
+				priv->memdesc.physaddr, priv->memdesc.size);
+			if (result) {
+				DRM_ERROR(
+				"Unable to get sg list\n");
+				ion_free(kgsl_drm_ion_phys_client,
+					priv->ion_handle);
+				priv->ion_handle = NULL;
+				return result;
+			}
+
+			result = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
+					GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+			if (result) {
+				DRM_ERROR(
+				"Unable to map GPU\n");
+				ion_free(kgsl_drm_ion_phys_client,
+					priv->ion_handle);
+				priv->ion_handle = NULL;
+				return result;
+			}
 		}
 		else
 			return -EINVAL;
@@ -296,7 +335,16 @@
 	kgsl_gem_mem_flush(&priv->memdesc,  priv->type,
 			   DRM_KGSL_GEM_CACHE_OP_FROM_DEV);
 
-	kgsl_sharedmem_free(&priv->memdesc);
+	if (priv->memdesc.gpuaddr)
+		kgsl_mmu_unmap(priv->memdesc.pagetable, &priv->memdesc);
+
+	kgsl_sg_free(priv->memdesc.sg, priv->memdesc.sglen);
+
+	if (priv->ion_handle)
+		ion_free(kgsl_drm_ion_phys_client, priv->ion_handle);
+	priv->ion_handle = NULL;
+
+	memset(&priv->memdesc, 0, sizeof(priv->memdesc));
 
 	kgsl_mmu_putpagetable(priv->pagetable);
 	priv->pagetable = NULL;
@@ -1447,6 +1495,16 @@
 		      DRM_MASTER),
 };
 
+static const struct file_operations kgsl_drm_driver_fops = {
+	.owner = THIS_MODULE,
+	.open = drm_open,
+	.release = drm_release,
+	.unlocked_ioctl = drm_ioctl,
+	.mmap = msm_drm_gem_mmap,
+	.poll = drm_poll,
+	.fasync = drm_fasync,
+};
+
 static struct drm_driver driver = {
 	.driver_features = DRIVER_GEM,
 	.load = kgsl_drm_load,
@@ -1458,17 +1516,7 @@
 	.gem_init_object = kgsl_gem_init_object,
 	.gem_free_object = kgsl_gem_free_object,
 	.ioctls = kgsl_drm_ioctls,
-
-	.fops = {
-		 .owner = THIS_MODULE,
-		 .open = drm_open,
-		 .release = drm_release,
-		 .unlocked_ioctl = drm_ioctl,
-		 .mmap = msm_drm_gem_mmap,
-		 .poll = drm_poll,
-		 .fasync = drm_fasync,
-		 },
-
+	.fops = &kgsl_drm_driver_fops,
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 	.date = DRIVER_DATE,
@@ -1497,6 +1545,14 @@
 		gem_buf_fence[i].fence_id = ENTRY_EMPTY;
 	}
 
+	/* Create ION Client */
+	kgsl_drm_ion_phys_client = msm_ion_client_create(
+			ION_HEAP_CARVEOUT_MASK, ION_SF_HEAP_NAME);
+	if (!kgsl_drm_ion_phys_client) {
+		DRM_ERROR("Unable to create ION client\n");
+		return -ENOMEM;
+	}
+
 	return drm_platform_init(&driver, dev);
 }
 
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 46dab5c..16f7e2c 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -388,7 +388,9 @@
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
 	struct v4l2_event dqevent;
+	struct v4l2_control control = {0};
 	struct msm_vidc_cb_event *event_notify;
+	int rc = 0;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
 		dqevent.id = 0;
@@ -396,7 +398,16 @@
 		switch (event_notify->hal_event_type) {
 		case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
 			dqevent.type =
-				V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
+				V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
+			control.id =
+				V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
+			rc = v4l2_g_ctrl(&inst->ctrl_handler, &control);
+			if (rc)
+				dprintk(VIDC_WARN,
+					"Failed to get Smooth streamng flag\n");
+			if (!rc && control.value == true)
+				dqevent.type =
+					V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
 			break;
 		case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
 			dqevent.type =
diff --git a/drivers/media/video/msm_wfd/wfd-util.c b/drivers/media/video/msm_wfd/wfd-util.c
index 233668b0..5c00e5c 100644
--- a/drivers/media/video/msm_wfd/wfd-util.c
+++ b/drivers/media/video/msm_wfd/wfd-util.c
@@ -159,10 +159,10 @@
 	}
 	case WFD_STAT_EVENT_MDP_QUEUE:
 		stats->mdp_buf_count++;
-		stats->mdp_updates++;
 		break;
 	case WFD_STAT_EVENT_MDP_DEQUEUE:
 		stats->mdp_buf_count--;
+		stats->mdp_updates++;
 		break;
 	case WFD_STAT_EVENT_ENC_QUEUE: {
 		struct wfd_stats_encode_sample *sample = NULL;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 49bbe09..95e7753 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2215,7 +2215,9 @@
 		}
 
 		if ((mrq->cmd->opcode == MMC_WRITE_BLOCK) ||
-		    (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK))
+		    (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) ||
+		    ((mrq->cmd->opcode == SD_IO_RW_EXTENDED) &&
+		     is_data_pend_for_cmd53(host)))
 			host->curr.use_wr_data_pend = true;
 	}
 
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index af5498e..9fa2027 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -446,6 +446,7 @@
 #define MSMSDCC_AUTO_CMD19	(1 << 9)
 #define MSMSDCC_AUTO_CMD21	(1 << 10)
 #define MSMSDCC_SW_RST_CFG_BROKEN	(1 << 11)
+#define MSMSDCC_DATA_PEND_FOR_CMD53	(1 << 12)
 
 #define set_hw_caps(h, val)		((h)->hw_caps |= val)
 #define is_sps_mode(h)			((h)->hw_caps & MSMSDCC_SPS_BAM_SUP)
@@ -461,6 +462,7 @@
 #define is_auto_cmd21(h)		((h)->hw_caps & MSMSDCC_AUTO_CMD21)
 #define is_sw_reset_save_config_broken(h) \
 				((h)->hw_caps & MSMSDCC_SW_RST_CFG_BROKEN)
+#define is_data_pend_for_cmd53(h) ((h)->hw_caps & MSMSDCC_DATA_PEND_FOR_CMD53)
 
 /* Set controller capabilities based on version */
 static inline void set_default_hw_caps(struct msmsdcc_host *host)
@@ -493,7 +495,8 @@
 
 	if (step >= 0x2b) /* SDCC v4 2.1.0 and greater */
 		host->hw_caps |= MSMSDCC_SW_RST | MSMSDCC_SW_RST_CFG |
-					MSMSDCC_AUTO_CMD21;
+				 MSMSDCC_AUTO_CMD21 |
+				 MSMSDCC_DATA_PEND_FOR_CMD53;
 
 	if (step == 0x2b)
 		host->hw_caps |= MSMSDCC_SW_RST_CFG_BROKEN;
diff --git a/drivers/power/bq28400_battery.c b/drivers/power/bq28400_battery.c
index 47fced1..7b82b32 100644
--- a/drivers/power/bq28400_battery.c
+++ b/drivers/power/bq28400_battery.c
@@ -509,13 +509,15 @@
 		return POWER_SUPPLY_STATUS_FULL;
 	}
 
+	/* Enable charging when battery is not full */
+	bq28400_enable_charging(bq28400_dev, true);
+
 	/*
 	* Positive current indicates charging
 	* Negative current indicates discharging.
 	* Charging is stopped at termination-current.
 	*/
 	if (current_ma < 0) {
-		bq28400_enable_charging(bq28400_dev, true);
 		pr_debug("Discharging.\n");
 		status = POWER_SUPPLY_STATUS_DISCHARGING;
 	} else if (current_ma > BQ_TERMINATION_CURRENT_MA) {
diff --git a/drivers/power/smb350_charger.c b/drivers/power/smb350_charger.c
index 93e208c..319caba 100644
--- a/drivers/power/smb350_charger.c
+++ b/drivers/power/smb350_charger.c
@@ -753,13 +753,22 @@
 
 	i2c_set_clientdata(client, dev);
 
-	pr_debug("set charge-enable + not suspend.\n");
-	gpio_set_value_cansleep(dev->chg_en_n_gpio, 1);	/* Disable */
+	/* Disable battery charging by default on power up.
+	 * Battery charging is enabled by BMS or Battery-Gauge
+	 * by using the set_property callback.
+	 */
+	smb350_enable_charging(dev, false);
 	msleep(100);
 	gpio_set_value_cansleep(dev->chg_susp_n_gpio, 1); /* Normal */
 	msleep(100); /* Allow the device to exist shutdown */
 
-	smb350_read_reg(client, I2C_SLAVE_ADDR_REG);
+	/* I2C transaction allowed only after device exit suspend */
+	ret = smb350_read_reg(client, I2C_SLAVE_ADDR_REG);
+	if ((ret>>1) != client->addr) {
+		pr_err("No device.\n");
+		ret = -ENODEV;
+		goto err_no_dev;
+	}
 
 	ret = smb350_set_volatile_params(dev);
 	if (ret)
@@ -784,14 +793,13 @@
 		goto err_irq;
 	}
 
-	smb350_enable_charging(dev, true);
-
 	return 0;
 
 err_irq:
 err_debugfs:
 	if (dev->dent)
 		debugfs_remove_recursive(dev->dent);
+err_no_dev:
 err_set_params:
 	gpio_free(dev->chg_en_n_gpio);
 err_en_gpio:
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 1994b1b..527b02f 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -3279,7 +3279,9 @@
 		ret = wait_for_completion_interruptible_timeout(
 		&mfd->msmfb_no_update_notify, 4*HZ);
 	}
-	return (ret > 0) ? 0 : -1;
+	if (ret == 0)
+		ret = -ETIMEDOUT;
+	return (ret > 0) ? 0 : ret;
 }
 
 static int msmfb_handle_pp_ioctl(struct msm_fb_data_type *mfd,