msm8960: slim: Program slimbus slew rate register

If applicable, make sure that slimbus doesn't violate slew rate spec
by programming the slimbus slew rate register

CRs-Fixed: 307733
Signed-off-by: Sagar Dharia <sdharia@codeaurora.org>
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 5eeca31..cc1264d 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1720,6 +1720,7 @@
 
 #define LPASS_SLIMBUS_PHYS	0x28080000
 #define LPASS_SLIMBUS_BAM_PHYS	0x28084000
+#define LPASS_SLIMBUS_SLEW	(MSM8960_TLMM_PHYS + 0x207C)
 /* Board info for the slimbus slave device */
 static struct resource slimbus_res[] = {
 	{
@@ -1735,6 +1736,12 @@
 		.name	= "slimbus_bam_physical",
 	},
 	{
+		.start	= LPASS_SLIMBUS_SLEW,
+		.end	= LPASS_SLIMBUS_SLEW + 4 - 1,
+		.flags	= IORESOURCE_MEM,
+		.name	= "slimbus_slew_reg",
+	},
+	{
 		.start	= SLIMBUS0_CORE_EE1_IRQ,
 		.end	= SLIMBUS0_CORE_EE1_IRQ,
 		.flags	= IORESOURCE_IRQ,
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 3678b30..1e4302b 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -204,6 +204,7 @@
 	struct slim_framer	framer;
 	struct device		*dev;
 	void __iomem		*base;
+	struct resource		*slew_mem;
 	u32			curr_bw;
 	u8			msg_cnt;
 	u32			tx_buf[10];
@@ -1463,6 +1464,40 @@
 	sps_deregister_bam_device(dev->bam.hdl);
 }
 
+static void msm_slim_prg_slew(struct platform_device *pdev,
+				struct msm_slim_ctrl *dev)
+{
+	struct resource *slew_io;
+	void __iomem *slew_reg;
+	/* SLEW RATE register for this slimbus */
+	dev->slew_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						"slimbus_slew_reg");
+	if (!dev->slew_mem) {
+		dev_dbg(&pdev->dev, "no slimbus slew resource\n");
+		return;
+	}
+	slew_io = request_mem_region(dev->slew_mem->start,
+				resource_size(dev->slew_mem), pdev->name);
+	if (!slew_io) {
+		dev_dbg(&pdev->dev, "slimbus-slew mem claimed\n");
+		dev->slew_mem = NULL;
+		return;
+	}
+
+	slew_reg = ioremap(dev->slew_mem->start, resource_size(dev->slew_mem));
+	if (!slew_reg) {
+		dev_dbg(dev->dev, "slew register mapping failed");
+		release_mem_region(dev->slew_mem->start,
+					resource_size(dev->slew_mem));
+		dev->slew_mem = NULL;
+		return;
+	}
+	writel_relaxed(1, slew_reg);
+	/* Make sure slimbus-slew rate enabling goes through */
+	wmb();
+	iounmap(slew_reg);
+}
+
 static int __devinit msm_slim_probe(struct platform_device *pdev)
 {
 	struct msm_slim_ctrl *dev;
@@ -1562,10 +1597,7 @@
 
 
 	dev->rclk = clk_get(dev->dev, "audio_slimbus_clk");
-	if (dev->rclk) {
-		clk_set_rate(dev->rclk, SLIM_ROOT_FREQ);
-		clk_enable(dev->rclk);
-	} else {
+	if (!dev->rclk) {
 		dev_err(dev->dev, "slimbus clock not found");
 		goto err_clk_get_failed;
 	}
@@ -1592,6 +1624,11 @@
 		ret = -ENOMEM;
 		goto err_sat_failed;
 	}
+
+	msm_slim_prg_slew(pdev, dev);
+	clk_set_rate(dev->rclk, SLIM_ROOT_FREQ);
+	clk_enable(dev->rclk);
+
 	dev->satd->dev = dev;
 	dev->satd->satcl.name  = "msm_sat_dev";
 	spin_lock_init(&dev->satd->lock);
@@ -1695,6 +1732,7 @@
 	struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
 	struct resource *bam_mem;
 	struct resource *slim_mem;
+	struct resource *slew_mem = dev->slew_mem;
 	struct msm_slim_sat *sat = dev->satd;
 	slim_remove_device(&sat->satcl);
 	kfree(sat->satch);
@@ -1713,6 +1751,8 @@
 						"slimbus_bam_physical");
 	if (bam_mem)
 		release_mem_region(bam_mem->start, resource_size(bam_mem));
+	if (slew_mem)
+		release_mem_region(slew_mem->start, resource_size(slew_mem));
 	slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						"slimbus_physical");
 	if (slim_mem)