Merge "msm: kgsl: Remove wakelock and pm_qos requirements" into msm-3.0
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 604989d..e4f88ec 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -149,7 +149,7 @@
 	obj-$(CONFIG_ARCH_MSM7X01A) += pm.o
 	obj-y += pm-boot.o
 else
-	obj-y += no-pm.o
+	obj-y += no-pm.o hotplug.o
 endif
 
 obj-$(CONFIG_MSM_SPM_V1) += spm.o
diff --git a/arch/arm/mach-msm/board-apq8064.c b/arch/arm/mach-msm/board-apq8064.c
index b131989..6662751 100644
--- a/arch/arm/mach-msm/board-apq8064.c
+++ b/arch/arm/mach-msm/board-apq8064.c
@@ -18,6 +18,8 @@
 #include <linux/slimbus/slimbus.h>
 #include <linux/msm_ssbi.h>
 #include <linux/spi/spi.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_data/qcom_crypto_device.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -37,6 +39,7 @@
 #include <mach/msm_memtypes.h>
 #include <linux/bootmem.h>
 #include <asm/setup.h>
+#include <mach/dma.h>
 
 #include "msm_watchdog.h"
 #include "board-apq8064.h"
@@ -443,6 +446,118 @@
 	apq8064_add_sdcc(3, apq8064_sdc3_pdata);
 }
 
