Merge "ASoC: msm: Add VSS_IVOCPROC_CMD_SET_MUTE case in cvp callback" into msm-3.0
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 0a23a17..5cb44b8 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1277,6 +1277,83 @@
 	.id   = -1,
 };
 
+#ifdef CONFIG_QSEECOM
+/* qseecom bus scaling */
+static struct msm_bus_vectors qseecom_clks_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ib = 0,
+		.ab = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = 0,
+		.ab = 0,
+	},
+};
+
+static struct msm_bus_vectors qseecom_enable_dfab_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ib = (492 * 8) * 1000000UL,
+		.ab = (492 * 8) *  100000UL,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = 0,
+		.ab = 0,
+	},
+};
+
+static struct msm_bus_vectors qseecom_enable_sfpb_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ib = 0,
+		.ab = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = (64 * 8) * 1000000UL,
+		.ab = (64 * 8) *  100000UL,
+	},
+};
+
+static struct msm_bus_paths qseecom_hw_bus_scale_usecases[] = {
+	{
+		ARRAY_SIZE(qseecom_clks_init_vectors),
+		qseecom_clks_init_vectors,
+	},
+	{
+		ARRAY_SIZE(qseecom_enable_dfab_vectors),
+		qseecom_enable_sfpb_vectors,
+	},
+	{
+		ARRAY_SIZE(qseecom_enable_sfpb_vectors),
+		qseecom_enable_sfpb_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata qseecom_bus_pdata = {
+	qseecom_hw_bus_scale_usecases,
+	ARRAY_SIZE(qseecom_hw_bus_scale_usecases),
+	.name = "qsee",
+};
+
+static struct platform_device qseecom_device = {
+	.name		= "qseecom",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &qseecom_bus_pdata,
+	},
+};
+#endif
+
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
 		defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -1809,6 +1886,10 @@
 	&msm8064_device_saw_regulator_core1,
 	&msm8064_device_saw_regulator_core2,
 	&msm8064_device_saw_regulator_core3,
+#if defined(CONFIG_QSEECOM)
+	&qseecom_device,
+#endif
+
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
 	&qcrypto_device,
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 173ec95..6859b9f 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -654,6 +654,83 @@
 	.dev		= {.platform_data = &qcom_wcnss_pdata},
 };
 
+#ifdef CONFIG_QSEECOM
+/* qseecom bus scaling */
+static struct msm_bus_vectors qseecom_clks_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ib = 0,
+		.ab = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = 0,
+		.ab = 0,
+	},
+};
+
+static struct msm_bus_vectors qseecom_enable_dfab_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ib = (492 * 8) * 1000000UL,
+		.ab = (492 * 8) *  100000UL,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = 0,
+		.ab = 0,
+	},
+};
+
+static struct msm_bus_vectors qseecom_enable_sfpb_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ib = 0,
+		.ab = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = (64 * 8) * 1000000UL,
+		.ab = (64 * 8) *  100000UL,
+	},
+};
+
+static struct msm_bus_paths qseecom_hw_bus_scale_usecases[] = {
+	{
+		ARRAY_SIZE(qseecom_clks_init_vectors),
+		qseecom_clks_init_vectors,
+	},
+	{
+		ARRAY_SIZE(qseecom_enable_dfab_vectors),
+		qseecom_enable_sfpb_vectors,
+	},
+	{
+		ARRAY_SIZE(qseecom_enable_sfpb_vectors),
+		qseecom_enable_sfpb_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata qseecom_bus_pdata = {
+	qseecom_hw_bus_scale_usecases,
+	ARRAY_SIZE(qseecom_hw_bus_scale_usecases),
+	.name = "qsee",
+};
+
+static struct platform_device qseecom_device = {
+	.name		= "qseecom",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &qseecom_bus_pdata,
+	},
+};
+#endif
+
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
 		defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -1646,6 +1723,10 @@
 	&msm8960_device_qup_i2c_gsbi12,
 	&msm_slim_ctrl,
 	&msm_device_wcnss_wlan,
+#if defined(CONFIG_QSEECOM)
+		&qseecom_device,
+#endif
+
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
 	&qcrypto_device,
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index a21788b..1ca25cc 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -41,6 +41,7 @@
 #include <linux/ks8851.h>
 #include <linux/i2c/isa1200.h>
 #include <linux/memory.h>
+#include <linux/memblock.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -159,6 +160,12 @@
 #define MSM_LIQUID_ION_MM_SIZE (MSM_ION_MM_SIZE + 0x600000)
 #define MSM_LIQUID_ION_SF_SIZE MSM_LIQUID_PMEM_SIZE
 #define MSM_HDMI_PRIM_ION_SF_SIZE MSM_HDMI_PRIM_PMEM_SIZE
+
+#define MSM8960_FIXED_AREA_START 0xa0000000
+#define MAX_FIXED_AREA_SIZE	0x10000000
+#define MSM_MM_FW_SIZE		0x200000
+#define MSM8960_FW_START	(MSM8960_FIXED_AREA_START - MSM_MM_FW_SIZE)
+
 static unsigned msm_ion_sf_size = MSM_ION_SF_SIZE;
 #else
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0x110C000
@@ -367,6 +374,7 @@
 	.align = PAGE_SIZE,
 	.reusable = FMEM_ENABLED,
 	.mem_is_fmem = FMEM_ENABLED,
+	.fixed_position = FIXED_MIDDLE,
 };
 
 static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
@@ -374,6 +382,7 @@
 	.align = PAGE_SIZE,
 	.reusable = 0,
 	.mem_is_fmem = FMEM_ENABLED,
+	.fixed_position = FIXED_HIGH,
 };
 
 static struct ion_co_heap_pdata co_ion_pdata = {
@@ -386,6 +395,7 @@
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
 	.align = SZ_128K,
 	.mem_is_fmem = FMEM_ENABLED,
+	.fixed_position = FIXED_LOW,
 };
 #endif
 
@@ -513,6 +523,24 @@
 	msm8960_reserve_table[mem_type].size += size;
 }
 
