isa1200: Add support for pwm clk

PWM generation mode needs clk to generate internal PWM
for vibration. Add clk apis to enable/disable clock as
needed.

Change-Id: I2ba591509fc899186bf0ad7069133a9f1d0e6a42
Signed-off-by: Mohan Pallaka <mpallaka@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index e4958f5..a73ef72 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1220,6 +1220,7 @@
 	.name = "vibrator",
 	.dev_setup = isa1200_dev_setup,
 	.clk_enable = isa1200_clk_enable,
+	.need_pwm_clk = true,
 	.hap_en_gpio = ISA1200_HAP_EN_GPIO,
 	.hap_len_gpio = ISA1200_HAP_LEN_GPIO,
 	.max_timeout = 15000,
diff --git a/drivers/misc/isa1200.c b/drivers/misc/isa1200.c
index 555dfdd..6c3e787 100644
--- a/drivers/misc/isa1200.c
+++ b/drivers/misc/isa1200.c
@@ -20,6 +20,7 @@
 #include <linux/workqueue.h>
 #include <linux/slab.h>
 #include <linux/regulator/consumer.h>
+#include <linux/clk.h>
 #include <linux/i2c/isa1200.h>
 #include "../staging/android/timed_output.h"
 
@@ -48,6 +49,7 @@
 	struct regulator **regs;
 	bool clk_on;
 	u8 hctrl0_val;
+	struct clk *pwm_clk;
 };
 
 static int isa1200_read_reg(struct i2c_client *client, int reg)
@@ -107,13 +109,23 @@
 				goto chip_dwn;
 			}
 		} else if (haptic->pdata->mode_ctrl == PWM_GEN_MODE) {
-			/* vote for clock */
-			if (haptic->pdata->clk_enable && !haptic->clk_on) {
+			/* check for board specific clk callback */
+			if (haptic->pdata->clk_enable) {
 				rc = haptic->pdata->clk_enable(true);
 				if (rc < 0) {
+					pr_err("%s: clk enable cb failed\n",
+								__func__);
+					goto chip_dwn;
+				}
+			}
+
+			/* vote for clock */
+			if (haptic->pdata->need_pwm_clk && !haptic->clk_on) {
+				rc = clk_enable(haptic->pwm_clk);
+				if (rc < 0) {
 					pr_err("%s: clk enable failed\n",
 								__func__);
-					goto chip_dwn;
+					goto dis_clk_cb;
 				}
 				haptic->clk_on = true;
 			}
@@ -150,29 +162,35 @@
 				pr_err("%s: stop vibartion fail\n", __func__);
 
 			/* de-vote clock */
-			if (haptic->pdata->clk_enable && haptic->clk_on) {
-				rc = haptic->pdata->clk_enable(false);
-				if (rc < 0) {
-					pr_err("%s: clk disable failed\n",
-								__func__);
-					return;
-				}
+			if (haptic->pdata->need_pwm_clk && haptic->clk_on) {
+				clk_disable(haptic->pwm_clk);
 				haptic->clk_on = false;
 			}
+			/* check for board specific clk callback */
+			if (haptic->pdata->clk_enable) {
+				rc = haptic->pdata->clk_enable(false);
+				if (rc < 0)
+					pr_err("%s: clk disable cb failed\n",
+								__func__);
+			}
 		}
 	}
 
 	return;
 
 dis_clk:
-	if (haptic->pdata->clk_enable && haptic->clk_on) {
-		rc = haptic->pdata->clk_enable(false);
-		if (rc < 0) {
-			pr_err("%s: clk disable failed\n", __func__);
-			return;
-		}
+	if (haptic->pdata->need_pwm_clk && haptic->clk_on) {
+		clk_disable(haptic->pwm_clk);
 		haptic->clk_on = false;
 	}
+
+dis_clk_cb:
+	if (haptic->pdata->clk_enable) {
+		rc = haptic->pdata->clk_enable(false);
+		if (rc < 0)
+			pr_err("%s: clk disable cb failed\n", __func__);
+	}
+
 chip_dwn:
 	if (haptic->is_len_gpio_valid == true)
 		gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 0);
@@ -545,6 +563,13 @@
 			ret = PTR_ERR(haptic->pwm);
 			goto reset_hctrl0;
 		}
+	} else if (haptic->pdata->need_pwm_clk) {
+		haptic->pwm_clk = clk_get(&client->dev, "pwm_clk");
+		if (IS_ERR(haptic->pwm_clk)) {
+			dev_err(&client->dev, "pwm_clk get failed\n");
+			ret = PTR_ERR(haptic->pwm_clk);
+			goto reset_hctrl0;
+		}
 	}
 
 	printk(KERN_INFO "%s: %s registered\n", __func__, id->name);
diff --git a/include/linux/i2c/isa1200.h b/include/linux/i2c/isa1200.h
index 9dab3eb..ffadf96 100644
--- a/include/linux/i2c/isa1200.h
+++ b/include/linux/i2c/isa1200.h
@@ -49,6 +49,7 @@
 	bool smart_en; /* smart mode enable/disable */
 	bool is_erm;
 	bool ext_clk_en;
+	bool need_pwm_clk;
 	unsigned int chip_en;
 	unsigned int duty;
 	struct isa1200_regulator *regulator_info;