+#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
+		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
+		defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
+		defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
+
+#define QCE_SIZE		0x10000
+#define QCE_0_BASE		0x11000000
+
+#define QCE_HW_KEY_SUPPORT	0
+#define QCE_SHA_HMAC_SUPPORT	1
+#define QCE_SHARE_CE_RESOURCE	3
+#define QCE_CE_SHARED		0
+
+static struct resource qcrypto_resources[] = {
+	[0] = {
+		.start = QCE_0_BASE,
+		.end = QCE_0_BASE + QCE_SIZE - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.name = "crypto_channels",
+		.start = DMOV8064_CE_IN_CHAN,
+		.end = DMOV8064_CE_OUT_CHAN,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.name = "crypto_crci_in",
+		.start = DMOV8064_CE_IN_CRCI,
+		.end = DMOV8064_CE_IN_CRCI,
+		.flags = IORESOURCE_DMA,
+	},
+	[3] = {
+		.name = "crypto_crci_out",
+		.start = DMOV8064_CE_OUT_CRCI,
+		.end = DMOV8064_CE_OUT_CRCI,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct resource qcedev_resources[] = {
+	[0] = {
+		.start = QCE_0_BASE,
+		.end = QCE_0_BASE + QCE_SIZE - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.name = "crypto_channels",
+		.start = DMOV8064_CE_IN_CHAN,
+		.end = DMOV8064_CE_OUT_CHAN,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.name = "crypto_crci_in",
+		.start = DMOV8064_CE_IN_CRCI,
+		.end = DMOV8064_CE_IN_CRCI,
+		.flags = IORESOURCE_DMA,
+	},
+	[3] = {
+		.name = "crypto_crci_out",
+		.start = DMOV8064_CE_OUT_CRCI,
+		.end = DMOV8064_CE_OUT_CRCI,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
+		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
+
+static struct msm_ce_hw_support qcrypto_ce_hw_suppport = {
+	.ce_shared = QCE_CE_SHARED,
+	.shared_ce_resource = QCE_SHARE_CE_RESOURCE,
+	.hw_key_support = QCE_HW_KEY_SUPPORT,
+	.sha_hmac = QCE_SHA_HMAC_SUPPORT,
+};
+
+static struct platform_device qcrypto_device = {
+	.name		= "qcrypto",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(qcrypto_resources),
+	.resource	= qcrypto_resources,
+	.dev		= {
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &qcrypto_ce_hw_suppport,
+	},
+};
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
+		defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
+
+static struct msm_ce_hw_support qcedev_ce_hw_suppport = {
+	.ce_shared = QCE_CE_SHARED,
+	.shared_ce_resource = QCE_SHARE_CE_RESOURCE,
+	.hw_key_support = QCE_HW_KEY_SUPPORT,
+	.sha_hmac = QCE_SHA_HMAC_SUPPORT,
+};
+
+static struct platform_device qcedev_device = {
+	.name		= "qce",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(qcedev_resources),
+	.resource	= qcedev_resources,
+	.dev		= {
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &qcedev_ce_hw_suppport,
+	},
+};
+#endif
+
+
 #define MSM_SHARED_RAM_PHYS 0x80000000
 static void __init apq8064_map_io(void)
 {
@@ -526,6 +641,15 @@
 	&msm8064_device_saw_regulator_core1,
 	&msm8064_device_saw_regulator_core2,
 	&msm8064_device_saw_regulator_core3,
+#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
+		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
+	&qcrypto_device,
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
+		defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
+	&qcedev_device,
+#endif
 };
 
 static struct platform_device *sim_devices[] __initdata = {
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 9813715..22767cec 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -4288,7 +4288,7 @@
 	.update_time		= 60000,
 	.max_voltage		= 4200,
 	.min_voltage		= 3200,
-	.resume_voltage		= 4100,
+	.resume_voltage_delta	= 100,
 	.term_current		= 100,
 	.cool_temp		= 10,
 	.warm_temp		= 40,
@@ -4378,6 +4378,10 @@
 		.num_configs = ARRAY_SIZE(pm8921_led_configs),
 };
 
+static struct pm8xxx_ccadc_platform_data pm8xxx_ccadc_pdata = {
+	.r_sense		= 10,
+};
+
 static struct pm8921_platform_data pm8921_platform_data __devinitdata = {
 	.irq_pdata		= &pm8xxx_irq_pdata,
 	.gpio_pdata		= &pm8xxx_gpio_pdata,
@@ -4391,6 +4395,7 @@
 	.bms_pdata		= &pm8921_bms_pdata,
 	.adc_pdata		= &pm8921_adc_pdata,
 	.leds_pdata		= &pm8xxx_leds_pdata,
+	.ccadc_pdata		= &pm8xxx_ccadc_pdata,
 };
 
 static struct msm_ssbi_platform_data msm8960_ssbi_pm8921_pdata __devinitdata = {
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index aaf6c83..c16c2ee 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5158,8 +5158,14 @@
 	CLK_LOOKUP("usb_fs_sys_clk",	usb_fs1_sys_clk.c,	NULL),
 	CLK_LOOKUP("iface_clk",		ce1_p_clk.c,		NULL),
 	CLK_LOOKUP("core_clk",		ce1_core_clk.c,		NULL),
-	CLK_LOOKUP("ref_clk",		sata_phy_ref_clk.c,     NULL),
+	CLK_LOOKUP("ref_clk",		sata_phy_ref_clk.c,	NULL),
 	CLK_LOOKUP("cfg_clk",		sata_phy_cfg_clk.c,	NULL),
+	CLK_LOOKUP("iface_clk",		ce3_p_clk.c,		"qce.0"),
+	CLK_LOOKUP("iface_clk",		ce3_p_clk.c,		"qcrypto.0"),
+	CLK_LOOKUP("core_clk",		ce3_core_clk.c,		"qce.0"),
+	CLK_LOOKUP("core_clk",		ce3_core_clk.c,		"qcrypto.0"),
+	CLK_LOOKUP("ce3_core_src_clk",	ce3_src_clk.c,		"qce.0"),
+	CLK_LOOKUP("ce3_core_src_clk",	ce3_src_clk.c,		"qcrypto.0"),
 	CLK_LOOKUP("dma_bam_pclk",	dma_bam_p_clk.c,	NULL),
 	CLK_LOOKUP("iface_clk",		gsbi1_p_clk.c,		NULL),
 	CLK_LOOKUP("iface_clk",		gsbi2_p_clk.c,		NULL),
@@ -5178,9 +5184,6 @@
 	CLK_LOOKUP("iface_clk",		sdc3_p_clk.c,		"msm_sdcc.3"),
 	CLK_LOOKUP("iface_clk",		sdc4_p_clk.c,		"msm_sdcc.4"),
 	CLK_LOOKUP("iface_clk",		pcie_p_clk.c,		NULL),
-	CLK_LOOKUP("core_src_clk",	ce3_src_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",          ce3_core_clk.c,         NULL),
-	CLK_LOOKUP("iface_clk",         ce3_p_clk.c,            NULL),
 	CLK_LOOKUP("core_clk",		adm0_clk.c,		"msm_dmov"),
 	CLK_LOOKUP("iface_clk",		adm0_p_clk.c,		"msm_dmov"),
 	CLK_LOOKUP("iface_clk",		pmic_arb0_p_clk.c,	NULL),
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 9b8d5ac..afc2649 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -761,6 +761,12 @@
 	CLK_DUMMY("dfab_clk",		DFAB_CLK,		NULL, 0),
 	CLK_DUMMY("dma_bam_pclk",	DMA_BAM_P_CLK,		NULL, 0),
 	CLK_DUMMY("mem_clk",		EBI1_ADM_CLK,	  "msm_dmov", 0),
+	CLK_DUMMY("ce3_core_src_clk",	CE3_SRC_CLK,     "qce.0", OFF),
+	CLK_DUMMY("ce3_core_src_clk",	CE3_SRC_CLK, "qcrypto.0", OFF),
+	CLK_DUMMY("core_clk",		CE3_CORE_CLK,	      "qce.0", OFF),
+	CLK_DUMMY("core_clk",		CE3_CORE_CLK,	  "qcrypto.0", OFF),
+	CLK_DUMMY("iface_clk",		CE3_P_CLK,	     "qce0.0", OFF),
+	CLK_DUMMY("iface_clk",		CE3_P_CLK,	  "qcrypto.0", OFF),
 };
 
 struct clock_init_data apq8064_dummy_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index 5a31f70..e8aa38e 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -12,6 +12,7 @@
 
 #include <asm/cacheflush.h>
 
+#ifdef CONFIG_SMP
 extern volatile int pen_release;
 
 static inline void cpu_enter_lowpower(void)
@@ -55,6 +56,7 @@
 		pr_debug("CPU%u: spurious wakeup call\n", cpu);
 	}
 }
+#endif
 
 int platform_cpu_kill(unsigned int cpu)
 {
@@ -68,6 +70,7 @@
  */
 void platform_cpu_die(unsigned int cpu)
 {
+#ifdef CONFIG_SMP
 	/*
 	 * we're ready for shutdown now, so do it
 	 */
@@ -79,6 +82,7 @@
 	 * coherency, and then restore interrupts
 	 */
 	cpu_leave_lowpower();
+#endif
 }
 
 int platform_cpu_disable(unsigned int cpu)
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index 1474fcb..3cb79b7 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -245,6 +245,13 @@
 #define DMOV_HSUART2_RX_CRCI   15
 #endif
 
+/* channels for APQ8064 */
+#define DMOV8064_CE_IN_CHAN        2
+#define DMOV8064_CE_IN_CRCI       14
+
+#define DMOV8064_CE_OUT_CHAN       3
+#define DMOV8064_CE_OUT_CRCI       15
+
 
 /* no client rate control ifc (eg, ram) */
 #define DMOV_NONE_CRCI        0
diff --git a/arch/arm/mach-msm/no-pm.c b/arch/arm/mach-msm/no-pm.c
index e34abb1..d6cdbe7 100644
--- a/arch/arm/mach-msm/no-pm.c
+++ b/arch/arm/mach-msm/no-pm.c
@@ -25,16 +25,3 @@
 
 void msm_pm_set_max_sleep_time(int64_t max_sleep_time_ns) { }
 EXPORT_SYMBOL(msm_pm_set_max_sleep_time);
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	return -ENOSYS;
-}
-
-int platform_cpu_kill(unsigned int cpu)
-{
-	return -ENOSYS;
-}
-
-void platform_cpu_die(unsigned int cpu)
-{ }
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index e2f7271..bddc80f 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -125,14 +125,6 @@
 #define LOAD_INT(x) ((x) >> FSHIFT)
 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
 
-static int get_loadavg(void)
-{
-	unsigned long this = this_cpu_load();
-
-
-	return LOAD_INT(this) * 10 + LOAD_FRAC(this) / 10;
-}
-
 static inline int which_bucket(unsigned int duration)
 {
 	int bucket = 0;
@@ -170,15 +162,6 @@
 {
 	int mult = 1;
 
-	/* for higher loadavg, we are more reluctant */
-
-	/*
-	 * this doesn't work as intended - it is almost always 0, but can
-	 * sometimes, depending on workload, spike very high into the hundreds
-	 * even when the average cpu load is under 10%.
-	 */
-	/* mult += 2 * get_loadavg(); */
-
 	/* for IO wait tasks (per cpu!) we add 5x each */
 	mult += 10 * nr_iowait_cpu(smp_processor_id());
 
diff --git a/drivers/crypto/msm/qce40.c b/drivers/crypto/msm/qce40.c
index 893933b..60a5aff 100644
--- a/drivers/crypto/msm/qce40.c
+++ b/drivers/crypto/msm/qce40.c
@@ -58,8 +58,9 @@
 	void __iomem *iobase;	    /* Virtual io base of CE HW  */
 	unsigned int phy_iobase;    /* Physical io base of CE HW    */
 
-	struct clk *ce_core_clk;	    /* Handle to CE clk */
-	struct clk *ce_clk;	    /* Handle to CE clk */
+	struct clk *ce_core_src_clk;	/* Handle to CE src clk*/
+	struct clk *ce_core_clk;	/* Handle to CE clk */
+	struct clk *ce_clk;		/* Handle to CE clk */
 
 	qce_comp_func_ptr_t qce_cb;	/* qce callback function pointer */
 
@@ -2391,6 +2392,8 @@
 	struct resource *resource;
 	struct clk *ce_core_clk;
 	struct clk *ce_clk;
+	struct clk *ce_core_src_clk;
+	int ret = 0;
 
 	pce_dev = kzalloc(sizeof(struct qce_device), GFP_KERNEL);
 	if (!pce_dev) {
@@ -2461,10 +2464,26 @@
 		goto err;
 	}
 
+	/* Get CE3 src core clk. */
+	ce_core_src_clk = clk_get(pce_dev->pdev, "ce3_core_src_clk");
+	if (!IS_ERR(ce_core_src_clk)) {
+		pce_dev->ce_core_src_clk = ce_core_src_clk;
+
+		/* Set the core src clk @100Mhz */
+		ret = clk_set_rate(pce_dev->ce_core_src_clk, 100000000);
+		if (ret) {
+			clk_put(pce_dev->ce_core_src_clk);
+			goto err;
+		}
+	} else
+		pce_dev->ce_core_src_clk = NULL;
+
 	/* Get CE core clk */
 	ce_core_clk = clk_get(pce_dev->pdev, "core_clk");
 	if (IS_ERR(ce_core_clk)) {
 		*rc = PTR_ERR(ce_core_clk);
+		if (pce_dev->ce_core_src_clk != NULL)
+			clk_put(pce_dev->ce_core_src_clk);
 		goto err;
 	}
 	pce_dev->ce_core_clk = ce_core_clk;
@@ -2472,6 +2491,8 @@
 	ce_clk = clk_get(pce_dev->pdev, "iface_clk");
 	if (IS_ERR(ce_clk)) {
 		*rc = PTR_ERR(ce_clk);
+		if (pce_dev->ce_core_src_clk != NULL)
+			clk_put(pce_dev->ce_core_src_clk);
 		clk_put(pce_dev->ce_core_clk);
 		goto err;
 	}
@@ -2480,6 +2501,8 @@
 	/* Enable CE core clk */
 	*rc = clk_enable(pce_dev->ce_core_clk);
 	if (*rc) {
+		if (pce_dev->ce_core_src_clk != NULL)
+			clk_put(pce_dev->ce_core_src_clk);
 		clk_put(pce_dev->ce_core_clk);
 		clk_put(pce_dev->ce_clk);
 		goto err;
@@ -2488,6 +2511,8 @@
 		*rc = clk_enable(pce_dev->ce_clk);
 		if (*rc) {
 			clk_disable(pce_dev->ce_core_clk);
+			if (pce_dev->ce_core_src_clk != NULL)
+				clk_put(pce_dev->ce_core_src_clk);
 			clk_put(pce_dev->ce_core_clk);
 			clk_put(pce_dev->ce_clk);
 			goto err;
@@ -2539,6 +2564,9 @@
 	clk_disable(pce_dev->ce_clk);
 	clk_disable(pce_dev->ce_core_clk);
 
+	if (pce_dev->ce_core_src_clk != NULL)
+		clk_put(pce_dev->ce_core_src_clk);
+
 	clk_put(pce_dev->ce_clk);
 	clk_put(pce_dev->ce_core_clk);
 
@@ -2571,4 +2599,4 @@
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Mona Hossain <mhossain@codeaurora.org>");
 MODULE_DESCRIPTION("Crypto Engine driver");
-MODULE_VERSION("2.13");
+MODULE_VERSION("2.14");
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 742d8dd..b72ceb3 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -270,7 +270,6 @@
 	SINGLE_IRQ_RESOURCE("PM8921_BMS_OCV_FOR_R", PM8921_BMS_OCV_FOR_R),
 	SINGLE_IRQ_RESOURCE("PM8921_BMS_GOOD_OCV", PM8921_BMS_GOOD_OCV),
 	SINGLE_IRQ_RESOURCE("PM8921_BMS_VSENSE_AVG", PM8921_BMS_VSENSE_AVG),
-	SINGLE_IRQ_RESOURCE("PM8921_BMS_CCADC_EOC", PM8921_BMS_CCADC_EOC),
 };
 
 static struct mfd_cell charger_cell __devinitdata = {
@@ -342,6 +341,17 @@
 	.pdata_size	= sizeof(struct pm8xxx_batt_alarm_core_data),
 };
 
+static const struct resource ccadc_cell_resources[] __devinitconst = {
+	SINGLE_IRQ_RESOURCE("PM8921_BMS_CCADC_EOC", PM8921_BMS_CCADC_EOC),
+};
+
+static struct mfd_cell ccadc_cell __devinitdata = {
+	.name		= PM8XXX_CCADC_DEV_NAME,
+	.id		= -1,
+	.resources	= ccadc_cell_resources,
+	.num_resources	= ARRAY_SIZE(ccadc_cell_resources),
+};
+
 static struct mfd_cell vibrator_cell __devinitdata = {
 	.name           = PM8XXX_VIBRATOR_DEV_NAME,
 	.id             = -1,
@@ -566,6 +576,19 @@
 		}
 	}
 
+	if (pdata->ccadc_pdata) {
+		ccadc_cell.platform_data = pdata->ccadc_pdata;
+		ccadc_cell.pdata_size =
+				sizeof(struct pm8xxx_ccadc_platform_data);
+
+		ret = mfd_add_devices(pmic->dev, 0, &ccadc_cell, 1, NULL,
+					irq_base);
+		if (ret) {
+			pr_err("Failed to add ccadc subdevice ret=%d\n", ret);
+			goto bail;
+		}
+	}
+
 	return 0;
 bail:
 	if (pmic->irq_chip) {
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index 3b3758e..bb20a3f 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.c
@@ -308,6 +308,7 @@
 	}
 
 	dev->trans_start = jiffies;
+	/* if write() succeeds, skb access is unsafe in this process */
 	bam_ret = msm_bam_dmux_write(p->ch_id, skb);
 
 	if (bam_ret != 0) {
@@ -316,16 +317,6 @@
 		goto xmit_out;
 	}
 
-	if (count_this_packet(skb->data, skb->len)) {
-		p->stats.tx_packets++;
-		p->stats.tx_bytes += skb->len;
-#ifdef CONFIG_MSM_RMNET_DEBUG
-		p->wakeups_xmit += rmnet_cause_wakeup(p);
-#endif
-	}
-	DBG1("[%s] Tx packet #%lu len=%d mark=0x%x\n",
-	    dev->name, p->stats.tx_packets, skb->len, skb->mark);
-
 	return 0;
 xmit_out:
 	/* data xmited, safe to release skb */
@@ -335,7 +326,21 @@
 
 static void bam_write_done(void *dev, struct sk_buff *skb)
 {
+	struct rmnet_private *p = netdev_priv(dev);
+	u32 opmode = p->operation_mode;
+
 	DBG1("%s: write complete\n", __func__);
+	if (RMNET_IS_MODE_IP(opmode) ||
+				count_this_packet(skb->data, skb->len)) {
+		p->stats.tx_packets++;
+		p->stats.tx_bytes += skb->len;
+#ifdef CONFIG_MSM_RMNET_DEBUG
+		p->wakeups_xmit += rmnet_cause_wakeup(p);
+#endif
+	}
+	DBG1("[%s] Tx packet #%lu len=%d mark=0x%x\n",
+	    ((struct net_device *)(dev))->name, p->stats.tx_packets,
+	    skb->len, skb->mark);
 	dev_kfree_skb_any(skb);
 	netif_wake_queue(dev);
 }
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 3590e6d..7c8dfea 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -332,7 +332,14 @@
 	help
 	  Say Y here to enable support for pm8921 chip charger subdevice
 
+config PM8XXX_CCADC
+	tristate "PM8XXX battery current adc driver"
+	depends on MFD_PM8921_CORE
+	help
+	  Say Y here to enable support for pm8921 chip bms subdevice
+
 config PM8921_BMS
+	select PM8XXX_CCADC
 	tristate "PM8921 Battery Monitoring System driver"
 	depends on MFD_PM8921_CORE
 	help
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index f61c88a..e168590 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -45,5 +45,6 @@
 obj-$(CONFIG_BATTERY_BQ27520)	+= bq27520_fuelgauger.o
 obj-$(CONFIG_BATTERY_BQ27541)	+= bq27541_fuelgauger.o
 obj-$(CONFIG_SMB137B_CHARGER)   += smb137b.o
+obj-$(CONFIG_PM8XXX_CCADC)	+= pm8xxx-ccadc.o
 obj-$(CONFIG_PM8921_BMS)	+= pm8921-bms.o
 obj-$(CONFIG_PM8921_CHARGER)	+= pm8921-charger.o
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index d7cf3a8..143d9b5 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -19,6 +19,7 @@
 #include <linux/mfd/pm8xxx/pm8921-bms.h>
 #include <linux/mfd/pm8xxx/core.h>
 #include <linux/mfd/pm8xxx/pm8921-adc.h>
+#include <linux/mfd/pm8xxx/ccadc.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/debugfs.h>
@@ -29,15 +30,6 @@
 #define BMS_OUTPUT0		0x230
 #define BMS_OUTPUT1		0x231
 #define BMS_TEST1		0x237
-#define CCADC_ANA_PARAM		0x240
-#define CCADC_DIG_PARAM		0x241
-#define CCADC_RSV		0x242
-#define CCADC_DATA0		0x244
-#define CCADC_DATA1		0x245
-#define CCADC_OFFSET_TRIM1	0x34A
-#define CCADC_OFFSET_TRIM0	0x34B
-#define CCADC_FULLSCALE_TRIM1	0x34C
-#define CCADC_FULLSCALE_TRIM0	0x34D
 
 #define ADC_ARB_SECP_CNTRL	0x190
 #define ADC_ARB_SECP_AMUX_CNTRL	0x191
@@ -57,7 +49,6 @@
 	PM8921_BMS_OCV_FOR_R,
 	PM8921_BMS_GOOD_OCV,
 	PM8921_BMS_VSENSE_AVG,
-	PM8921_BMS_CCADC_EOC,
 	PM_BMS_MAX_INTS,
 };
 
@@ -75,8 +66,6 @@
 	struct work_struct	calib_hkadc_work;
 	struct delayed_work	calib_ccadc_work;
 	unsigned int		calib_delay_ms;
-	int			ccadc_gain_uv;
-	u16			ccadc_result_offset;
 	unsigned int		revision;
 	unsigned int		xoadc_v0625;
 	unsigned int		xoadc_v125;
@@ -400,56 +389,6 @@
 				cc_to_microvolt_v2((s64)cc);
 }
 
-#define CCADC_READING_RESOLUTION_N_V1	1085069
-#define CCADC_READING_RESOLUTION_D_V1	100000
-#define CCADC_READING_RESOLUTION_N_V2	542535
-#define CCADC_READING_RESOLUTION_D_V2	100000
-static s64 ccadc_reading_to_microvolt_v1(s64 cc)
-{
-	return div_s64(cc * CCADC_READING_RESOLUTION_N_V1,
-					CCADC_READING_RESOLUTION_D_V1);
-}
-
-static s64 ccadc_reading_to_microvolt_v2(s64 cc)
-{
-	return div_s64(cc * CCADC_READING_RESOLUTION_N_V2,
-					CCADC_READING_RESOLUTION_D_V2);
-}
-
-static s64 ccadc_reading_to_microvolt(struct pm8921_bms_chip *chip, s64 cc)
-{
-	/*
-	 * resolution (the value of a single bit) was changed after revision 2.0
-	 * for more accurate readings
-	 */
-	return (chip->revision < PM8XXX_REVISION_8921_2p0) ?
-				ccadc_reading_to_microvolt_v1((s64)cc) :
-				ccadc_reading_to_microvolt_v2((s64)cc);
-}
-
-static s64 microvolt_to_ccadc_reading_v1(s64 uv)
-{
-	return div_s64(uv * CCADC_READING_RESOLUTION_D_V1,
-				CCADC_READING_RESOLUTION_N_V1);
-}
-
-static s64 microvolt_to_ccadc_reading_v2(s64 uv)
-{
-	return div_s64(uv * CCADC_READING_RESOLUTION_D_V2,
-				CCADC_READING_RESOLUTION_N_V2);
-}
-
-static s64 microvolt_to_ccadc_reading(struct pm8921_bms_chip *chip, s64 cc)
-{
-	/*
-	 * resolution (the value of a single bit) was changed after revision 2.0
-	 * for more accurate readings
-	 */
-	return (chip->revision < PM8XXX_REVISION_8921_2p0) ?
-				microvolt_to_ccadc_reading_v1((s64)cc) :
-				microvolt_to_ccadc_reading_v2((s64)cc);
-}
-
 #define CC_READING_TICKS	55
 #define SLEEP_CLK_HZ		32768
 #define SECONDS_PER_HOUR	3600
@@ -459,19 +398,6 @@
 			SLEEP_CLK_HZ * SECONDS_PER_HOUR);
 }
 
-#define GAIN_REFERENCE_UV 25000
-/*
- * gain compensation for ccadc readings - common for vsense based and
- * couloumb counter based readings
- */
-static s64 cc_adjust_for_gain(struct pm8921_bms_chip *chip, s64 cc)
-{
-	if (chip->ccadc_gain_uv == 0)
-		return cc;
-
-	return div_s64(cc * GAIN_REFERENCE_UV, chip->ccadc_gain_uv);
-}
-
 /* returns the signed value read from the hardware */
 static int read_cc(struct pm8921_bms_chip *chip, int *result)
 {
@@ -559,9 +485,9 @@
 		pr_err("fail to read VSENSE_FOR_RBATT rc = %d\n", rc);
 		return rc;
 	}
-	*result = ccadc_reading_to_microvolt(chip, reading);
+	*result = pm8xxx_ccadc_reading_to_microvolt(chip->revision, reading);
 	pr_debug("raw = %04x vsense_for_r_uV = %u\n", reading, *result);
-	*result = cc_adjust_for_gain(chip, *result);
+	*result = pm8xxx_cc_adjust_for_gain(*result);
 	pr_debug("after adj vsense_for_r_uV = %u\n", *result);
 	return 0;
 }