+static void __init msm8960_reserve_fixed_area(unsigned long fixed_area_size)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+	int ret;
+
+	if (fixed_area_size > MAX_FIXED_AREA_SIZE)
+		panic("fixed area size is larger than %dM\n",
+			MAX_FIXED_AREA_SIZE >> 20);
+
+	reserve_info->fixed_area_size = fixed_area_size;
+	reserve_info->fixed_area_start = MSM8960_FW_START;
+
+	ret = memblock_remove(reserve_info->fixed_area_start,
+		reserve_info->fixed_area_size);
+	BUG_ON(ret);
+#endif
+}
+
 /**
  * Reserve memory for ION and calculate amount of reusable memory for fmem.
  * We only reserve memory for heaps that are not reusable. However, we only
@@ -530,11 +558,17 @@
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	unsigned int i;
 	unsigned int reusable_count = 0;
+	unsigned int fixed_size = 0;
+	unsigned int fixed_low_size, fixed_middle_size, fixed_high_size;
+	unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
 
 	adjust_mem_for_liquid();
 	fmem_pdata.size = 0;
 	fmem_pdata.reserved_size_low = 0;
 	fmem_pdata.reserved_size_high = 0;
+	fixed_low_size = 0;
+	fixed_middle_size = 0;
+	fixed_high_size = 0;
 
 	/* We only support 1 reusable heap. Check if more than one heap
 	 * is specified as reusable and set as non-reusable if found.
@@ -557,40 +591,98 @@
 	}
 
 	for (i = 0; i < ion_pdata.nr; ++i) {
-		int reusable = 0;
-		int adjacent_heap_id = INVALID_HEAP_ID;
-		int mem_is_fmem = 0;
 		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
 
 		if (heap->extra_data) {
+			int fixed_position = NOT_FIXED;
+			int mem_is_fmem = 0;
+
 			switch (heap->type) {
 			case ION_HEAP_TYPE_CP:
-				reusable = ((struct ion_cp_heap_pdata *)
-						heap->extra_data)->reusable;
 				mem_is_fmem = ((struct ion_cp_heap_pdata *)
-						heap->extra_data)->mem_is_fmem;
+					heap->extra_data)->mem_is_fmem;
+				fixed_position = ((struct ion_cp_heap_pdata *)
+					heap->extra_data)->fixed_position;
 				break;
 			case ION_HEAP_TYPE_CARVEOUT:
-				adjacent_heap_id = ((struct ion_co_heap_pdata *)
-					heap->extra_data)->adjacent_mem_id;
 				mem_is_fmem = ((struct ion_co_heap_pdata *)
-						heap->extra_data)->mem_is_fmem;
+					heap->extra_data)->mem_is_fmem;
+				fixed_position = ((struct ion_co_heap_pdata *)
+					heap->extra_data)->fixed_position;
+				break;
+			default:
+				break;
+			}
+
+			if (fixed_position != NOT_FIXED)
+				fixed_size += heap->size;
+			else
+				reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
+
+			if (fixed_position == FIXED_LOW)
+				fixed_low_size += heap->size;
+			else if (fixed_position == FIXED_MIDDLE)
+				fixed_middle_size += heap->size;
+			else if (fixed_position == FIXED_HIGH)
+				fixed_high_size += heap->size;
+
+			if (mem_is_fmem)
+				fmem_pdata.size += heap->size;
+		}
+	}
+
+	if (!fixed_size)
+		return;
+
+	if (fmem_pdata.size) {
+		fmem_pdata.reserved_size_low = fixed_low_size;
+		fmem_pdata.reserved_size_high = fixed_high_size;
+	}
+
+	/* Since the fixed area may be carved out of lowmem,
+	 * make sure the length is a multiple of 1M.
+	 */
+	fixed_size = (fixed_size + MSM_MM_FW_SIZE + SECTION_SIZE - 1)
+		& SECTION_MASK;
+	msm8960_reserve_fixed_area(fixed_size);
+
+	fixed_low_start = MSM8960_FIXED_AREA_START;
+	fixed_middle_start = fixed_low_start + fixed_low_size;
+	fixed_high_start = fixed_middle_start + fixed_middle_size;
+
+	for (i = 0; i < ion_pdata.nr; ++i) {
+		struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+
+		if (heap->extra_data) {
+			int fixed_position = NOT_FIXED;
+
+			switch (heap->type) {
+			case ION_HEAP_TYPE_CP:
+				fixed_position = ((struct ion_cp_heap_pdata *)
+					heap->extra_data)->fixed_position;
+				break;
+			case ION_HEAP_TYPE_CARVEOUT:
+				fixed_position = ((struct ion_co_heap_pdata *)
+					heap->extra_data)->fixed_position;
+				break;
+			default:
+				break;
+			}
+
+			switch (fixed_position) {
+			case FIXED_LOW:
+				heap->base = fixed_low_start;
+				break;
+			case FIXED_MIDDLE:
+				heap->base = fixed_middle_start;
+				break;
+			case FIXED_HIGH:
+				heap->base = fixed_high_start;
 				break;
 			default:
 				break;
 			}
 		}
-
-		if (mem_is_fmem && !reusable) {
-			if (adjacent_heap_id != INVALID_HEAP_ID)
-				fmem_pdata.reserved_size_low += heap->size;
-			else
-				fmem_pdata.reserved_size_high += heap->size;
-		}
-		if (mem_is_fmem)
-			fmem_pdata.size += heap->size;
-		else
-			reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
 	}
 #endif
 }
@@ -659,6 +751,7 @@
 static struct reserve_info msm8960_reserve_info __initdata = {
 	.memtype_reserve_table = msm8960_reserve_table,
 	.calculate_reserve_sizes = msm8960_calculate_reserve_sizes,
+	.reserve_fixed_area = msm8960_reserve_fixed_area,
 	.paddr_to_memtype = msm8960_paddr_to_memtype,
 };
 
@@ -674,6 +767,8 @@
 	unsigned long low, high;
 
 	bank_size = msm8960_memory_bank_size();
+	msm8960_reserve_info.bank_size = bank_size;
+
 	low = meminfo.bank[0].start;
 	high = mb->start + mb->size;
 
@@ -681,12 +776,14 @@
 	if (high < mb->start)
 		high = ~0UL;
 
+	if (high < MAX_FIXED_AREA_SIZE + MSM8960_FIXED_AREA_START)
+		panic("fixed area extends beyond end of memory\n");
+
 	low &= ~(bank_size - 1);
 
 	if (high - low <= bank_size)
-		return;
+		goto no_dmm;
 
-	msm8960_reserve_info.bank_size = bank_size;
 #ifdef CONFIG_ENABLE_DMM
 	msm8960_reserve_info.low_unstable_address = mb->start -
 					MIN_MEMORY_BLOCK_SIZE + mb->size;
@@ -695,10 +792,11 @@
 		msm8960_reserve_info.low_unstable_address,
 		msm8960_reserve_info.max_unstable_size,
 		msm8960_reserve_info.bank_size);
-#else
-	msm8960_reserve_info.low_unstable_address = 0;
-	msm8960_reserve_info.max_unstable_size = 0;
+	return;
 #endif
+no_dmm:
+	msm8960_reserve_info.low_unstable_address = high;
+	msm8960_reserve_info.max_unstable_size = 0;
 }
 
 static void __init place_movable_zone(void)
@@ -740,7 +838,18 @@
 {
 	msm8960_set_display_params(prim_panel_name, ext_panel_name);
 	msm_reserve();
-	fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
+	if (fmem_pdata.size) {
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+		fmem_pdata.phys = reserve_info->fixed_area_start +
+			MSM_MM_FW_SIZE;
+		pr_info("mm fw at %lx (fixed) size %x\n",
+			reserve_info->fixed_area_start, MSM_MM_FW_SIZE);
+		pr_info("fmem start %lx (fixed) size %lx\n",
+			fmem_pdata.phys, fmem_pdata.size);
+#else
+		fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
+#endif
+	}
 }
 
 static int msm8960_change_memory_power(u64 start, u64 size,
@@ -958,6 +1067,83 @@
 	.dev		= {.platform_data = &qcom_wcnss_pdata},
 };
 
