From 95faacfa576e911db1752deba4aaf1af49798588 Mon Sep 17 00:00:00 2001
From: linjh <linjh@rock-chips.com>
Date: Fri, 15 Apr 2011 16:53:08 +0800
Subject: [PATCH] open uart3 and add gps module

---
 arch/arm/configs/rk29_phonesdk_defconfig |   5 +-
 arch/arm/mach-rk29/board-rk29-phonesdk.c |  40 +++---
 drivers/misc/gps/rk29_gps.c              | 167 +++++++++++++++++------
 drivers/misc/gps/rk29_gps.h              |   7 +-
 4 files changed, 152 insertions(+), 67 deletions(-)

diff --git a/arch/arm/configs/rk29_phonesdk_defconfig b/arch/arm/configs/rk29_phonesdk_defconfig
index 0e667e02e9cb..929b7a26c43a 100755
--- a/arch/arm/configs/rk29_phonesdk_defconfig
+++ b/arch/arm/configs/rk29_phonesdk_defconfig
@@ -643,7 +643,8 @@ CONFIG_MTK23D=y
 # CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
 # CONFIG_RK29_SUPPORT_MODEM is not set
-# CONFIG_RK29_GPS is not set
+CONFIG_RK29_GPS=y
+CONFIG_GPS_GNS7560=y
 
 #
 # Motion Sensors Support
@@ -928,7 +929,7 @@ CONFIG_UART0_CTS_RTS_RK29=y
 CONFIG_UART1_RK29=y
 CONFIG_UART2_RK29=y
 CONFIG_UART2_CTS_RTS_RK29=y
-# CONFIG_UART3_RK29 is not set
+CONFIG_UART3_RK29=y
 CONFIG_SERIAL_RK29_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
