Merge "msm: clock-local: Set 'auto_off' ops for PLL clocks" into msm-3.0
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index c869beb..235db63 100755
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -355,6 +355,7 @@
 CONFIG_LEDS_PM8XXX=y
 # CONFIG_LEDS_MSM_PMIC is not set
 CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_SWITCH=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_DRV_MSM is not set
diff --git a/arch/arm/mach-msm/board-apq8064.c b/arch/arm/mach-msm/board-apq8064.c
index 88ce818..0e30aee 100644
--- a/arch/arm/mach-msm/board-apq8064.c
+++ b/arch/arm/mach-msm/board-apq8064.c
@@ -482,6 +482,7 @@
 }
 
 static struct platform_device *common_devices[] __initdata = {
+	&apq8064_device_dmov,
 	&apq8064_device_qup_i2c_gsbi4,
 	&apq8064_device_qup_spi_gsbi5,
 	&apq8064_slim_ctrl,
@@ -498,7 +499,6 @@
 };
 
 static struct platform_device *sim_devices[] __initdata = {
-	&apq8064_device_dmov,
 	&apq8064_device_uart_gsbi3,
 	&msm_device_sps_apq8064,
 };
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index c264011..7448cc6 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -206,7 +206,6 @@
 	}
 }
 
-#define FPGA_CS_GPIO		14
 #define KS8851_RST_GPIO		89
 #define KS8851_IRQ_GPIO		90
 
@@ -241,6 +240,18 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+static struct gpiomux_setting spi_active_config2 = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting spi_suspended_config2 = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
 static struct gpiomux_setting gsbi3_suspended_cfg = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_2MA,
@@ -320,12 +331,6 @@
 			[GPIOMUX_SUSPENDED] = &gpio_eth_config,
 		}
 	},
-	{
-		.gpio = FPGA_CS_GPIO,
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &gpio_eth_config,
-		}
-	},
 #endif
 };
 
@@ -359,6 +364,13 @@
 		},
 	},
 	{
+		.gpio      = 14,		/* GSBI1 SPI_CS_1 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &spi_suspended_config2,
+			[GPIOMUX_ACTIVE] = &spi_active_config2,
+		},
+	},
+	{
 		.gpio      = 16,	/* GSBI3 I2C QUP SDA */
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
@@ -1969,6 +1981,7 @@
 	}
 };
 
+#define FPGA_3D_GPIO_CONFIG_ADDR	0xB5
 static int dsi2lvds_gpio[2] = {
 	0,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
 	0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
@@ -1994,6 +2007,8 @@
 };
 
 static struct mipi_dsi_panel_platform_data novatek_pdata = {
+	.fpga_3d_config_addr  = FPGA_3D_GPIO_CONFIG_ADDR,
+	.fpga_ctrl_mode = FPGA_SPI_INTF,
 	.phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
 };
 
@@ -3605,6 +3620,13 @@
 		.mode                   = SPI_MODE_0,
 		.platform_data		= &spi_eth_pdata
 	},
+	{
+		.modalias               = "dsi_novatek_3d_panel_spi",
+		.max_speed_hz           = 10800000,
+		.bus_num                = 0,
+		.chip_select            = 1,
+		.mode                   = SPI_MODE_0,
+	},
 };
 
 static struct platform_device msm_device_saw_core0 = {
@@ -4226,30 +4248,6 @@
 	},
 };
 