+#ifdef CONFIG_QSEECOM
+/* qseecom bus scaling */
+static struct msm_bus_vectors qseecom_clks_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ib = 0,
+		.ab = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = 0,
+		.ab = 0,
+	},
+};
+
+static struct msm_bus_vectors qseecom_enable_dfab_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ib = (492 * 8) * 1000000UL,
+		.ab = (492 * 8) *  100000UL,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = 0,
+		.ab = 0,
+	},
+};
+
+static struct msm_bus_vectors qseecom_enable_sfpb_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ib = 0,
+		.ab = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = (64 * 8) * 1000000UL,
+		.ab = (64 * 8) *  100000UL,
+	},
+};
+
+static struct msm_bus_paths qseecom_hw_bus_scale_usecases[] = {
+	{
+		ARRAY_SIZE(qseecom_clks_init_vectors),
+		qseecom_clks_init_vectors,
+	},
+	{
+		ARRAY_SIZE(qseecom_enable_dfab_vectors),
+		qseecom_enable_sfpb_vectors,
+	},
+	{
+		ARRAY_SIZE(qseecom_enable_sfpb_vectors),
+		qseecom_enable_sfpb_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata qseecom_bus_pdata = {
+	qseecom_hw_bus_scale_usecases,
+	ARRAY_SIZE(qseecom_hw_bus_scale_usecases),
+	.name = "qsee",
+};
+
+static struct platform_device qseecom_device = {
+	.name		= "qseecom",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &qseecom_bus_pdata,
+	},
+};
+#endif
+
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
 		defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -2268,6 +2454,9 @@
 #endif
 	&msm_slim_ctrl,
 	&msm_device_wcnss_wlan,
+#if defined(CONFIG_QSEECOM)
+	&qseecom_device,
+#endif
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
 	&qcrypto_device,
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index d5a1d3f..c92c049 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -483,12 +483,18 @@
 	{ 0 }
 };
 
-static struct clk_data gfx3d_clks[] = {
+static struct clk_data gfx3d_8660_clks[] = {
 	{ .name = "core_clk", .reset_rate = 27000000 },
 	{ .name = "iface_clk" },
 	{ 0 }
 };
 
+static struct clk_data gfx3d_8064_clks[] = {
+	{ .name = "core_clk", .reset_rate = 27000000 },
+	{ .name = "iface_clk" },
+	{ .name = "bus_clk" },
+	{ 0 }
+};
 
 static struct clk_data ijpeg_clks[] = {
 	{ .name = "core_clk" },
@@ -579,7 +585,7 @@
 		GFX2D1_GFS_CTL_REG, 31, gfx2d1_clks,
 		MSM_BUS_MASTER_GRAPHICS_2D_CORE1, 0),
 	FOOTSWITCH(FS_GFX3D, "fs_gfx3d", &standard_fs_ops,
-		GFX3D_GFS_CTL_REG, 31, gfx3d_clks,
+		GFX3D_GFS_CTL_REG, 31, gfx3d_8660_clks,
 		MSM_BUS_MASTER_GRAPHICS_3D, 0),
 	FOOTSWITCH(FS_IJPEG, "fs_ijpeg", &standard_fs_ops,
 		GEMINI_GFS_CTL_REG, 31, ijpeg_clks,
@@ -625,10 +631,13 @@
 	if (pdev->id == FS_MDP) {
 		if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_apq8064())
 			fs->clk_data = mdp_8960_clks;
-		else if (cpu_is_msm8x60())
-			fs->clk_data = mdp_8660_clks;
 		else
-			BUG();
+			fs->clk_data = mdp_8660_clks;
+	} else if (pdev->id == FS_GFX3D) {
+		if (cpu_is_msm8930() || cpu_is_apq8064())
+			fs->clk_data = gfx3d_8064_clks;
+		else
+			fs->clk_data = gfx3d_8660_clks;
 	}
 
 	for (clock = fs->clk_data; clock->name; clock++) {
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h
index 29a9d4a..6f9bed1 100644
--- a/arch/arm/mach-msm/include/mach/msm_memtypes.h
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h
@@ -55,10 +55,13 @@
 struct reserve_info {
 	struct memtype_reserve *memtype_reserve_table;
 	void (*calculate_reserve_sizes)(void);
+	void (*reserve_fixed_area)(unsigned long);
 	int (*paddr_to_memtype)(unsigned int);
 	unsigned long low_unstable_address;
 	unsigned long max_unstable_size;
 	unsigned long bank_size;
+	unsigned long fixed_area_start;
+	unsigned long fixed_area_size;
 };
 
 extern struct reserve_info *reserve_info;
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 8dbf304..0db160e 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -317,6 +317,8 @@
 			if (size >= mt->size) {
 				size = stable_size(mb,
 					reserve_info->low_unstable_address);
+				if (!size)
+					continue;
 				/* mt->size may be larger than size, all this
 				 * means is that we are carving the memory pool
 				 * out of multiple contiguous memory banks.
@@ -370,10 +372,24 @@
 	}
 }
 
+#define  MAX_FIXED_AREA_SIZE 0x11000000
+
 void __init msm_reserve(void)
 {
+	unsigned long msm_fixed_area_size;
+	unsigned long msm_fixed_area_start;
+
 	memory_pool_init();
 	reserve_info->calculate_reserve_sizes();
+
+	msm_fixed_area_size = reserve_info->fixed_area_size;
+	msm_fixed_area_start = reserve_info->fixed_area_start;
+	if (msm_fixed_area_size)
+		if (msm_fixed_area_start > reserve_info->low_unstable_address
+			- MAX_FIXED_AREA_SIZE)
+			reserve_info->low_unstable_address =
+			msm_fixed_area_start;
+
 	calculate_reserve_limits();
 	adjust_reserve_sizes();
 	reserve_memory_for_mempools();
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 42befd1..8a46a2e 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -248,13 +248,16 @@
 	 */
 	if (action == MEM_ONLINE) {
 		for (i = 0; i < nr_pages; i++) {
-			if (PageReserved(first_page+i))
-				continue;
-
-			printk(KERN_WARNING "section number %ld page number %d "
-				"not reserved, was it already online?\n",
-				phys_index, i);
-			return -EBUSY;
+			if (page_is_ram(page_to_pfn(first_page+i))) {
+				if (PageReserved(first_page+i))
+					continue;
+					printk(KERN_WARNING
+						"section number %ld page number"
+						" %d not reserved, was it "
+						" already online?\n",
+						phys_index, i);
+					return -EBUSY;
+			}
 		}
 	}
 
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 6aed95c..2d33096 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -412,9 +412,12 @@
 {
 	int input  = 0;
 	int bypass = 0;
-	int ret, cpu, reenable_timer;
+	int ret, cpu, reenable_timer, j;
 	struct cpu_dbs_info_s *dbs_info;
 
+	struct cpumask cpus_timer_done;
+	cpumask_clear(&cpus_timer_done);
+
 	ret = sscanf(buf, "%d", &input);
 
 	if (ret != 1)
@@ -447,10 +450,23 @@
 					continue;
 
 				dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
+
+				for_each_cpu(j, &cpus_timer_done) {
+					if (!dbs_info->cur_policy) {
+						pr_err("Dbs policy is NULL\n");
+						goto skip_this_cpu;
+					}
+					if (cpumask_test_cpu(j, dbs_info->
+							cur_policy->cpus))
+						goto skip_this_cpu;
+				}
+
+				cpumask_set_cpu(cpu, &cpus_timer_done);
 				if (dbs_info->cur_policy) {
 					/* restart dbs timer */
 					dbs_timer_init(dbs_info);
 				}
+skip_this_cpu:
 				unlock_policy_rwsem_write(cpu);
 			}
 		}
@@ -463,6 +479,19 @@
 				continue;
 
 			dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
+
+			for_each_cpu(j, &cpus_timer_done) {
+				if (!dbs_info->cur_policy) {
+					pr_err("Dbs policy is NULL\n");
+					goto skip_this_cpu_bypass;
+				}
+				if (cpumask_test_cpu(j, dbs_info->
+							cur_policy->cpus))
+					goto skip_this_cpu_bypass;
+			}
+
+			cpumask_set_cpu(cpu, &cpus_timer_done);
+
 			if (dbs_info->cur_policy) {
 				/* cpu using ondemand, cancel dbs timer */
 				mutex_lock(&dbs_info->timer_mutex);
@@ -475,6 +504,7 @@
 
 				mutex_unlock(&dbs_info->timer_mutex);
 			}
+skip_this_cpu_bypass:
 			unlock_policy_rwsem_write(cpu);
 		}
 	}
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 203b41a..15c0ec5 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -81,12 +81,44 @@
 	return 0;
 }
 