diff --git a/arch/arm/mach-rk29/board-rk29-phonesdk.c b/arch/arm/mach-rk29/board-rk29-phonesdk.c
index 2872efbb9fe5..2b2dff5eb741 100755
--- a/arch/arm/mach-rk29/board-rk29-phonesdk.c
+++ b/arch/arm/mach-rk29/board-rk29-phonesdk.c
@@ -1231,41 +1231,42 @@ struct wm831x_pdata wm831x_platdata = {
 #define 	RK29_GPS_POWER_PIN 		RK29_PIN6_PB2
 #define 	RK29_GPS_RESET_PIN	  	RK29_PIN6_PC1
 
-static int gps_open =0;
-
 int rk29_gps_power_up(void)
 {	
-	gps_open = 1;	
 	printk("%s \n", __FUNCTION__);  
-       gpio_request(RK29_GPS_POWER_PIN, NULL);    
+
+    gpio_request(RK29_GPS_POWER_PIN, NULL);    
 	gpio_direction_output(RK29_GPS_POWER_PIN, GPIO_HIGH);	
-	gpio_request(RK29_GPS_RESET_PIN, NULL);        
-	gpio_direction_output(RK29_GPS_RESET_PIN, GPIO_LOW);	  
-	rk29_mux_api_set(GPIO2B3_UART3SOUT_NAME, GPIO2L_UART3_SOUT);
-	rk29_mux_api_set(GPIO2B2_UART3SIN_NAME, GPIO2L_UART3_SIN); 	
-	mdelay(100);	
-	gpio_direction_output(RK29_GPS_RESET_PIN, GPIO_HIGH);		
+
 	return 0;
 }
 
 int rk29_gps_power_down(void)
 {	
-	gps_open =0;	
 	printk("%s \n", __FUNCTION__);	
+
 	gpio_direction_output(RK29_GPS_POWER_PIN, GPIO_LOW);		
-	mdelay(100);	  
-	gpio_direction_output(RK29_GPS_RESET_PIN, GPIO_LOW);	//uart1	
+
 	return 0;
 }
 
+int rk29_gps_reset_set(int level)
+{
+	gpio_request(RK29_GPS_RESET_PIN, NULL);
+	if (level)
+		gpio_direction_output(RK29_GPS_RESET_PIN, GPIO_HIGH);
+	else
+		gpio_direction_output(RK29_GPS_RESET_PIN, GPIO_LOW);
+
+	return 0;
+}
 
 struct rk29_gps_data rk29_gps_info = {	
 	.power_up = rk29_gps_power_up,	
 	.power_down = rk29_gps_power_down,	
+	.reset = rk29_gps_reset_set,
 	.uart_id = 3,
-	.powerpin = RK29_GPS_POWER_PIN,
-	.powerflag = 1,
-	};
+};
 
 struct platform_device rk29_device_gps = {
 	.name = "rk29_gps",
@@ -1392,7 +1393,7 @@ struct wm8994_pdata wm8994_platdata = {
 #define HEADSET_GPIO RK29_PIN4_PD2
 struct rk2818_headset_data rk2818_headset_info = {
 	.gpio		= HEADSET_GPIO,
-	.irq_type	= IRQF_TRIGGER_RISING,//IRQF_TRIGGER_RISING -- ÉÏÉýÑØ	IRQF_TRIGGER_FALLING -- ϽµÑØ
+	.irq_type	= IRQF_TRIGGER_RISING,//IRQF_TRIGGER_RISING -- ??????	IRQF_TRIGGER_FALLING -- ?½???
 	.headset_in_type= HEADSET_IN_HIGH,
 };
 
@@ -2614,6 +2615,9 @@ static struct platform_device *devices[] __initdata = {
 #ifdef CONFIG_RK_HEADSET_DET
     &rk28_device_headset,
 #endif
+#ifdef CONFIG_RK29_GPS
+	&rk29_device_gps,
+#endif
 };
 
 #ifdef CONFIG_RK29_VMAC
@@ -2772,7 +2776,7 @@ struct rk29xx_spi_platform_data rk29xx_spi1_platdata = {
  * author: hhb@rock-chips.com
  *****************************************************************************************/
 #if defined(CONFIG_TOUCHSCREEN_XPT2046_NORMAL_SPI) || defined(CONFIG_TOUCHSCREEN_XPT2046_TSLIB_SPI)
-#define XPT2046_GPIO_INT           RK29_PIN4_PD5 //中断è„?#define DEBOUNCE_REPTIME  3
+#define XPT2046_GPIO_INT           RK29_PIN4_PD5 //中断???#define DEBOUNCE_REPTIME  3
 
 static struct xpt2046_platform_data xpt2046_info = {
 	.model			= 2046,
diff --git a/drivers/misc/gps/rk29_gps.c b/drivers/misc/gps/rk29_gps.c
index 088a885c70b1..a40e342c1190 100644
--- a/drivers/misc/gps/rk29_gps.c
+++ b/drivers/misc/gps/rk29_gps.c
@@ -23,97 +23,174 @@
 
 static struct rk29_gps_data *pgps;
 
-
-int rk29_gps_suspend(struct platform_device *pdev,  pm_message_t state)
+static int rk29_gps_uart_to_gpio(int uart_id)
 {
-	struct rk29_gps_data *pdata = pdev->dev.platform_data;
-	if(!pdata)
-	return -1;
-		
-	if(pdata->uart_id == 3)
-	{
+	if(uart_id == 3) {
 		rk29_mux_api_set(GPIO2B3_UART3SOUT_NAME, GPIO2L_GPIO2B3); 			
-		gpio_request(RK29_PIN2_PB3, NULL);
-		gpio_direction_output(RK29_PIN2_PB3,GPIO_LOW);
-
 		rk29_mux_api_set(GPIO2B2_UART3SIN_NAME, GPIO2L_GPIO2B2); 		
+
+		gpio_request(RK29_PIN2_PB3, NULL);
 		gpio_request(RK29_PIN2_PB2, NULL);
-		gpio_direction_output(RK29_PIN2_PB2,GPIO_LOW);
 
+		gpio_direction_output(RK29_PIN2_PB3, GPIO_LOW);
+		gpio_direction_output(RK29_PIN2_PB2, GPIO_LOW);
 	}
-	else
-	{
+	else if(uart_id == 2) {
+		rk29_mux_api_set(GPIO2B1_UART2SOUT_NAME, GPIO2L_GPIO2B1); 			
+		rk29_mux_api_set(GPIO2B0_UART2SIN_NAME, GPIO2L_GPIO2B0); 		
+
+		gpio_request(RK29_PIN2_PB1, NULL);
+		gpio_request(RK29_PIN2_PB0, NULL);
+
+		gpio_direction_output(RK29_PIN2_PB1, GPIO_LOW);
+		gpio_direction_output(RK29_PIN2_PB0, GPIO_LOW);
+	}
+	else if(uart_id == 1) {
+		rk29_mux_api_set(GPIO2A5_UART1SOUT_NAME, GPIO2L_GPIO2A5); 			
+		rk29_mux_api_set(GPIO2A4_UART1SIN_NAME, GPIO2L_GPIO2A4); 		
+
+		gpio_request(RK29_PIN2_PA5, NULL);
+		gpio_request(RK29_PIN2_PA4, NULL);
+
+		gpio_direction_output(RK29_PIN2_PA5, GPIO_LOW);
+		gpio_direction_output(RK29_PIN2_PA4, GPIO_LOW);
+	}
+	else {
 		//to do
+	}
+
+	return 0;
+}
+
+static int rk29_gps_gpio_to_uart(int uart_id)
+{
+	if(uart_id == 3) {
+		rk29_mux_api_set(GPIO2B3_UART3SOUT_NAME, GPIO2L_UART3_SOUT);
+		rk29_mux_api_set(GPIO2B2_UART3SIN_NAME, GPIO2L_UART3_SIN); 
+
+		gpio_request(RK29_PIN2_PB3, NULL);
+		gpio_request(RK29_PIN2_PB2, NULL);
+
+		gpio_direction_output(RK29_PIN2_PB3, GPIO_HIGH);
+		gpio_direction_output(RK29_PIN2_PB2, GPIO_HIGH);
+	}
+	else if(uart_id == 2) {
+		rk29_mux_api_set(GPIO2B1_UART2SOUT_NAME, GPIO2L_UART2_SOUT); 			
+		rk29_mux_api_set(GPIO2B0_UART2SIN_NAME, GPIO2L_UART2_SIN); 		
+
+		gpio_request(RK29_PIN2_PB1, NULL);
+		gpio_request(RK29_PIN2_PB0, NULL);
+
+		gpio_direction_output(RK29_PIN2_PB1, GPIO_HIGH);
+		gpio_direction_output(RK29_PIN2_PB0, GPIO_HIGH);
+	}
+	else if(uart_id == 1) {
+		rk29_mux_api_set(GPIO2A5_UART1SOUT_NAME, GPIO2L_UART1_SOUT); 			
+		rk29_mux_api_set(GPIO2A4_UART1SIN_NAME, GPIO2L_UART1_SIN); 		
+
+		gpio_request(RK29_PIN2_PA5, NULL);
+		gpio_request(RK29_PIN2_PA4, NULL);
 
+		gpio_direction_output(RK29_PIN2_PA5, GPIO_HIGH);
+		gpio_direction_output(RK29_PIN2_PA4, GPIO_HIGH);
 	}
+	else {
+		//to do
+	}
+
+	return 0;
+
+}
+
+int rk29_gps_suspend(struct platform_device *pdev,  pm_message_t state)
+{
+	struct rk29_gps_data *pdata = pdev->dev.platform_data;
 
-	if(pdata->powerflag == 1)
+	if(!pdata)
+		return -1;
+		
+	if(pdata->power_flag == 1)
 	{
+		rk29_gps_uart_to_gpio(pdata->uart_id);
 		pdata->power_down();	
-		pdata->powerflag = 0;
+		pdata->reset(GPIO_LOW);
 	}
 	
 	printk("%s\n",__FUNCTION__);
+
 	return 0;	
 }
 
 int rk29_gps_resume(struct platform_device *pdev)
 {
 	struct rk29_gps_data *pdata = pdev->dev.platform_data;
+
 	if(!pdata)
-	return -1;
+		return -1;
 	
-	if(pdata->uart_id == 3)
+	if(pdata->power_flag == 1)
 	{
-		 rk29_mux_api_set(GPIO2B3_UART3SOUT_NAME, GPIO2L_UART3_SOUT);
-		 rk29_mux_api_set(GPIO2B2_UART3SIN_NAME, GPIO2L_UART3_SIN); 
-	}
-	else
-	{
-		//to do
-
-	}
-
-	if(pdata->powerflag == 0)
-	{
-		  pdata->power_up();
-		  pdata->powerflag = 1;
+		pdata->reset(GPIO_LOW);
+		mdelay(10);
+		pdata->power_up();
+		mdelay(500);
+		pdata->reset(GPIO_HIGH);
+		rk29_gps_gpio_to_uart(pdata->uart_id);
 	}
 	
 	printk("%s\n",__FUNCTION__);
+
 	return 0;
 }
 
 int rk29_gps_open(struct inode *inode, struct file *filp)
 {
-    	DBG("rk29_gps_open\n");
+    DBG("rk29_gps_open\n");
 
 	return 0;
 }
 
 int rk29_gps_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
 {
-    	int ret = 0;
-    
-    	DBG("rk29_gps_ioctl: cmd = %d\n",cmd);
+	int ret = 0;
+	struct rk29_gps_data *pdata = pgps;
+
+	DBG("rk29_gps_ioctl: cmd = %d\n",cmd);
+
+	ret = down_interruptible(&pdata->power_sem);
+	if (ret < 0) {
+		printk("%s: down power_sem error ret = %d\n", __func__, ret);
+		return ret;
+	}
 
-    	switch (cmd){
+	switch (cmd){
 		case ENABLE:
-			pgps->power_up();
-			pgps->powerflag = 1;
+			pdata->reset(GPIO_LOW);
+			mdelay(10);
+			pdata->power_up();
+			mdelay(10);
+			rk29_gps_gpio_to_uart(pdata->uart_id);
+			mdelay(500);
+			pdata->reset(GPIO_HIGH);
+			pdata->power_flag = 1;
 			break;
-	        
+			
 		case DISABLE:
-			pgps->power_down();
-			pgps->powerflag = 0;
+			rk29_gps_uart_to_gpio(pdata->uart_id);
+			pdata->power_down();
+			pdata->reset(GPIO_LOW);
+			pdata->power_flag = 0;
 			break;
-	        
+			
 		default:
 			printk("unknown ioctl cmd!\n");
+			up(&pdata->power_sem);
 			ret = -EINVAL;
 			break;
 	}
 
+	up(&pdata->power_sem);
+
 	return ret;
 }
 
@@ -142,6 +219,7 @@ static struct miscdevice rk29_gps_dev =
 static int rk29_gps_probe(struct platform_device *pdev)
 {
 	int ret = 0;
+	printk("\n\n=========================\n%s\n", __func__);
 	struct rk29_gps_data *pdata = pdev->dev.platform_data;
 	if(!pdata)
 		return -1;
@@ -152,8 +230,9 @@ static int rk29_gps_probe(struct platform_device *pdev)
 		return ret;
 	}
 	
-	if(pdata->power_up)
-	pdata->power_up();
+	init_MUTEX(&pdata->power_sem);
+	pdata->power_flag = 0;
+
 	pgps = pdata;
 
 
diff --git a/drivers/misc/gps/rk29_gps.h b/drivers/misc/gps/rk29_gps.h
index a54c5d1da65d..9e22ff5fd517 100644
--- a/drivers/misc/gps/rk29_gps.h
+++ b/drivers/misc/gps/rk29_gps.h
@@ -1,5 +1,5 @@
 /*
-	2011.01.16  lw@rock-chips.com
+	2011.01.2  lw@rock-chips.com
 */
 
 #ifndef __RK29_GPS_H__
@@ -8,9 +8,10 @@
 struct rk29_gps_data {
 	int (*power_up)(void);
 	int (*power_down)(void);
+	int (*reset)(int);
 	int uart_id;
-	int powerpin;
-	int powerflag;
+	int power_flag;
+	struct semaphore power_sem;
 };
 
 #endif
-- 
2.34.1