-#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
-static int fpga_init(void)
-{
-	int ret;
-
-	ret = gpio_request(FPGA_CS_GPIO, "fpga_cs");
-	if (ret) {
-		pr_err("FPGA CS gpio_request failed: %d\n", ret);
-		goto fail;
-	}
-
-	gpio_direction_output(FPGA_CS_GPIO, 1);
-
-	return 0;
-fail:
-	return ret;
-}
-#else
-static int fpga_init(void)
-{
-	return 0;
-}
-#endif
-
 static struct msm_cpuidle_state msm_cstates[] __initdata = {
 	{0, 0, "C0", "WFI",
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
@@ -4638,8 +4636,6 @@
 #endif
 	msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
 	gpiomux_init();
-	if (machine_is_msm8960_cdp())
-		fpga_init();
 	if (machine_is_msm8960_liquid())
 		pm8921_platform_data.keypad_pdata = &keypad_data_liquid;
 	msm8960_device_qup_spi_gsbi1.dev.platform_data =
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index dca8268..d2a1df1 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -194,11 +194,10 @@
 
 static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
 {
-	/* TODO: Update these voltages when info becomes available. */
 	static const int vdd_uv[] = {
-		[VDD_DIG_NONE]    = 1150000,
-		[VDD_DIG_LOW]     = 1150000,
-		[VDD_DIG_NOMINAL] = 1150000,
+		[VDD_DIG_NONE]    =       0,
+		[VDD_DIG_LOW]     =  945000,
+		[VDD_DIG_NOMINAL] = 1050000,
 		[VDD_DIG_HIGH]    = 1150000
 	};
 
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index ab4d8c1..78586a8 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -141,9 +141,24 @@
 	return ret;
 }
 
+
+static int clock_debug_print_clock(struct clk *c)
+{
+	size_t ln = 0;
+	char s[128];
+
+	if (!c || !c->count)
+		return 0;
+
+	ln += snprintf(s, sizeof(s), "\t%s", c->dbg_name);
+	while (ln < sizeof(s) && (c = clk_get_parent(c)))
+		ln += snprintf(s + ln, sizeof(s) - ln, " -> %s", c->dbg_name);
+	pr_info("%s\n", s);
+	return 1;
+}
+
 void clock_debug_print_enabled(void)
 {
-	struct clk *clk;
 	unsigned i;
 	int cnt = 0;
 
@@ -151,14 +166,8 @@
 		return;
 
 	pr_info("Enabled clocks:\n");
-	for (i = 0; i < num_msm_clocks; i++) {
-		clk = msm_clocks[i].clk;
-
-		if (clk && clk->ops->is_enabled && clk->ops->is_enabled(clk)) {
-			pr_info("\t%s\n", clk->dbg_name);
-			cnt++;
-		}
-	}
+	for (i = 0; i < num_msm_clocks; i++)
+		cnt += clock_debug_print_clock(msm_clocks[i].clk);
 
 	if (cnt)
 		pr_info("Enabled clock count: %d\n", cnt);
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index de89382..4f3ad95 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -230,12 +230,13 @@
 }
 EXPORT_SYMBOL(clk_get_rate);
 
-int clk_set_rate(struct clk *clk, unsigned long rate)
+static int _clk_set_rate(struct clk *clk, unsigned long rate,
+			 int (*set_fn)(struct clk *, unsigned))
 {
 	unsigned long start_rate, flags;
 	int rc;
 
-	if (!clk->ops->set_rate)
+	if (!set_fn)
 		return -ENOSYS;
 
 	spin_lock_irqsave(&clk->lock, flags);
@@ -245,13 +246,13 @@
 		rc = vote_rate_vdd(clk, rate);
 		if (rc)
 			goto err_vote_vdd;
-		rc = clk->ops->set_rate(clk, rate);
+		rc = set_fn(clk, rate);
 		if (rc)
 			goto err_set_rate;
 		/* Release vdd requirements for starting frequency. */
 		unvote_rate_vdd(clk, start_rate);
 	} else {
-		rc = clk->ops->set_rate(clk, rate);
+		rc = set_fn(clk, rate);
 	}
 	spin_unlock_irqrestore(&clk->lock, flags);
 	return rc;
@@ -262,7 +263,6 @@
 	spin_unlock_irqrestore(&clk->lock, flags);
 	return rc;
 }
-EXPORT_SYMBOL(clk_set_rate);
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
@@ -273,12 +273,15 @@
 }
 EXPORT_SYMBOL(clk_round_rate);
 
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	return _clk_set_rate(clk, rate, clk->ops->set_rate);
+}
+EXPORT_SYMBOL(clk_set_rate);
+
 int clk_set_min_rate(struct clk *clk, unsigned long rate)
 {
-	if (!clk->ops->set_min_rate)
-		return -ENOSYS;
-
-	return clk->ops->set_min_rate(clk, rate);
+	return _clk_set_rate(clk, rate, clk->ops->set_min_rate);
 }
 EXPORT_SYMBOL(clk_set_min_rate);
 
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 35a69df..f1a0404 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -664,8 +664,8 @@
 	CLK_DUMMY("iface_clk",		SDC2_P_CLK,		NULL, OFF),
 	CLK_DUMMY("iface_clk",		SDC3_P_CLK,		NULL, OFF),
 	CLK_DUMMY("iface_clk",		SDC4_P_CLK,		NULL, OFF),
-	CLK_DUMMY("core_clk",		ADM0_CLK,		NULL, OFF),
-	CLK_DUMMY("iface_clk",		ADM0_P_CLK,		NULL, OFF),
+	CLK_DUMMY("core_clk",		ADM0_CLK,	"msm_dmov", OFF),
+	CLK_DUMMY("iface_clk",		ADM0_P_CLK,	"msm_dmov", OFF),
 	CLK_DUMMY("iface_clk",		PMIC_ARB0_P_CLK,	NULL, OFF),
 	CLK_DUMMY("iface_clk",		PMIC_ARB1_P_CLK,	NULL, OFF),
 	CLK_DUMMY("core_clk",		PMIC_SSBI2_CLK,		NULL, OFF),
