Merge "hwmon: pm8xxx-adc: Add PM8018 ADC Driver" into msm-3.0
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 52a4d20..43ac10a 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -20,6 +20,7 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_BZIP2=y
 CONFIG_RD_LZMA=y
+CONFIG_PANIC_TIMEOUT=5
 CONFIG_KALLSYMS_ALL=y
 CONFIG_EMBEDDED=y
 # CONFIG_PERF_EVENTS is not set
@@ -41,6 +42,7 @@
 CONFIG_MSM_SMD_PKG4=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_WATCHDOG=y
+CONFIG_MSM_DLOAD_MODE=y
 CONFIG_SWP_EMULATE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -132,7 +134,7 @@
 # CONFIG_MMC_MSM_SDC3_SUPPORT is not set
 # CONFIG_MMC_MSM_SDC4_SUPPORT is not set
 # CONFIG_MMC_MSM_SDC5_SUPPORT is not set
-# CONFIG_MMC_MSM_SPS_SUPPORT is not set
+CONFIG_MMC_MSM_SPS_SUPPORT=y
 CONFIG_MSM_SSBI=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 5bd19e5..99655d0 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1598,7 +1598,7 @@
 
 config MSM_DLOAD_MODE
 	bool "Enable download mode on crashes"
-	depends on ARCH_MSM8X60 || ARCH_MSM8960
+	depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM9615
 	default n
 	help
 		This makes the SoC enter download mode when it resets
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 4a34512..b5e6475 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -14,6 +14,7 @@
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/msm_ssbi.h>
+#include <linux/platform_data/qcom_crypto_device.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/mmc.h>
@@ -39,6 +40,9 @@
 	&msm9615_device_tsens,
 	&msm_device_nand,
 	&msm_rpm_device,
+#ifdef CONFIG_HW_RANDOM_MSM
+	&msm_device_rng,
+#endif
 
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
diff --git a/arch/arm/mach-msm/board-apq8064.c b/arch/arm/mach-msm/board-apq8064.c
index d37fb7b..4328b85 100644
--- a/arch/arm/mach-msm/board-apq8064.c
+++ b/arch/arm/mach-msm/board-apq8064.c
@@ -36,6 +36,18 @@
 
 #include "board-apq8064.h"
 
+static struct platform_device android_usb_device = {
+	.name = "android_usb",
+	.id = -1,
+};
+
+static struct msm_otg_platform_data msm_otg_pdata = {
+	.mode			= USB_PERIPHERAL,
+	.otg_control		= OTG_PHY_CONTROL,
+	.phy_type		= SNPS_28NM_INTEGRATED_PHY,
+	.pclk_src_name		= "dfab_usb_hs_clk",
+};
+
 /* APQ8064 have 4 SDCC controllers */
 enum sdcc_controllers {
 	SDCC1,
@@ -310,6 +322,9 @@
 	&apq8064_device_ssbi_pmic1,
 	&apq8064_device_ssbi_pmic2,
 	&msm_device_smd_apq8064,
+	&apq8064_device_otg,
+	&apq8064_device_gadget_peripheral,
+	&android_usb_device,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -326,13 +341,6 @@
 	.max_clock_speed = 26000000,
 };
 
