improve spi_uart.c for bt
authorluowei <lw@rock-chips.com>
Sat, 28 Aug 2010 13:47:00 +0000 (21:47 +0800)
committerluowei <lw@rock-chips.com>
Sat, 28 Aug 2010 13:47:00 +0000 (21:47 +0800)
arch/arm/mach-rk2818/include/mach/spi_fpga.h
drivers/fpga/spi_fpga_init.c
drivers/fpga/spi_uart.c

index f507f83118044a65af51be805fd2cc714bebaff8..d5c7023608128baaa6f4d4e5320b02fdb85b8b3a 100755 (executable)
@@ -15,7 +15,7 @@ defines of FPGA chip ICE65L08's register
 \r
 #define SPI_FPGA_I2C_EVENT     1\r
 #define SPI_FPGA_POLL_WAIT     0\r
-#define SPI_FPGA_TRANS_WORK    0\r
+#define SPI_FPGA_TRANS_WORK    1\r
 #define SPI_FPGA_TEST_DEBUG    0\r
 #if SPI_FPGA_TEST_DEBUG\r
 #define SPI_FPGA_TEST_DEBUG_PIN RK2818_PIN_PE0\r
index 06cda28ba8502f814a5bda6173dea5731ebced29..71bc6c7fae7d92ba134fc16ecae6195843cbebbc 100755 (executable)
@@ -43,7 +43,7 @@
 #include <linux/jiffies.h>\r
 #include <linux/i2c.h>\r
 #include <mach/rk2818_iomap.h>\r
-\r
+#include <linux/poll.h>\r
 #include <mach/spi_fpga.h>\r
 \r
 #if defined(CONFIG_SPI_FPGA_INIT_DEBUG)\r
 \r
 struct spi_fpga_port *pFpgaPort;\r
 \r