+static void ion_set_base_address(struct ion_platform_heap *heap,
+			    struct ion_platform_heap *shared_heap,
+			    struct ion_co_heap_pdata *co_heap_data,
+			    struct ion_cp_heap_pdata *cp_data)
+{
+	if (cp_data->reusable) {
+		const struct fmem_data *fmem_info = fmem_get_info();
+
+		if (!fmem_info) {
+			pr_err("fmem info pointer NULL!\n");
+			BUG();
+		}
+
+		heap->base = fmem_info->phys - fmem_info->reserved_size_low;
+		cp_data->virt_addr = fmem_info->virt;
+		pr_info("ION heap %s using FMEM\n", shared_heap->name);
+	} else {
+		heap->base = msm_ion_get_base(heap->size + shared_heap->size,
+						shared_heap->memory_type,
+						co_heap_data->align);
+	}
+	if (heap->base) {
+		shared_heap->base = heap->base + heap->size;
+		cp_data->secure_base = heap->base;
+		cp_data->secure_size = heap->size + shared_heap->size;
+	} else {
+		pr_err("%s: could not get memory for heap %s (id %x)\n",
+			__func__, heap->name, heap->id);
+	}
+}
+
 static void allocate_co_memory(struct ion_platform_heap *heap,
 			       struct ion_platform_heap heap_data[],
 			       unsigned int nr_heaps)
 {
 	struct ion_co_heap_pdata *co_heap_data =
 		(struct ion_co_heap_pdata *) heap->extra_data;
+
 	if (co_heap_data->adjacent_mem_id != INVALID_HEAP_ID) {
 		struct ion_platform_heap *shared_heap =
 			find_heap(heap_data, nr_heaps,
@@ -94,30 +126,23 @@
 		if (shared_heap) {
 			struct ion_cp_heap_pdata *cp_data =
 			   (struct ion_cp_heap_pdata *) shared_heap->extra_data;
-			if (cp_data->reusable) {
+			if (cp_data->fixed_position == FIXED_MIDDLE) {
 				const struct fmem_data *fmem_info =
 					fmem_get_info();
-				heap->base = fmem_info->phys -
-					     fmem_info->reserved_size_low;
+
+				if (!fmem_info) {
+					pr_err("fmem info pointer NULL!\n");
+					BUG();
+				}
+
 				cp_data->virt_addr = fmem_info->virt;
-				pr_info("ION heap %s using FMEM\n",
-							shared_heap->name);
-			} else {
-				heap->base = msm_ion_get_base(
-					heap->size + shared_heap->size,
-					shared_heap->memory_type,
-					co_heap_data->align);
-			}
-			if (heap->base) {
-				shared_heap->base = heap->base + heap->size;
 				cp_data->secure_base = heap->base;
 				cp_data->secure_size =
 						heap->size + shared_heap->size;
-			} else {
-				pr_err("%s: could not get memory for heap %s "
-				   "(id %x)\n", __func__, heap->name, heap->id);
+			} else if (!heap->base) {
+				ion_set_base_address(heap, shared_heap,
+					co_heap_data, cp_data);
 			}
-
 		}
 	}
 }
@@ -138,7 +163,7 @@
 
 	for (i = 0; i < nr_heaps; i++) {
 		struct ion_platform_heap *heap = &heap_data[i];
-		if (!heap->base && heap->type == ION_HEAP_TYPE_CARVEOUT) {
+		if (heap->type == ION_HEAP_TYPE_CARVEOUT) {
 			if (heap->extra_data)
 				allocate_co_memory(heap, heap_data, nr_heaps);
 		}
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 83f402b..87f259d 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -106,10 +106,8 @@
 		},
 #endif
 	},
-	.gmemspace = {
-		.gpu_base = 0,
-		.sizebytes = SZ_256K,
-	},
+	.gmem_base = 0,
+	.gmem_size = SZ_256K,
 	.pfp_fw = NULL,
 	.pm4_fw = NULL,
 	.wait_timeout = 10000, /* in milliseconds */
@@ -472,7 +470,7 @@
 	adreno_dev->istore_size = adreno_gpulist[i].istore_size;
 	adreno_dev->pix_shader_start = adreno_gpulist[i].pix_shader_start;
 	adreno_dev->instruction_size = adreno_gpulist[i].instruction_size;
-	adreno_dev->gmemspace.sizebytes = adreno_gpulist[i].gmem_size;
+	adreno_dev->gmem_size = adreno_gpulist[i].gmem_size;
 }
 
 static int __devinit
@@ -792,10 +790,8 @@
 			devinfo.chip_id = adreno_dev->chip_id;
 			devinfo.mmu_enabled = kgsl_mmu_enabled();
 			devinfo.gpu_id = adreno_dev->gpurev;
-			devinfo.gmem_gpubaseaddr = adreno_dev->gmemspace.
-					gpu_base;
-			devinfo.gmem_sizebytes = adreno_dev->gmemspace.
-					sizebytes;
+			devinfo.gmem_gpubaseaddr = adreno_dev->gmem_base;
+			devinfo.gmem_sizebytes = adreno_dev->gmem_size;
 
 			if (copy_to_user(value, &devinfo, sizeof(devinfo)) !=
 					0) {
@@ -869,6 +865,48 @@
 	return status;
 }
 
+static int adreno_setproperty(struct kgsl_device *device,
+				enum kgsl_property_type type,
+				void *value,
+				unsigned int sizebytes)
+{
+	int status = -EINVAL;
+
+	switch (type) {
+	case KGSL_PROP_PWRCTRL: {
+			unsigned int enable;
+			struct kgsl_device_platform_data *pdata =
+				kgsl_device_get_drvdata(device);
+
+			if (sizebytes != sizeof(enable))
+				break;
+
+			if (copy_from_user(&enable, (void __user *) value,
+				sizeof(enable))) {
+				status = -EFAULT;
+				break;
+			}
+
+			if (enable) {
+				if (pdata->nap_allowed)
+					device->pwrctrl.nap_allowed = true;
+
+				kgsl_pwrscale_enable(device);
+			} else {
+				device->pwrctrl.nap_allowed = false;
+				kgsl_pwrscale_disable(device);
+			}
+
+			status = 0;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return status;
+}
+
 static inline void adreno_poke(struct kgsl_device *device)
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
@@ -1065,9 +1103,8 @@
 				unsigned int *value)
 {
 	unsigned int *reg;
-	BUG_ON(offsetwords*sizeof(uint32_t) >= device->regspace.sizebytes);
-	reg = (unsigned int *)(device->regspace.mmio_virt_base
-				+ (offsetwords << 2));
+	BUG_ON(offsetwords*sizeof(uint32_t) >= device->reg_len);
+	reg = (unsigned int *)(device->reg_virt + (offsetwords << 2));
 
 	if (!in_interrupt())
 		kgsl_pre_hwaccess(device);
@@ -1083,14 +1120,13 @@
 {
 	unsigned int *reg;
 
-	BUG_ON(offsetwords*sizeof(uint32_t) >= device->regspace.sizebytes);
+	BUG_ON(offsetwords*sizeof(uint32_t) >= device->reg_len);
 
 	if (!in_interrupt())
 		kgsl_pre_hwaccess(device);
 
 	kgsl_cffdump_regwrite(device->id, offsetwords << 2, value);
-	reg = (unsigned int *)(device->regspace.mmio_virt_base
-				+ (offsetwords << 2));
+	reg = (unsigned int *)(device->reg_virt + (offsetwords << 2));
 
 	/*ensure previous writes post before this one,
 	 * i.e. act like normal writel() */
@@ -1280,12 +1316,23 @@
 	unsigned int timestamp = 0;
 	unsigned int context_id = _get_context_id(context);
 
-	if (type == KGSL_TIMESTAMP_CONSUMED)
+	switch (type) {
+	case KGSL_TIMESTAMP_QUEUED: {
+		struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+		struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+
+		timestamp = rb->timestamp[context_id];
+		break;
+	}
+	case KGSL_TIMESTAMP_CONSUMED:
 		adreno_regread(device, REG_CP_TIMESTAMP, &timestamp);
-	else if (type == KGSL_TIMESTAMP_RETIRED)
+		break;
+	case KGSL_TIMESTAMP_RETIRED:
 		kgsl_sharedmem_readl(&device->memstore, &timestamp,
-				 KGSL_MEMSTORE_OFFSET(context_id,
-					 eoptimestamp));
+			KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp));
+		break;
+	}
+
 	rmb();
 
 	return timestamp;
@@ -1401,6 +1448,7 @@
 	.setstate = adreno_setstate,
 	.drawctxt_create = adreno_drawctxt_create,
 	.drawctxt_destroy = adreno_drawctxt_destroy,
+	.setproperty = adreno_setproperty,
 };
 
 static struct platform_device_id adreno_id_table[] = {
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 48e70c8..491cf62 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -62,7 +62,8 @@
 	struct kgsl_device dev;    /* Must be first field in this struct */
 	unsigned int chip_id;
 	enum adreno_gpurev gpurev;
-	struct kgsl_memregion gmemspace;
+	unsigned long gmem_base;
+	unsigned int gmem_size;
 	struct adreno_context *drawctxt_active;
 	const char *pfp_fwfile;
 	unsigned int *pfp_fw;
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 18d0e83..6fa053b 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1325,9 +1325,8 @@
 {
 	int result;
 
-	calc_gmemsize(&drawctxt->context_gmem_shadow,
-		adreno_dev->gmemspace.sizebytes);
-	tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
+	calc_gmemsize(&drawctxt->context_gmem_shadow, adreno_dev->gmem_base);
+	tmp_ctx.gmem_base = adreno_dev->gmem_base;
 
 	result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
 		drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
@@ -1849,12 +1848,8 @@
 	unsigned int gmem_size;
 	unsigned int edram_value = 0;
 
-	/* make sure edram range is aligned to size */
-	BUG_ON(adreno_dev->gmemspace.gpu_base &
-				(adreno_dev->gmemspace.sizebytes - 1));
-
 	/* get edram_size value equivalent */
-	gmem_size = (adreno_dev->gmemspace.sizebytes >> 14);
+	gmem_size = (adreno_dev->gmem_size >> 14);
 	while (gmem_size >>= 1)
 		edram_value++;
 
@@ -1864,7 +1859,7 @@
 	rb_edram_info.f.edram_mapping_mode = 0; /* EDRAM_MAP_UPPER */
 
 	/* must be aligned to size */
-	rb_edram_info.f.edram_range = (adreno_dev->gmemspace.gpu_base >> 14);
+	rb_edram_info.f.edram_range = (adreno_dev->gmem_base >> 14);
 
 	adreno_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val);
 }
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 32603bd..6b58545 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2138,9 +2138,8 @@
 {
 	int result;
 
-	calc_gmemsize(&drawctxt->context_gmem_shadow,
-		adreno_dev->gmemspace.sizebytes);
-	tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
+	calc_gmemsize(&drawctxt->context_gmem_shadow, adreno_dev->gmem_size);
+	tmp_ctx.gmem_base = adreno_dev->gmem_base;
 
 	result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
 		drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index a93529a..9e9bbf2 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2426,7 +2426,6 @@
 {
 	int result;
 	int status = -EINVAL;
-	struct kgsl_memregion *regspace = NULL;
 	struct resource *res;
 	struct platform_device *pdev =
 		container_of(device->parentdev, struct platform_device, dev);
@@ -2447,26 +2446,25 @@
 		goto error_pwrctrl_close;
 	}
 	if (res->start == 0 || resource_size(res) == 0) {
-		KGSL_DRV_ERR(device, "dev %d invalid regspace\n", device->id);
+		KGSL_DRV_ERR(device, "dev %d invalid register region\n",
+			device->id);
 		status = -EINVAL;
 		goto error_pwrctrl_close;
 	}
 
-	regspace = &device->regspace;
-	regspace->mmio_phys_base = res->start;
-	regspace->sizebytes = resource_size(res);
+	device->reg_phys = res->start;
+	device->reg_len = resource_size(res);
 
-	if (!request_mem_region(regspace->mmio_phys_base,
-				regspace->sizebytes, device->name)) {
+	if (!request_mem_region(device->reg_phys, device->reg_len,
+		device->name)) {
 		KGSL_DRV_ERR(device, "request_mem_region failed\n");
 		status = -ENODEV;
 		goto error_pwrctrl_close;
 	}
 
-	regspace->mmio_virt_base = ioremap(regspace->mmio_phys_base,
-					   regspace->sizebytes);
+	device->reg_virt = ioremap(device->reg_phys, device->reg_len);
 
-	if (regspace->mmio_virt_base == NULL) {
+	if (device->reg_virt == NULL) {
 		KGSL_DRV_ERR(device, "ioremap failed\n");
 		status = -ENODEV;
 		goto error_release_mem;
@@ -2483,9 +2481,9 @@
 	disable_irq(device->pwrctrl.interrupt_num);
 
 	KGSL_DRV_INFO(device,
-		"dev_id %d regs phys 0x%08x size 0x%08x virt %p\n",
-		device->id, regspace->mmio_phys_base,
-		regspace->sizebytes, regspace->mmio_virt_base);
+		"dev_id %d regs phys 0x%08lx size 0x%08x virt %p\n",
+		device->id, device->reg_phys, device->reg_len,
+		device->reg_virt);
 
 	result = kgsl_drm_init(pdev);
 	if (result)
@@ -2498,10 +2496,10 @@
 	free_irq(device->pwrctrl.interrupt_num, NULL);
 	device->pwrctrl.have_irq = 0;
 error_iounmap:
-	iounmap(regspace->mmio_virt_base);
-	regspace->mmio_virt_base = NULL;
+	iounmap(device->reg_virt);
+	device->reg_virt = NULL;
 error_release_mem:
-	release_mem_region(regspace->mmio_phys_base, regspace->sizebytes);
+	release_mem_region(device->reg_phys, device->reg_len);
 error_pwrctrl_close:
 	kgsl_pwrctrl_close(device);
 error:
@@ -2511,15 +2509,12 @@
 
 void kgsl_device_platform_remove(struct kgsl_device *device)
 {
-	struct kgsl_memregion *regspace = &device->regspace;
-
 	kgsl_unregister_device(device);
 
-	if (regspace->mmio_virt_base != NULL) {
-		iounmap(regspace->mmio_virt_base);
-		regspace->mmio_virt_base = NULL;
-		release_mem_region(regspace->mmio_phys_base,
-					regspace->sizebytes);
+	if (device->reg_virt != NULL) {
+		iounmap(device->reg_virt);
+		device->reg_virt = NULL;
+		release_mem_region(device->reg_phys, device->reg_len);
 	}
 	kgsl_pwrctrl_close(device);
 
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index fece715..7d3cfca 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -110,13 +110,6 @@
 		unsigned int sizebytes);
 };
 
-struct kgsl_memregion {
-	unsigned char *mmio_virt_base;
-	unsigned int mmio_phys_base;
-	uint32_t gpu_base;
-	unsigned int sizebytes;
-};
-
 /* MH register values */
 struct kgsl_mh {
 	unsigned int     mharb;
@@ -143,7 +136,9 @@
 	unsigned int ver_minor;
 	uint32_t flags;
 	enum kgsl_deviceid id;
-	struct kgsl_memregion regspace;
+	unsigned long reg_phys;
+	void *reg_virt;
+	unsigned int reg_len;
 	struct kgsl_memdesc memstore;
 	const char *iomemname;
 
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 3efafee..c8db702 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -63,7 +63,8 @@
 	 * return the global timestamp for all contexts
 	 */
 
-	header->timestamp_queued = -1;
+	header->timestamp_queued = device->ftbl->readtimestamp(device,
+		context, KGSL_TIMESTAMP_QUEUED);
 	header->timestamp_retired = device->ftbl->readtimestamp(device,
 		context, KGSL_TIMESTAMP_RETIRED);
 
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index bc5c960..cff7fec 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -700,10 +700,9 @@
 {
 	unsigned int *reg;
 
-	BUG_ON(offsetwords * sizeof(uint32_t) >= device->regspace.sizebytes);
+	BUG_ON(offsetwords * sizeof(uint32_t) >= device->reg_len);
 
-	reg = (unsigned int *)(device->regspace.mmio_virt_base
-			+ (offsetwords << 2));
+	reg = (unsigned int *)(device->reg_virt + (offsetwords << 2));
 
 	/*ensure this read finishes before the next one.
 	 * i.e. act like normal readl() */
@@ -718,10 +717,9 @@
 {
 	unsigned int *reg;
 
-	BUG_ON(offsetwords*sizeof(uint32_t) >= device->regspace.sizebytes);
+	BUG_ON(offsetwords*sizeof(uint32_t) >= device->reg_len);
 
-	reg = (unsigned int *)(device->regspace.mmio_virt_base
-			+ (offsetwords << 2));
+	reg = (unsigned int *)(device->reg_virt + (offsetwords << 2));
 	kgsl_cffdump_regwrite(device->id, offsetwords << 2, value);
 	/*ensure previous writes post before this one,
 	 * i.e. act like normal writel() */
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 6026fda..2c42bc7 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -33,6 +33,7 @@
 #include <linux/clk.h>
 #include <linux/qseecom.h>
 #include <linux/freezer.h>
+#include <mach/board.h>
 #include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
 #include <mach/scm.h>
@@ -68,6 +69,11 @@
 	QSEOS_RESULT_FAILURE  = 0xFFFFFFFF
 };
 
+enum qseecom_clk_definitions {
+	CLK_DFAB = 0,
+	CLK_SFPB,
+};
+
 __packed struct qseecom_check_app_ireq {
 	uint32_t qsee_cmd_id;
 	char     app_name[MAX_APP_NAME_SIZE];
@@ -137,9 +143,11 @@
 
 static DEFINE_MUTEX(send_msg_lock);
 static DEFINE_MUTEX(qsee_bw_mutex);
+static DEFINE_MUTEX(qsee_sfpb_bw_mutex);
 static DEFINE_MUTEX(app_access_lock);
 
 static int qsee_bw_count;
+static int qsee_sfpb_bw_count;
 static struct clk *qseecom_bus_clk;
 static uint32_t qsee_perf_client;
 
@@ -203,6 +211,10 @@
 	atomic_t          ioctl_count;
 };
 
+/* Function proto types */
+static int qsee_vote_for_clock(int32_t);
+static void qsee_disable_clock_vote(int32_t);
+
 static int __qseecom_is_svc_unique(struct qseecom_dev_handle *data,
 		struct qseecom_register_listener_req *svc)
 {
@@ -601,6 +613,10 @@
 		pr_err("copy_from_user failed\n");
 		return -EFAULT;
 	}
+	/* Vote for the SFPB clock */
+	ret = qsee_vote_for_clock(CLK_SFPB);
+	if (ret)
+		pr_warning("Unable to vote for SFPB clock");
 
 	req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
 	memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
@@ -642,6 +658,7 @@
 					load_img_req.ifd_data_fd);
 		if (IS_ERR_OR_NULL(ihandle)) {
 			pr_err("Ion client could not retrieve the handle\n");
+			qsee_disable_clock_vote(CLK_SFPB);
 			return -ENOMEM;
 		}
 
@@ -667,6 +684,7 @@
 			pr_err("scm_call rsp.result is QSEOS_RESULT_FAILURE\n");
 			if (!IS_ERR_OR_NULL(ihandle))
 				ion_free(qseecom.ion_clnt, ihandle);
+			qsee_disable_clock_vote(CLK_SFPB);
 			return -EFAULT;
 		}
 
@@ -677,6 +695,7 @@
 						ret);
 				if (!IS_ERR_OR_NULL(ihandle))
 					ion_free(qseecom.ion_clnt, ihandle);
+				qsee_disable_clock_vote(CLK_SFPB);
 				return ret;
 			}
 		}
@@ -685,6 +704,7 @@
 					resp.result);
 			if (!IS_ERR_OR_NULL(ihandle))
 				ion_free(qseecom.ion_clnt, ihandle);