-static struct msm_otg_platform_data msm_otg_pdata = {
-	.mode			= USB_PERIPHERAL,
-	.otg_control		= OTG_PHY_CONTROL,
-	.phy_type		= SNPS_28NM_INTEGRATED_PHY,
-	.pclk_src_name		= "dfab_usb_hs_clk",
-};
-
 #define KS8851_IRQ_GPIO		43
 
 static struct spi_board_info spi_board_info[] __initdata = {
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 058bc47..1c277c8 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -233,7 +233,13 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
-static struct gpiomux_setting gsbi3 = {
+static struct gpiomux_setting gsbi3_suspended_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_KEEPER,
+};
+
+static struct gpiomux_setting gsbi3_active_cfg = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_8MA,
 	.pull = GPIOMUX_PULL_NONE,
@@ -347,13 +353,15 @@
 	{
 		.gpio      = 16,	/* GSBI3 I2C QUP SDA */
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &gsbi3,
+			[GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
 		},
 	},
 	{
 		.gpio      = 17,	/* GSBI3 I2C QUP SCL */
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &gsbi3,
+			[GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
 		},
 	},
 	{
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 4552f80..3d2d720 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -1513,7 +1513,7 @@
 	SND(FM_DIGITAL_STEREO_HEADSET, 26),
 	SND(FM_DIGITAL_SPEAKER_PHONE, 27),
 	SND(FM_DIGITAL_BT_A2DP_HEADSET, 28),
-	SND(CURRENT, 34),
+	SND(CURRENT, 0x7FFFFFFE),
 	SND(FM_ANALOG_STEREO_HEADSET, 35),
 	SND(FM_ANALOG_STEREO_HEADSET_CODEC, 36),
 };
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index ea2d9d2..3265ffa 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5190,6 +5190,8 @@
 	CLK_LOOKUP("core_clk",		gsbi10_qup_clk.c,	"qup_i2c.10"),
 	CLK_LOOKUP("core_clk",		gsbi11_qup_clk.c,	NULL),
 	CLK_LOOKUP("core_clk",		gsbi12_qup_clk.c,	"qup_i2c.12"),
+	CLK_LOOKUP("tsif_pclk",		tsif_p_clk.c,		NULL),
+	CLK_LOOKUP("tsif_ref_clk",	tsif_ref_clk.c,		NULL),
 	CLK_LOOKUP("pdm_clk",		pdm_clk.c,		NULL),
 	CLK_LOOKUP("mem_clk",		pmem_clk.c,		"msm_sps"),
 	CLK_LOOKUP("core_clk",		prng_clk.c,		"msm_rng.0"),
@@ -5445,13 +5447,19 @@
 	/* Deassert MM SW_RESET_ALL signal. */
 	writel_relaxed(0, SW_RESET_ALL_REG);
 
+	/*
+	 * Some bits are only used on either 8960 or 8064 and are marked as
+	 * reserved bits on the other SoC. Writing to these reserved bits
+	 * should have no effect.
+	 */
 	/* Initialize MM AHB registers: Enable the FPB clock and disable HW
 	 * gating for all clocks. Also set VFE_AHB's FORCE_CORE_ON bit to
 	 * prevent its memory from being collapsed when the clock is halted.
 	 * The sleep and wake-up delays are set to safe values. */
 	rmwreg(0x00000003, AHB_EN_REG,  0x6C000103);
 	writel_relaxed(0x000007F9, AHB_EN2_REG);
-	rmwreg(0x00000000, AHB_EN3_REG, 0x00000001);
+	if (cpu_is_apq8064())
+		rmwreg(0x00000000, AHB_EN3_REG, 0x00000001);
 
 	/* Deassert all locally-owned MM AHB resets. */
 	rmwreg(0, SW_RESET_AHB_REG, 0xFFF7DFFF);
@@ -5465,7 +5473,8 @@
 	rmwreg(0x3027FCFF, MAXI_EN2_REG, 0x3A3FFFFF);
 	rmwreg(0x0027FCFF, MAXI_EN3_REG, 0x003FFFFF);
 	rmwreg(0x0027FCFF, MAXI_EN4_REG, 0x017FFFFF);
-	rmwreg(0x009FE4FF, MAXI_EN5_REG, 0x01FFEFFF);
+	if (cpu_is_apq8064())
+		rmwreg(0x009FE4FF, MAXI_EN5_REG, 0x01FFEFFF);
 	rmwreg(0x000003C7, SAXI_EN_REG,  0x00003FFF);
 
 	/* Initialize MM CC registers: Set MM FORCE_CORE_ON bits so that core
@@ -5477,22 +5486,26 @@
 	rmwreg(0x80FF0000, DSI2_BYTE_CC_REG,  0xE0FF0010);
 	rmwreg(0x80FF0000, DSI_PIXEL_CC_REG,  0xE0FF0010);
 	rmwreg(0x80FF0000, DSI2_PIXEL_CC_REG, 0xE0FF0010);
-	rmwreg(0x80FF0000, GFX2D0_CC_REG,     0xE0FF0010);
-	rmwreg(0x80FF0000, GFX2D1_CC_REG,     0xE0FF0010);
 	rmwreg(0x80FF0000, GFX3D_CC_REG,      0xE0FF0010);
 	rmwreg(0x80FF0000, IJPEG_CC_REG,      0xE0FF0010);
 	rmwreg(0x80FF0000, JPEGD_CC_REG,      0xE0FF0010);
 	rmwreg(0x80FF0000, MDP_CC_REG,        0xE1FF0010);
 	rmwreg(0x80FF0000, MDP_LUT_CC_REG,    0xE0FF0010);
 	rmwreg(0x80FF0000, ROT_CC_REG,        0xE0FF0010);
-	rmwreg(0x80FF0000, TV_CC_REG,         0xE1FFC010);
 	rmwreg(0x000004FF, TV_CC2_REG,        0x000007FF);
 	rmwreg(0xC0FF0000, VCODEC_CC_REG,     0xE0FF0010);
 	rmwreg(0x80FF0000, VFE_CC_REG,        0xE0FF4010);
 	rmwreg(0x800000FF, VFE_CC2_REG,       0xE00000FF);
 	rmwreg(0x80FF0000, VPE_CC_REG,        0xE0FF0010);
-	if (cpu_is_apq8064())
+	if (cpu_is_msm8960()) {
+		rmwreg(0x80FF0000, GFX2D0_CC_REG,     0xE0FF0010);
+		rmwreg(0x80FF0000, GFX2D1_CC_REG,     0xE0FF0010);
+		rmwreg(0x80FF0000, TV_CC_REG,         0xE1FFC010);
+	}
+	if (cpu_is_apq8064()) {
+		rmwreg(0x00000000, TV_CC_REG,         0x00004010);
 		rmwreg(0x80FF0000, VCAP_CC_REG,       0xE0FF1010);
+	}
 
 	/*
 	 * Initialize USB_HS_HCLK_FS registers: Set FORCE_C_ON bits so that
@@ -5500,8 +5513,10 @@
 	 * and wake-up value to max.
 	 */
 	rmwreg(0x0000004F, USB_HS1_HCLK_FS_REG, 0x0000007F);
-	rmwreg(0x0000004F, USB_HS3_HCLK_FS_REG, 0x0000007F);
-	rmwreg(0x0000004F, USB_HS4_HCLK_FS_REG, 0x0000007F);
+	if (cpu_is_apq8064()) {
+		rmwreg(0x0000004F, USB_HS3_HCLK_FS_REG, 0x0000007F);
+		rmwreg(0x0000004F, USB_HS4_HCLK_FS_REG, 0x0000007F);
+	}
 
 	/* De-assert MM AXI resets to all hardware blocks. */
 	writel_relaxed(0, SW_RESET_AXI_REG);
@@ -5527,7 +5542,8 @@
 	writel_relaxed(BIT(15), PDM_CLK_NS_REG);
 
 	/* Source SLIMBus xo src from slimbus reference clock */
-	writel_relaxed(0x3, SLIMBUS_XO_SRC_CLK_CTL_REG);
+	if (cpu_is_msm8960())
+		writel_relaxed(0x3, SLIMBUS_XO_SRC_CLK_CTL_REG);
 
 	/* Source the dsi_byte_clks from the DSI PHY PLLs */
 	rmwreg(0x1, DSI1_BYTE_NS_REG, 0x7);
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 9b9ac4a..84121ef 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1524,7 +1524,7 @@
 
 	CLK_LOOKUP("pdm_clk",		pdm_clk.c,		NULL),
 	CLK_LOOKUP("mem_clk",		pmem_clk.c,		"msm_sps"),
-	CLK_LOOKUP("prng_clk",		prng_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		prng_clk.c,		"msm_rng.0"),
 	CLK_LOOKUP("core_clk",		sdc1_clk.c,		"msm_sdcc.1"),
 	CLK_LOOKUP("core_clk",		sdc2_clk.c,		"msm_sdcc.2"),
 	CLK_LOOKUP("ce_pclk",		ce1_p_clk.c,		NULL),
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index d542b96..df84527 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -257,6 +257,22 @@
 	.id		= -1,
 };
 