+#if SPI_FPGA_TRANS_WORK\r
+#define ID_SPI_FPGA_WRITE 1\r
+#define ID_SPI_FPGA_READ 2\r
+struct spi_fpga_transfer\r
+{\r
+       const u8 *txbuf;\r
+       unsigned n_tx;\r
+       u8 *rxbuf;\r
+       unsigned n_rx;\r
+       int id;\r
+       struct list_head        queue;\r
+};\r
+\r
+static void spi_fpga_trans_work_handler(struct work_struct *work)\r
+{\r
+       struct spi_fpga_port *port =\r
+               container_of(work, struct spi_fpga_port, fpga_trans_work);\r
+\r
+       while (!list_empty(&port->trans_queue)) \r
+       {\r
+               struct spi_fpga_transfer        *t = NULL;\r
+               list_for_each_entry(t, &port->trans_queue, queue)\r
+               {\r
+\r
+                       if (t->id == 0) \r
+                               break;  \r
+                       DBG("%s:id=%d,txbuf=0x%x\n",__FUNCTION__,t->id,(int)t->txbuf);\r
+                       switch(t->id)\r
+                       {\r
+                               case ID_SPI_FPGA_WRITE:\r
+                                       spi_write(port->spi, t->txbuf, t->n_tx);\r
+                                       break;\r
+                               default:\r
+                                       break;\r
+                                       \r
+                       }\r
+                       kfree(t);\r
+                       kfree(t->txbuf);\r
+               }\r
+               list_del_init(&port->trans_queue);\r
+       }\r
+\r
+}\r
+\r
+int spi_write_work(struct spi_device *spi, const u8 *buf, size_t len)\r
+{\r
+       struct spi_fpga_port *port = spi_get_drvdata(spi);\r
+       struct spi_fpga_transfer *t;\r
+       unsigned long flags;\r
+\r
+       t = kzalloc(sizeof(struct spi_fpga_transfer), GFP_KERNEL);\r
+       if (!t)\r
+       {\r
+               printk("err:%s:ENOMEM\n",__FUNCTION__);\r
+               return ;\r
+       }\r
+\r
+       t->txbuf = (char *)kmalloc(32, GFP_KERNEL);\r
+       if(t->txbuf == NULL)\r
+       {\r
+           printk("%s:t->txbuf kzalloc err!!!\n",__FUNCTION__);\r
+           return -ENOMEM;\r
+       }\r
+\r
+       memcpy(t->txbuf, buf, len);\r
+       t->n_tx = len;\r
+       t->id = ID_SPI_FPGA_WRITE;\r
+\r
+       spin_lock_irqsave(&port->work_lock, flags);\r
+       list_add_tail(&t->queue, &port->trans_queue);\r
+       queue_work(port->fpga_trans_workqueue, &port->fpga_trans_work);\r
+       spin_unlock_irqrestore(&port->work_lock, flags);\r
+\r
+       return 0;\r
+\r
+}\r
+\r
+#endif\r
+\r
+\r
+#if SPI_FPGA_POLL_WAIT\r
+\r
+#define SPI_BUFSIZE 1028\r
+static void spi_fpga_complete(void *arg)\r
+{\r
+       struct spi_fpga_port *port = pFpgaPort;\r
+       msleep(5);\r
+       wake_up_interruptible(&port->spi_wait_q);\r
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+}\r
+\r
+int spi_fpga_write(struct spi_device *spi, const u8 *buf, size_t len)\r
+{\r
+       struct spi_transfer     t = {\r
+                       .tx_buf         = buf,\r
+                       .len            = len,\r
+               };\r
+       struct spi_message      m;\r
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+       spi_message_init(&m);\r
+       spi_message_add_tail(&t, &m);\r
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+       return spi_async(spi, &m);\r
+}\r
+\r
+struct poll_table_struct wait;\r
+struct file filp;\r
+int spi_fpga_write_then_read(struct spi_device *spi,\r
+               const u8 *txbuf, unsigned n_tx,\r
+               u8 *rxbuf, unsigned n_rx)\r
+{\r
+       struct spi_fpga_port *port = spi_get_drvdata(spi);\r
+       int                     status;\r
+       struct spi_message      message;\r
+       struct spi_transfer     x[2];\r
+       u8                      *local_buf;\r
+       printk("%s:line=%d,n_tx+n_rx=%d\n",__FUNCTION__,__LINE__,(n_tx + n_rx));\r
+       /* Use preallocated DMA-safe buffer.  We can't avoid copying here,\r
+        * (as a pure convenience thing), but we can keep heap costs\r
+        * out of the hot path ...\r
+        */\r
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+\r
+       if ((n_tx + n_rx) > SPI_BUFSIZE)\r
+               return -EINVAL;\r
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+\r
+       spi_message_init(&message);\r
+       memset(x, 0, sizeof x);\r
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+       if (n_tx) {\r
+               x[0].len = n_tx;\r
+               spi_message_add_tail(&x[0], &message);\r
+       }\r
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+\r
+       if (n_rx) {\r
+               x[1].len = n_rx;\r
+               spi_message_add_tail(&x[1], &message);\r
+       }\r
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+       /* ... unless someone else is using the pre-allocated buffer */\r
+\r
+       local_buf = kmalloc(SPI_BUFSIZE, GFP_KERNEL);\r
+       if (!local_buf)\r
+               return -ENOMEM;\r
+\r
+       memcpy(local_buf, txbuf, n_tx);\r
+       x[0].tx_buf = local_buf;\r
+       x[1].rx_buf = local_buf + n_tx;\r
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+       message.complete = spi_fpga_complete;\r
+\r
+       /* do the i/o */\r
+       status = spi_async(spi, &message);\r
+#if 1\r
+       //poll_wait(&filp, &port->spi_wait_q, &wait);\r
+\r
+       //if (status == 0)\r
+       memcpy(rxbuf, x[1].rx_buf, n_rx);\r
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+       kfree(local_buf);\r
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+#endif\r
+       return status;\r
+}\r
+\r
+#define spi_write spi_fpga_write\r
+#define spi_write_then_read spi_fpga_write_then_read \r
+\r
+#endif\r
+\r
 /*------------------------spi¶ÁдµÄ»ù±¾º¯Êý-----------------------*/\r
 unsigned int spi_in(struct spi_fpga_port *port, int reg, int type)\r
 {\r
@@ -138,7 +310,7 @@ void spi_out(struct spi_fpga_port *port, int reg, int value, int type)
 {\r
        unsigned char index = 0;\r
        unsigned char tx_buf[3];\r
-       //printk("index2=%d,",index);\r
+       int reg_temp = reg;\r
        switch(type)\r
        {\r
 #if defined(CONFIG_SPI_FPGA_UART)\r
@@ -148,6 +320,9 @@ void spi_out(struct spi_fpga_port *port, int reg, int value, int type)
                        tx_buf[0] = reg & 0xff;\r
                        tx_buf[1] = (value>>8) & 0xff;\r
                        tx_buf[2] = value & 0xff;\r
+                       if(reg_temp == UART_IER)\r
+                       spi_write_work(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf));\r
+                       else\r
                        spi_write(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf));\r
                        DBG("%s,SEL_UART reg=0x%x,value=0x%x\n",__FUNCTION__,reg&0xff,value&0xffff);\r
                        break;\r
@@ -347,12 +522,27 @@ static int __devinit spi_fpga_probe(struct spi_device * spi)
        if (!port)\r
                return -ENOMEM;\r
        DBG("port=0x%x\n",(int)port);\r
-\r
-       spin_lock_init(&port->work_lock);\r
+       \r
        mutex_init(&port->spi_lock);\r
-\r
+       spin_lock_init(&port->work_lock);\r
+       \r
        spi_open_sysclk(GPIO_HIGH);\r
 \r
+#if SPI_FPGA_TRANS_WORK\r
+       init_waitqueue_head(&port->wait_wq);\r
+       init_waitqueue_head(&port->wait_rq);\r
+       port->write_en = TRUE;\r
+       port->read_en = TRUE;\r
+       sprintf(b, "fpga_trans_workqueue");\r
+       port->fpga_trans_workqueue = create_freezeable_workqueue(b);\r
+       if (!port->fpga_trans_workqueue) {\r
+               printk("cannot create workqueue\n");\r
+               return -EBUSY;\r
+       }\r
+       INIT_WORK(&port->fpga_trans_work, spi_fpga_trans_work_handler);\r
+       INIT_LIST_HEAD(&port->trans_queue);\r
+#endif\r
+\r
        spi_fpga_rst();\r
        sprintf(b, "fpga_irq_workqueue");\r
        port->fpga_irq_workqueue = create_freezeable_workqueue(b);\r
index 407d0eec8f5b89c6038962101409e5cbfa30755b..e0b024296275f62204c819f8c9f225774645630d 100755 (executable)
@@ -37,7 +37,7 @@
 #endif\r
 \r
 #define SPI_UART_TEST 0\r
-\r
+int gBaud = 0;\r
 #define SPI_UART_FIFO_LEN      32\r
 #define SPI_UART_TXRX_BUF      1               //send or recieve several bytes one time\r
 \r
@@ -309,6 +309,7 @@ static void spi_uart_change_speed(struct spi_uart *uart,
        }\r
        //quot = (2 * uart->uartclk + baud) / (2 * baud);\r
        quot = (uart->uartclk / baud);\r
+       //gBaud = baud;\r
        printk("baud=%d,quot=0x%x\n",baud,quot);\r
        if (baud < 2400)\r
                fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;\r
@@ -348,19 +349,17 @@ static void spi_uart_change_speed(struct spi_uart *uart,
         */\r
        uart->ier &= ~UART_IER_MSI;\r
        if ((termios->c_cflag & CRTSCTS) || !(termios->c_cflag & CLOCAL))\r
-       {\r
-               //uart->ier |= UART_IER_MSI;\r
-               //uart->mcr = UART_MCR_RTS;//mcr = UART_MCR_RTS while start RTSCTS\r
-       }\r
+               uart->ier |= UART_IER_MSI;\r
 \r
        uart->lcr = cval;\r
-\r
-       spi_out(port, UART_IER, uart->ier, SEL_UART);\r
+       \r
        spi_out(port, UART_LCR, cval | UART_LCR_DLAB, SEL_UART);\r
        spi_out(port, UART_DLL, quot & 0xff, SEL_UART);\r
        spi_out(port, UART_DLM, quot >> 8, SEL_UART);\r
        spi_out(port, UART_LCR, cval, SEL_UART);\r
        spi_out(port, UART_FCR, fcr, SEL_UART);\r
+       spi_out(port, UART_IER, uart->ier, SEL_UART);//slow\r
+\r
        DBG("%s:LINE=%d,baud=%d,uart->ier=0x%x,cval=0x%x,fcr=0x%x,quot=0x%x\n",\r
                __FUNCTION__,__LINE__,baud,uart->ier,cval,fcr,quot);\r
        spi_uart_write_mctrl(uart, uart->mctrl);\r
@@ -369,30 +368,22 @@ static void spi_uart_change_speed(struct spi_uart *uart,
 static void spi_uart_start_tx(struct spi_uart *uart)\r
 {\r
        struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
-#if 1\r
-       //unsigned long flags;\r
        if (!(uart->ier & UART_IER_THRI)) {\r
-               //spin_lock_irqsave(&uart->write_lock, flags);\r
                uart->ier |= UART_IER_THRI;\r
                spi_out(port, UART_IER, uart->ier, SEL_UART);\r
-               //spin_unlock_irqrestore(&uart->write_lock, flags);     \r
                printk("t,");\r
        }       \r
        \r
        DBG("%s:UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
-#endif\r
+\r
 }\r
 \r
 static void spi_uart_stop_tx(struct spi_uart *uart)\r
 {\r
        struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
-       //unsigned long flags;\r
        if (uart->ier & UART_IER_THRI) {\r
-               //spin_lock_irqsave(&uart->write_lock, flags);\r
                uart->ier &= ~UART_IER_THRI;\r
                spi_out(port, UART_IER, uart->ier, SEL_UART);\r
-               //spin_unlock_irqrestore(&uart->write_lock, flags);     \r
-               //printk("p");\r
        }\r
        DBG("%s:UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
 }\r
@@ -411,12 +402,18 @@ static void spi_uart_receive_chars(struct spi_uart *uart, unsigned int *status)
        struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
        unsigned int ch, flag;\r
        int max_count = 1024;\r
-\r
+       //printk("rx:");\r
 #if SPI_UART_TXRX_BUF\r
        int ret,count,stat = 0,num = 0;\r
+       int i;\r
        unsigned char buf[SPI_UART_FIFO_LEN];\r
        while (max_count >0 )\r
        {\r
+               stat = spi_in(port, UART_LSR, SEL_UART);\r
+               if((((stat >> 8) & 0x3f) != 0) && (!(stat & UART_LSR_DR)))\r
+               printk("%s:warning:no receive data but count =%d \n",__FUNCTION__,((stat >> 8) & 0x3f));\r
+               if(!(stat & UART_LSR_DR))\r
+                       break;\r
                ret = spi_in(port, UART_RX, SEL_UART);\r
                count = (ret >> 8) & 0x3f;      \r
                DBG("%s:count=%d\n",__FUNCTION__,count);\r
@@ -430,21 +427,23 @@ static void spi_uart_receive_chars(struct spi_uart *uart, unsigned int *status)
                        printk("err:%s:stat=%d,fail to read uart data because of spi bus error!\n",__FUNCTION__,stat);  \r
                }\r
                max_count -= count;\r
-               while (count-- >0 )\r
+               for(i=0;i<count;i++)\r
                {\r
                        flag = TTY_NORMAL;\r
                        uart->icount.rx++;\r
                        ch = buf[num++];\r
                        tty_insert_flip_char(tty, ch, flag);\r
-                       //printk("%c,",ch);\r
+                       //if(gBaud == 1500000)\r
+                       //printk("0x%x,",ch);\r
                }\r
                //printk("\n");\r
-       }\r
+       }       \r
 \r
        tty_flip_buffer_push(tty); \r
+       //if(gBaud == 1500000)\r
+       //printk("\n");\r
        \r
 #else  \r
-       //printk("rx:");\r
        while (--max_count >0 )\r
        {\r
                ch = spi_in(port, UART_RX, SEL_UART);//\r
@@ -533,10 +532,15 @@ static void spi_uart_transmit_chars(struct spi_uart *uart)
                if (circ_empty(xmit))\r
                break;\r
                buf[SPI_UART_FIFO_LEN - count] = xmit->buf[xmit->tail];\r
+               //if(gBaud == 1500000)\r
+               //printk("0x%x,",buf[SPI_UART_FIFO_LEN - count]&0xff);\r
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);\r
                uart->icount.tx++;\r
                --count;\r
+\r
        }\r
+       //if(gBaud == 1500000)\r
+       //printk("\n");\r
        if(SPI_UART_FIFO_LEN - count > 0)\r
        spi_uart_write_buf(uart,buf,SPI_UART_FIFO_LEN - count);\r
 #else\r
@@ -573,7 +577,7 @@ static void spi_uart_transmit_chars(struct spi_uart *uart)
        DBG("uart->tty->hw_stopped = %d\n",uart->tty->hw_stopped);\r
 }\r
 \r
-#if 0\r
+#if 1\r
 static void spi_uart_check_modem_status(struct spi_uart *uart)\r
 {\r
        int status;\r
@@ -744,7 +748,7 @@ void spi_uart_handle_irq(struct spi_device *spi)
                spi_uart_receive_chars(uart, &lsr);     \r
        }\r
 \r
-       //spi_uart_check_modem_status(uart);\r
+       spi_uart_check_modem_status(uart);\r
        \r
        \r
        if (lsr & UART_LSR_THRE)\r