@@ -760,6 +760,7 @@
 	CLK_DUMMY("bus_clk",		DFAB_SDC4_CLK,		NULL, 0),
 	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),
 };
 
 struct clock_init_data apq8064_dummy_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index ba36f69..4e047c5 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1134,6 +1134,12 @@
 		.flags  = IORESOURCE_IO,
 	},
 	{
+		.name   = "spi_cs1",
+		.start  = 14,
+		.end    = 14,
+		.flags  = IORESOURCE_IO,
+	},
+	{
 		.name   = "spi_miso",
 		.start  = 7,
 		.end    = 7,
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 8ae3b72..28e98de 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -13,26 +13,67 @@
 #ifndef _ARCH_IOMMU_DOMAINS_H
 #define _ARCH_IOMMU_DOMAINS_H
 
-/*
- * Nothing in this file is to be used outside of the iommu wrappers.
- * Do NOT try and use anything here in a driver. Doing so is incorrect.
- */
+enum {
+	GLOBAL_DOMAIN,
+	MAX_DOMAINS
+};
 
-/*
- * These subsytem ids are NOT for public use. Please check the iommu
- * wrapper header for the properly abstracted id to pass in.
- */
+enum {
+	VIDEO_FIRMWARE_POOL,
+	LOW_256MB_POOL,
+	HIGH_POOL,
+};
+
 
 #if defined(CONFIG_MSM_IOMMU)
-extern struct iommu_domain *msm_subsystem_get_domain(int subsys_id);
 
-extern struct mem_pool *msm_subsystem_get_pool(int subsys_id);
+extern struct iommu_domain *msm_get_iommu_domain(int domain_num);
+
+extern unsigned long msm_allocate_iova_address(unsigned int iommu_domain,
+					unsigned int partition_no,
+					unsigned long size,
+					unsigned long align);
+
+extern void msm_free_iova_address(unsigned long iova,
+			unsigned int iommu_domain,
+			unsigned int partition_no,
+			unsigned long size);
+
+extern unsigned long msm_subsystem_get_domain_no(int subsys_id);
+
+extern unsigned long msm_subsystem_get_partition_no(int subsys_id);
+
+extern int msm_use_iommu(void);
 #else
 static inline struct iommu_domain
-	*msm_subsystem_get_domain(int subsys_id) { return NULL; }
+	*msm_get_iommu_domain(int subsys_id) { return NULL; }
 
-static inline struct mem_pool
-	*msm_subsystem_get_pool(int subsys_id) { return NULL; }
+
+
+static inline unsigned long msm_allocate_iova_address(unsigned int iommu_domain,
+					unsigned int partition_no,
+					unsigned long size,
+					unsigned long align) { return 0; }
+
+static inline void msm_free_iova_address(unsigned long iova,
+			unsigned int iommu_domain,
+			unsigned int partition_no,
+			unsigned long size) { return; }
+
+static inline unsigned long msm_subsystem_get_domain_no(int subsys_id)
+{
+	return 0xFFFFFFFF;
+}
+
+static inline unsigned long msm_subsystem_get_partition_no(int subsys_id)
+{
+	return 0xFFFFFFFF;
+}
+
+static inline int msm_use_iommu(void)
+{
+	return 0;
+}
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 290ba33..e849cdb 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -18,24 +18,23 @@
 #include <linux/init.h>
 #include <mach/iommu.h>
 #include <mach/iommu_domains.h>
+#include <mach/socinfo.h>
 
 struct msm_iommu_domain {
-	int domain_idx;
-	int iova_pool_idx;
+	/* iommu domain to map in */
+	struct iommu_domain *domain;
+	/* total number of allocations from this domain */
+	atomic_t allocation_cnt;
+	/* number of iova pools */
+	int npools;
+	/*
+	 * array of gen_pools for allocating iovas.
+	 * behavior is undefined if these overlap
+	 */
+	struct mem_pool *iova_pools;
+
 };
 
-enum {
-	GLOBAL_DOMAIN,
-	VIDEO_DOMAIN,
-	EMPTY_DOMAIN,
-	MAX_DOMAINS
-};
-
-enum {
-	GLOBAL_MEMORY_POOL,
-	VIDEO_FIRMWARE_POOL,
-	VIDEO_ALLOC_POOL,
-};
 
 struct {
 	char *name;
@@ -114,114 +113,175 @@
 	/* Video */
 	{
 		.name = "vcodec_a_mm1",
-		.domain = VIDEO_DOMAIN,
+		.domain = GLOBAL_DOMAIN,
 	},
 	/* Video */
 	{
 		.name = "vcodec_b_mm2",
-		.domain = VIDEO_DOMAIN,
+		.domain = GLOBAL_DOMAIN,
 	},
 	/* Video */
 	{
 		.name = "vcodec_a_stream",
-		.domain = VIDEO_DOMAIN,
+		.domain = GLOBAL_DOMAIN,
 	},
 };
 
-static struct iommu_domain *msm_iommu_domains[MAX_DOMAINS];
-
-static struct mem_pool msm_iommu_iova_pools[] = {
-	[GLOBAL_MEMORY_POOL] = {
-		.paddr	= SZ_4K,
-		.size	= SZ_2G - SZ_4K,
-	},
+static struct mem_pool global_pools[] =  {
+	[VIDEO_FIRMWARE_POOL] =
+	/* Low addresses, intended for video firmware */
+		{
+			.paddr	= SZ_128K,
+			.size	= SZ_16M - SZ_128K,
+		},
+	[LOW_256MB_POOL] =
 	/*
-	 * The video hardware has several constraints:
-	 * 1) The start address for firmware must be 128K aligned
-	 * 2) The video firmware must exist at a lower address than
-	 *	all other video allocations
-	 * 3) Video allocations cannot be more than 256MB away from the
-	 *	firmware
-	 *
-	 * Splitting the video pools makes sure that firmware will
-	 * always be lower than regular allocations and the maximum
-	 * size of 256MB will be enforced.
+	 * Video can only access first 256MB of memory
+	 * dedicated pool for such allocations
 	 */
-	[VIDEO_FIRMWARE_POOL] = {
-		.paddr	= SZ_128K,
-		.size	= SZ_16M - SZ_128K,
-	},
-	[VIDEO_ALLOC_POOL] = {
-		.paddr	= SZ_16M,
-		.size	= SZ_256M - SZ_16M - SZ_128K,
+		{
+			.paddr	= SZ_16M,
+			.size	= SZ_256M - SZ_16M,
+		},
+	[HIGH_POOL] =
+	/* Remaining address space up to 2G */
+		{
+			.paddr	= SZ_256M,
+			.size	= SZ_2G - SZ_256M,
+		}
+};
+
+
+static struct msm_iommu_domain msm_iommu_domains[] = {
+	[GLOBAL_DOMAIN] = {
+		.iova_pools = global_pools,
+		.npools = ARRAY_SIZE(global_pools),
 	}
 };
 
-static struct msm_iommu_domain msm_iommu_subsystems[] = {
-	[MSM_SUBSYSTEM_VIDEO]	= {
-		.domain_idx	= VIDEO_DOMAIN,
-		.iova_pool_idx	= VIDEO_ALLOC_POOL,
-	},
-	[MSM_SUBSYSTEM_VIDEO_FWARE]	= {
-		.domain_idx	= VIDEO_DOMAIN,
-		.iova_pool_idx	= VIDEO_FIRMWARE_POOL,
-	},
-	[MSM_SUBSYSTEM_CAMERA]	= {
-		.domain_idx	= GLOBAL_DOMAIN,
-		.iova_pool_idx	= GLOBAL_MEMORY_POOL,
-	},
-	[MSM_SUBSYSTEM_DISPLAY]	= {
-		.domain_idx	= GLOBAL_DOMAIN,
-		.iova_pool_idx	= GLOBAL_MEMORY_POOL,
-	},
-	[MSM_SUBSYSTEM_ROTATOR]	= {
-		.domain_idx	= GLOBAL_DOMAIN,
-		.iova_pool_idx	= GLOBAL_MEMORY_POOL,
-	},
-};
-
-struct iommu_domain *msm_subsystem_get_domain(int subsys_id)
+struct iommu_domain *msm_get_iommu_domain(int domain_num)
 {
-	int id = msm_iommu_subsystems[subsys_id].domain_idx;
-
-	return msm_iommu_domains[id];
+	if (domain_num >= 0 && domain_num < MAX_DOMAINS)
+		return msm_iommu_domains[domain_num].domain;
+	else
+		return NULL;
 }
 
-struct mem_pool *msm_subsystem_get_pool(int subsys_id)
+unsigned long msm_subsystem_get_domain_no(int subsys_id)
 {
-	int id = msm_iommu_subsystems[subsys_id].iova_pool_idx;
+	return GLOBAL_DOMAIN;
+}
 
-	return &msm_iommu_iova_pools[id];
+unsigned long msm_subsystem_get_partition_no(int subsys_id)
+{
+	switch (subsys_id) {
+	case MSM_SUBSYSTEM_VIDEO_FWARE:
+		return VIDEO_FIRMWARE_POOL;
+	case MSM_SUBSYSTEM_VIDEO:
+		return LOW_256MB_POOL;
+	case MSM_SUBSYSTEM_CAMERA:
+	case MSM_SUBSYSTEM_DISPLAY:
+	case MSM_SUBSYSTEM_ROTATOR:
+		return HIGH_POOL;
+	default:
+		return 0xFFFFFFFF;
+	}
+}
+
+unsigned long msm_allocate_iova_address(unsigned int iommu_domain,
+					unsigned int partition_no,
+					unsigned long size,
+					unsigned long align)
+{
+	struct mem_pool *pool;
+	unsigned long iova;
+
+	if (iommu_domain >= MAX_DOMAINS)
+		return 0;
+
+	if (partition_no >= msm_iommu_domains[iommu_domain].npools)
+		return 0;
+
+	pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+
+	if (!pool->gpool)
+		return 0;
+
+	iova = gen_pool_alloc_aligned(pool->gpool, size, ilog2(align));
+	if (iova)
+		pool->free -= size;
+
+	return iova;
+}
+
+void msm_free_iova_address(unsigned long iova,
+			   unsigned int iommu_domain,
+			   unsigned int partition_no,
+			   unsigned long size)
+{
+	struct mem_pool *pool;
+
+	if (iommu_domain >= MAX_DOMAINS) {
+		WARN(1, "Invalid domain %d\n", iommu_domain);
+		return;
+	}
+
+	if (partition_no >= msm_iommu_domains[iommu_domain].npools) {
+		WARN(1, "Invalid partition %d for domain %d\n",
+			partition_no, iommu_domain);
+		return;
+	}
+
+	pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+
+	if (!pool)
+		return;
+
+	pool->free += size;
+	gen_pool_free(pool->gpool, iova, size);
+}
+
+int msm_use_iommu()
+{
+	/*
+	 * For now, just detect if the iommu is attached.
+	 */
+	return iommu_found();
 }
 
 static int __init msm_subsystem_iommu_init(void)
 {
-	int i;
+	int i, j;
 
-	for (i = 0; i < (ARRAY_SIZE(msm_iommu_domains) - 1); i++)
-		msm_iommu_domains[i] = iommu_domain_alloc(0);
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_iova_pools); i++) {
-		mutex_init(&msm_iommu_iova_pools[i].pool_mutex);
-		msm_iommu_iova_pools[i].gpool = gen_pool_create(PAGE_SHIFT, -1);
-
-		if (!msm_iommu_iova_pools[i].gpool) {
-			pr_err("%s: could not allocate iova pool. iommu"
-				" programming will not work with iova space"
-				" %d\n", __func__, i);
+	for (i = 0; i < ARRAY_SIZE(msm_iommu_domains); i++) {
+		msm_iommu_domains[i].domain = iommu_domain_alloc(0);
+		if (!msm_iommu_domains[i].domain)
 			continue;
-		}
 
-		if (gen_pool_add(msm_iommu_iova_pools[i].gpool,
-				msm_iommu_iova_pools[i].paddr,
-				msm_iommu_iova_pools[i].size,
-				-1)) {
-			pr_err("%s: could not add memory to iova pool. iommu"
-				" programming will not work with iova space"
-				" %d\n", __func__, i);
-			gen_pool_destroy(msm_iommu_iova_pools[i].gpool);
-			msm_iommu_iova_pools[i].gpool = NULL;
-			continue;
+		for (j = 0; j < msm_iommu_domains[i].npools; j++) {
+			struct mem_pool *pool = &msm_iommu_domains[i].
+							iova_pools[j];
+			mutex_init(&pool->pool_mutex);
+			pool->gpool = gen_pool_create(PAGE_SHIFT, -1);
+
+			if (!pool->gpool) {
+				pr_err("%s: domain %d: could not allocate iova"
+					" pool. iommu programming will not work"
+					" with iova space %d\n", __func__,
+					i, j);
+				continue;
+			}
+
+			if (gen_pool_add(pool->gpool, pool->paddr, pool->size,
+						-1)) {
+				pr_err("%s: domain %d: could not add memory to"
+					" iova pool. iommu programming will not"
+					" work with iova space %d\n", __func__,
+					i, j);
+				gen_pool_destroy(pool->gpool);
+				pool->gpool = NULL;
+				continue;
+			}
 		}
 	}
 
@@ -235,15 +295,15 @@
 
 		domain_idx = msm_iommu_ctx_names[i].domain;
 
-		if (!msm_iommu_domains[domain_idx])
+		if (!msm_iommu_domains[domain_idx].domain)
 			continue;
 
-		if (iommu_attach_device(msm_iommu_domains[domain_idx], ctx)) {
-			pr_err("%s: could not attach domain %d to context %s."
+		if (iommu_attach_device(msm_iommu_domains[domain_idx].domain,
+					ctx)) {
+			WARN(1, "%s: could not attach domain %d to context %s."
 				" iommu programming will not occur.\n",
 				__func__, domain_idx,
 				msm_iommu_ctx_names[i].name);
-			msm_iommu_subsystems[i].domain_idx = EMPTY_DOMAIN;
 			continue;
 		}
 	}
diff --git a/arch/arm/mach-msm/mdm.c b/arch/arm/mach-msm/mdm.c
index 9fa1a4a..01cc48a 100644
--- a/arch/arm/mach-msm/mdm.c
+++ b/arch/arm/mach-msm/mdm.c
@@ -119,6 +119,9 @@
 
 	CHARM_DBG("%s: setting AP2MDM_ERRFATAL high for a non graceful reset\n",
 			 __func__);
+	if (get_restart_level() == RESET_SOC)
+		pm8058_stay_on();
+
 	charm_disable_irqs();
 	gpio_set_value(AP2MDM_ERRFATAL, 1);
 	gpio_set_value(AP2MDM_WAKEUP, 1);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
index 56bc71d..7b9a16e 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
@@ -412,8 +412,16 @@
 	struct msm_bus_client *client = NULL;
 	int i;
 	int src, dest, nfab;
+	struct msm_bus_fabric_device *deffab;
+
+	deffab = msm_bus_get_fabric_device(MSM_BUS_FAB_DEFAULT);
+	if (!deffab) {
+		MSM_BUS_ERR("Error finding default fabric\n");
+		return -ENXIO;
+	}
+
 	nfab = msm_bus_get_num_fab();
-	if (nfab < NUM_FAB) {
+	if (nfab < deffab->board_algo->board_nfab) {
 		MSM_BUS_ERR("Can't register client!\n"
 				"Num of fabrics up: %d\n",
 				nfab);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
index fde2322..ff2876c 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
@@ -23,6 +23,7 @@
 
 #define NMASTERS 39
 #define NSLAVES 67
+#define NFAB_8660 5
 
 enum msm_bus_fabric_tiered_slave_type {
 	MSM_BUS_SYSTEM_TIERED_SLAVE_FAB_APPSS = 1,
@@ -830,6 +831,7 @@
 }
 
 static struct msm_bus_board_algorithm msm_bus_board_algo = {
+	.board_nfab = NFAB_8660,
 	.get_iid = msm_bus_board_8660_get_iid,
 	.assign_iids = msm_bus_board_assign_iids,
 };
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
index 47f3c81..1dda082 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
@@ -23,6 +23,7 @@
 
 #define NMASTERS 45
 #define NSLAVES 75
+#define NFAB_8960 5
 
 enum msm_bus_fabric_tiered_slave_type {
 	MSM_BUS_SYSTEM_TIERED_SLAVE_FAB_APPSS_0 = 1,
@@ -863,6 +864,7 @@
 }
 
 static struct msm_bus_board_algorithm msm_bus_board_algo = {
+	.board_nfab = NFAB_8960,
 	.get_iid = msm_bus_board_8960_get_iid,
 	.assign_iids = msm_bus_board_assign_iids,
 };
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index 8a46026..c4c01e8 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -134,6 +134,7 @@
 };
 
 struct msm_bus_board_algorithm {
+	const int board_nfab;
 	void (*assign_iids)(struct msm_bus_fabric_registration *fabreg,
 		int fabid);
 	int (*get_iid)(int id);
diff --git a/arch/arm/mach-msm/qdsp6v2/pcm_out.c b/arch/arm/mach-msm/qdsp6v2/pcm_out.c
index 75975cc..a4a6b72 100644
--- a/arch/arm/mach-msm/qdsp6v2/pcm_out.c
+++ b/arch/arm/mach-msm/qdsp6v2/pcm_out.c
@@ -380,7 +380,7 @@
 	while (count > 0) {
 		rc = wait_event_timeout(pcm->write_wait,
 				(atomic_read(&pcm->out_count) ||
-				atomic_read(&pcm->out_stopped)), 5 * HZ);
+				atomic_read(&pcm->out_stopped)), 1 * HZ);
 		if (!rc) {
 			pr_err("%s: wait_event_timeout failed for session %d\n",
 				__func__, pcm->ac->session);
diff --git a/arch/arm/mach-msm/subsystem_map.c b/arch/arm/mach-msm/subsystem_map.c
index 41d8072..11fe26c 100644
--- a/arch/arm/mach-msm/subsystem_map.c
+++ b/arch/arm/mach-msm/subsystem_map.c
@@ -208,58 +208,18 @@
 	return 0;
 }
 
-static unsigned long allocate_iova_address(unsigned long size,
-					int subsys_id,
-					unsigned long align)
-{
-	struct mem_pool *pool = msm_subsystem_get_pool(subsys_id);
-	unsigned long iova;
-
-	iova = gen_pool_alloc_aligned(pool->gpool, size, ilog2(align));
-	if (iova)
-		pool->free -= size;
-
-	return iova;
-}
-
-static void free_iova_address(unsigned long iova,
-			unsigned long size,
-			int subsys_id)
-{
-	struct mem_pool *pool = msm_subsystem_get_pool(subsys_id);
-
-	pool->free += size;
-	gen_pool_free(pool->gpool, iova, size);
-}
-
-static int subsys_validate(int subsys_id)
-{
-	struct mem_pool *pool;
-	struct iommu_domain *subsys_domain;
-
-	if (!msm_subsystem_check_id(subsys_id)) {
-		WARN(1, "subsystem id is not valid. Caller should check this.");
-		return 0;
-	}
-
-	pool = msm_subsystem_get_pool(subsys_id);
-	subsys_domain = msm_subsystem_get_domain(subsys_id);
-
-	return subsys_domain && pool && pool->gpool;
-}
-
 phys_addr_t msm_subsystem_check_iova_mapping(int subsys_id, unsigned long iova)
 {
 	struct iommu_domain *subsys_domain;
 
-	if (!subsys_validate(subsys_id))
+	if (!msm_use_iommu())
 		/*
-		 * If the subsystem is not valid, assume a phys = iova
-		 * mapping. Just return the iova in this case.
+		 * If there is no iommu, Just return the iova in this case.
 		 */
 		return iova;
 
-	subsys_domain = msm_subsystem_get_domain(subsys_id);
+	subsys_domain = msm_get_iommu_domain(msm_subsystem_get_domain_no
+								(subsys_id));
 
 	return iommu_iova_to_phys(subsys_domain, iova);
 }
@@ -355,15 +315,29 @@
 		min_align = flags & ~(SZ_4K - 1);
 
 		for (i = 0; i < nsubsys; i++) {
-			if (!subsys_validate(subsys_ids[i])) {
+			unsigned int domain_no, partition_no;
+
+			if (!msm_use_iommu()) {
 				buf->iova[i] = phys;
 				continue;
 			}
 
-			d = msm_subsystem_get_domain(subsys_ids[i]);
+			d = msm_get_iommu_domain(
+				msm_subsystem_get_domain_no(subsys_ids[i]));
 
-			iova_start = allocate_iova_address(length,
-						subsys_ids[i],
+			if (!d) {
+				pr_err("%s: could not get domain for subsystem"
+					" %d\n", __func__, subsys_ids[i]);
+				continue;
+			}
+
+			domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
+			partition_no = msm_subsystem_get_partition_no(
+								subsys_ids[i]);
+
+			iova_start = msm_allocate_iova_address(domain_no,
+						partition_no,
+						length,
 						max(min_align, SZ_4K));
 
 			if (!iova_start) {
@@ -410,19 +384,26 @@
 		iommu_unmap(d, temp_va, get_order(SZ_4K));
 outdomain:
 	if (flags & MSM_SUBSYSTEM_MAP_IOVA) {
+		/* Unmap the rest of the current domain, i */
 		for (j -= SZ_4K, temp_va -= SZ_4K;
 			j > 0; temp_va -= SZ_4K, j -= SZ_4K)
 			iommu_unmap(d, temp_va, get_order(SZ_4K));
 
+		/* Unmap all the other domains */
 		for (i--; i >= 0; i--) {
-			if (!subsys_validate(subsys_ids[i]))
+			unsigned int domain_no, partition_no;
+			if (!msm_use_iommu())
 				continue;
+			domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
+			partition_no = msm_subsystem_get_partition_no(
+								subsys_ids[i]);
 
 			temp_va = buf->iova[i];
 			for (j = length; j > 0; j -= SZ_4K,
 						temp_va += SZ_4K)
 				iommu_unmap(d, temp_va, get_order(SZ_4K));
-			free_iova_address(buf->iova[i], length, subsys_ids[i]);
+			msm_free_iova_address(buf->iova[i], domain_no,
+					partition_no, length);
 		}
 
 		kfree(buf->iova);
@@ -464,25 +445,32 @@
 	}
 
 	if (buf->iova) {
-		for (i = 0; i < node->nsubsys; i++) {
-			struct iommu_domain *subsys_domain;
+		if (msm_use_iommu())
+			for (i = 0; i < node->nsubsys; i++) {
+				struct iommu_domain *subsys_domain;
+				unsigned int domain_no, partition_no;
 
-			if (!subsys_validate(node->subsystems[i]))
-				continue;
+				subsys_domain = msm_get_iommu_domain(
+						msm_subsystem_get_domain_no(
+						node->subsystems[i]));
 
-			subsys_domain = msm_subsystem_get_domain(
+				domain_no = msm_subsystem_get_domain_no(
 							node->subsystems[i]);
-			temp_va = buf->iova[i];
-			for (j = node->length; j > 0; j -= SZ_4K,
-				temp_va += SZ_4K) {
-				ret = iommu_unmap(subsys_domain, temp_va,
+				partition_no = msm_subsystem_get_partition_no(
+							node->subsystems[i]);
+
+				temp_va = buf->iova[i];
+				for (j = node->length; j > 0; j -= SZ_4K,
+					temp_va += SZ_4K) {
+					ret = iommu_unmap(subsys_domain,
+							temp_va,
 							get_order(SZ_4K));
-				WARN(ret, "iommu_unmap returned a non-zero"
-						" value.\n");
+					WARN(ret, "iommu_unmap returned a "
+						" non-zero value.\n");
+				}
+				msm_free_iova_address(buf->iova[i], domain_no,
+						partition_no, node->length);
 			}
-			free_iova_address(buf->iova[i], node->length,
-							node->subsystems[i]);
-		}
 		kfree(buf->iova);
 
 	}
diff --git a/drivers/media/radio/radio-iris-transport.c b/drivers/media/radio/radio-iris-transport.c
index 6628c9d..50ca58c 100644
--- a/drivers/media/radio/radio-iris-transport.c
+++ b/drivers/media/radio/radio-iris-transport.c
@@ -51,13 +51,13 @@
 	len = smd_read_avail(hsmd->fm_channel);
 
 	while (len) {
-		skb = alloc_skb(len, GFP_KERNEL);
+		skb = alloc_skb(len, GFP_ATOMIC);
 		if (!skb) {
 			FMDERR("Memory not allocated for the socket");
 			return;
 		}
 
-		buf = kmalloc(len, GFP_KERNEL);
+		buf = kmalloc(len, GFP_ATOMIC);
 		if (!buf) {
 			kfree_skb(skb);
 			FMDERR("Error in allocating buffer memory");
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 6181758..ce13d27 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1024,8 +1024,6 @@
 
 	if (data->flags & MMC_DATA_READ)
 		datactrl |= (MCI_DPSM_DIRECTION | MCI_RX_DATA_PEND);
-	else if (data->flags & MMC_DATA_WRITE)
-		datactrl |= MCI_DATA_PEND;
 
 	clks = (unsigned long long)data->timeout_ns * host->clk_rate;
 	do_div(clks, 1000000000UL);
@@ -1364,6 +1362,9 @@
 			msmsdcc_start_command(host, host->curr.mrq->cmd, 0);
 		else
 			msmsdcc_request_start(host, host->curr.mrq);
+	} else if (cmd->data) {
+		if (!(cmd->data->flags & MMC_DATA_READ))
+			msmsdcc_start_data(host, cmd->data, NULL, 0);
 	}
 }
 
@@ -1570,9 +1571,9 @@
 static void
 msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq)
 {
-	if (mrq->data) {
+	if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
 		/* Queue/read data, daisy-chain command when data starts */
-		if (mrq->sbc && (mrq->data->flags & MMC_DATA_READ))
+		if (mrq->sbc)
 			msmsdcc_start_data(host, mrq->data, mrq->sbc, 0);
 		else
 			msmsdcc_start_data(host, mrq->data, mrq->cmd, 0);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 590c293..12aa54b 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -77,7 +77,6 @@
 #define MCI_DPSM_DIRECTION	(1 << 1)
 #define MCI_DPSM_MODE		(1 << 2)
 #define MCI_DPSM_DMAENABLE	(1 << 3)
-#define MCI_DATA_PEND		(1 << 17)
 #define MCI_AUTO_PROG_DONE	(1 << 19)
 #define MCI_RX_DATA_PEND	(1 << 20)
 
diff --git a/drivers/power/isl9519q.c b/drivers/power/isl9519q.c
index 733de45..e4729f2 100644
--- a/drivers/power/isl9519q.c
+++ b/drivers/power/isl9519q.c
@@ -60,6 +60,8 @@
 	bool				trickle;
 };
 
+static struct isl9519q_struct *the_isl_chg;
+
 static int isl9519q_read_reg(struct i2c_client *client, int reg,
 	u16 *val)
 {
@@ -485,6 +487,71 @@
 
 	return 0;
 }
+static int set_reg(void *data, u64 val)
+{
+	int addr = (int)data;
+	int ret;
+	u16 temp;
+
+	temp = (u16) val;
+	ret = isl9519q_write_reg(the_isl_chg->client, addr, temp);
+
+	if (ret) {
+		pr_err("isl9519q_write_reg to %x value =%d errored = %d\n",
+			addr, temp, ret);
+		return -EAGAIN;
+	}
+	return 0;
+}
+static int get_reg(void *data, u64 *val)
+{
+	int addr = (int)data;
+	int ret;
+	u16 temp;
+
+	ret = isl9519q_read_reg(the_isl_chg->client, addr, &temp);
+	if (ret) {
+		pr_err("isl9519q_read_reg to %x value =%d errored = %d\n",
+			addr, temp, ret);
+		return -EAGAIN;
+	}
+
+	*val = temp;
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_reg, set_reg, "0x%02llx\n");
+
+static void create_debugfs_entries(struct isl9519q_struct *isl_chg)
+{
+	isl_chg->dent = debugfs_create_dir("isl9519q", NULL);
+
+	if (IS_ERR(isl_chg->dent)) {
+		pr_err("isl9519q driver couldn't create debugfs dir\n");
+		return;
+	}
+
+	debugfs_create_file("CHG_CURRENT_REG", 0644, isl_chg->dent,
+				(void *) CHG_CURRENT_REG, &reg_fops);
+	debugfs_create_file("MAX_SYS_VOLTAGE_REG", 0644, isl_chg->dent,
+				(void *) MAX_SYS_VOLTAGE_REG, &reg_fops);
+	debugfs_create_file("CONTROL_REG", 0644, isl_chg->dent,
+				(void *) CONTROL_REG, &reg_fops);
+	debugfs_create_file("MIN_SYS_VOLTAGE_REG", 0644, isl_chg->dent,
+				(void *) MIN_SYS_VOLTAGE_REG, &reg_fops);
+	debugfs_create_file("INPUT_CURRENT_REG", 0644, isl_chg->dent,
+				(void *) INPUT_CURRENT_REG, &reg_fops);
+	debugfs_create_file("MANUFACTURER_ID_REG", 0644, isl_chg->dent,
+				(void *) MANUFACTURER_ID_REG, &reg_fops);
+	debugfs_create_file("DEVICE_ID_REG", 0644, isl_chg->dent,
+				(void *) DEVICE_ID_REG, &reg_fops);
+}
+
+static void remove_debugfs_entries(struct isl9519q_struct *isl_chg)
+{
+	if (isl_chg->dent)
+		debugfs_remove_recursive(isl_chg->dent);
+}
 
 static int __devinit isl9519q_probe(struct i2c_client *client,
 				    const struct i2c_device_id *id)
@@ -582,6 +649,9 @@
 	if (ret)
 		goto free_isl_chg;
 
+	the_isl_chg = isl_chg;
+	create_debugfs_entries(isl_chg);
+
 	pr_info("%s OK.\n", __func__);
 
 	return 0;
@@ -603,6 +673,9 @@
 	cancel_delayed_work_sync(&isl_chg->charge_work);
 	msm_charger_notify_event(&isl_chg->adapter_hw_chg, CHG_REMOVED_EVENT);
 	msm_charger_unregister(&isl_chg->adapter_hw_chg);
+	remove_debugfs_entries(isl_chg);
+	the_isl_chg = NULL;
+	kfree(isl_chg);
 	return 0;
 }
 
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 093a170..350f286 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -65,9 +65,10 @@
 
 #define ULPI_IO_TIMEOUT_USEC	(10 * 1000)
 
-#define USB_PHY_VDD_DIG_VOL_MIN	1000000 /* uV */
-#define USB_PHY_VDD_DIG_VOL_MAX	1320000 /* uV */
-#define USB_PHY_VDD_DIG_LOAD	49360	/* uA */
+#define USB_PHY_VDD_DIG_VOL_SUSP_MIN	500000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MIN		1000000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX		1320000 /* uV */
+#define USB_PHY_VDD_DIG_LOAD		49360	/* uA */
 
 static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
 {
@@ -431,6 +432,12 @@
 				"TCXO D1 buffer%d\n", __func__, ret);
 	}
 
+	ret = regulator_set_voltage(mehci->hsic_vddcx,
+				USB_PHY_VDD_DIG_VOL_SUSP_MIN,
+				USB_PHY_VDD_DIG_VOL_MAX);
+	if (ret < 0)
+		dev_err(mehci->dev, "unable to set vddcx voltage: min:0.5v max:1.3v\n");
+
 	atomic_set(&mehci->in_lpm, 1);
 	enable_irq(hcd->irq);
 	wake_unlock(&mehci->wlock);
@@ -454,6 +461,12 @@
 
 	wake_lock(&mehci->wlock);
 
+	ret = regulator_set_voltage(mehci->hsic_vddcx,
+				USB_PHY_VDD_DIG_VOL_MIN,
+				USB_PHY_VDD_DIG_VOL_MAX);
+	if (ret < 0)
+		dev_err(mehci->dev, "unable to set vddcx voltage: min:1v max:1.3v\n");
+
 	pdata = mehci->dev->platform_data;
 	if (pdata->hub_reset) {
 		ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_ON);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 6c60cc9..7f1641f 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -600,6 +600,9 @@
 	if (motg->core_clk)
 		clk_disable(motg->core_clk);
 
+	if (!IS_ERR(motg->system_clk))
+		clk_disable(motg->system_clk);
+
 	if (!IS_ERR(motg->pclk_src))
 		clk_disable(motg->pclk_src);
 
@@ -642,6 +645,9 @@
 	if (!IS_ERR(motg->pclk_src))
 		clk_enable(motg->pclk_src);
 
+	if (!IS_ERR(motg->system_clk))
+		clk_enable(motg->system_clk);
+
 	clk_enable(motg->pclk);
 	if (motg->core_clk)
 		clk_enable(motg->core_clk);
@@ -2070,6 +2076,8 @@
 	clk_disable(motg->pclk);
 	if (motg->core_clk)
 		clk_disable(motg->core_clk);
+	if (!IS_ERR(motg->system_clk))
+		clk_disable(motg->system_clk);
 	if (!IS_ERR(motg->pclk_src)) {
 		clk_disable(motg->pclk_src);
 		clk_put(motg->pclk_src);