From: lyx <lyx@rock-chips.com>
Date: Fri, 29 Jul 2011 01:26:21 +0000 (-0700)
Subject: newton: updata irda serial driver
X-Git-Tag: firefly_0821_release~10065
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=cdad3accf23f933acdf7408c8bff92f30827f71b;p=firefly-linux-kernel-4.4.55.git

newton: updata irda serial driver
add ioctl get frame length and start send function
---

diff --git a/drivers/net/irda/ir_serial.c b/drivers/net/irda/ir_serial.c
index 676340e5fd03..a1c12abfcca6 100755
--- a/drivers/net/irda/ir_serial.c
+++ b/drivers/net/irda/ir_serial.c
@@ -21,35 +21,34 @@
 #include <mach/board.h>
 #include <linux/irq.h>
 #include <mach/gpio.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
 
 #include "bu92725guw.h"
+#include "ir_serial.h"
 
 struct bu92747_port {
 	struct device		*dev;
 	struct irda_info *pdata;
 	struct uart_port port;
-	
-	int cts;	        /* last CTS received for flow ctrl */
+
+	/*for FIR fream read*/
+	unsigned long last_frame_length;
+	unsigned long cur_frame_length; 
+	wait_queue_head_t data_ready_wq;
+	atomic_t data_ready;
+
 	int tx_empty;		/* last TX empty bit */
 
 	spinlock_t conf_lock;	/* shared data */
-	int conf_commit;	/* need to make changes */
-	int conf;		/* configuration for the MAX31000
-				 * (bits 0-7, bits 8-11 are irqs) */
-	int rts_commit;	        /* need to change rts */
-	int rts;		/* rts status */
 	int baud;		/* current baud rate */
 
-	int parity;		/* keeps track if we should send parity */
 	int rx_enabled;	        /* if we should rx chars */
 
 	int irq;		/* irq assigned to the bu92747 */
 
 	int minor;		/* minor number */
-	int crystal;		/* 1 if 3.6864Mhz crystal 0 for 1.8432 */
-	int loopback;		/* 1 if we are in loopback mode */
 
-	/* for handling irqs: need workqueue since we do spi_sync */
 	struct workqueue_struct *workqueue;
 	struct work_struct work;
 	/* set to 1 to make the workhandler exit as soon as possible */
@@ -57,10 +56,6 @@ struct bu92747_port {
 	/* need to know we are suspending to avoid deadlock on workqueue */
 	int suspending;
 
-	/* poll time (in ms) for ctrl lines */
-	int poll_time;
-	/* and its timer */
-	struct timer_list	timer;
 };
 
 #define MAX_BU92747 1
@@ -128,12 +123,14 @@ static int bu92747_irda_do_tx(struct bu92747_port *s)
 	}
 	BU92747_IRDA_DBG("\n");
 	
+	if (len>0) {		
+		s->tx_empty = 0;
+	}
+	
 	BU92725GUW_send_data(xmit->buf+xmit->tail, len, NULL, 0);
 	s->port.icount.tx += len;
 	xmit->tail = (xmit->tail + len) & (UART_XMIT_SIZE - 1);
 
-	if (len>0)		
-		s->tx_empty = 0;
 	
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(&s->port);
@@ -151,7 +148,6 @@ static void bu92747_irda_dowork(struct bu92747_port *s)
 static void bu92747_irda_work(struct work_struct *w)
 {
 	struct bu92747_port *s = container_of(w, struct bu92747_port, work);
-	u32 irq_src = 0;	
 	struct circ_buf *xmit = &s->port.state->xmit;
 
 	dev_dbg(s->dev, "%s\n", __func__);
@@ -172,7 +168,8 @@ static void bu92747_irda_work(struct work_struct *w)
 static irqreturn_t bu92747_irda_irq(int irqno, void *dev_id)
 {
 	struct bu92747_port *s = dev_id;
-	u32 irq_src = 0;	
+	u32 irq_src = 0;
+	unsigned long len;
 
 	dev_dbg(s->dev, "%s\n", __func__);
 	BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);
@@ -183,19 +180,30 @@ static irqreturn_t bu92747_irda_irq(int irqno, void *dev_id)
 		| REG_INT_AC | REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX)) {
 		BU92747_IRDA_DBG("[%s][%d]: do err\n", __FUNCTION__, __LINE__);
 		//BU92725GUW_dump_register();
-		//BU92725GUW_clr_fifo();
+		BU92725GUW_clr_fifo();
 		BU92725GUW_reset();
+		if ((BU92725GUW_SEND==irda_hw_get_mode())
+			|| (BU92725GUW_MULTI_SEND==irda_hw_get_mode())) {
+			s->tx_empty = 1;
+		}
 	}
 	
 	if (irq_src & (REG_INT_DRX | FRM_EVT_RX_EOFRX | FRM_EVT_RX_RDE)) {
-		bu92747_irda_do_rx(s);
+		len = bu92747_irda_do_rx(s);
 		if (!IS_FIR(s))
 			tty_flip_buffer_push(s->port.state->port.tty);
-
+		else
+			s->cur_frame_length += len;
 	}
 	
 	if ((irq_src & REG_INT_EOF) && (s->port.state->port.tty != NULL)) {
 		tty_flip_buffer_push(s->port.state->port.tty);
+		if (IS_FIR(s)) {
+			s->last_frame_length = s->cur_frame_length;
+			s->cur_frame_length = 0;
+			atomic_set(&(s->data_ready), 1);
+			wake_up(&(s->data_ready_wq) );
+		}
 	}
 	
 	if (irq_src & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) {
@@ -226,6 +234,10 @@ static void bu92747_irda_start_tx(struct uart_port *port)
 
 	dev_dbg(s->dev, "%s\n", __func__);
 
+	//wait for start cmd
+	if (IS_FIR(s))
+		return	;
+
 	if (s->tx_empty)
 		bu92747_irda_do_tx(s);
 	else 
@@ -256,7 +268,7 @@ static unsigned int bu92747_irda_tx_empty(struct uart_port *port)
 	dev_dbg(s->dev, "%s\n", __func__);
 
 	/* may not be truly up-to-date */
-	bu92747_irda_dowork(s);
+	//bu92747_irda_dowork(s);
 	return s->tx_empty;
 }
 
