newton: updata irda serial driver
authorlyx <lyx@rock-chips.com>
Fri, 29 Jul 2011 01:26:21 +0000 (18:26 -0700)
committerlyx <lyx@rock-chips.com>
Fri, 29 Jul 2011 01:29:52 +0000 (18:29 -0700)
add ioctl get frame length and start send function

drivers/net/irda/ir_serial.c
drivers/net/irda/ir_serial.h

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