@@ -593,9 +519,10 @@
 		pr_err("fail to read VSENSE_AVG rc = %d\n", rc);
 		return rc;
 	}
-	*result = ccadc_reading_to_microvolt(chip, reading);
+	*result = pm8xxx_ccadc_reading_to_microvolt(the_chip->revision,
+								reading);
 	pr_debug("raw = %04x vsense = %d\n", reading, *result);
-	*result = cc_adjust_for_gain(the_chip, (s64)*result);
+	*result = pm8xxx_cc_adjust_for_gain((s64)*result);
 	pr_debug("after adj vsense = %d\n", *result);
 	return 0;
 }
@@ -976,7 +903,7 @@
 	rc = read_cc(the_chip, coulumb_counter);
 	cc_voltage_uv = (int64_t)*coulumb_counter;
 	cc_voltage_uv = cc_to_microvolt(chip, cc_voltage_uv);
-	cc_voltage_uv = cc_adjust_for_gain(chip, cc_voltage_uv);
+	cc_voltage_uv = pm8xxx_cc_adjust_for_gain(cc_voltage_uv);
 	pr_debug("cc_voltage_uv = %lld microvolts\n", cc_voltage_uv);
 	cc_uvh = ccmicrovolt_to_uvh(cc_voltage_uv);
 	pr_debug("cc_uvh = %lld micro_volt_hour\n", cc_uvh);
@@ -1224,386 +1151,12 @@
 	calib_hkadc(chip);
 }
 
