msm: acpuclock-8226: Use gpll0 during power collapse.

Change the source used while going into power collapse to gpll0. This
also requires gpll0 to be always on when linux is on, since clocks
cannot be prepared/unprepared in the atomic power collapse path.

Change-Id: Id4beb86df6e5310ab8d6b2aca5209fa7d3ede475
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index 6e93c57..799d629 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/cpr-regulator.h>
@@ -82,17 +83,21 @@
 		.update_mask = RCG_CONFIG_UPDATE_BIT,
 		.poll_mask = RCG_CONFIG_UPDATE_BIT,
 	},
+	.power_collapse_khz = 300000,
+	.wait_for_irq_khz = 300000,
 };
 
 static int __init acpuclk_a7_probe(struct platform_device *pdev)
 {
 	struct resource *res;
+	u32 i;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rcg_base");
 	if (!res)
 		return -EINVAL;
 
-	drv_data.apcs_rcg_cmd = ioremap(res->start, resource_size(res));
+	drv_data.apcs_rcg_cmd = devm_ioremap(&pdev->dev, res->start,
+		resource_size(res));
 	if (!drv_data.apcs_rcg_cmd)
 		return -ENOMEM;
 
@@ -110,6 +115,21 @@
 		return PTR_ERR(drv_data.vdd_mem);
 	}
 
+	for (i = 0; i < NUM_SRC; i++) {
+		if (!drv_data.src_clocks[i].name)
+			continue;
+		drv_data.src_clocks[i].clk =
+			devm_clk_get(&pdev->dev, drv_data.src_clocks[i].name);
+		if (IS_ERR(drv_data.src_clocks[i].clk)) {
+			dev_err(&pdev->dev, "Unable to get clock %s\n",
+				drv_data.src_clocks[i].name);
+			return -EPROBE_DEFER;
+		}
+	}
+
+	/* Enable the always on source */
+	clk_prepare_enable(drv_data.src_clocks[PLL0].clk);
+
 	return acpuclk_cortex_init(pdev, &drv_data);
 }
 
diff --git a/arch/arm/mach-msm/acpuclock-9625.c b/arch/arm/mach-msm/acpuclock-9625.c
index 34952fb..42659f9 100644
--- a/arch/arm/mach-msm/acpuclock-9625.c
+++ b/arch/arm/mach-msm/acpuclock-9625.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/errno.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
@@ -80,18 +81,21 @@
 		.update_mask = RCG_CONFIG_PGM_DATA_BIT | RCG_CONFIG_PGM_ENA_BIT,
 		.poll_mask = RCG_CONFIG_PGM_DATA_BIT,
 	},
+	.power_collapse_khz = 19200,
+	.wait_for_irq_khz = 19200,
 };
 
 static int __init acpuclk_9625_probe(struct platform_device *pdev)
 {
 	struct resource *res;
-	u32 regval;
+	u32 regval, i;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rcg_base");
 	if (!res)
 		return -EINVAL;
 
-	drv_data.apcs_rcg_config = ioremap(res->start, resource_size(res));
+	drv_data.apcs_rcg_config = devm_ioremap(&pdev->dev, res->start,
+		resource_size(res));
 	if (!drv_data.apcs_rcg_config)
 		return -ENOMEM;
 
@@ -117,6 +121,18 @@
 		return PTR_ERR(drv_data.vdd_mem);
 	}
 
+	for (i = 0; i < NUM_SRC; i++) {
+		if (!drv_data.src_clocks[i].name)
+			continue;
+		drv_data.src_clocks[i].clk =
+			devm_clk_get(&pdev->dev, drv_data.src_clocks[i].name);
+		if (IS_ERR(drv_data.src_clocks[i].clk)) {
+			dev_err(&pdev->dev, "Unable to get clock %s\n",
+				drv_data.src_clocks[i].name);
+			return -EPROBE_DEFER;
+		}
+	}
+
 	/* Disable hardware gating of gpll0 to A5SS */
 	regval = readl_relaxed(drv_data.apcs_cpu_pwr_ctl);
 	regval |= GPLL0_TO_A5_ALWAYS_ENABLE;
diff --git a/arch/arm/mach-msm/acpuclock-cortex.c b/arch/arm/mach-msm/acpuclock-cortex.c
index 88bf919..ca7fc2b 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.c
+++ b/arch/arm/mach-msm/acpuclock-cortex.c
@@ -317,8 +317,6 @@
 static struct acpuclk_data acpuclk_cortex_data = {
 	.set_rate = acpuclk_cortex_set_rate,
 	.get_rate = acpuclk_cortex_get_rate,
-	.power_collapse_khz = 19200,
-	.wait_for_irq_khz = 19200,
 };
 
 int __init acpuclk_cortex_init(struct platform_device *pdev,
@@ -330,20 +328,15 @@
 	priv = data;
 	mutex_init(&priv->lock);
 
+	acpuclk_cortex_data.power_collapse_khz = priv->wait_for_irq_khz;
+	acpuclk_cortex_data.wait_for_irq_khz = priv->wait_for_irq_khz;
+
 	bus_perf_client = msm_bus_scale_register_client(priv->bus_scale);
 	if (!bus_perf_client) {
 		pr_err("Unable to register bus client\n");
 		BUG();
 	}
 
-	for (i = 0; i < NUM_SRC; i++) {
-		if (!priv->src_clocks[i].name)
-			continue;
-		priv->src_clocks[i].clk =
-			devm_clk_get(&pdev->dev, priv->src_clocks[i].name);
-		BUG_ON(IS_ERR(priv->src_clocks[i].clk));
-	}
-
 	/* Improve boot time by ramping up CPU immediately */
 	for (i = 0; priv->freq_tbl[i].khz != 0; i++)
 		if (priv->freq_tbl[i].use_for_scaling)
diff --git a/arch/arm/mach-msm/acpuclock-cortex.h b/arch/arm/mach-msm/acpuclock-cortex.h
index 2db3987..89a0a84 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.h
+++ b/arch/arm/mach-msm/acpuclock-cortex.h
@@ -63,6 +63,8 @@
 	unsigned long			vdd_max_mem;
 	struct src_clock		src_clocks[NUM_SRC];
 	struct acpuclk_reg_data		reg_data;
+	unsigned long                   power_collapse_khz;
+	unsigned long                   wait_for_irq_khz;
 };
 
 /* Instantaneous bandwidth requests in MB/s. */