@@ -331,6 +343,11 @@ static void bu92747_irda_shutdown(struct uart_port *port)
 		destroy_workqueue(s->workqueue);
 		s->workqueue = NULL;
 	}
+	
+	atomic_set(&(s->data_ready), 0);
+	s->last_frame_length = 0;
+	s->cur_frame_length = 0;
+		
 	if (s->irq)
 		free_irq(s->irq, s);
 	
@@ -352,6 +369,8 @@ static int bu92747_irda_startup(struct uart_port *port)
 
 	s->baud = 9600;
 	s->rx_enabled = 1;
+	s->last_frame_length = 0;
+	s->cur_frame_length = 0;
 
 	if (s->suspending)
 		return 0;
@@ -367,6 +386,8 @@ static int bu92747_irda_startup(struct uart_port *port)
 	}
 	INIT_WORK(&s->work, bu92747_irda_work);
 
+	atomic_set(&(s->data_ready), 0);
+
 	if (request_irq(s->irq, bu92747_irda_irq,
 			IRQ_TYPE_LEVEL_LOW, "bu92747_irda", s) < 0) {
 		dev_warn(s->dev, "cannot allocate irq %d\n", s->irq);
@@ -426,7 +447,6 @@ static void bu92747_irda_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	struct bu92747_port *s = container_of(port,
 						  struct bu92747_port,
 						  port);
-	int rts;
 
 	dev_dbg(s->dev, "%s\n", __func__);
 	BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);
@@ -472,6 +492,57 @@ bu92747_irda_set_termios(struct uart_port *port, struct ktermios *termios,
 
 }
 
+static int bu92747_get_frame_length(struct bu92747_port *s)
+{
+	unsigned long len;
+	wait_event_interruptible_timeout(s->data_ready_wq, 
+									 atomic_read(&(s->data_ready) ),
+									 msecs_to_jiffies(1000) );
+	if ( 0 == atomic_read(&(s->data_ready)) ) {
+		printk("waiting 'data_ready_wq' timed out.");
+		return -1;
+	}
+
+	len = s->last_frame_length;
+	s->last_frame_length = 0;
+	
+	atomic_set(&(s->data_ready), 0);
+	
+	return len;
+}
+
+static int bu92747_irda_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
+{
+	struct bu92747_port *s = container_of(port,
+						  struct bu92747_port,
+						  port);
+	void __user *argp = (void __user *)arg;
+	unsigned long len = 0;
+	int ret = 0;
+	BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);
+
+	switch (cmd) {
+	case TTYIR_GETLENGTH:
+		len = bu92747_get_frame_length(s);
+		if (len > 0) {
+			if (copy_to_user(argp, &len, sizeof(len)))
+				ret = -EFAULT;
+		}
+		else
+			ret = -EFAULT;
+		break;
+		
+	case TTYIR_STARTSEND:		
+		bu92747_irda_dowork(s);
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+	
+	return ret;
+}
+
 static struct uart_ops bu92747_irda_ops = {
 	.tx_empty	= bu92747_irda_tx_empty,
 	.set_mctrl	= bu92747_irda_set_mctrl,
@@ -489,6 +560,7 @@ static struct uart_ops bu92747_irda_ops = {
 	.request_port   = bu92747_irda_request_port,
 	.config_port	= bu92747_irda_config_port,
 	.verify_port	= bu92747_irda_verify_port,
+	.ioctl			= bu92747_irda_ioctl,
 };
 
 static struct uart_driver bu92747_irda_uart_driver = {
@@ -565,6 +637,8 @@ static int __devinit bu92747_irda_probe(struct platform_device *pdev)
 	/* set shutdown mode to save power. Will be woken-up on open */
 	if (bu92747s[i]->pdata->irda_pwr_ctl)
 		bu92747s[i]->pdata->irda_pwr_ctl(0);
+	
+	init_waitqueue_head(&(bu92747s[i]->data_ready_wq));
 
 	mutex_unlock(&bu92747s_lock);
 	
diff --git a/drivers/net/irda/ir_serial.h b/drivers/net/irda/ir_serial.h
index c2abcac496e0..f0b3fe436bf1 100755
--- a/drivers/net/irda/ir_serial.h
+++ b/drivers/net/irda/ir_serial.h
@@ -3,4 +3,22 @@
 
 #include "bu92725guw.h"
 
+/*
+ * define IOCTL macro
+ */
+/* magic number */
+#define TTYIR_IOC_TYPE  0x56
+
+/* TTYIR_STARTSEND */
+/* function: start to send a frame in FIR mode */
+/* parameter: no parameter */
+/* return: no return code */
+#define TTYIR_STARTSEND			   _IO(TTYIR_IOC_TYPE, 0)
+
+/* TTYIR_GETLENGTH */
+/* function: get the length of DATA field in the current frame */
+/* paramter: no paramter */
+/* return: the length of DATA field (unit:byte) */
+#define TTYIR_GETLENGTH			   _IOR(TTYIR_IOC_TYPE, 1, unsigned long)
+
 #endif