-#define START_CONV_BIT	BIT(7)
-#define EOC_CONV_BIT	BIT(6)
-#define SEL_CCADC_BIT	BIT(1)
-#define EN_ARB_BIT	BIT(0)
-
-#define CCADC_CALIB_DIG_PARAM	0xE3
-#define CCADC_CALIB_RSV_GND	0x40
-#define CCADC_CALIB_RSV_25MV	0x80
-#define CCADC_CALIB_ANA_PARAM	0x1B
-#define SAMPLE_COUNT		16
-#define ADC_WAIT_COUNT		10
-
-#define CCADC_MAX_25MV		30000
-#define CCADC_MIN_25MV		20000
-#define CCADC_MAX_0UV		-4000
-#define CCADC_MIN_0UV		-7000
-
-#define CCADC_INTRINSIC_OFFSET  0xC000
-
-#define REG_SBI_CONFIG		0x04F
-#define PAGE3_ENABLE_MASK	0x6
-
-static int calib_ccadc_enable_trim_access(struct pm8921_bms_chip *chip,
-								u8 *sbi_config)
-{
-	u8 reg;
-	int rc;
-
-	rc = pm8xxx_readb(chip->dev->parent, REG_SBI_CONFIG, sbi_config);
-	if (rc) {
-		pr_err("error = %d reading sbi config reg\n", rc);
-		return rc;
-	}
-
-	reg = *sbi_config | PAGE3_ENABLE_MASK;
-	return pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, reg);
-}
-
-static int calib_ccadc_restore_trim_access(struct pm8921_bms_chip *chip,
-							u8 sbi_config)
-{
-	return pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, sbi_config);
-}
-
-static int calib_ccadc_enable_arbiter(struct pm8921_bms_chip *chip)
-{
-	int rc;
-
-	/* enable Arbiter, must be sent twice */
-	rc = pm_bms_masked_write(chip, ADC_ARB_SECP_CNTRL,
-			SEL_CCADC_BIT | EN_ARB_BIT, SEL_CCADC_BIT | EN_ARB_BIT);
-	if (rc < 0) {
-		pr_err("error = %d enabling arbiter for offset\n", rc);
-		return rc;
-	}
-	rc = pm_bms_masked_write(chip, ADC_ARB_SECP_CNTRL,
-			SEL_CCADC_BIT | EN_ARB_BIT, SEL_CCADC_BIT | EN_ARB_BIT);
-	if (rc < 0) {
-		pr_err("error = %d writing ADC_ARB_SECP_CNTRL\n", rc);
-		return rc;
-	}
-	return 0;
-}
-
-static int calib_start_conv(struct pm8921_bms_chip *chip,
-					u16 *result)
-{
-	int rc, i;
-	u8 data_msb, data_lsb, reg;
-
-	/* Start conversion */
-	rc = pm_bms_masked_write(chip, ADC_ARB_SECP_CNTRL,
-					START_CONV_BIT, START_CONV_BIT);
-	if (rc < 0) {
-		pr_err("error = %d starting offset meas\n", rc);
-		return rc;
-	}
-
-	/* Wait for End of conversion */
-	for (i = 0; i < ADC_WAIT_COUNT; i++) {
-		rc = pm8xxx_readb(chip->dev->parent,
-					ADC_ARB_SECP_CNTRL, &reg);
-		if (rc < 0) {
-			pr_err("error = %d read eoc for offset\n", rc);
-			return rc;
-		}
-		if ((reg & (START_CONV_BIT | EOC_CONV_BIT)) != EOC_CONV_BIT)
-			msleep(60);
-		else
-			break;
-	}
-	if (i == ADC_WAIT_COUNT) {
-		pr_err("waited too long for offset eoc\n");
-		return rc;
-	}
-
-	rc = pm8xxx_readb(chip->dev->parent, ADC_ARB_SECP_DATA0, &data_lsb);
-	if (rc < 0) {
-		pr_err("error = %d reading offset lsb\n", rc);
-		return rc;
-	}
-
-	rc = pm8xxx_readb(chip->dev->parent, ADC_ARB_SECP_DATA1, &data_msb);
-	if (rc < 0) {
-		pr_err("error = %d reading offset msb\n", rc);
-		return rc;
-	}
-
-	*result = (data_msb << 8) | data_lsb;
-	return 0;
-}
-
-static int calib_ccadc_read_trim(struct pm8921_bms_chip *chip,
-					int addr, u8 *data_msb, u8 *data_lsb)
-{
-	int rc;
-	u8 sbi_config;
-
-	calib_ccadc_enable_trim_access(chip, &sbi_config);
-	rc = pm8xxx_readb(chip->dev->parent, addr, data_msb);
-	if (rc < 0) {
-		pr_err("error = %d read msb\n", rc);
-		return rc;
-	}
-	rc = pm8xxx_readb(chip->dev->parent, addr + 1, data_lsb);
-	if (rc < 0) {
-		pr_err("error = %d read lsb\n", rc);
-		return rc;
-	}
-	calib_ccadc_restore_trim_access(chip, sbi_config);
-	return 0;
-}
-
-static int calib_ccadc_read_gain_uv(struct pm8921_bms_chip *chip)
-{
-	s8 data_msb;
-	u8 data_lsb;
-	int rc, gain, offset;
-
-	rc = calib_ccadc_read_trim(chip, CCADC_FULLSCALE_TRIM1,
-						&data_msb, &data_lsb);
-	gain = (data_msb << 8) | data_lsb;
-
-	rc = calib_ccadc_read_trim(chip, CCADC_OFFSET_TRIM1,
-						&data_msb, &data_lsb);
-	offset = (data_msb << 8) | data_lsb;
-
-	pr_debug("raw gain trim = 0x%x offset trim =0x%x\n", gain, offset);
-	gain = ccadc_reading_to_microvolt(chip, (s64)gain - offset);
-	return gain;
-}
-
-#define CCADC_PROGRAM_TRIM_COUNT	2
-#define ADC_ARB_BMS_CNTRL_CCADC_SHIFT	4
-#define ADC_ARB_BMS_CNTRL_CONV_MASK	0x03
-#define BMS_CONV_IN_PROGRESS		0x2
-
-static int calib_ccadc_program_trim(struct pm8921_bms_chip *chip,
-					int addr, u8 data_msb, u8 data_lsb,
-					int wait)
-{
-	int i, rc, loop;
-	u8 cntrl, sbi_config;
-	bool in_progress = 0;
-
-	loop = wait ? CCADC_PROGRAM_TRIM_COUNT : 0;
-
-	calib_ccadc_enable_trim_access(chip, &sbi_config);
-
-	for (i = 0; i < loop; i++) {
-		rc = pm8xxx_readb(chip->dev->parent, ADC_ARB_BMS_CNTRL, &cntrl);
-		if (rc < 0) {
-			pr_err("error = %d reading ADC_ARB_BMS_CNTRL\n", rc);
-			return rc;
-		}
-
-		/* break if a ccadc conversion is not happening */
-		in_progress = (((cntrl >> ADC_ARB_BMS_CNTRL_CCADC_SHIFT)
-			& ADC_ARB_BMS_CNTRL_CONV_MASK) == BMS_CONV_IN_PROGRESS);
-
-		if (!in_progress)
-			break;
-	}
-
-	if (in_progress) {
-		pr_debug("conv in progress cannot write trim,returing EBUSY\n");
-		return -EBUSY;
-	}
-
-	rc = pm8xxx_writeb(chip->dev->parent, addr, data_msb);
-	if (rc < 0) {
-		pr_err("error = %d write msb = 0x%x\n", rc, data_msb);
-		return rc;
-	}
-	rc = pm8xxx_writeb(chip->dev->parent, addr + 1, data_lsb);
-	if (rc < 0) {
-		pr_err("error = %d write lsb = 0x%x\n", rc, data_lsb);
-		return rc;
-	}
-	calib_ccadc_restore_trim_access(chip, sbi_config);
-	return 0;
-}
-
-static void calib_ccadc(struct pm8921_bms_chip *chip)
-{
-	u8 data_msb, data_lsb, sec_cntrl;
-	int result_offset, voltage_offset, result_gain;
-	u16 result;
-	int i, rc;
-
-	rc = pm8xxx_readb(chip->dev->parent, ADC_ARB_SECP_CNTRL, &sec_cntrl);
-	if (rc < 0) {
-		pr_err("error = %d reading ADC_ARB_SECP_CNTRL\n", rc);
-		return;
-	}
-
-	rc = calib_ccadc_enable_arbiter(chip);
-	if (rc < 0) {
-		pr_err("error = %d enabling arbiter for offset\n", rc);
-		goto bail;
-	}
-
-	/*
-	 * Set decimation ratio to 4k, lower ratio may be used in order to speed
-	 * up, pending verification through bench
-	 */
-	rc = pm8xxx_writeb(chip->dev->parent, ADC_ARB_SECP_DIG_PARAM,
-							CCADC_CALIB_DIG_PARAM);
-	if (rc < 0) {
-		pr_err("error = %d writing ADC_ARB_SECP_DIG_PARAM\n", rc);
-		goto bail;
-	}
-
-	result_offset = 0;
-	for (i = 0; i < SAMPLE_COUNT; i++) {
-		/* Short analog inputs to CCADC internally to ground */
-		rc = pm8xxx_writeb(chip->dev->parent, ADC_ARB_SECP_RSV,
-							CCADC_CALIB_RSV_GND);
-		if (rc < 0) {
-			pr_err("error = %d selecting gnd voltage\n", rc);
-			goto bail;
-		}
-
-		/* Enable CCADC */
-		rc = pm8xxx_writeb(chip->dev->parent, ADC_ARB_SECP_ANA_PARAM,
-							CCADC_CALIB_ANA_PARAM);
-		if (rc < 0) {
-			pr_err("error = %d enabling ccadc\n", rc);
-			goto bail;
-		}
-
-		rc = calib_start_conv(chip, &result);
-		if (rc < 0) {
-			pr_err("error = %d for zero volt measurement\n", rc);
-			goto bail;
-		}
-
-		result_offset += result;
-	}
-
-	result_offset = result_offset / SAMPLE_COUNT;
-
-	voltage_offset = ccadc_reading_to_microvolt(chip,
-			((s64)result_offset - CCADC_INTRINSIC_OFFSET));
-
-	pr_debug("offset result_offset = 0x%x, voltage = %d microVolts\n",
-				result_offset, voltage_offset);
-
-	/* Sanity Check */
-	if (voltage_offset > CCADC_MAX_0UV) {
-		pr_err("offset voltage = %d is huge limiting to %d\n",
-					voltage_offset, CCADC_MAX_0UV);
-		result_offset = CCADC_INTRINSIC_OFFSET
-			+ microvolt_to_ccadc_reading(chip, (s64)CCADC_MAX_0UV);
-	} else if (voltage_offset < CCADC_MIN_0UV) {
-		pr_err("offset voltage = %d is too low limiting to %d\n",
-					voltage_offset, CCADC_MIN_0UV);
-		result_offset = CCADC_INTRINSIC_OFFSET
-			+ microvolt_to_ccadc_reading(chip, (s64)CCADC_MIN_0UV);
-	}
-
-	chip->ccadc_result_offset = result_offset;
-	data_msb = chip->ccadc_result_offset >> 8;
-	data_lsb = chip->ccadc_result_offset;
-
-	rc = calib_ccadc_program_trim(chip, CCADC_OFFSET_TRIM1,
-						data_msb, data_lsb, 1);
-	if (rc) {
-		pr_debug("error = %d programming offset trim 0x%02x 0x%02x\n",
-					rc, data_msb, data_lsb);
-		/* enable the interrupt and write it when it fires */
-		pm8921_bms_enable_irq(chip, PM8921_BMS_CCADC_EOC);
-	}
-
-	rc = calib_ccadc_enable_arbiter(chip);
-	if (rc < 0) {
-		pr_err("error = %d enabling arbiter for gain\n", rc);
-		goto bail;
-	}
-
-	/*
-	 * Set decimation ratio to 4k, lower ratio may be used in order to speed
-	 * up, pending verification through bench
-	 */
-	rc = pm8xxx_writeb(chip->dev->parent, ADC_ARB_SECP_DIG_PARAM,
-							CCADC_CALIB_DIG_PARAM);
-	if (rc < 0) {
-		pr_err("error = %d enabling decimation ration for gain\n", rc);
-		goto bail;
-	}
-
-	result_gain = 0;
-	for (i = 0; i < SAMPLE_COUNT; i++) {
-		rc = pm8xxx_writeb(chip->dev->parent,
-					ADC_ARB_SECP_RSV, CCADC_CALIB_RSV_25MV);
-		if (rc < 0) {
-			pr_err("error = %d selecting 25mV for gain\n", rc);
-			goto bail;
-		}
-
-		/* Enable CCADC */
-		rc = pm8xxx_writeb(chip->dev->parent, ADC_ARB_SECP_ANA_PARAM,
-							CCADC_CALIB_ANA_PARAM);
-		if (rc < 0) {
-			pr_err("error = %d enabling ccadc\n", rc);
-			goto bail;
-		}
-
-		rc = calib_start_conv(chip, &result);
-		if (rc < 0) {
-			pr_err("error = %d for adc reading 25mV\n", rc);
-			goto bail;
-		}
-
-		result_gain += result;
-	}
-	result_gain = result_gain / SAMPLE_COUNT;
-
-	/*
-	 * result_offset includes INTRINSIC OFFSET
-	 * chip->ccadc_gain_uv will be the actual voltage
-	 * measured for 25000UV
-	 */
-	chip->ccadc_gain_uv = ccadc_reading_to_microvolt(chip,
-				((s64)result_gain - result_offset));
-
-	pr_debug("gain result_gain = 0x%x, voltage = %d microVolts\n",
-							result_gain,
-							chip->ccadc_gain_uv);
-	/* Sanity Check */
-	if (chip->ccadc_gain_uv > CCADC_MAX_25MV) {
-		pr_err("gain voltage = %d is huge limiting to %d\n",
-					chip->ccadc_gain_uv, CCADC_MAX_25MV);
-		chip->ccadc_gain_uv = CCADC_MAX_25MV;
-		result_gain = result_offset +
-			microvolt_to_ccadc_reading(chip, CCADC_MAX_25MV);
-	} else if (chip->ccadc_gain_uv < CCADC_MIN_25MV) {
-		pr_err("gain voltage = %d is too low limiting to %d\n",
-					chip->ccadc_gain_uv, CCADC_MIN_25MV);
-		chip->ccadc_gain_uv = CCADC_MIN_25MV;
-		result_gain = result_offset +
-			microvolt_to_ccadc_reading(chip, CCADC_MIN_25MV);
-	}
-
-	data_msb = result_gain >> 8;
-	data_lsb = result_gain;
-	rc = calib_ccadc_program_trim(chip, CCADC_FULLSCALE_TRIM1,
-						data_msb, data_lsb, 0);
-	if (rc)
-		pr_debug("error = %d programming gain trim\n", rc);
-bail:
-	pm8xxx_writeb(chip->dev->parent, ADC_ARB_SECP_CNTRL, sec_cntrl);
-}
-
 static void calibrate_ccadc_work(struct work_struct *work)
 {
 	struct pm8921_bms_chip *chip = container_of(work,
 				struct pm8921_bms_chip, calib_ccadc_work.work);
 
-	calib_ccadc(chip);
+	pm8xxx_calib_ccadc();
 	schedule_delayed_work(&chip->calib_ccadc_work,
 			round_jiffies_relative(msecs_to_jiffies
 			(chip->calib_delay_ms)));
@@ -1810,23 +1363,6 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t pm8921_bms_ccadc_eoc_handler(int irq, void *data)
-{
-	u8 data_msb, data_lsb;
-	struct pm8921_bms_chip *chip = data;
-	int rc;
-
-	pr_debug("irq = %d triggered\n", irq);
-	data_msb = chip->ccadc_result_offset >> 8;
-	data_lsb = chip->ccadc_result_offset;
-
-	rc = calib_ccadc_program_trim(chip, CCADC_OFFSET_TRIM1,
-						data_msb, data_lsb, 0);
-	pm8921_bms_disable_irq(chip, PM8921_BMS_CCADC_EOC);
-
-	return IRQ_HANDLED;
-}
-
 struct pm_bms_irq_init_data {
 	unsigned int	irq_id;
 	char		*name;
@@ -1857,8 +1393,6 @@
 				pm8921_bms_good_ocv_handler),
 	BMS_IRQ(PM8921_BMS_VSENSE_AVG, IRQF_TRIGGER_RISING,
 				pm8921_bms_vsense_avg_handler),
-	BMS_IRQ(PM8921_BMS_CCADC_EOC, IRQF_TRIGGER_RISING,
-				pm8921_bms_ccadc_eoc_handler),
 };
 
 static void free_irqs(struct pm8921_bms_chip *chip)
@@ -2076,7 +1610,7 @@
 	case CALIB_CCADC:
 		/* reading this will trigger calibration */
 		*val = 0;
-		calib_ccadc(the_chip);
+		pm8xxx_calib_ccadc();
 		break;
 	default:
 		ret = -EINVAL;
