From: luowei <lw@rock-chips.com>
Date: Tue, 19 Apr 2011 06:04:03 +0000 (+0800)
Subject: add timed gpio support for A22
X-Git-Tag: firefly_0821_release~10452
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6b51c6ed3b3a0c27981892ba4226d9a9f99ca044;p=firefly-linux-kernel-4.4.55.git

add timed gpio support for A22
---

diff --git a/arch/arm/mach-rk29/board-rk29-a22.c b/arch/arm/mach-rk29/board-rk29-a22.c
index 6c15a30e7e15..449a103e24e6 100755
--- a/arch/arm/mach-rk29/board-rk29-a22.c
+++ b/arch/arm/mach-rk29/board-rk29-a22.c
@@ -62,6 +62,7 @@
 #endif
 
 #include "../../../drivers/headset_observe/rk_headset.h"
+#include "../../../drivers/staging/android/timed_gpio.h"
 /*set touchscreen different type header*/
 #if defined(CONFIG_TOUCHSCREEN_XPT2046_NORMAL_SPI)
 #include "../../../drivers/input/touchscreen/xpt2046_ts.h"
@@ -2487,8 +2488,37 @@ static struct platform_device rk29_device_keys = {
 };
 #endif
 
+#if CONFIG_ANDROID_TIMED_GPIO
+static struct timed_gpio timed_gpios[] = {
+	{
+		.name = "vibrator",
+		.gpio = RK29_PIN1_PB5,
+		.max_timeout = 1000,
+		.active_low = 0,
+		.adjust_time =20,      //adjust for diff product
+	},
+};
+
+struct timed_gpio_platform_data rk29_vibrator_info = {
+	.num_gpios = 1,
+	.gpios = timed_gpios,
+};
+
+struct platform_device rk29_device_vibrator ={
+	.name = "timed-gpio",
+	.id = -1,
+	.dev = {
+		.platform_data = &rk29_vibrator_info,
+		},
+
+};
+#endif 
+
 static void __init rk29_board_iomux_init(void)
 {
+	#if CONFIG_ANDROID_TIMED_GPIO
+	rk29_mux_api_set(GPIO1B5_PWM0_NAME, GPIO1L_GPIO1B5);//for timed gpio
+	#endif
 	#ifdef CONFIG_RK29_PWM_REGULATOR
 	rk29_mux_api_set(REGULATOR_PWM_MUX_NAME,REGULATOR_PWM_MUX_MODE);
 	#endif
@@ -2618,6 +2648,9 @@ static struct platform_device *devices[] __initdata = {
 #ifdef CONFIG_RK29_GPS
 	&rk29_device_gps,
 #endif
+#ifdef CONFIG_ANDROID_TIMED_GPIO
+	&rk29_device_vibrator,
+#endif
 };
 
 #ifdef CONFIG_RK29_VMAC
diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c
old mode 100644
new mode 100755
index 15aee9180659..bb6c212f8674
--- a/drivers/staging/android/timed_gpio.c
+++ b/drivers/staging/android/timed_gpio.c
@@ -19,15 +19,12 @@
 #include <linux/hrtimer.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
-
+#include <linux/wakelock.h>
+#include <linux/delay.h>
 #include "timed_output.h"
 #include "timed_gpio.h"
 
-#if defined(CONFIG_MACH_RAHO)||defined(CONFIG_MACH_RAHOSDK)
-#define GPIO_TYPE   1       //ʹÓÃFPGAÀ©Õ¹µÄIO²»ÄÜʹÓÃÖжÏÄÚ²¿Ö±½Ó²Ù×÷IO
-#else
-#define GPIO_TYPE   0
-#endif
+#define GPIO_TYPE   0 
 
 struct timed_gpio_data {
 	struct timed_output_dev dev;
@@ -36,17 +33,27 @@ struct timed_gpio_data {
 	unsigned 	gpio;
 	int 		max_timeout;
 	u8 		active_low;
+	int             adjust_time;
 #if (GPIO_TYPE == 1)
 	struct work_struct 	timed_gpio_work;	
 #endif
+	struct wake_lock 	irq_wake;
 };
 
 #if (GPIO_TYPE == 1)
 static void timed_gpio_work_handler(struct work_struct *work)
 {
-    struct timed_gpio_data *data =
+	struct timed_gpio_data *data =
 		container_of(work, struct timed_gpio_data, timed_gpio_work);
-    gpio_direction_output(data->gpio, data->active_low ? 1 : 0);
+	int ret = 0,i = 0;
+	//set gpio several times once error happened
+	for(i=0; i<3; i++)
+	{
+		ret = gpio_direction_output(data->gpio, data->active_low ? 1 : 0);
+		if(!ret)		
+			break;
+		printk("%s:ret=%d,fail to set gpio and set again,i=%d\n",__FUNCTION__,ret,i);
+	}
 }
 #endif
 
@@ -80,23 +87,26 @@ static void gpio_enable(struct timed_output_dev *dev, int value)
 {
 	struct timed_gpio_data	*data =
 		container_of(dev, struct timed_gpio_data, dev);
-	//unsigned long	flags;
-	//spin_lock_irqsave(&data->lock, flags);
+	int ret = 0,i = 0;
 
 	/* cancel previous timer and set GPIO according to value */
 	hrtimer_cancel(&data->timer);
-	gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
-
+	//set gpio several times once error happened
+	for(i=0; i<3; i++)
+	{
+		ret = gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
+		if(!ret)		
+			break;
+		printk("%s:ret=%d,fail to set gpio and set again,i=%d\n",__FUNCTION__,ret,i);
+	}
 	if (value > 0) {
+		value += data->adjust_time;
 		if (value > data->max_timeout)
 			value = data->max_timeout;
-
 		hrtimer_start(&data->timer,
 			ktime_set(value / 1000, (value % 1000) * 1000000),
 			HRTIMER_MODE_REL);
 	}
-
-	//spin_unlock_irqrestore(&data->lock, flags);
 }
 
 static int timed_gpio_probe(struct platform_device *pdev)
@@ -144,12 +154,17 @@ static int timed_gpio_probe(struct platform_device *pdev)
 		gpio_dat->gpio = cur_gpio->gpio;
 		gpio_dat->max_timeout = cur_gpio->max_timeout;
 		gpio_dat->active_low = cur_gpio->active_low;
+		gpio_dat->adjust_time = cur_gpio->adjust_time;
 		gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low);
 	}
 #if (GPIO_TYPE == 1)
     INIT_WORK(&gpio_dat->timed_gpio_work, timed_gpio_work_handler);
 #endif    
 	platform_set_drvdata(pdev, gpio_data);
+	wake_lock_init(&gpio_data->irq_wake, WAKE_LOCK_SUSPEND, "timed_gpio_wake");
+
+	gpio_enable(&gpio_data ->dev, 100);
+	printk("%s\n",__FUNCTION__);
 
 	return 0;
 }
@@ -189,7 +204,7 @@ static void __exit timed_gpio_exit(void)
 	platform_driver_unregister(&timed_gpio_driver);
 }
 
-module_init(timed_gpio_init);
+subsys_initcall(timed_gpio_init);
 module_exit(timed_gpio_exit);
 
 MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
diff --git a/drivers/staging/android/timed_gpio.h b/drivers/staging/android/timed_gpio.h
index a0e15f8be3f7..c8487df9a109 100644
--- a/drivers/staging/android/timed_gpio.h
+++ b/drivers/staging/android/timed_gpio.h
@@ -23,6 +23,7 @@ struct timed_gpio {
 	unsigned 	gpio;
 	int		max_timeout;
 	u8 		active_low;
+	int         adjust_time;
 };
 
 struct timed_gpio_platform_data {