+#ifdef CONFIG_HW_RANDOM_MSM
+/* PRNG device */
+#define MSM_PRNG_PHYS		0x1A500000
+static struct resource rng_resources = {
+	.flags = IORESOURCE_MEM,
+	.start = MSM_PRNG_PHYS,
+	.end   = MSM_PRNG_PHYS + SZ_512 - 1,
+};
+
+struct platform_device msm_device_rng = {
+	.name          = "msm_rng",
+	.id            = 0,
+	.num_resources = 1,
+	.resource      = &rng_resources,
+};
+#endif
 
 #define MSM_SDC1_BASE         0x12180000
 #define MSM_SDC1_DML_BASE     (MSM_SDC1_BASE + 0x800)
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 4a82b33..1ebc2a7 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -192,4 +192,5 @@
 
 extern struct platform_device ion_dev;
 extern struct platform_device msm_rpm_device;
+extern struct platform_device msm_device_rng;
 #endif
diff --git a/arch/arm/mach-msm/sdio_al.c b/arch/arm/mach-msm/sdio_al.c
index 8267fad..ace437b 100644
--- a/arch/arm/mach-msm/sdio_al.c
+++ b/arch/arm/mach-msm/sdio_al.c
@@ -108,6 +108,7 @@
  *  packet) rx data.
  */
 #define DEFAULT_READ_THRESHOLD  	(1024)
+#define LOW_LATENCY_THRESHOLD		(1)
 
 /* Extra bytes to ensure getting the rx threshold interrupt on stream channels
    when restoring the threshold after sleep */
@@ -119,7 +120,6 @@
 
 #define THRESHOLD_DISABLE_VAL  		(0xFFFFFFFF)
 
-
 /** Mailbox polling time for packet channels */
 #define DEFAULT_POLL_DELAY_MSEC		10
 /** Mailbox polling time for streaming channels */
@@ -986,7 +986,7 @@
 			continue;
 		}
 		if (ch->is_packet_mode == false) {
-			ch->read_threshold = 1;
+			ch->read_threshold = LOW_LATENCY_THRESHOLD;
 			set_pipe_threshold(sdio_al_dev,
 					   ch->rx_pipe_index,
 					   ch->read_threshold);
@@ -1156,13 +1156,22 @@
 					sdio_al_dev->host->index);
 			}
 			ch->read_avail = read_avail;
-			/* Restore default thresh for non packet channels */
+
+			/*
+			 * Restore default thresh for non packet channels.
+			 * in case it IS low latency channel then read_threshold
+			 * and def_read_threshold are both
+			 * LOW_LATENCY_THRESHOLD
+			 */
 			if ((ch->read_threshold != ch->def_read_threshold) &&
 			    (read_avail >= ch->threshold_change_cnt)) {
-				ch->read_threshold = ch->def_read_threshold;
-				set_pipe_threshold(sdio_al_dev,
-						   ch->rx_pipe_index,
-						   ch->read_threshold);
+				if (!ch->is_low_latency_ch) {
+					ch->read_threshold =
+						ch->def_read_threshold;
+					set_pipe_threshold(sdio_al_dev,
+							   ch->rx_pipe_index,
+							   ch->read_threshold);
+				}
 			}
 		}
 
@@ -1968,14 +1977,18 @@
 		goto exit_err;
 	}
 
-	/* Aggregation up to 90% of the maximum size */
-	ch->read_threshold = (ch_config->max_rx_threshold * 9) / 10;
+	ch->read_threshold = LOW_LATENCY_THRESHOLD;
+	ch->is_low_latency_ch = ch_config->is_low_latency_ch;
 	/* Threshold on 50% of the maximum size , sdioc uses double-buffer */
 	ch->write_threshold = (ch_config->max_tx_threshold * 5) / 10;
 	ch->threshold_change_cnt = ch->ch_config.max_rx_threshold -
 			ch->read_threshold + THRESHOLD_CHANGE_EXTRA_BYTES;
 
-	ch->def_read_threshold = ch->read_threshold;
+	if (ch->is_low_latency_ch)
+		ch->def_read_threshold = LOW_LATENCY_THRESHOLD;
+	else /* Aggregation up to 90% of the maximum size */
+		ch->def_read_threshold = (ch_config->max_rx_threshold * 9) / 10;
+
 	ch->is_packet_mode = ch_config->is_packet_mode;
 	if (!ch->is_packet_mode) {
 		ch->poll_delay_msec = DEFAULT_POLL_DELAY_NOPACKET_MSEC;
diff --git a/arch/arm/mach-msm/sdio_al_private.h b/arch/arm/mach-msm/sdio_al_private.h
index f352499..36d9ec1 100644
--- a/arch/arm/mach-msm/sdio_al_private.h
+++ b/arch/arm/mach-msm/sdio_al_private.h
@@ -66,7 +66,8 @@
 	u32 is_host_ok_to_sleep;
 	u32 is_packet_mode;
 	u32 peer_operation;
-	u32 reserved[24];
+	u32 is_low_latency_ch;
+	u32 reserved[23];
 };
 
 
@@ -173,6 +174,7 @@
 	int min_write_avail;
 	int poll_delay_msec;
 	int is_packet_mode;
+	int is_low_latency_ch;
 
 	struct peer_sdioc_channel_config ch_config;
 
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index 31634ff..66bab6b 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -302,6 +302,7 @@
 		break;
 	}
 
+	kfree_skb(skb);
 	wake_unlock(&hs.wake_lock_tx);
 	return ret;
 }
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index 3a2cd9a..5937c78 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/types.h>
+#include <mach/socinfo.h>
 
 #define DRIVER_NAME "msm_rng"
 
@@ -78,11 +79,11 @@
 	/* read random data from h/w */
 	do {
 		/* check status bit if data is available */
-		if (!(readl(base + PRNG_STATUS_OFFSET) & 0x00000001))
+		if (!(readl_relaxed(base + PRNG_STATUS_OFFSET) & 0x00000001))
 			break;	/* no data to read so just bail */
 
 		/* read FIFO */
-		val = readl(base + PRNG_DATA_OUT_OFFSET);
+		val = readl_relaxed(base + PRNG_DATA_OUT_OFFSET);
 		if (!val)
 			break;	/* no data to read so just bail */
 
@@ -106,6 +107,45 @@
 	.read = msm_rng_read,
 };
 