+			qsee_disable_clock_vote(CLK_SFPB);
 			return -EFAULT;
 		}
 
@@ -693,6 +713,7 @@
 		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 		if (!entry) {
 			pr_err("kmalloc failed\n");
+			qsee_disable_clock_vote(CLK_SFPB);
 			return -ENOMEM;
 		}
 		entry->app_id = app_id;
@@ -715,8 +736,10 @@
 	if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) {
 		pr_err("copy_to_user failed\n");
 		kzfree(entry);
+		qsee_disable_clock_vote(CLK_SFPB);
 		return -EFAULT;
 	}
+	qsee_disable_clock_vote(CLK_SFPB);
 	return 0;
 }
 
@@ -1151,61 +1174,96 @@
 	return 0;
 }
 
-static int qsee_vote_for_clock(void)
+static int qsee_vote_for_clock(int32_t clk_type)
 {
 	int ret = 0;
 
 	if (!qsee_perf_client)
 		return ret;
 
-	/* Check if the clk is valid */
-	if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
-		pr_warn("qseecom bus clock is null or error");
-		return -EINVAL;
-	}
-
-	mutex_lock(&qsee_bw_mutex);
-	if (!qsee_bw_count) {
-		ret = msm_bus_scale_client_update_request(
-				qsee_perf_client, 1);
-		if (ret) {
-			pr_err("Bandwidth request failed (%d)\n", ret);
-		} else {
-			ret = clk_enable(qseecom_bus_clk);
-			if (ret)
-				pr_err("Clock enable failed\n");
+	switch (clk_type) {
+	case CLK_DFAB:
+		/* Check if the clk is valid */
+		if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
+			pr_warn("qseecom bus clock is null or error");
+			return -EINVAL;
 		}
+		mutex_lock(&qsee_bw_mutex);
+		if (!qsee_bw_count) {
+			ret = msm_bus_scale_client_update_request(
+					qsee_perf_client, 1);
+			if (ret)
+				pr_err("DFAB Bandwidth req failed (%d)\n",
+								ret);
+			else
+				qsee_bw_count++;
+		}
+		mutex_unlock(&qsee_bw_mutex);
+		break;
+	case CLK_SFPB:
+		mutex_lock(&qsee_sfpb_bw_mutex);
+		if (!qsee_sfpb_bw_count) {
+			ret = msm_bus_scale_client_update_request(
+					qsee_perf_client, 2);
+			if (ret)
+				pr_err("SFPB Bandwidth req failed (%d)\n",
+								ret);
+			else
+				qsee_sfpb_bw_count++;
+		}
+		mutex_unlock(&qsee_sfpb_bw_mutex);
+		break;
+	default:
+		pr_err("Clock type not defined\n");
+		break;
 	}
-	if (ret)
-		msm_bus_scale_client_update_request(qsee_perf_client, 0);
-	else
-		qsee_bw_count++;
-
-	mutex_unlock(&qsee_bw_mutex);
 	return ret;
 }
 