@@ -2169,7 +1703,7 @@
 {
 	int i;
 
-	chip->dent = debugfs_create_dir("pm8921_bms", NULL);
+	chip->dent = debugfs_create_dir("pm8921-bms", NULL);
 
 	if (IS_ERR(chip->dent)) {
 		pr_err("pmic bms couldnt create debugfs dir\n");
@@ -2184,20 +1718,6 @@
 			(void *)BMS_OUTPUT1, &reg_fops);
 	debugfs_create_file("BMS_TEST1", 0644, chip->dent,
 			(void *)BMS_TEST1, &reg_fops);
-	debugfs_create_file("CCADC_ANA_PARAM", 0644, chip->dent,
-			(void *)CCADC_ANA_PARAM, &reg_fops);
-	debugfs_create_file("CCADC_DIG_PARAM", 0644, chip->dent,
-			(void *)CCADC_DIG_PARAM, &reg_fops);
-	debugfs_create_file("CCADC_RSV", 0644, chip->dent,
-			(void *)CCADC_RSV, &reg_fops);
-	debugfs_create_file("CCADC_DATA0", 0644, chip->dent,
-			(void *)CCADC_DATA0, &reg_fops);
-	debugfs_create_file("CCADC_DATA1", 0644, chip->dent,
-			(void *)CCADC_DATA1, &reg_fops);
-	debugfs_create_file("CCADC_OFFSET_TRIM1", 0644, chip->dent,
-			(void *)CCADC_OFFSET_TRIM1, &reg_fops);
-	debugfs_create_file("CCADC_OFFSET_TRIM0", 0644, chip->dent,
-			(void *)CCADC_OFFSET_TRIM0, &reg_fops);
 
 	debugfs_create_file("test_batt_temp", 0644, chip->dent,
 				(void *)TEST_BATT_TEMP, &temp_fops);
@@ -2296,7 +1816,6 @@
 	create_debugfs_entries(chip);
 
 	check_initial_ocv(chip);
-	chip->ccadc_gain_uv = calib_ccadc_read_gain_uv(chip);
 
 	INIT_DELAYED_WORK(&chip->calib_ccadc_work, calibrate_ccadc_work);
 	/* begin calibration only on chips > 2.0 */
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 148a5e5..af44f45 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -201,8 +201,8 @@
  * @update_time:		how frequently the userland needs to be updated
  * @max_voltage:		the max volts the batt should be charged up to
  * @min_voltage:		the min battery voltage before turning the FETon
- * @resume_voltage:		the voltage at which the battery should resume
- *				charging
+ * @resume_voltage_delta:	the voltage delta from vdd max at which the
+ *				battery should resume charging
  * @term_current:		The charging based term current
  *
  */
@@ -225,7 +225,9 @@
 	unsigned int			warm_bat_chg_current;
 	unsigned int			cool_bat_voltage;
 	unsigned int			warm_bat_voltage;
-	unsigned int			resume_voltage;
+	unsigned int			is_bat_cool;
+	unsigned int			is_bat_warm;
+	unsigned int			resume_voltage_delta;
 	unsigned int			term_current;
 	unsigned int			vbat_channel;
 	unsigned int			batt_temp_channel;
@@ -1898,11 +1900,17 @@
 			the_chip->cool_temp + TEMP_HYSTERISIS_DEGC;
 		pm_chg_ibatmax_set(the_chip, the_chip->cool_bat_chg_current);
 		pm_chg_vddmax_set(the_chip, the_chip->cool_bat_voltage);
+		pm_chg_vbatdet_set(the_chip,
+			the_chip->cool_bat_voltage
+			- the_chip->resume_voltage_delta);
 	} else {
 		btm_config.low_thr_temp = the_chip->cool_temp;
 		pm_chg_ibatmax_set(the_chip, the_chip->max_bat_chg_current);
 		pm_chg_vddmax_set(the_chip, the_chip->max_voltage);
+		pm_chg_vbatdet_set(the_chip,
+			the_chip->max_voltage - the_chip->resume_voltage_delta);
 	}
+	the_chip->is_bat_cool = enter;
 	schedule_work(&btm_config_work);
 }
 
@@ -1914,11 +1922,17 @@
 			the_chip->warm_temp - TEMP_HYSTERISIS_DEGC;
 		pm_chg_ibatmax_set(the_chip, the_chip->warm_bat_chg_current);
 		pm_chg_vddmax_set(the_chip, the_chip->warm_bat_voltage);
+		pm_chg_vbatdet_set(the_chip,
+			the_chip->warm_bat_voltage
+			- the_chip->resume_voltage_delta);
 	} else {
 		btm_config.high_thr_temp = the_chip->warm_temp;
 		pm_chg_ibatmax_set(the_chip, the_chip->max_bat_chg_current);
 		pm_chg_vddmax_set(the_chip, the_chip->max_voltage);
+		pm_chg_vbatdet_set(the_chip,
+			the_chip->max_voltage - the_chip->resume_voltage_delta);
 	}
+	the_chip->is_bat_warm = enter;
 	schedule_work(&btm_config_work);
 }
 
@@ -2211,10 +2225,11 @@
 						chip->max_voltage, rc);
 		return rc;
 	}
-	rc = pm_chg_vbatdet_set(chip, chip->resume_voltage);
+	rc = pm_chg_vbatdet_set(chip,
+				chip->max_voltage - chip->resume_voltage_delta);
 	if (rc) {
 		pr_err("Failed to set vbatdet comprator voltage to %d rc=%d\n",
-						chip->resume_voltage, rc);
+			chip->max_voltage - chip->resume_voltage_delta, rc);
 		return rc;
 	}
 
@@ -2458,6 +2473,24 @@
 }
 DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_reg, set_reg, "0x%02llx\n");
 