+static int __devinit msm_rng_enable_hw(struct msm_rng_device *msm_rng_dev)
+{
+	unsigned long val = 0;
+	int ret = 0;
+	int error = 0;
+
+	ret = clk_enable(msm_rng_dev->prng_clk);
+	if (ret) {
+		dev_err(&(msm_rng_dev->pdev)->dev,
+				"failed to enable clock in probe\n");
+		error = -EPERM;
+		return error;
+	}
+
+	/* enable PRNG h/w*/
+	val = readl_relaxed(msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET) &
+			PRNG_LFSR_CFG_MASK;
+	val |= PRNG_LFSR_CFG_MASK;
+	writel_relaxed(val, msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
+
+	/* The PRNG CONFIG register should be read after writing to the
+	* PRNG_LFSR_CFG register.
+	*/
+	mb();
+	val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET) &
+			PRNG_CONFIG_MASK;
+	val |= PRNG_CONFIG_ENABLE;
+	writel_relaxed(val, msm_rng_dev->base + PRNG_CONFIG_OFFSET);
+
+	/* The PRNG clk should be disabled only after we have enabled the
+	* PRNG H/W by writting to the PRNG_CONFIG register.
+	*/
+	mb();
+
+	clk_disable(msm_rng_dev->prng_clk);
+
+	return error;
+}
+
 static int __devinit msm_rng_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -147,18 +187,25 @@
 	msm_rng_dev->pdev = pdev;
 	platform_set_drvdata(pdev, msm_rng_dev);
 
+	/* Enable rng h/w */
+	if (cpu_is_msm9615())
+		error = msm_rng_enable_hw(msm_rng_dev);
+
+	if (error)
+		goto rollback_clk;
+
 	/* register with hwrng framework */
 	msm_rng.priv = (unsigned long) msm_rng_dev;
 	error = hwrng_register(&msm_rng);
 	if (error) {
 		dev_err(&pdev->dev, "failed to register hwrng\n");
 		error = -EPERM;
-		goto err_hw_register;
+		goto rollback_clk;
 	}
 
 	return 0;
 
-err_hw_register:
+rollback_clk:
 	clk_put(msm_rng_dev->prng_clk);
 err_clk_get:
 	iounmap(msm_rng_dev->base);
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 7c7f0dc..cc69360 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -25,6 +25,7 @@
 #include "a2xx_reg.h"
 
 #define INVALID_RB_CMD 0xaaaaaaaa
+#define NUM_DWORDS_OF_RINGBUFFER_HISTORY 100
 
 struct pm_id_name {
 	uint32_t id;
@@ -536,7 +537,12 @@
 	kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3);
 	KGSL_LOG_DUMP(device,
 		"CP_RB:  BASE = %08X | CNTL   = %08X | RPTR_ADDR = %08X"
-		"\n", cp_rb_base, r2, r3);
+		" | rb_count = %08X\n", cp_rb_base, r2, r3, rb_count);
+	{
+		struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+		if (rb->sizedwords != rb_count)
+			rb_count = rb->sizedwords;
+	}
 
 	kgsl_regread(device, REG_CP_RB_RPTR, &cp_rb_rptr);
 	kgsl_regread(device, REG_CP_RB_WPTR, &cp_rb_wptr);
@@ -683,13 +689,13 @@
 		goto error_vfree;
 	}
 
-	read_idx = (int)cp_rb_rptr - 64;
+	read_idx = (int)cp_rb_rptr - NUM_DWORDS_OF_RINGBUFFER_HISTORY;
 	if (read_idx < 0)
 		read_idx += rb_count;
 	write_idx = (int)cp_rb_wptr + 16;
 	if (write_idx > rb_count)
 		write_idx -= rb_count;
-	num_item += 64+16;
+	num_item += NUM_DWORDS_OF_RINGBUFFER_HISTORY+16;
 	if (num_item > rb_count)
 		num_item = rb_count;
 	if (write_idx >= read_idx)
@@ -736,7 +742,7 @@
 	   the process in whose context the GPU hung */
 	cur_pt_base = pt_base;
 