-static void qsee_disable_clock_vote(void)
+static void qsee_disable_clock_vote(int32_t clk_type)
 {
+	int32_t ret = 0;
 
 	if (!qsee_perf_client)
 		return;
 
-	/* Check if the clk is valid */
-	if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
-		pr_warn("qseecom bus clock is null or error");
-		return;
+	switch (clk_type) {
+	case CLK_DFAB:
+		/* Check if the DFAB clk is valid */
+		if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
+			pr_warn("qseecom bus clock is null or error");
+			return;
+		}
+		mutex_lock(&qsee_bw_mutex);
+		if (qsee_bw_count > 0) {
+			if (qsee_bw_count-- == 1) {
+				ret = msm_bus_scale_client_update_request(
+						qsee_perf_client, 0);
+				if (ret)
+					pr_err("SFPB Bandwidth req fail (%d)\n",
+								ret);
+			}
+		}
+		mutex_unlock(&qsee_bw_mutex);
+		break;
+	case CLK_SFPB:
+		mutex_lock(&qsee_sfpb_bw_mutex);
+		if (qsee_sfpb_bw_count > 0) {
+			if (qsee_sfpb_bw_count-- == 1) {
+				ret = msm_bus_scale_client_update_request(
+						qsee_perf_client, 0);
+				if (ret)
+					pr_err("SFPB Bandwidth req fail (%d)\n",
+								ret);
+			}
+		}
+		mutex_unlock(&qsee_sfpb_bw_mutex);
+		break;
+	default:
+		pr_err("Clock type not defined\n");
+		break;
 	}
 