+enum {
+	BAT_WARM_ZONE,
+	BAT_COOL_ZONE,
+};
+static int get_warm_cool(void *data, u64 * val)
+{
+	if (!the_chip) {
+		pr_err("%s called before init\n", __func__);
+		return -EINVAL;
+	}
+	if ((int)data == BAT_WARM_ZONE)
+		*val = the_chip->is_bat_warm;
+	if ((int)data == BAT_COOL_ZONE)
+		*val = the_chip->is_bat_cool;
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(warm_cool_fops, get_warm_cool, NULL, "0x%lld\n");
+
 static void create_debugfs_entries(struct pm8921_chg_chip *chip)
 {
 	int i;
@@ -2524,6 +2557,11 @@
 	debugfs_create_file("REGULATION_LOOP_CONTROL", 0644, chip->dent, NULL,
 			    &reg_loop_fops);
 
+	debugfs_create_file("BAT_WARM_ZONE", 0644, chip->dent,
+				(void *)BAT_WARM_ZONE, &warm_cool_fops);
+	debugfs_create_file("BAT_COOL_ZONE", 0644, chip->dent,
+				(void *)BAT_COOL_ZONE, &warm_cool_fops);
+
 	for (i = 0; i < ARRAY_SIZE(chg_irq_data); i++) {
 		if (chip->pmic_chg_irq[chg_irq_data[i].irq_id])
 			debugfs_create_file(chg_irq_data[i].name, 0444,
@@ -2558,7 +2596,7 @@
 	chip->update_time = pdata->update_time;
 	chip->max_voltage = pdata->max_voltage;
 	chip->min_voltage = pdata->min_voltage;
-	chip->resume_voltage = pdata->resume_voltage;
+	chip->resume_voltage_delta = pdata->resume_voltage_delta;
 	chip->term_current = pdata->term_current;
 	chip->vbat_channel = pdata->charger_cdata.vbat_channel;
 	chip->batt_temp_channel = pdata->charger_cdata.batt_temp_channel;
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
new file mode 100644
index 0000000..1245045
--- /dev/null
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -0,0 +1,761 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pm8xxx/ccadc.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#define CCADC_ANA_PARAM		0x240
+#define CCADC_DIG_PARAM		0x241
+#define CCADC_RSV		0x242
+#define CCADC_DATA0		0x244
+#define CCADC_DATA1		0x245
+#define CCADC_OFFSET_TRIM1	0x34A
+#define CCADC_OFFSET_TRIM0	0x34B
+#define CCADC_FULLSCALE_TRIM1	0x34C
+#define CCADC_FULLSCALE_TRIM0	0x34D
+
+/* note : TRIM1 is the msb and TRIM0 is the lsb */
+#define ADC_ARB_SECP_CNTRL	0x190
+#define ADC_ARB_SECP_AMUX_CNTRL	0x191
+#define ADC_ARB_SECP_ANA_PARAM	0x192
+#define ADC_ARB_SECP_DIG_PARAM	0x193
+#define ADC_ARB_SECP_RSV	0x194
+#define ADC_ARB_SECP_DATA1	0x195
+#define ADC_ARB_SECP_DATA0	0x196
+
+#define ADC_ARB_BMS_CNTRL	0x18D
+
+#define START_CONV_BIT	BIT(7)
+#define EOC_CONV_BIT	BIT(6)
+#define SEL_CCADC_BIT	BIT(1)
+#define EN_ARB_BIT	BIT(0)
+
+#define CCADC_CALIB_DIG_PARAM	0xE3
+#define CCADC_CALIB_RSV_GND	0x40
+#define CCADC_CALIB_RSV_25MV	0x80
+#define CCADC_CALIB_ANA_PARAM	0x1B
+#define SAMPLE_COUNT		16
+#define ADC_WAIT_COUNT		10
+
+#define CCADC_MAX_25MV		30000
+#define CCADC_MIN_25MV		20000
+#define CCADC_MAX_0UV		-4000
+#define CCADC_MIN_0UV		-7000
+
+#define CCADC_INTRINSIC_OFFSET  0xC000
+
+struct pm8xxx_ccadc_chip {
+	struct device		*dev;
+	struct dentry		*dent;
+	u16			ccadc_offset;
+	int			ccadc_gain_uv;
+	unsigned int		revision;
+	int			eoc_irq;
+	int			r_sense;
+};
+
+static struct pm8xxx_ccadc_chip *the_chip;
+
+static s64 microvolt_to_ccadc_reading_v1(s64 uv)
+{
+	return div_s64(uv * CCADC_READING_RESOLUTION_D_V1,
+				CCADC_READING_RESOLUTION_N_V1);
+}
+
+static s64 microvolt_to_ccadc_reading_v2(s64 uv)
+{
+	return div_s64(uv * CCADC_READING_RESOLUTION_D_V2,
+				CCADC_READING_RESOLUTION_N_V2);
+}
+
+static s64 microvolt_to_ccadc_reading(struct pm8xxx_ccadc_chip *chip, s64 cc)
+{
+	/*
+	 * resolution (the value of a single bit) was changed after revision 2.0
+	 * for more accurate readings
+	 */
+	return (the_chip->revision < PM8XXX_REVISION_8921_2p0) ?
+				microvolt_to_ccadc_reading_v1((s64)cc) :
+				microvolt_to_ccadc_reading_v2((s64)cc);
+}
+
+static int cc_adjust_for_offset(u16 raw)
+{
+	/* this has the intrinsic offset */
+	return (int)raw - the_chip->ccadc_offset;
+}
+
+#define GAIN_REFERENCE_UV 25000
+/*
+ * gain compensation for ccadc readings - common for vsense based and
+ * couloumb counter based readings
+ */
+s64 pm8xxx_cc_adjust_for_gain(s64 uv)
+{
+	if (the_chip == NULL || the_chip->ccadc_gain_uv == 0)
+		return uv;
+
+	return div_s64(uv * GAIN_REFERENCE_UV, the_chip->ccadc_gain_uv);
+}
+EXPORT_SYMBOL(pm8xxx_cc_adjust_for_gain);
+
+static int pm_ccadc_masked_write(struct pm8xxx_ccadc_chip *chip, u16 addr,
+							u8 mask, u8 val)
+{
+	int rc;
+	u8 reg;
+
+	rc = pm8xxx_readb(chip->dev->parent, addr, &reg);
+	if (rc) {
+		pr_err("read failed addr = %03X, rc = %d\n", addr, rc);
+		return rc;
+	}
+	reg &= ~mask;
+	reg |= val & mask;
+	rc = pm8xxx_writeb(chip->dev->parent, addr, reg);
+	if (rc) {
+		pr_err("write failed addr = %03X, rc = %d\n", addr, rc);
+		return rc;
+	}
+	return 0;
+}
+
+#define REG_SBI_CONFIG		0x04F
+#define PAGE3_ENABLE_MASK	0x6
+static int calib_ccadc_enable_trim_access(struct pm8xxx_ccadc_chip *chip,
+								u8 *sbi_config)
+{
+	u8 reg;
+	int rc;
+
+	rc = pm8xxx_readb(chip->dev->parent, REG_SBI_CONFIG, sbi_config);
+	if (rc) {
+		pr_err("error = %d reading sbi config reg\n", rc);
+		return rc;
+	}
+
+	reg = *sbi_config | PAGE3_ENABLE_MASK;
+	return pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, reg);
+}
+
+static int calib_ccadc_restore_trim_access(struct pm8xxx_ccadc_chip *chip,
+							u8 sbi_config)
+{
+	return pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, sbi_config);
+}
+
+static int calib_ccadc_enable_arbiter(struct pm8xxx_ccadc_chip *chip)
+{
+	int rc;
+
+	/* enable Arbiter, must be sent twice */
+	rc = pm_ccadc_masked_write(chip, ADC_ARB_SECP_CNTRL,
+			SEL_CCADC_BIT | EN_ARB_BIT, SEL_CCADC_BIT | EN_ARB_BIT);
+	if (rc < 0) {
+		pr_err("error = %d enabling arbiter for offset\n", rc);
+		return rc;
+	}
+	rc = pm_ccadc_masked_write(chip, ADC_ARB_SECP_CNTRL,
+			SEL_CCADC_BIT | EN_ARB_BIT, SEL_CCADC_BIT | EN_ARB_BIT);
+	if (rc < 0) {
+		pr_err("error = %d writing ADC_ARB_SECP_CNTRL\n", rc);
+		return rc;
+	}
+	return 0;
+}
+
+static int calib_start_conv(struct pm8xxx_ccadc_chip *chip,
+					u16 *result)
+{
+	int rc, i;
+	u8 data_msb, data_lsb, reg;
+
+	/* Start conversion */
+	rc = pm_ccadc_masked_write(chip, ADC_ARB_SECP_CNTRL,
+					START_CONV_BIT, START_CONV_BIT);
+	if (rc < 0) {
+		pr_err("error = %d starting offset meas\n", rc);
+		return rc;
+	}
+
+	/* Wait for End of conversion */
+	for (i = 0; i < ADC_WAIT_COUNT; i++) {
+		rc = pm8xxx_readb(chip->dev->parent,
+					ADC_ARB_SECP_CNTRL, &reg);
+		if (rc < 0) {
+			pr_err("error = %d read eoc for offset\n", rc);
+			return rc;
+		}
+		if ((reg & (START_CONV_BIT | EOC_CONV_BIT)) != EOC_CONV_BIT)
+			msleep(60);
+		else
+			break;
+	}
+	if (i == ADC_WAIT_COUNT) {
+		pr_err("waited too long for offset eoc\n");
+		return rc;
+	}
+
+	rc = pm8xxx_readb(chip->dev->parent, ADC_ARB_SECP_DATA0, &data_lsb);
+	if (rc < 0) {
+		pr_err("error = %d reading offset lsb\n", rc);
+		return rc;
+	}
+
+	rc = pm8xxx_readb(chip->dev->parent, ADC_ARB_SECP_DATA1, &data_msb);
+	if (rc < 0) {
+		pr_err("error = %d reading offset msb\n", rc);
+		return rc;
+	}
+
+	*result = (data_msb << 8) | data_lsb;
+	return 0;
+}
+
+static int calib_ccadc_read_trim(struct pm8xxx_ccadc_chip *chip,
+					int addr, u8 *data_msb, u8 *data_lsb)
+{
+	int rc;
+	u8 sbi_config;
+
+	calib_ccadc_enable_trim_access(chip, &sbi_config);
+	rc = pm8xxx_readb(chip->dev->parent, addr, data_msb);
+	if (rc < 0) {
+		pr_err("error = %d read msb\n", rc);
+		return rc;
+	}
+	rc = pm8xxx_readb(chip->dev->parent, addr + 1, data_lsb);
+	if (rc < 0) {
+		pr_err("error = %d read lsb\n", rc);
+		return rc;
+	}
+	calib_ccadc_restore_trim_access(chip, sbi_config);
+	return 0;
+}
+
+static void calib_ccadc_read_offset_and_gain(struct pm8xxx_ccadc_chip *chip,
+						int *gain, u16 *offset)
+{
+	s8 data_msb;
+	u8 data_lsb;
+	int rc;
+
+	rc = calib_ccadc_read_trim(chip, CCADC_FULLSCALE_TRIM1,
+						&data_msb, &data_lsb);
+	*gain = (data_msb << 8) | data_lsb;
+
+	rc = calib_ccadc_read_trim(chip, CCADC_OFFSET_TRIM1,
+						&data_msb, &data_lsb);
+	*offset = (data_msb << 8) | data_lsb;
+
+	pr_debug("raw gain trim = 0x%x offset trim =0x%x\n", *gain, *offset);
+	*gain = pm8xxx_ccadc_reading_to_microvolt(chip->revision,
+							(s64)*gain - *offset);
+	pr_debug("gain uv = %duV offset=0x%x\n", *gain, *offset);
+}
+
+#define CCADC_PROGRAM_TRIM_COUNT	2
+#define ADC_ARB_BMS_CNTRL_CCADC_SHIFT	4
+#define ADC_ARB_BMS_CNTRL_CONV_MASK	0x03
+#define BMS_CONV_IN_PROGRESS		0x2
+
+static int calib_ccadc_program_trim(struct pm8xxx_ccadc_chip *chip,
+					int addr, u8 data_msb, u8 data_lsb,
+					int wait)
+{
+	int i, rc, loop;
+	u8 cntrl, sbi_config;
+	bool in_progress = 0;
+
+	loop = wait ? CCADC_PROGRAM_TRIM_COUNT : 0;
+
+	calib_ccadc_enable_trim_access(chip, &sbi_config);
+
+	for (i = 0; i < loop; i++) {
+		rc = pm8xxx_readb(chip->dev->parent, ADC_ARB_BMS_CNTRL, &cntrl);
+		if (rc < 0) {
+			pr_err("error = %d reading ADC_ARB_BMS_CNTRL\n", rc);
+			return rc;
+		}
+
+		/* break if a ccadc conversion is not happening */
+		in_progress = (((cntrl >> ADC_ARB_BMS_CNTRL_CCADC_SHIFT)
+			& ADC_ARB_BMS_CNTRL_CONV_MASK) == BMS_CONV_IN_PROGRESS);
+
+		if (!in_progress)
+			break;
+	}
+
+	if (in_progress) {
+		pr_debug("conv in progress cannot write trim,returing EBUSY\n");
+		return -EBUSY;
+	}
+
+	rc = pm8xxx_writeb(chip->dev->parent, addr, data_msb);
+	if (rc < 0) {
+		pr_err("error = %d write msb = 0x%x\n", rc, data_msb);
+		return rc;
+	}
+	rc = pm8xxx_writeb(chip->dev->parent, addr + 1, data_lsb);
+	if (rc < 0) {
+		pr_err("error = %d write lsb = 0x%x\n", rc, data_lsb);
+		return rc;
+	}
+	calib_ccadc_restore_trim_access(chip, sbi_config);
+	return 0;
+}
+
+void pm8xxx_calib_ccadc(void)
+{
+	u8 data_msb, data_lsb, sec_cntrl;
+	int result_offset, voltage_offset, result_gain;
+	u16 result;
+	int i, rc;
+
+	rc = pm8xxx_readb(the_chip->dev->parent,
+					ADC_ARB_SECP_CNTRL, &sec_cntrl);
+	if (rc < 0) {
+		pr_err("error = %d reading ADC_ARB_SECP_CNTRL\n", rc);
+		return;
+	}
+
+	rc = calib_ccadc_enable_arbiter(the_chip);
+	if (rc < 0) {
+		pr_err("error = %d enabling arbiter for offset\n", rc);
+		goto bail;
+	}
+
+	/*
+	 * Set decimation ratio to 4k, lower ratio may be used in order to speed
+	 * up, pending verification through bench
+	 */
+	rc = pm8xxx_writeb(the_chip->dev->parent, ADC_ARB_SECP_DIG_PARAM,
+							CCADC_CALIB_DIG_PARAM);
+	if (rc < 0) {
+		pr_err("error = %d writing ADC_ARB_SECP_DIG_PARAM\n", rc);
+		goto bail;
+	}
+
+	result_offset = 0;
+	for (i = 0; i < SAMPLE_COUNT; i++) {
+		/* Short analog inputs to CCADC internally to ground */
+		rc = pm8xxx_writeb(the_chip->dev->parent, ADC_ARB_SECP_RSV,
+							CCADC_CALIB_RSV_GND);
+		if (rc < 0) {
+			pr_err("error = %d selecting gnd voltage\n", rc);
+			goto bail;
+		}
+
+		/* Enable CCADC */
+		rc = pm8xxx_writeb(the_chip->dev->parent,
+				ADC_ARB_SECP_ANA_PARAM, CCADC_CALIB_ANA_PARAM);
+		if (rc < 0) {
+			pr_err("error = %d enabling ccadc\n", rc);
+			goto bail;
+		}
+
+		rc = calib_start_conv(the_chip, &result);
+		if (rc < 0) {
+			pr_err("error = %d for zero volt measurement\n", rc);
+			goto bail;
+		}
+
+		result_offset += result;
+	}
+
+	result_offset = result_offset / SAMPLE_COUNT;
+
+	voltage_offset = pm8xxx_ccadc_reading_to_microvolt(the_chip->revision,
+			((s64)result_offset - CCADC_INTRINSIC_OFFSET));
+
+	pr_debug("offset result_offset = 0x%x, voltage = %d microVolts\n",
+				result_offset, voltage_offset);
+
+	/* Sanity Check */
+	if (voltage_offset > CCADC_MAX_0UV) {
+		pr_err("offset voltage = %d is huge limiting to %d\n",
+					voltage_offset, CCADC_MAX_0UV);
+		result_offset = CCADC_INTRINSIC_OFFSET
+			+ microvolt_to_ccadc_reading(the_chip,
+							(s64)CCADC_MAX_0UV);
+	} else if (voltage_offset < CCADC_MIN_0UV) {
+		pr_err("offset voltage = %d is too low limiting to %d\n",
+					voltage_offset, CCADC_MIN_0UV);
+		result_offset = CCADC_INTRINSIC_OFFSET
+			+ microvolt_to_ccadc_reading(the_chip,
+							(s64)CCADC_MIN_0UV);
+	}
+
+	the_chip->ccadc_offset = result_offset;
+	data_msb = the_chip->ccadc_offset >> 8;
+	data_lsb = the_chip->ccadc_offset;
+
+	rc = calib_ccadc_program_trim(the_chip, CCADC_OFFSET_TRIM1,
+						data_msb, data_lsb, 1);
+	if (rc) {
+		pr_debug("error = %d programming offset trim 0x%02x 0x%02x\n",
+					rc, data_msb, data_lsb);
+		/* enable the interrupt and write it when it fires */
+		enable_irq(the_chip->eoc_irq);
+	}
+
+	rc = calib_ccadc_enable_arbiter(the_chip);
+	if (rc < 0) {
+		pr_err("error = %d enabling arbiter for gain\n", rc);
+		goto bail;
+	}
+
+	/*
+	 * Set decimation ratio to 4k, lower ratio may be used in order to speed
+	 * up, pending verification through bench
+	 */
+	rc = pm8xxx_writeb(the_chip->dev->parent, ADC_ARB_SECP_DIG_PARAM,
+							CCADC_CALIB_DIG_PARAM);
+	if (rc < 0) {
+		pr_err("error = %d enabling decimation ration for gain\n", rc);
+		goto bail;
+	}
+
+	result_gain = 0;
+	for (i = 0; i < SAMPLE_COUNT; i++) {
+		rc = pm8xxx_writeb(the_chip->dev->parent,
+					ADC_ARB_SECP_RSV, CCADC_CALIB_RSV_25MV);
+		if (rc < 0) {
+			pr_err("error = %d selecting 25mV for gain\n", rc);
+			goto bail;
+		}
+
+		/* Enable CCADC */
+		rc = pm8xxx_writeb(the_chip->dev->parent,
+			ADC_ARB_SECP_ANA_PARAM, CCADC_CALIB_ANA_PARAM);
+		if (rc < 0) {
+			pr_err("error = %d enabling ccadc\n", rc);
+			goto bail;
+		}
+
+		rc = calib_start_conv(the_chip, &result);
+		if (rc < 0) {
+			pr_err("error = %d for adc reading 25mV\n", rc);
+			goto bail;
+		}
+
+		result_gain += result;
+	}
+	result_gain = result_gain / SAMPLE_COUNT;
+
+	/*
+	 * result_offset includes INTRINSIC OFFSET
+	 * the_chip->ccadc_gain_uv will be the actual voltage
+	 * measured for 25000UV
+	 */
+	the_chip->ccadc_gain_uv = pm8xxx_ccadc_reading_to_microvolt(
+				the_chip->revision,
+				((s64)result_gain - result_offset));
+
+	pr_debug("gain result_gain = 0x%x, voltage = %d microVolts\n",
+					result_gain, the_chip->ccadc_gain_uv);
+	/* Sanity Check */
+	if (the_chip->ccadc_gain_uv > CCADC_MAX_25MV) {
+		pr_err("gain voltage = %d is huge limiting to %d\n",
+					the_chip->ccadc_gain_uv,
+					CCADC_MAX_25MV);
+		the_chip->ccadc_gain_uv = CCADC_MAX_25MV;
+		result_gain = result_offset +
+			microvolt_to_ccadc_reading(the_chip, CCADC_MAX_25MV);
+	} else if (the_chip->ccadc_gain_uv < CCADC_MIN_25MV) {
+		pr_err("gain voltage = %d is too low limiting to %d\n",
+					the_chip->ccadc_gain_uv,
+					CCADC_MIN_25MV);
+		the_chip->ccadc_gain_uv = CCADC_MIN_25MV;
+		result_gain = result_offset +
+			microvolt_to_ccadc_reading(the_chip, CCADC_MIN_25MV);
+	}
+
+	data_msb = result_gain >> 8;
+	data_lsb = result_gain;
+	rc = calib_ccadc_program_trim(the_chip, CCADC_FULLSCALE_TRIM1,
+						data_msb, data_lsb, 0);
+	if (rc)
+		pr_debug("error = %d programming gain trim\n", rc);
+bail:
+	pm8xxx_writeb(the_chip->dev->parent, ADC_ARB_SECP_CNTRL, sec_cntrl);
+}
+EXPORT_SYMBOL(pm8xxx_calib_ccadc);
+
+static irqreturn_t pm8921_bms_ccadc_eoc_handler(int irq, void *data)
+{
+	u8 data_msb, data_lsb;
+	struct pm8xxx_ccadc_chip *chip = data;
+	int rc;
+
+	pr_debug("irq = %d triggered\n", irq);
+	data_msb = chip->ccadc_offset >> 8;
+	data_lsb = chip->ccadc_offset;
+
+	rc = calib_ccadc_program_trim(chip, CCADC_OFFSET_TRIM1,
+						data_msb, data_lsb, 0);
+	disable_irq_nosync(chip->eoc_irq);
+
+	return IRQ_HANDLED;
+}
+
+#define CCADC_IBAT_DIG_PARAM	0xA3
+#define CCADC_IBAT_RSV		0x10
+#define CCADC_IBAT_ANA_PARAM	0x1A
+static int ccadc_get_rsense_voltage(int *voltage_uv)
+{
+	u16 raw;
+	int result;
+	int rc = 0;
+
+	rc = calib_ccadc_enable_arbiter(the_chip);
+	if (rc < 0) {
+		pr_err("error = %d enabling arbiter for offset\n", rc);
+		return rc;
+	}
+
+	rc = pm8xxx_writeb(the_chip->dev->parent, ADC_ARB_SECP_DIG_PARAM,
+							CCADC_IBAT_DIG_PARAM);
+	if (rc < 0) {
+		pr_err("error = %d writing ADC_ARB_SECP_DIG_PARAM\n", rc);
+		return rc;
+	}
+
+	rc = pm8xxx_writeb(the_chip->dev->parent, ADC_ARB_SECP_RSV,
+						CCADC_IBAT_RSV);
+	if (rc < 0) {
+		pr_err("error = %d selecting rsense\n", rc);
+		return rc;
+	}
+
+	rc = pm8xxx_writeb(the_chip->dev->parent,
+			ADC_ARB_SECP_ANA_PARAM, CCADC_IBAT_ANA_PARAM);
+	if (rc < 0) {
+		pr_err("error = %d enabling ccadc\n", rc);
+		return rc;
+	}
+
+	rc = calib_start_conv(the_chip, &raw);
+	if (rc < 0) {
+		pr_err("error = %d for zero volt measurement\n", rc);
+		return rc;
+	}
+
+	pr_debug("Vsense raw = 0x%x\n", raw);
+	result = cc_adjust_for_offset(raw);
+	pr_debug("Vsense after offset raw = 0x%x offset=0x%x\n",
+					result,
+					the_chip->ccadc_offset);
+	*voltage_uv = pm8xxx_ccadc_reading_to_microvolt(the_chip->revision,
+			((s64)result));
+	pr_debug("Vsense before gain = %d uV\n", *voltage_uv);
+	*voltage_uv = pm8xxx_cc_adjust_for_gain(*voltage_uv);
+
+	pr_debug("Vsense = %d uV\n", *voltage_uv);
+	return 0;
+}
+
+int pm8xxx_ccadc_get_battery_current(int *bat_current)
+{
+	int voltage_uv, rc;
+
+	rc = ccadc_get_rsense_voltage(&voltage_uv);
+	if (rc) {
+		pr_err("cant get voltage across rsense rc = %d\n", rc);
+		return rc;
+	}
+
+	*bat_current = voltage_uv/the_chip->r_sense;
+	/*
+	 * ccadc reads +ve current when the battery is charging
+	 * We need to return -ve if the battery is charging
+	 */
+	*bat_current = -1 * (*bat_current);
+	pr_debug("bat current = %d ma\n", *bat_current);
+	return 0;
+}
+EXPORT_SYMBOL(pm8xxx_ccadc_get_battery_current);
+
+static int get_reg(void *data, u64 * val)
+{
+	int addr = (int)data;
+	int ret;
+	u8 temp;
+
+	ret = pm8xxx_readb(the_chip->dev->parent, addr, &temp);
+	if (ret) {
+		pr_err("pm8xxx_readb to %x value = %d errored = %d\n",
+			addr, temp, ret);
+		return -EAGAIN;
+	}
+	*val = temp;
+	return 0;
+}
+
+static int set_reg(void *data, u64 val)
+{
+	int addr = (int)data;
+	int ret;
+	u8 temp;
+
+	temp = (u8) val;
+	ret = pm8xxx_writeb(the_chip->dev->parent, addr, temp);
+	if (ret) {
+		pr_err("pm8xxx_writeb to %x value = %d errored = %d\n",
+			addr, temp, ret);
+		return -EAGAIN;
+	}
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_reg, set_reg, "0x%02llx\n");
+
+static int get_calc(void *data, u64 * val)
+{
+	int ibat, rc;
+
+	rc = pm8xxx_ccadc_get_battery_current(&ibat);
+	*val = ibat;
+	return rc;
+}
+DEFINE_SIMPLE_ATTRIBUTE(calc_fops, get_calc, NULL, "%lld\n");
+
+static void create_debugfs_entries(struct pm8xxx_ccadc_chip *chip)
+{
+	chip->dent = debugfs_create_dir("pm8xxx-ccadc", NULL);
+
+	if (IS_ERR(chip->dent)) {
+		pr_err("ccadc couldnt create debugfs dir\n");
+		return;
+	}
+
+	debugfs_create_file("CCADC_ANA_PARAM", 0644, chip->dent,
+			(void *)CCADC_ANA_PARAM, &reg_fops);
+	debugfs_create_file("CCADC_DIG_PARAM", 0644, chip->dent,
+			(void *)CCADC_DIG_PARAM, &reg_fops);
+	debugfs_create_file("CCADC_RSV", 0644, chip->dent,
+			(void *)CCADC_RSV, &reg_fops);
+	debugfs_create_file("CCADC_DATA0", 0644, chip->dent,
+			(void *)CCADC_DATA0, &reg_fops);
+	debugfs_create_file("CCADC_DATA1", 0644, chip->dent,
+			(void *)CCADC_DATA1, &reg_fops);
+	debugfs_create_file("CCADC_OFFSET_TRIM1", 0644, chip->dent,
+			(void *)CCADC_OFFSET_TRIM1, &reg_fops);
+	debugfs_create_file("CCADC_OFFSET_TRIM0", 0644, chip->dent,
+			(void *)CCADC_OFFSET_TRIM0, &reg_fops);
+	debugfs_create_file("CCADC_FULLSCALE_TRIM1", 0644, chip->dent,
+			(void *)CCADC_FULLSCALE_TRIM1, &reg_fops);
+	debugfs_create_file("CCADC_FULLSCALE_TRIM0", 0644, chip->dent,
+			(void *)CCADC_FULLSCALE_TRIM0, &reg_fops);
+
+	debugfs_create_file("show_ibatt", 0644, chip->dent,
+				(void *)0, &calc_fops);
+}
+
+static int __devinit pm8xxx_ccadc_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	struct pm8xxx_ccadc_chip *chip;
+	struct resource *res;
+	const struct pm8xxx_ccadc_platform_data *pdata
+				= pdev->dev.platform_data;
+
+	if (!pdata) {
+		pr_err("missing platform data\n");
+		return -EINVAL;
+	}
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+			"PM8921_BMS_CCADC_EOC");
+	if  (!res) {
+		pr_err("failed to get irq\n");
+		return -EINVAL;
+	}
+
+	chip = kzalloc(sizeof(struct pm8xxx_ccadc_chip), GFP_KERNEL);
+	if (!chip) {
+		pr_err("Cannot allocate pm_bms_chip\n");
+		return -ENOMEM;
+	}
+	chip->dev = &pdev->dev;
+	chip->revision = pm8xxx_get_revision(chip->dev->parent);
+	chip->eoc_irq = res->start;
+	chip->r_sense = pdata->r_sense;
+
+	rc = request_irq(chip->eoc_irq,
+			pm8921_bms_ccadc_eoc_handler, IRQF_TRIGGER_RISING,
+			"bms_eoc_ccadc", chip);
+	if (rc) {
+		pr_err("failed to request %d irq rc= %d\n", chip->eoc_irq, rc);
+		goto free_chip;
+	}
+
+	platform_set_drvdata(pdev, chip);
+	the_chip = chip;
+
+	create_debugfs_entries(chip);
+
+	calib_ccadc_read_offset_and_gain(chip,
+					&chip->ccadc_gain_uv,
+					&chip->ccadc_offset);
+	return 0;
+
+free_chip:
+	kfree(chip);
+	return rc;
+}
+
+static int __devexit pm8xxx_ccadc_remove(struct platform_device *pdev)
+{
+	struct pm8xxx_ccadc_chip *chip = platform_get_drvdata(pdev);
+
+	debugfs_remove_recursive(chip->dent);
+	the_chip = NULL;
+	kfree(chip);
+	return 0;
+}
+
+static struct platform_driver pm8xxx_ccadc_driver = {
+	.probe	= pm8xxx_ccadc_probe,
+	.remove	= __devexit_p(pm8xxx_ccadc_remove),
+	.driver	= {
+		.name	= PM8XXX_CCADC_DEV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init pm8xxx_ccadc_init(void)
+{
+	return platform_driver_register(&pm8xxx_ccadc_driver);
+}
+
+static void __exit pm8xxx_ccadc_exit(void)
+{
+	platform_driver_unregister(&pm8xxx_ccadc_driver);
+}
+
+module_init(pm8xxx_ccadc_init);
+module_exit(pm8xxx_ccadc_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PMIC8XXX ccadc driver");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:" PM8XXX_CCADC_DEV_NAME);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 4622725..f8b320f 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -567,6 +567,7 @@
 	struct msm_otg_platform_data *pdata = motg->pdata;
 	int cnt = 0;
 	bool session_active;
+	u32 phy_ctrl_val = 0;
 
 	if (atomic_read(&motg->in_lpm))
 		return 0;
@@ -638,8 +639,13 @@
 	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
 
 	if (motg->caps & ALLOW_PHY_RETENTION && !session_active) {
-		writel_relaxed(readl_relaxed(USB_PHY_CTRL) & ~PHY_RETEN,
-				USB_PHY_CTRL);
+		phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
+		if (motg->pdata->otg_control == OTG_PHY_CONTROL)
+			/* Enable PHY HV interrupts to wake MPM/Link */
+			phy_ctrl_val |=
+				(PHY_IDHV_INTEN | PHY_OTGSESSVLDHV_INTEN);
+
+		writel_relaxed(phy_ctrl_val & ~PHY_RETEN, USB_PHY_CTRL);
 		motg->lpm_flags |= PHY_RETENTIONED;
 	}
 
@@ -688,6 +694,7 @@
 	struct usb_bus *bus = otg->host;
 	int cnt = 0;
 	unsigned temp;
+	u32 phy_ctrl_val = 0;
 
 	if (!atomic_read(&motg->in_lpm))
 		return 0;
@@ -711,8 +718,13 @@
 	if (motg->lpm_flags & PHY_RETENTIONED) {
 		msm_hsusb_mhl_switch_enable(motg, 1);
 		msm_hsusb_config_vddcx(1);
-		writel_relaxed(readl_relaxed(USB_PHY_CTRL) | PHY_RETEN,
-				USB_PHY_CTRL);
+		phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
+		phy_ctrl_val |= PHY_RETEN;
+		if (motg->pdata->otg_control == OTG_PHY_CONTROL)
+			/* Disable PHY HV interrupts */
+			phy_ctrl_val &=
+				~(PHY_IDHV_INTEN | PHY_OTGSESSVLDHV_INTEN);
+		writel_relaxed(phy_ctrl_val, USB_PHY_CTRL);
 		motg->lpm_flags &= ~PHY_RETENTIONED;
 	}
 
@@ -2362,13 +2374,17 @@
 	if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
 		pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
 
-	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
-			motg->pdata->otg_control == OTG_PMIC_CONTROL &&
+	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) {
+		if (motg->pdata->otg_control == OTG_PMIC_CONTROL &&
 			motg->pdata->pmic_id_irq)
-		motg->caps = ALLOW_PHY_POWER_COLLAPSE |
+			motg->caps = ALLOW_PHY_POWER_COLLAPSE |
 				ALLOW_PHY_RETENTION |
 				ALLOW_PHY_COMP_DISABLE;
 
+		if (motg->pdata->otg_control == OTG_PHY_CONTROL)
+			motg->caps = ALLOW_PHY_RETENTION;
+	}
+
 	wake_lock(&motg->wlock);
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
diff --git a/include/linux/mfd/pm8xxx/ccadc.h b/include/linux/mfd/pm8xxx/ccadc.h
new file mode 100644
index 0000000..6f6cb39
--- /dev/null
+++ b/include/linux/mfd/pm8xxx/ccadc.h
@@ -0,0 +1,100 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PMIC8XXX_CCADC_H__
+#define __PMIC8XXX_CCADC_H__
+
+#include <linux/mfd/pm8xxx/core.h>
+
+#define PM8XXX_CCADC_DEV_NAME "pm8xxx-ccadc"
+
+/**
+ * struct pm8xxx_ccadc_platform_data -
+ * @r_sense:		sense resistor value in (mOhms)
+ */
+struct pm8xxx_ccadc_platform_data {
+	int r_sense;
+};
+
+#define CCADC_READING_RESOLUTION_N_V1	1085069
+#define CCADC_READING_RESOLUTION_D_V1	100000
+#define CCADC_READING_RESOLUTION_N_V2	542535
+#define CCADC_READING_RESOLUTION_D_V2	100000
+
+static s64 pm8xxx_ccadc_reading_to_microvolt_v1(s64 cc)
+{
+	return div_s64(cc * CCADC_READING_RESOLUTION_N_V1,
+					CCADC_READING_RESOLUTION_D_V1);
+}
+
+static s64 pm8xxx_ccadc_reading_to_microvolt_v2(s64 cc)
+{
+	return div_s64(cc * CCADC_READING_RESOLUTION_N_V2,
+					CCADC_READING_RESOLUTION_D_V2);
+}
+
+static inline s64 pm8xxx_ccadc_reading_to_microvolt(int revision, s64 cc)
+{
+	/*
+	 * resolution (the value of a single bit) was changed after revision 2.0
+	 * for more accurate readings
+	 */
+	return (revision < PM8XXX_REVISION_8921_2p0) ?
+				pm8xxx_ccadc_reading_to_microvolt_v1((s64)cc) :
+				pm8xxx_ccadc_reading_to_microvolt_v2((s64)cc);
+}
+
+#if defined(CONFIG_PM8XXX_CCADC) || defined(CONFIG_PM8XXX_CCADC_MODULE)
+/**
+ * pm8xxx_cc_adjust_for_gain - the function to adjust the voltage read from
+ *			ccadc for gain compensation
+ * @v:	the voltage which needs to be gain compensated in microVolts
+ *
+ *
+ * RETURNS: gain compensated voltage
+ */
+s64 pm8xxx_cc_adjust_for_gain(s64 uv);
+
+/**
+ * pm8xxx_calib_ccadc - calibration for ccadc. This will calculate gain
+ *			and offset and reprogram them in the appropriate
+ *			registers
+ */
+void pm8xxx_calib_ccadc(void);
+
+/**
+ * pm8xxx_ccadc_get_battery_current - return the battery current based on vsense
+ *				resitor in milliamperes
+ * @result:	The pointer where the voltage will be updated. A -ve
+ *		result means that the current is flowing in
+ *		the battery - during battery charging
+ *
+ * RETURNS:	Error code if there was a problem reading vsense, Zero otherwise
+ *		The result won't be updated in case of an error.
+ *
+ */
+int pm8xxx_ccadc_get_battery_current(int *bat_current);
+#else
+static inline s64 pm8xxx_cc_adjust_for_gain(s64 uv)
+{
+	return -ENXIO;
+}
+static inline void pm8xxx_calib_ccadc(void)
+{
+}
+static inline int pm8xxx_ccadc_get_battery_current(int *bat_current)
+{
+	return -ENXIO;
+}
+#endif
+
+#endif /* __PMIC8XXX_CCADC_H__ */
diff --git a/include/linux/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h
index 73067b7..f39c00f 100644
--- a/include/linux/mfd/pm8xxx/pm8921-charger.h
+++ b/include/linux/mfd/pm8xxx/pm8921-charger.h
@@ -44,8 +44,8 @@
  * @min_voltage:	the voltage (mV) where charging method switches from
  *			trickle to fast. This is also the minimum voltage the
  *			system operates at
- * @resume_voltage:	the voltage (mV) to wait for before resume charging
- *			after the battery has been fully charged
+ * @resume_voltage_delta:	the (mV) drop to wait for before resume charging
+ *				after the battery has been fully charged
  * @term_current:	the charger current (mA) at which EOC happens
  * @cool_temp:		the temperature (degC) at which the battery is
  *			considered cool charging current and voltage is reduced
@@ -91,7 +91,7 @@
 	unsigned int			update_time;
 	unsigned int			max_voltage;
 	unsigned int			min_voltage;
-	unsigned int			resume_voltage;
+	unsigned int			resume_voltage_delta;
 	unsigned int			term_current;
 	unsigned int			cool_temp;
 	unsigned int			warm_temp;
diff --git a/include/linux/mfd/pm8xxx/pm8921.h b/include/linux/mfd/pm8xxx/pm8921.h
index 64bdab1..2c931b6 100644
--- a/include/linux/mfd/pm8xxx/pm8921.h
+++ b/include/linux/mfd/pm8xxx/pm8921.h
@@ -35,6 +35,7 @@
 #include <linux/mfd/pm8xxx/pm8921-bms.h>
 #include <linux/leds-pm8xxx.h>
 #include <linux/mfd/pm8xxx/vibrator.h>
+#include <linux/mfd/pm8xxx/ccadc.h>
 
 #define PM8921_NR_IRQS		256
 
@@ -128,6 +129,7 @@
 	struct pm8921_adc_platform_data		*adc_pdata;
 	struct pm8xxx_led_platform_data		*leds_pdata;
 	struct pm8xxx_vibrator_platform_data	*vibrator_pdata;
+	struct pm8xxx_ccadc_platform_data	*ccadc_pdata;
 };
 
 #endif
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 9cb8356..fcd91da 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -51,6 +51,8 @@
 #define ASYNC_INTR_CTRL         (1 << 29) /* Enable async interrupt */
 #define ULPI_STP_CTRL           (1 << 30) /* Block communication with PHY */
 #define PHY_RETEN               (1 << 1) /* PHY retention enable/disable */
+#define PHY_IDHV_INTEN          (1 << 8) /* PHY ID HV interrupt */
+#define PHY_OTGSESSVLDHV_INTEN  (1 << 9) /* PHY Session Valid HV int. */
 
 /* OTG definitions */
 #define OTGSC_INTSTS_MASK	(0x7f << 16)
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
index 97c08c0..cbe2eae 100755
--- a/scripts/gcc-wrapper.py
+++ b/scripts/gcc-wrapper.py
@@ -54,7 +54,6 @@
     "inode.c:72",
     "inode.c:73",
     "inode.c:74",
-    "menu.c:128",
     "msm_sdcc.c:126",
     "msm_sdcc.c:128",
     "nf_conntrack_netlink.c:790",