-	read_idx = (int)cp_rb_rptr - 64;
+	read_idx = (int)cp_rb_rptr - NUM_DWORDS_OF_RINGBUFFER_HISTORY;
 	if (read_idx < 0)
 		read_idx += rb_count;
 	KGSL_LOG_DUMP(device,
@@ -745,13 +751,14 @@
 	adreno_dump_rb(device, rb_copy, num_item<<2, read_idx, rb_count);
 
 	if (adreno_ib_dump_enabled()) {
-		for (read_idx = 64; read_idx >= 0; --read_idx) {
+		for (read_idx = NUM_DWORDS_OF_RINGBUFFER_HISTORY;
+			read_idx >= 0; --read_idx) {
 			uint32_t this_cmd = rb_copy[read_idx];
 			if (this_cmd == cp_type3_packet(
 				CP_INDIRECT_BUFFER_PFD, 2)) {
 				uint32_t ib_addr = rb_copy[read_idx+1];
 				uint32_t ib_size = rb_copy[read_idx+2];
-				if (cp_ib1_bufsz && cp_ib1_base == ib_addr) {
+				if (ib_size && cp_ib1_base == ib_addr) {
 					KGSL_LOG_DUMP(device,
 						"IB1: base:%8.8X  "
 						"count:%d\n", ib_addr, ib_size);
@@ -762,9 +769,9 @@
 			}
 		}
 		for (i = 0; i < ib_list.count; ++i) {
-			if (cp_ib2_bufsz && cp_ib2_base == ib_list.bases[i]) {
-				uint32_t ib_size = ib_list.sizes[i];
-				uint32_t ib_offset = ib_list.offsets[i];
+			uint32_t ib_size = ib_list.sizes[i];
+			uint32_t ib_offset = ib_list.offsets[i];
+			if (ib_size && cp_ib2_base == ib_list.bases[i]) {
 				KGSL_LOG_DUMP(device,
 					"IB2: base:%8.8X  count:%d\n",
 					cp_ib2_base, ib_size);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 165bbbf..0f8d474 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -329,6 +329,12 @@
 			KGSL_PWR_WARN(device, "state -> SUSPEND, device %d\n",
 				device->id);
 			break;
+		case KGSL_STATE_SLUMBER:
+			INIT_COMPLETION(device->hwaccess_gate);
+			device->state = KGSL_STATE_SUSPEND;
+			KGSL_PWR_WARN(device, "state -> SUSPEND, device %d\n",
+				device->id);
+			break;
 		default:
 			KGSL_PWR_ERR(device, "suspend fail, device %d\n",
 					device->id);
@@ -355,28 +361,16 @@
 	KGSL_PWR_WARN(device, "resume start\n");
 	mutex_lock(&device->mutex);
 	if (device->state == KGSL_STATE_SUSPEND) {
-		device->requested_state = KGSL_STATE_ACTIVE;
-		kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_NOMINAL);
-		status = device->ftbl->start(device, 0);
-		if (status == 0) {
-			device->state = KGSL_STATE_ACTIVE;
-			KGSL_PWR_WARN(device,
-					"state -> ACTIVE, device %d\n",
-					device->id);
-		} else {
-			KGSL_PWR_ERR(device,
-					"resume failed, device %d\n",
-					device->id);
-			device->state = KGSL_STATE_INIT;
-			goto end;
-		}
+		device->state = KGSL_STATE_SLUMBER;
+		status = 0;
+		KGSL_PWR_WARN(device,
+				"state -> SLUMBER, device %d\n",
+				device->id);
 		complete_all(&device->hwaccess_gate);
 	}
 	device->requested_state = KGSL_STATE_NONE;
 
-end:
 	mutex_unlock(&device->mutex);
-	kgsl_check_idle(device);
 	KGSL_PWR_WARN(device, "resume end\n");
 	return status;
 }
@@ -417,9 +411,12 @@
 {
 	struct kgsl_device *device = container_of(h,
 					struct kgsl_device, display_off);
+	KGSL_PWR_WARN(device, "early suspend start\n");
 	mutex_lock(&device->mutex);
-	kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_NOMINAL);
+	device->requested_state = KGSL_STATE_SLUMBER;
+	kgsl_pwrctrl_sleep(device);
 	mutex_unlock(&device->mutex);
+	KGSL_PWR_WARN(device, "early suspend end\n");
 }
 EXPORT_SYMBOL(kgsl_early_suspend_driver);
 
@@ -442,9 +439,13 @@
 {
 	struct kgsl_device *device = container_of(h,
 					struct kgsl_device, display_off);
+	KGSL_PWR_WARN(device, "late resume start\n");
 	mutex_lock(&device->mutex);
-	kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO);
+	kgsl_pwrctrl_wake(device);
+	device->pwrctrl.restore_slumber = 0;
 	mutex_unlock(&device->mutex);
+	kgsl_check_idle(device);
+	KGSL_PWR_WARN(device, "late resume end\n");
 }
 EXPORT_SYMBOL(kgsl_late_resume_driver);
 
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 2f369ed..b6e79b8 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -46,6 +46,7 @@
 #define KGSL_STATE_SUSPEND	0x00000010
 #define KGSL_STATE_HUNG		0x00000020
 #define KGSL_STATE_DUMP_AND_RECOVER	0x00000040
+#define KGSL_STATE_SLUMBER	0x00000080
 
 #define KGSL_GRAPHICS_MEMORY_LOW_WATERMARK  0x1000000
 
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 84f2b33..b4f22ee 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -583,7 +583,8 @@
 
 	mutex_lock(&device->mutex);
 	if (device->ftbl->isidle(device) &&
-		(device->requested_state != KGSL_STATE_SLEEP))
+		(device->requested_state != KGSL_STATE_SLEEP) &&
+		(device->requested_state != KGSL_STATE_SLUMBER))
 		kgsl_pwrscale_idle(device);
 
 	if (device->state & (KGSL_STATE_ACTIVE | KGSL_STATE_NAP)) {
@@ -622,7 +623,8 @@
 void kgsl_pre_hwaccess(struct kgsl_device *device)
 {
 	BUG_ON(!mutex_is_locked(&device->mutex));
-	if (device->state & (KGSL_STATE_SLEEP | KGSL_STATE_NAP))
+	if (device->state & (KGSL_STATE_SLEEP | KGSL_STATE_NAP |
+				KGSL_STATE_SLUMBER))
 		kgsl_pwrctrl_wake(device);
 }
 EXPORT_SYMBOL(kgsl_pre_hwaccess);
@@ -640,8 +642,40 @@
 		wait_for_completion(&device->recovery_gate);
 		mutex_lock(&device->mutex);
 	}
- }
+}
 
+static int
+_slumber(struct kgsl_device *device)
+{
+	int status = -EINVAL;
+	if (!device)
+		return -EINVAL;
+	KGSL_PWR_WARN(device, "Slumber start\n");
+
+	device->requested_state = KGSL_STATE_SLUMBER;
+	del_timer(&device->idle_timer);
+	switch (device->state) {
+	case KGSL_STATE_ACTIVE:
+		/* Wait for the device to become idle */
+		device->ftbl->idle(device, KGSL_TIMEOUT_DEFAULT);
+	case KGSL_STATE_NAP:
+	case KGSL_STATE_SLEEP:
+		device->ftbl->suspend_context(device);
+		device->ftbl->stop(device);
+		device->state = KGSL_STATE_SLUMBER;
+		device->pwrctrl.restore_slumber = 1;
+		KGSL_PWR_WARN(device, "state -> SLUMBER, device %d\n",
+				device->id);
+		break;
+	default:
+		break;
+	}
+	status = 0;
+	/* Don't set requested state to NONE
+	It's done in kgsl_pwrctrl_sleep*/
+	KGSL_PWR_WARN(device, "Done going to slumber\n");
+	return status;
+}
 
 /******************************************************************/
 /* Caller must hold the device mutex. */
@@ -656,13 +690,24 @@
 			goto nap;
 	} else if (device->requested_state == KGSL_STATE_SLEEP) {
 		if (device->state == KGSL_STATE_NAP ||
-			device->ftbl->isidle(device))
-			goto sleep;
+			device->ftbl->isidle(device)) {
+			if (!device->pwrctrl.restore_slumber)
+				goto sleep;
+			else
+				goto slumber;
+			}
+	} else if (device->requested_state == KGSL_STATE_SLUMBER) {
+		if (device->ftbl->isidle(device))
+			goto slumber;
 	}
 
 	device->requested_state = KGSL_STATE_NONE;
 	return -EBUSY;
 
+
+slumber:
+	_slumber(device);
+
 sleep:
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
 	kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_OFF);
@@ -694,6 +739,24 @@
 }
 EXPORT_SYMBOL(kgsl_pwrctrl_sleep);
 