-	mutex_lock(&qsee_bw_mutex);
-	if (qsee_bw_count > 0) {
-		if (qsee_bw_count-- == 1) {
-			msm_bus_scale_client_update_request(qsee_perf_client,
-							0);
-			clk_disable(qseecom_bus_clk);
-		}
-	}
-	mutex_unlock(&qsee_bw_mutex);
 }
 
 static int qseecom_load_external_elf(struct qseecom_dev_handle *data,
@@ -1417,15 +1475,15 @@
 	}
 	case QSEECOM_IOCTL_PERF_ENABLE_REQ:{
 		atomic_inc(&data->ioctl_count);
-		ret = qsee_vote_for_clock();
+		ret = qsee_vote_for_clock(CLK_DFAB);
 		if (ret)
-			pr_err("Failed to vote for clock%d\n", ret);
+			pr_err("Failed to vote for DFAB clock%d\n", ret);
 		atomic_dec(&data->ioctl_count);
 		break;
 	}
 	case QSEECOM_IOCTL_PERF_DISABLE_REQ:{
 		atomic_inc(&data->ioctl_count);
-		qsee_disable_clock_vote();
+		qsee_disable_clock_vote(CLK_DFAB);
 		atomic_dec(&data->ioctl_count);
 		break;
 	}
@@ -1527,41 +1585,11 @@
 		mutex_unlock(&pil_access_lock);
 	}
 	kfree(data);
-	qsee_disable_clock_vote();
+	qsee_disable_clock_vote(CLK_DFAB);
 
 	return ret;
 }
 
-/* qseecom bus scaling */
-static struct msm_bus_paths qsee_bw_table[] = {
-	{
-		.vectors = (struct msm_bus_vectors[]){
-			{
-				.src = MSM_BUS_MASTER_SPS,
-				.dst = MSM_BUS_SLAVE_EBI_CH0,
-			},
-		},
-		.num_paths = 1,
-	},
-	{
-		.vectors = (struct msm_bus_vectors[]){
-			{
-				.src = MSM_BUS_MASTER_SPS,
-				.dst = MSM_BUS_SLAVE_EBI_CH0,
-				.ib = (492 * 8) * 1000000UL,
-				.ab = (492 * 8) *  100000UL,
-			},
-		},
-		.num_paths = 1,
-	},
-};
-
-static struct msm_bus_scale_pdata qsee_bus_pdata = {
-	.usecase = qsee_bw_table,
-	.num_usecases = ARRAY_SIZE(qsee_bw_table),
-	.name = "qsee",
-};
-
 static const struct file_operations qseecom_fops = {
 		.owner = THIS_MODULE,
 		.unlocked_ioctl = qseecom_ioctl,
@@ -1569,11 +1597,12 @@
 		.release = qseecom_release
 };
 
-static int __init qseecom_init(void)
+static int __devinit qseecom_probe(struct platform_device *pdev)
 {
 	int rc;
 	struct device *class_dev;
 	char qsee_not_legacy = 0;
+	struct msm_bus_scale_pdata *qseecom_platform_support;
 	uint32_t system_call_id = QSEOS_CHECK_VERSION_CMD;
 
 	qsee_bw_count = 0;
@@ -1639,8 +1668,10 @@
 	}
 
 	/* register client for bus scaling */
+	qseecom_platform_support = (struct msm_bus_scale_pdata *)
+					pdev->dev.platform_data;
 	qsee_perf_client = msm_bus_scale_register_client(
-					&qsee_bus_pdata);
+					qseecom_platform_support);
 	if (!qsee_perf_client) {
 		pr_err("Unable to register bus client\n");
 	} else {
@@ -1663,7 +1694,28 @@
 	return rc;
 }
 
-static void __exit qseecom_exit(void)
+static int __devinit qseecom_remove(struct platform_device *pdev)
+{
+	if (pdev->dev.platform_data != NULL)
+		msm_bus_scale_unregister_client(qsee_perf_client);
+	return 0;
+};
+
+static struct platform_driver qseecom_plat_driver = {
+	.probe = qseecom_probe,
+	.remove = qseecom_remove,
+	.driver = {
+		.name = "qseecom",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __devinit qseecom_init(void)
+{
+	return platform_driver_register(&qseecom_plat_driver);
+}
+
+static void __devexit qseecom_exit(void)
 {
 	clk_put(qseecom_bus_clk);
 
diff --git a/include/linux/ion.h b/include/linux/ion.h
index d761e1e..ae49bce 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -79,6 +79,13 @@
 	ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_SECURE flag */
 };
 
+enum ion_fixed_position {
+	NOT_FIXED,
+	FIXED_LOW,
+	FIXED_MIDDLE,
+	FIXED_HIGH,
+};
+
 /**
  * Flag to use when allocating to indicate that a heap is secure.
  */
@@ -168,6 +175,7 @@
  *			(see FMEM)
  * @mem_is_fmem		Flag indicating whether this memory is coming from fmem
  *			or not.
+ * @fixed_position	If nonzero, position in the fixed area.
  * @virt_addr:		Virtual address used when using fmem.
  * @request_region:	function to be called when the number of allocations
  *			goes from 0 -> 1
@@ -183,6 +191,7 @@
 	size_t secure_size; /* Size used for securing heap when heap is shared*/
 	int reusable;
 	int mem_is_fmem;
+	enum ion_fixed_position fixed_position;
 	ion_virt_addr_t *virt_addr;
 	int (*request_region)(void *);
 	int (*release_region)(void *);
@@ -195,6 +204,7 @@
  * @align:		Alignment requirement for the memory
  * @mem_is_fmem		Flag indicating whether this memory is coming from fmem
  *			or not.
+ * @fixed_position	If nonzero, position in the fixed area.
  * @request_region:	function to be called when the number of allocations
  *			goes from 0 -> 1
  * @release_region:	function to be called when the number of allocations
@@ -206,6 +216,7 @@
 	int adjacent_mem_id;
 	unsigned int align;
 	int mem_is_fmem;
+	enum ion_fixed_position fixed_position;
 	int (*request_region)(void *);
 	int (*release_region)(void *);
 	void *(*setup_region)(void);
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index ee1a22e..244b957 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -2,7 +2,7 @@
 #define _MSM_KGSL_H
 
 #define KGSL_VERSION_MAJOR        3
-#define KGSL_VERSION_MINOR        10
+#define KGSL_VERSION_MINOR        11
 
 /*context flags */
 #define KGSL_CONTEXT_SAVE_GMEM		0x00000001
@@ -112,7 +112,7 @@
 enum kgsl_timestamp_type {
 	KGSL_TIMESTAMP_CONSUMED = 0x00000001, /* start-of-pipeline timestamp */
 	KGSL_TIMESTAMP_RETIRED  = 0x00000002, /* end-of-pipeline timestamp*/
-	KGSL_TIMESTAMP_MAX      = 0x00000002,
+	KGSL_TIMESTAMP_QUEUED   = 0x00000003,
 };
 
 /* property types - used with kgsl_device_getproperty */
@@ -125,7 +125,8 @@
 	KGSL_PROP_MMU_ENABLE 	  = 0x00000006,
 	KGSL_PROP_INTERRUPT_WAITS = 0x00000007,
 	KGSL_PROP_VERSION         = 0x00000008,
-	KGSL_PROP_GPU_RESET_STAT  = 0x00000009
+	KGSL_PROP_GPU_RESET_STAT  = 0x00000009,
+	KGSL_PROP_PWRCTRL         = 0x0000000E,
 };
 
 struct kgsl_shadowprop {
diff --git a/kernel/resource.c b/kernel/resource.c
index fdd3939..ef4beab 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -357,12 +357,18 @@
 	while ((res.start < res.end) &&
 		(find_next_system_ram(&res, "System RAM") >= 0)) {
 		pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT;
-		end_pfn = (res.end + 1) >> PAGE_SHIFT;
+		if (res.end + 1 <= 0)
+			end_pfn = res.end >> PAGE_SHIFT;
+		else
+			end_pfn = (res.end + 1) >> PAGE_SHIFT;
 		if (end_pfn > pfn)
 			ret = (*func)(pfn, end_pfn - pfn, arg);
 		if (ret)
 			break;
-		res.start = res.end + 1;
+		if (res.end + 1 > res.start)
+			res.start = res.end + 1;
+		else
+			res.start = res.end;
 		res.end = orig_end;
 	}
 	return ret;