+static int
+_wake_from_slumber(struct kgsl_device *device)
+{
+	int status = -EINVAL;
+	if (!device)
+		return -EINVAL;
+
+	KGSL_PWR_WARN(device, "wake from slumber start\n");
+
+	device->requested_state = KGSL_STATE_ACTIVE;
+	kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_NOMINAL);
+	status = device->ftbl->start(device, 0);
+	device->requested_state = KGSL_STATE_NONE;
+
+	KGSL_PWR_WARN(device, "Done waking from slumber\n");
+	return status;
+}
+
 /******************************************************************/
 /* Caller must hold the device mutex. */
 void kgsl_pwrctrl_wake(struct kgsl_device *device)
@@ -701,6 +764,9 @@
 	if (device->state == KGSL_STATE_SUSPEND)
 		return;
 
+	if (device->state == KGSL_STATE_SLUMBER)
+		_wake_from_slumber(device);
+
 	if (device->state != KGSL_STATE_NAP) {
 		kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON);
 		kgsl_pwrscale_wake(device);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 127a19b..17dab76 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -56,6 +56,7 @@
 	const char *src_clk_name;
 	s64 time;
 	struct kgsl_busy busy;
+	unsigned int restore_slumber;
 };
 
 void kgsl_pwrctrl_clk(struct kgsl_device *device, int state);
diff --git a/drivers/mfd/pm8018-core.c b/drivers/mfd/pm8018-core.c
index 4dfc4cf..e60b97b 100644
--- a/drivers/mfd/pm8018-core.c
+++ b/drivers/mfd/pm8018-core.c
@@ -39,6 +39,9 @@
 #define PM8018_VERSION_VALUE	0x08F0
 #define PM8018_REVISION_MASK	0x000F
 
+#define REG_PM8018_PON_CNTRL_3	0x01D
+#define PM8018_RESTART_REASON_MASK	0x07
+
 #define SINGLE_IRQ_RESOURCE(_name, _irq) \
 { \
 	.name	= _name, \
@@ -325,6 +328,17 @@
 	return ret;
 }
 
+static const char * const pm8018_restart_reason[] = {
+	[0] = "Unknown",
+	[1] = "Triggered from CBL (external charger)",
+	[2] = "Triggered from KPD (power key press)",
+	[3] = "Triggered from CHG (usb charger insertion)",
+	[4] = "Triggered from SMPL (sudden momentary power loss)",
+	[5] = "Triggered from RTC (real time clock)",
+	[6] = "Triggered by Hard Reset",
+	[7] = "Triggered by General Purpose Trigger",
+};
+
 static const char * const pm8018_rev_names[] = {
 	[PM8XXX_REVISION_8018_TEST]	= "test",
 	[PM8XXX_REVISION_8018_1p0]	= "1.0",
@@ -386,6 +400,14 @@
 	} else {
 		WARN_ON(version != PM8XXX_VERSION_8018);
 	}
+	/* Log human readable restart reason */
+	rc = msm_ssbi_read(pdev->dev.parent, REG_PM8018_PON_CNTRL_3, &val, 1);
+	if (rc) {
+		pr_err("Cannot read restart reason rc=%d\n", rc);
+		goto err_read_rev;
+	}
+	val &= PM8018_RESTART_REASON_MASK;
+	pr_info("PMIC Restart Reason: %s\n", pm8018_restart_reason[val]);
 
 	rc = pm8018_add_subdevices(pdata, pmic);
 	if (rc) {
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index cd5624f..00ac2ab 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -23,6 +23,7 @@
 /* PON CTRL 1 register */
 #define REG_PM8058_PON_CTRL_1			0x01C
 #define REG_PM8921_PON_CTRL_1			0x01C
+#define REG_PM8018_PON_CTRL_1			0x01C
 
 #define PON_CTRL_1_PULL_UP_MASK			0xE0
 #define PON_CTRL_1_USB_PWR_EN			0x10
@@ -37,6 +38,7 @@
 /* SLEEP CTRL register */
 #define REG_PM8058_SLEEP_CTRL			0x02B
 #define REG_PM8921_SLEEP_CTRL			0x10A
+#define REG_PM8018_SLEEP_CTRL			0x10A
 
 #define SLEEP_CTRL_SMPL_EN_MASK			0x04
 #define SLEEP_CTRL_SMPL_EN_RESET		0x04
@@ -81,6 +83,35 @@
 	return rc;
 }
 
+static int __pm8018_reset_pwr_off(struct pm8xxx_misc_chip *chip, int reset)
+{
+	int rc;
+
+	/* Enable SMPL if resetting is desired. */
+	rc = pm8xxx_misc_masked_write(chip, REG_PM8018_SLEEP_CTRL,
+	       SLEEP_CTRL_SMPL_EN_MASK,
+	       (reset ? SLEEP_CTRL_SMPL_EN_RESET : SLEEP_CTRL_SMPL_EN_PWR_OFF));
+	if (rc) {
+		pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	/*
+	 * Select action to perform (reset or shutdown) when PS_HOLD goes low.
+	 * Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
+	 * USB charging is enabled.
+	 */
+	rc = pm8xxx_misc_masked_write(chip, REG_PM8018_PON_CTRL_1,
+		PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
+		| PON_CTRL_1_WD_EN_MASK,
+		PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
+		| (reset ? PON_CTRL_1_WD_EN_RESET : PON_CTRL_1_WD_EN_PWR_OFF));
+	if (rc)
+		pr_err("pm8xxx_misc_masked_write failed, rc=%d\n", rc);
+
+	return rc;
+}
+
 static int __pm8058_reset_pwr_off(struct pm8xxx_misc_chip *chip, int reset)
 {
 	int rc;
@@ -201,6 +232,9 @@
 	/* Loop over all attached PMICs and call specific functions for them. */
 	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
 		switch (chip->version) {
+		case PM8XXX_VERSION_8018:
+			rc = __pm8018_reset_pwr_off(chip, reset);
+			break;
 		case PM8XXX_VERSION_8058:
 			rc = __pm8058_reset_pwr_off(chip, reset);
 			break;
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index d0c1392..e666bfc 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -87,6 +87,7 @@
 	unsigned int		batt_id_channel;
 	unsigned int		pmic_bms_irq[PM_BMS_MAX_INTS];
 	DECLARE_BITMAP(enabled_irqs, PM_BMS_MAX_INTS);
+	spinlock_t		bms_output_lock;
 };
 
 static struct pm8921_bms_chip *the_chip;
@@ -156,6 +157,32 @@
 	return 0;
 }
 
+#define HOLD_OREG_DATA		BIT(1)
+static int pm_bms_lock_output_data(struct pm8921_bms_chip *chip)
+{
+	int rc;
+
+	rc = pm_bms_masked_write(chip, BMS_CONTROL, HOLD_OREG_DATA,
+					HOLD_OREG_DATA);
+	if (rc) {
+		pr_err("couldnt lock bms output rc = %d\n", rc);
+		return rc;
+	}
+	return 0;
+}
+
+static int pm_bms_unlock_output_data(struct pm8921_bms_chip *chip)
+{
+	int rc;
+
+	rc = pm_bms_masked_write(chip, BMS_CONTROL, HOLD_OREG_DATA, 0);
+	if (rc) {
+		pr_err("fail to unlock BMS_CONTROL rc = %d\n", rc);
+		return rc;
+	}
+	return 0;
+}
+
 #define SELECT_OUTPUT_DATA	0x1C
 #define SELECT_OUTPUT_TYPE_SHIFT	2
 #define OCV_FOR_RBATT		0x0
@@ -182,6 +209,18 @@
 		pr_err("invalid type %d asked to read\n", type);
 		return -EINVAL;
 	}
+
+	/* make sure the bms registers are locked */
+	rc = pm8xxx_readb(chip->dev->parent, BMS_CONTROL, &reg);
+	if (rc) {
+		pr_err("fail to read BMS_OUTPUT0 for type %d rc = %d\n",
+			type, rc);
+		return rc;
+	}
+
+	/* Output register data must be held (locked) while reading output */
+	WARN_ON(!(reg && HOLD_OREG_DATA));
+
 	rc = pm_bms_masked_write(chip, BMS_CONTROL, SELECT_OUTPUT_DATA,
 					type << SELECT_OUTPUT_TYPE_SHIFT);
 	if (rc) {
@@ -779,11 +818,16 @@
 						int64_t *cc_mah)
 {
 	int coulumb_counter;
+	unsigned long flags;
 
 	*fcc = calculate_fcc(chip, batt_temp, chargecycles);
 	pr_debug("FCC = %umAh batt_temp = %d, cycles = %d",
 					*fcc, batt_temp, chargecycles);
 
+	/* fcc doesnt need to be read from hardware, lock the bms now */
+	spin_lock_irqsave(&chip->bms_output_lock, flags);
+	pm_bms_lock_output_data(chip);
+
 	*unusable_charge = calculate_unusable_charge_mah(chip, *fcc,
 						batt_temp, chargecycles);
 
@@ -796,6 +840,9 @@
 
 	/* calculate cc milli_volt_hour */
 	calculate_cc_mah(chip, cc_mah, &coulumb_counter);
+
+	pm_bms_unlock_output_data(chip);
+	spin_unlock_irqrestore(&chip->bms_output_lock, flags);
 	pr_debug("cc_mah = %lldmAh cc = %d\n", *cc_mah, coulumb_counter);
 }
 
@@ -862,8 +909,7 @@
 			 * shutdown for low battery
 			 */
 			soc = BATTERY_POWER_SUPPLY_SOC;
-			pr_debug("Adjusting SOC to %d\n",
-						BATTERY_POWER_SUPPLY_SOC);
+			pr_debug("Adjusting SOC to %d\n", soc);
 		}
 	}
 
@@ -947,16 +993,26 @@
 
 int pm8921_bms_get_vsense_avg(int *result)
 {
-	if (the_chip)
-		return read_vsense_avg(the_chip, result);
+	int rc = -EINVAL;
+	unsigned long flags;
+
+	if (the_chip) {
+		spin_lock_irqsave(&the_chip->bms_output_lock, flags);
+		pm_bms_lock_output_data(the_chip);
+		rc = read_vsense_avg(the_chip, result);
+		pm_bms_unlock_output_data(the_chip);
+		spin_unlock_irqrestore(&the_chip->bms_output_lock, flags);
+	}
 
 	pr_err("called before initialization\n");
-	return -EINVAL;
+	return rc;
 }
 EXPORT_SYMBOL(pm8921_bms_get_vsense_avg);
 
 int pm8921_bms_get_battery_current(int *result)
 {
+	unsigned long flags;
+
 	if (!the_chip) {
 		pr_err("called before initialization\n");
 		return -EINVAL;
@@ -966,7 +1022,11 @@
 		return -EINVAL;
 	}
 
+	spin_lock_irqsave(&the_chip->bms_output_lock, flags);
+	pm_bms_lock_output_data(the_chip);
 	read_vsense_avg(the_chip, result);
+	pm_bms_unlock_output_data(the_chip);
+	spin_unlock_irqrestore(&the_chip->bms_output_lock, flags);
 	pr_debug("vsense=%d\n", *result);
 	/* cast for signed division */
 	*result = *result / (int)the_chip->r_sense;
@@ -1528,7 +1588,7 @@
 		pr_err("Cannot allocate pm_bms_chip\n");
 		return -ENOMEM;
 	}
-
+	spin_lock_init(&chip->bms_output_lock);
 	chip->dev = &pdev->dev;
 	chip->r_sense = pdata->r_sense;
 	chip->i_test = pdata->i_test;
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 5e38238..a86e049 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -346,7 +346,7 @@
 	char *name;
 	char buf[32], *b;
 	int once = 0, err = -1;
-	int (*notify)(uint32_t, const char *);
+	int (*notify)(uint32_t, const char *) = NULL;
 
 	strncpy(buf, diag_clients, sizeof(buf));
 	b = strim(buf);
@@ -354,10 +354,8 @@
 	while (b) {
 		name = strsep(&b, ",");
 		/* Allow only first diag channel to update pid and serial no */
-		if (!once++)
+		if (_android_dev->pdata && !once++)
 			notify = _android_dev->pdata->update_pid_and_serial_num;
-		else
-			notify = NULL;
 
 		if (name) {
 			err = diag_function_add(c, name, notify);
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 9017706..9d268d1 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1699,6 +1699,9 @@
 	if (mReq->req.status != -EALREADY)
 		return -EINVAL;
 
+	/* clean speculative fetches on req->ptr->token */
+	mb();
+
 	if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
 		return -EBUSY;
 
@@ -2074,7 +2077,6 @@
 			continue;   /* not configured */
 
 		if (hw_test_and_clear_complete(i)) {
-			udelay(200);
 			err = isr_tr_complete_low(mEp);
 			if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
 				if (err > 0)   /* needs status phase */
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index aa6aeb9..b67803a 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -708,6 +708,12 @@
 	__le16   sco_max_pkt;
 } __packed;
 
+#define HCI_OP_WRITE_CURRENT_IAC_LAP	0x0c3a
+struct hci_cp_write_current_iac_lap {
+	__u8     num_current_iac;
+	__u8     lap[6];
+} __packed;
+
 #define HCI_OP_WRITE_INQUIRY_MODE	0x0c45
 
 #define HCI_MAX_EIR_LENGTH		240
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 5e855dbf..208c157 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -90,6 +90,8 @@
 	__u8 major;
 	__u8 minor;
 } __packed;
+#define MGMT_MAJOR_CLASS_MASK		0x1F
+#define MGMT_MAJOR_CLASS_LIMITED	0x20
 
 #define MGMT_OP_SET_SERVICE_CACHE	0x000C
 struct mgmt_cp_set_service_cache {
@@ -214,6 +216,8 @@
 	bdaddr_t bdaddr;
 } __packed;
 
+#define MGMT_OP_SET_LIMIT_DISCOVERABLE	0x001F
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16 opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a328db9..ea72708 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -409,6 +409,124 @@
 	return err;
 }
 
+static u8 get_service_classes(struct hci_dev *hdev)
+{
+	struct list_head *p;
+	u8 val = 0;
+
+	list_for_each(p, &hdev->uuids) {
+		struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list);
+
+		val |= uuid->svc_hint;
+	}
+
+	return val;
+}
+
+static int update_class(struct hci_dev *hdev)
+{
+	u8 cod[3];
+
+	BT_DBG("%s", hdev->name);
+
+	if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
+		return 0;
+
+	cod[0] = hdev->minor_class;
+	cod[1] = hdev->major_class;
+	cod[2] = get_service_classes(hdev);
+
+	if (memcmp(cod, hdev->dev_class, 3) == 0)
+		return 0;
+
+	return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
+}
+
+static int set_limited_discoverable(struct sock *sk, u16 index,
+						unsigned char *data, u16 len)
+{
+	struct mgmt_mode *cp;
+	struct hci_dev *hdev;
+	struct pending_cmd *cmd;
+	struct hci_cp_write_current_iac_lap dcp;
+	int update_cod;
+	int err = 0;
+	/* General Inquiry LAP: 0x9E8B33, Limited Inquiry LAP: 0x9E8B00 */
+	u8 lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e };
+
+	cp = (void *) data;
+
+	BT_DBG("hci%u discoverable: %d", index, cp->val);
+
+	if (!cp || len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
+									EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
+									ENODEV);
+
+	hci_dev_lock(hdev);
+
+	if (!test_bit(HCI_UP, &hdev->flags)) {
+		err = cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
+								ENETDOWN);
+		goto failed;
+	}
+
+	if (mgmt_pending_find(MGMT_OP_SET_LIMIT_DISCOVERABLE, index)) {
+		err = cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
+									EBUSY);
+		goto failed;
+	}
+
+	if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
+					test_bit(HCI_PSCAN, &hdev->flags)) {
+		err = cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
+								EALREADY);
+		goto failed;
+	}
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_SET_LIMIT_DISCOVERABLE, index, data,
+									len);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	memset(&dcp, 0, sizeof(dcp));
+	dcp.num_current_iac = cp->val ? 2 : 1;
+	memcpy(&dcp.lap, lap, dcp.num_current_iac * 3);
+	update_cod = 1;
+
+	if (cp->val) {
+		if (hdev->major_class & MGMT_MAJOR_CLASS_LIMITED)
+			update_cod = 0;
+		hdev->major_class |= MGMT_MAJOR_CLASS_LIMITED;
+	} else {
+		if (!(hdev->major_class & MGMT_MAJOR_CLASS_LIMITED))
+			update_cod = 0;
+		hdev->major_class &= ~MGMT_MAJOR_CLASS_LIMITED;
+	}
+
+	if (update_cod)
+		err = update_class(hdev);
+
+	if (err >= 0)
+		err = hci_send_cmd(hdev, HCI_OP_WRITE_CURRENT_IAC_LAP,
+							sizeof(dcp), &dcp);
+
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+failed:
+	hci_dev_unlock(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
 static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
 									u16 len)
 {
@@ -751,39 +869,6 @@
 	return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
 }
 
-static u8 get_service_classes(struct hci_dev *hdev)
-{
-	struct list_head *p;
-	u8 val = 0;
-
-	list_for_each(p, &hdev->uuids) {
-		struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list);
-
-		val |= uuid->svc_hint;
-	}
-
-	return val;
-}
-
-static int update_class(struct hci_dev *hdev)
-{
-	u8 cod[3];
-
-	BT_DBG("%s", hdev->name);
-
-	if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
-		return 0;
-
-	cod[0] = hdev->minor_class;
-	cod[1] = hdev->major_class;
-	cod[2] = get_service_classes(hdev);
-
-	if (memcmp(cod, hdev->dev_class, 3) == 0)
-		return 0;
-
-	return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
-}
-
 static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
 {
 	struct mgmt_cp_add_uuid *cp;
@@ -912,7 +997,8 @@
 
 	hci_dev_lock(hdev);
 
-	hdev->major_class = cp->major;
+	hdev->major_class &= ~MGMT_MAJOR_CLASS_MASK;
+	hdev->major_class |= cp->major & MGMT_MAJOR_CLASS_MASK;
 	hdev->minor_class = cp->minor;
 
 	err = update_class(hdev);
@@ -2111,6 +2197,10 @@
 	case MGMT_OP_SET_DISCOVERABLE:
 		err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
 		break;
+	case MGMT_OP_SET_LIMIT_DISCOVERABLE:
+		err = set_limited_discoverable(sk, index, buf + sizeof(*hdr),
+									len);
+		break;
 	case MGMT_OP_SET_CONNECTABLE:
 		err = set_connectable(sk, index, buf + sizeof(*hdr), len);
 		break;