rk_serial: update serial driver
authorhhb <hhb@rock-chips.com>
Thu, 9 Aug 2012 10:25:20 +0000 (18:25 +0800)
committerhhb <hhb@rock-chips.com>
Thu, 9 Aug 2012 10:25:20 +0000 (18:25 +0800)
drivers/tty/serial/Kconfig
drivers/tty/serial/rk_serial.c

index 4763420c6a4af57a62a14b9177b7096c1cb20ca4..d3c690a3ddf935899d72ec02ce2f57f6cfe118de 100644 (file)
@@ -1526,9 +1526,13 @@ config UART0_CTS_RTS_RK29
        depends on UART0_RK29
 
 config UART0_DMA_RK29
-       bool "Serial port 0 DMA support (EXPERIMENTAL)"
+       int "Serial port 0 DMA support (EXPERIMENTAL)"
        depends on UART0_RK29
-
+       default 0
+       help 
+                1:enable dma tx
+                2:enable dma rx
+                3:both enable dma tx and rx 
 config UART1_RK29
        bool "Serial port 1 support"
        depends on SERIAL_RK29
@@ -1538,9 +1542,13 @@ config UART1_CTS_RTS_RK29
        depends on UART1_RK29 && !ARCH_RK29
 
 config UART1_DMA_RK29
-       bool "Serial port 1 DMA support (EXPERIMENTAL)"
+       int "Serial port 1 DMA support (EXPERIMENTAL)"
        depends on UART1_RK29
-
+       default 0
+       help 
+                1:enable dma tx
+                2:enable dma rx
+                3:both enable dma tx and rx 
 config UART2_RK29
        bool "Serial port 2 support"
        depends on SERIAL_RK29
@@ -1550,9 +1558,13 @@ config UART2_CTS_RTS_RK29
        depends on UART2_RK29 && !ARCH_RK30
 
 config UART2_DMA_RK29
-       bool "Serial port 2 DMA support (EXPERIMENTAL)"
+       int "Serial port 2 DMA support (EXPERIMENTAL)"
        depends on UART2_RK29
-
+       default 0
+       help 
+                1:enable dma tx
+                2:enable dma rx
+                3:both enable dma tx and rx 
 config UART3_RK29
        bool "Serial port 3 support"
        depends on SERIAL_RK29
@@ -1562,9 +1574,13 @@ config UART3_CTS_RTS_RK29
        depends on UART3_RK29
 
 config UART3_DMA_RK29
-       bool "Serial port 3 DMA support (EXPERIMENTAL)"
+       int "Serial port 3 DMA support (EXPERIMENTAL)"
        depends on UART3_RK29
-
+       default 0
+       help 
+                1:enable dma tx
+                2:enable dma rx
+                3:both enable dma tx and rx 
 config SERIAL_RK29_CONSOLE
        bool "Serial console support"
        depends on SERIAL_RK29=y
index b4d4756c80fda251b6348c16cb4fbe3770f52d89..7b41d278ec5c884d4a1244cf7a301a3f5be951d4 100644 (file)
@@ -24,7 +24,6 @@
 #define SUPPORT_SYSRQ\r
 #endif\r
 \r
-//#define DEBUG\r
 #include <linux/module.h>\r
 #include <linux/ioport.h>\r
 #include <linux/init.h>\r
@@ -38,7 +37,6 @@
 #include <linux/serial_reg.h>\r
 #include <linux/serial_core.h>\r
 #include <linux/serial.h>\r
-#include <linux/serial_8250.h>\r
 #include <linux/nmi.h>\r
 #include <linux/mutex.h>\r
 #include <linux/slab.h>\r
 #include <asm/io.h>\r
 #include <asm/irq.h>\r
 \r
+/*\r
+*                       Driver Version Note\r
+*\r
+*v0.0 : this driver is 2.6.32 kernel driver;\r
+*v0.1 : this driver is 3.0.8 kernel driver;\r
+*v1.0 : 1.modify dma dirver;\r
+*              2.enable Programmable THRE Interrupt Mode, so we can just judge ((up->iir & 0x0f) == 0x02) when transmit\r
+*              3.reset uart and set it to loopback state to ensure setting baud rate sucessfully \r
+*/\r
+#define VERSION_AND_TIME  "rk_serial.c v1.0 2012-08-09"\r
 \r
 #define PORT_RK                90\r
 #define UART_USR       0x1F    /* UART Status Register */\r
 #define UART_LSR_RFE   0x80    /* receive fifo error */\r
 #define UART_SRR               0x22    /* software reset register */\r
 #define UART_RESET             0x01\r
-#define RX_TIMEOUT             (3000*10)  //uint ms\r
 \r
 #define BOTH_EMPTY     (UART_LSR_TEMT | UART_LSR_THRE)\r
 \r
 #define UART_NR        4   //uart port number\r
-#define POWER_MANEGEMENT 1\r
 \r
-/* configurate whether the port transmit-receive by DMA */\r
+/* configurate whether the port transmit-receive by DMA in menuconfig*/\r
 #define OPEN_DMA      1\r
 #define CLOSE_DMA     0\r
 \r
-#ifdef CONFIG_UART0_DMA_RK29\r
-#define UART0_USE_DMA OPEN_DMA\r
+#define TX_DMA (1)\r
+#define RX_DMA (2)\r
+\r
+#ifdef CONFIG_UART0_DMA_RK29 \r
+#define UART0_USE_DMA CONFIG_UART0_DMA_RK29\r
 #else\r
 #define UART0_USE_DMA CLOSE_DMA\r
 #endif\r
-\r
+#ifdef CONFIG_UART1_DMA_RK29\r
+#define UART1_USE_DMA CONFIG_UART1_DMA_RK29\r
+#else\r
+#define UART1_USE_DMA CLOSE_DMA\r
+#endif\r
 #ifdef CONFIG_UART2_DMA_RK29\r
-#define UART2_USE_DMA OPEN_DMA\r
+#define UART2_USE_DMA CONFIG_UART2_DMA_RK29\r
 #else\r
 #define UART2_USE_DMA CLOSE_DMA\r
 #endif\r
-\r
 #ifdef CONFIG_UART3_DMA_RK29\r
-#define UART3_USE_DMA OPEN_DMA\r
+#define UART3_USE_DMA CONFIG_UART3_DMA_RK29\r
 #else\r
 #define UART3_USE_DMA CLOSE_DMA\r
 #endif\r
 \r
-#define UART1_USE_DMA CLOSE_DMA\r
+#define USE_TIMER    1           // use timer for dma transport\r
+#define POWER_MANEGEMENT 1\r
+#define RX_TIMEOUT             (3000*3)  //uint ms\r
+#define DMA_TX_TRRIGE_LEVEL 128\r
+#define SERIAL_CIRC_CNT_TO_END(xmit)   CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE)\r
+\r
 \r
 #define USE_DMA (UART0_USE_DMA | UART1_USE_DMA | UART2_USE_DMA | UART3_USE_DMA)\r
 #if USE_DMA\r
 #endif\r
 #endif\r
 \r
-#define DMA_TX_TRRIGE_LEVEL 30\r
 \r
-#define USE_TIMER 1           // use timer for dma transport\r
-#define THRE_MODE 0X00   //0yhh\r
 \r
 static struct uart_driver serial_rk_reg;\r
 \r
 /*\r
  * Debugging.\r
  */\r
+#ifdef CONFIG_ARCH_RK29\r
 #define DBG_PORT 1   //DBG_PORT which uart is used to print log message\r
-\r
+#else\r
+#define DBG_PORT -1   //DBG_PORT which uart is used to print log message\r
+#endif\r
 #ifdef CONFIG_SERIAL_CORE_CONSOLE\r
 #define uart_console(port)     ((port)->cons && (port)->cons->index == (port)->line)\r
 #else\r
 #define uart_console(port)     (0)\r
 #endif\r
 \r
-#define DEBUG 0\r
 \r
 extern void printascii(const char *);\r
 static void dbg(const char *fmt, ...)\r
@@ -131,8 +147,13 @@ static void dbg(const char *fmt, ...)
        printascii(buff);\r
 }\r
 \r
+//enable log output\r
+#define DEBUG 1\r
+static int log_port = -1;\r
+module_param(log_port, int, S_IRUGO|S_IWUSR);\r
+\r
 #if DEBUG\r
-#define DEBUG_INTR(fmt...)     if (!uart_console(&up->port)) dbg(fmt)\r
+#define DEBUG_INTR(fmt...)     if (up->port.line == log_port && !uart_console(&up->port)) dbg(fmt)\r
 #else\r
 #define DEBUG_INTR(fmt...)     do { } while (0)\r
 #endif\r
@@ -141,31 +162,36 @@ static void dbg(const char *fmt, ...)
 #if USE_DMA\r
 /* added by hhb@rock-chips.com for uart dma transfer */\r
 \r
-struct rk29_uart_dma_t {\r
+struct rk_uart_dma {\r
        u32 use_dma;            //1:used\r
-       u32 rx_dma_start;\r
        enum dma_ch rx_dmach;\r
        enum dma_ch tx_dmach;\r
-       u32 tx_dma_inited;\r
-       u32 rx_dma_inited;\r
-       spinlock_t              tx_lock;\r
-       spinlock_t              rx_lock;\r
-       char * rx_buffer;\r
+\r
+       //receive and transfer buffer\r
+       char * rx_buffer;    //visual memory\r
        char * tx_buffer;\r
-       dma_addr_t rx_phy_addr;\r
+       dma_addr_t rx_phy_addr;  //physical memory\r
        dma_addr_t tx_phy_addr;\r
-       u32 rx_buffer_size;\r
-       u32 tx_buffer_size;\r
+       u32 rb_size;             //buffer size\r
+       u32 tb_size;\r
 \r
-       u32 rb_cur_pos;\r
-       u32 rb_pre_pos;\r
+       //regard the rx buffer as a circular buffer\r
+       u32 rb_head;\r
+       u32 rb_tail;\r
        u32 rx_size;\r
-       char use_timer;\r
-       char tx_dma_used;\r
-       /* timer to poll activity on rx dma */\r
-       struct timer_list       rx_timer;\r
-       int                     rx_timeout;\r
 \r
+       spinlock_t              tx_lock;\r
+       spinlock_t              rx_lock;\r
+\r
+       char tx_dma_inited;   //1:dma tx channel has been init\r
+       char rx_dma_inited;      //1:dma rx channel has been init\r
+       char tx_dma_used;        //1:dma tx is working\r
+       char rx_dma_used;    //1:dma rx is working\r
+\r
+       /* timer to poll activity on rx dma */\r
+       char use_timer;\r
+       int      rx_timeout;\r
+       struct timer_list rx_timer;\r
 };\r
 #endif\r
 \r
@@ -193,27 +219,28 @@ struct uart_rk_port {
 #endif\r
 \r
        char                    name[12];\r
-       char                    fifo[32];\r
+       char                    fifo[64];\r
        char                    fifo_size;\r
        unsigned long           port_activity;\r
        struct work_struct uart_work;\r
        struct work_struct uart_work_rx;\r
        struct workqueue_struct *uart_wq;\r
 #if USE_DMA\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t;\r
+       struct rk_uart_dma *dma;\r
 #endif\r
 };\r
 \r
 #if USE_DMA\r
 static void serial_rk_release_dma_tx(struct uart_port *port);\r
 static int serial_rk_start_tx_dma(struct uart_port *port);\r
-static void serial_rk_rx_timeout(unsigned long uart);\r
+//static void serial_rk_rx_timeout(unsigned long uart);\r
 static void serial_rk_release_dma_rx(struct uart_port *port);\r
 static int serial_rk_start_rx_dma(struct uart_port *port);\r
 #else\r
 static inline int serial_rk_start_tx_dma(struct uart_port *port) { return 0; }\r
 #endif\r
 static int serial_rk_startup(struct uart_port *port);\r
+\r
 static inline unsigned int serial_in(struct uart_rk_port *up, int offset)\r
 {\r
        offset = offset << 2;\r
@@ -254,22 +281,23 @@ static inline int serial_dl_read(struct uart_rk_port *up)
 static int serial_dl_write(struct uart_rk_port *up, unsigned int value)\r
 {\r
        unsigned int tmout = 100;\r
-       if(up->port.line != DBG_PORT)\r
-       {\r
-               while(!(serial_in(up, UART_LCR) & UART_LCR_DLAB)){\r
-                       if (--tmout == 0){\r
+\r
+       while(!(serial_in(up, UART_LCR) & UART_LCR_DLAB)){\r
+               if (--tmout == 0){\r
+                       if(up->port.line != DBG_PORT)\r
                                dbg("set serial.%d baudrate fail with DLAB not set\n", up->port.line);\r
-                               return -1;\r
-                       }\r
+                       return -1;\r
                }\r
+       }\r
 \r
-               tmout = 15000;\r
-               while(serial_in(up, UART_USR) & UART_USR_BUSY){\r
-                       if (--tmout == 0){\r
+       tmout = 15000;\r
+       while(serial_in(up, UART_USR) & UART_USR_BUSY){\r
+               if (--tmout == 0){\r
+                       if(up->port.line != DBG_PORT)\r
                                dbg("set serial.%d baudrate timeout\n", up->port.line);\r
-                               return -1;\r
-                       }\r
+                       return -1;\r
                }\r
+               udelay(1);\r
        }\r
 \r
        serial_out(up, UART_DLL, value & 0xff);\r
@@ -283,16 +311,13 @@ static int serial_lcr_write(struct uart_rk_port *up, unsigned char value)
 {\r
        unsigned int tmout = 15000;\r
 \r
-       if(up->port.line != DBG_PORT)\r
-       {\r
-               while(serial_in(up, UART_USR) & UART_USR_BUSY){\r
-\r
-                       if (--tmout == 0){\r
+       while(serial_in(up, UART_USR) & UART_USR_BUSY){\r
+               if (--tmout == 0){\r
+                       if(up->port.line != DBG_PORT)\r
                                dbg("set serial.%d lc r = 0x%02x timeout\n", up->port.line, value);\r
-                               return -1;\r
-                       }\r
-                       udelay(1);\r
+                       return -1;\r
                }\r
+               udelay(1);\r
        }\r
 \r
        serial_out(up, UART_LCR, value);\r
@@ -316,7 +341,7 @@ static inline void serial_rk_disable_ier_thri(struct uart_rk_port *up)
                serial_out(up, UART_IER, up->ier);\r
        }\r
 }\r
-#if 0\r
+\r
 static int rk29_uart_dump_register(struct uart_rk_port *up){\r
 \r
        unsigned int reg_value = 0;\r
@@ -338,7 +363,6 @@ static int rk29_uart_dump_register(struct uart_rk_port *up){
        return 0;\r
 \r
 }\r
-#endif\r
 \r
 /*\r
  * FIFO support.\r
@@ -364,13 +388,13 @@ static void serial_rk_stop_tx(struct uart_port *port)
        struct uart_rk_port *up =\r
                container_of(port, struct uart_rk_port, port);\r
 #if USE_DMA\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-\r
-       if(OPEN_DMA == prk29_uart_dma_t->use_dma){\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       if(uart_dma->use_dma & TX_DMA){\r
                serial_rk_release_dma_tx(port);\r
        }\r
 #endif\r
        __stop_tx(up);\r
+\r
 }\r
 \r
 \r
@@ -379,11 +403,16 @@ static void serial_rk_start_tx(struct uart_port *port)
        struct uart_rk_port *up =\r
                container_of(port, struct uart_rk_port, port);\r
 \r
-\r
-       if(0 == serial_rk_start_tx_dma(port)){\r
+#if USE_DMA\r
+       if(up->dma->use_dma & TX_DMA) {\r
+               if(!up->dma->tx_dma_used)\r
+                       serial_rk_enable_ier_thri(up);\r
+       }else {\r
                serial_rk_enable_ier_thri(up);\r
        }\r
-\r
+#else\r
+       serial_rk_enable_ier_thri(up);\r
+#endif\r
 }\r
 \r
 \r
@@ -392,9 +421,8 @@ static void serial_rk_stop_rx(struct uart_port *port)
        struct uart_rk_port *up =\r
                container_of(port, struct uart_rk_port, port);\r
 #if USE_DMA\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-\r
-       if(OPEN_DMA == prk29_uart_dma_t->use_dma){\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       if(uart_dma->use_dma & RX_DMA){\r
                serial_rk_release_dma_rx(port);\r
        }\r
 #endif\r
@@ -425,17 +453,17 @@ static void serial_rk_enable_ms(struct uart_port *port)
 #define DMA_SERIAL_BUFFER_SIZE     UART_XMIT_SIZE\r
 \r
 /* added by hhb@rock-chips.com  for uart dma transfer*/\r
-static struct rk29_uart_dma_t rk29_uart_ports_dma_t[] = {\r
-               {UART0_USE_DMA, 0, DMACH_UART0_RX, DMACH_UART0_TX},\r
-               {UART1_USE_DMA, 0, DMACH_UART1_RX, DMACH_UART1_TX},\r
-               {UART2_USE_DMA, 0, DMACH_UART2_RX, DMACH_UART2_TX},\r
-               {UART3_USE_DMA, 0, DMACH_UART3_RX, DMACH_UART3_TX},\r
+static struct rk_uart_dma rk29_uart_ports_dma[] = {\r
+               {UART0_USE_DMA, DMACH_UART0_RX, DMACH_UART0_TX},\r
+               {UART1_USE_DMA, DMACH_UART1_RX, DMACH_UART1_TX},\r
+               {UART2_USE_DMA, DMACH_UART2_RX, DMACH_UART2_TX},\r
+               {UART3_USE_DMA, DMACH_UART3_RX, DMACH_UART3_TX},\r
 };\r
 \r
 \r
 /* DMAC PL330 add by hhb@rock-chips.com */\r
 static struct rk29_dma_client rk29_uart_dma_client = {\r
-       .name = "rk29xx-uart-dma",\r
+       .name = "rk-uart-dma",\r
 };\r
 \r
 /*TX*/\r
@@ -444,13 +472,14 @@ static void serial_rk_release_dma_tx(struct uart_port *port)
 {\r
        struct uart_rk_port *up =\r
                        container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
        if(!port){\r
                return;\r
        }\r
-       if(prk29_uart_dma_t && prk29_uart_dma_t->tx_dma_inited) {\r
-               rk29_dma_free(prk29_uart_dma_t->tx_dmach, &rk29_uart_dma_client);\r
-               prk29_uart_dma_t->tx_dma_inited = 0;\r
+       if(uart_dma && uart_dma->tx_dma_inited) {\r
+               rk29_dma_free(uart_dma->tx_dmach, &rk29_uart_dma_client);\r
+               uart_dma->tx_dma_inited = 0;\r
+               uart_dma->tx_dma_used = 0;\r
        }\r
 }\r
 \r
@@ -461,21 +490,21 @@ static void serial_rk_dma_txcb(void *buf, int size, enum rk29_dma_buffresult res
        struct circ_buf *xmit = &port->state->xmit;\r
 \r
        if(result != RK29_RES_OK){\r
+               printk(">>>>%s:%d result:%d\n", __func__, __LINE__, result);\r
+               up->dma->tx_dma_used = 0;\r
                return;\r
        }\r
 \r
-       port->icount.tx += size;\r
+       //spin_lock(&(up->dma->rx_lock));\r
        xmit->tail = (xmit->tail + size) & (UART_XMIT_SIZE - 1);\r
-\r
+       port->icount.tx += size;\r
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)\r
                uart_write_wakeup(&up->port);\r
-       spin_lock(&(up->prk29_uart_dma_t->tx_lock));\r
-       up->prk29_uart_dma_t->tx_dma_used = 0;\r
-       spin_unlock(&(up->prk29_uart_dma_t->tx_lock));\r
-       if (!uart_circ_empty(xmit)) {\r
-               serial_rk_start_tx_dma(port);\r
-       }\r
 \r
+       //spin_lock(&(up->dma->tx_lock));\r
+       up->dma->tx_dma_used = 0;\r
+       //spin_unlock(&(up->dma->tx_lock));\r
+       serial_rk_enable_ier_thri(up);\r
        up->port_activity = jiffies;\r
 //     dev_info(up->port.dev, "s:%d\n", size);\r
 }\r
@@ -484,35 +513,38 @@ static int serial_rk_init_dma_tx(struct uart_port *port) {
 \r
        struct uart_rk_port *up =\r
                                container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       if(!port || !prk29_uart_dma_t){\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+\r
+       if(!port || !uart_dma){\r
                dev_info(up->port.dev, "serial_rk_init_dma_tx fail\n");\r
                return -1;\r
        }\r
 \r
-       if(prk29_uart_dma_t->tx_dma_inited) {\r
+       if(uart_dma->tx_dma_inited) {\r
                return 0;\r
        }\r
 \r
-       if (rk29_dma_request(prk29_uart_dma_t->tx_dmach, &rk29_uart_dma_client, NULL) == -EBUSY) {\r
+       if (rk29_dma_request(uart_dma->tx_dmach, &rk29_uart_dma_client, NULL) == -EBUSY) {\r
                dev_info(up->port.dev, "rk29_dma_request tx fail\n");\r
                return -1;\r
        }\r
 \r
-       if (rk29_dma_set_buffdone_fn(prk29_uart_dma_t->tx_dmach, serial_rk_dma_txcb)) {\r
+       if (rk29_dma_set_buffdone_fn(uart_dma->tx_dmach, serial_rk_dma_txcb)) {\r
                dev_info(up->port.dev, "rk29_dma_set_buffdone_fn tx fail\n");\r
                return -1;\r
        }\r
-       if (rk29_dma_devconfig(prk29_uart_dma_t->tx_dmach, RK29_DMASRC_MEM, (unsigned long)(port->iobase + UART_TX))) {\r
+       \r
+       if (rk29_dma_devconfig(uart_dma->tx_dmach, RK29_DMASRC_MEM, (unsigned long)(port->iobase + UART_TX))) {\r
                dev_info(up->port.dev, "rk29_dma_devconfig tx fail\n");\r
                return -1;\r
        }\r
-       if (rk29_dma_config(prk29_uart_dma_t->tx_dmach, 1, 1)) {\r
+       \r
+       if (rk29_dma_config(uart_dma->tx_dmach, 1, 16)) {\r
                dev_info(up->port.dev, "rk29_dma_config tx fail\n");\r
                return -1;\r
        }\r
 \r
-       prk29_uart_dma_t->tx_dma_inited = 1;\r
+       uart_dma->tx_dma_inited = 1;\r
        dev_info(up->port.dev, "serial_rk_init_dma_tx sucess\n");\r
        return 0;\r
 \r
@@ -520,39 +552,37 @@ static int serial_rk_init_dma_tx(struct uart_port *port) {
 \r
 static int serial_rk_start_tx_dma(struct uart_port *port)\r
 {\r
-\r
+       int count = 0;\r
        struct circ_buf *xmit = &port->state->xmit;\r
        struct uart_rk_port *up = container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
 \r
-       if(0 == prk29_uart_dma_t->use_dma){\r
-               return CLOSE_DMA;\r
-       }\r
+       if(!uart_dma->use_dma)\r
+               goto err_out;\r
 \r
-       if(-1 == serial_rk_init_dma_tx(port)){\r
+       if(-1 == serial_rk_init_dma_tx(port))\r
                goto err_out;\r
-       }\r
 \r
-       if (1 == prk29_uart_dma_t->tx_dma_used){\r
+       if (1 == uart_dma->tx_dma_used)\r
                return 1;\r
-       }\r
-       if(!uart_circ_empty(xmit)){\r
-               if (rk29_dma_enqueue(prk29_uart_dma_t->tx_dmach, port,\r
-                               prk29_uart_dma_t->tx_phy_addr + xmit->tail,\r
-                               CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE))) {\r
+\r
+//     spin_lock(&(uart_dma->tx_lock));\r
+       __stop_tx(up);\r
+\r
+       count = SERIAL_CIRC_CNT_TO_END(xmit);\r
+       count -= count%16;\r
+       if(count >= DMA_TX_TRRIGE_LEVEL) {\r
+               if (rk29_dma_enqueue(uart_dma->tx_dmach, port, uart_dma->tx_phy_addr + xmit->tail , count)) {\r
                        goto err_out;\r
                }\r
+               rk29_dma_ctrl(uart_dma->tx_dmach, RK29_DMAOP_START);\r
+               up->dma->tx_dma_used = 1;\r
        }\r
-       rk29_dma_ctrl(prk29_uart_dma_t->tx_dmach, RK29_DMAOP_START);\r
-       spin_lock(&(prk29_uart_dma_t->tx_lock));\r
-       up->prk29_uart_dma_t->tx_dma_used = 1;\r
-       spin_unlock(&(prk29_uart_dma_t->tx_lock));\r
-\r
+//     spin_unlock(&(uart_dma->tx_lock));\r
        return 1;\r
 err_out:\r
        dev_info(up->port.dev, "-serial_rk_start_tx_dma-error-\n");\r
        return -1;\r
-\r
 }\r
 \r
 \r
@@ -560,23 +590,25 @@ err_out:
 /*RX*/\r
 static void serial_rk_dma_rxcb(void *buf, int size, enum rk29_dma_buffresult result) {\r
 \r
-\r
+       //printk(">>%s:%d\n", __func__, result);\r
 }\r
 \r
 static void serial_rk_release_dma_rx(struct uart_port *port)\r
 {\r
        struct uart_rk_port *up =\r
                                container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       \r
        if(!port){\r
                return;\r
        }\r
-       if(prk29_uart_dma_t && prk29_uart_dma_t->rx_dma_inited) {\r
-               del_timer(&prk29_uart_dma_t->rx_timer);\r
-               rk29_dma_free(prk29_uart_dma_t->rx_dmach, &rk29_uart_dma_client);\r
-               prk29_uart_dma_t->rb_pre_pos = 0;\r
-               prk29_uart_dma_t->rx_dma_inited = 0;\r
-               prk29_uart_dma_t->rx_dma_start = 0;\r
+       \r
+       if(uart_dma && uart_dma->rx_dma_inited) {\r
+               del_timer(&uart_dma->rx_timer);\r
+               rk29_dma_free(uart_dma->rx_dmach, &rk29_uart_dma_client);\r
+               uart_dma->rb_tail = 0;\r
+               uart_dma->rx_dma_inited = 0;\r
+               uart_dma->rx_dma_used = 0;\r
        }\r
 }\r
 \r
@@ -585,37 +617,40 @@ static int serial_rk_init_dma_rx(struct uart_port *port) {
 \r
        struct uart_rk_port *up =\r
                                container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       if(!port || !prk29_uart_dma_t){\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+\r
+       if(!port || !uart_dma){\r
                dev_info(up->port.dev, "serial_rk_init_dma_rx: port fail\n");\r
                return -1;\r
        }\r
-       if(prk29_uart_dma_t->rx_dma_inited) {\r
+\r
+       if(uart_dma->rx_dma_inited) {\r
                return 0;\r
        }\r
 \r
-       if (rk29_dma_request(prk29_uart_dma_t->rx_dmach, &rk29_uart_dma_client, NULL) == -EBUSY) {\r
+       if (rk29_dma_request(uart_dma->rx_dmach, &rk29_uart_dma_client, NULL) == -EBUSY) {\r
                dev_info(up->port.dev, "rk29_dma_request fail rx \n");\r
                return -1;\r
        }\r
 \r
-       if (rk29_dma_set_buffdone_fn(prk29_uart_dma_t->rx_dmach, serial_rk_dma_rxcb)) {\r
+       if (rk29_dma_set_buffdone_fn(uart_dma->rx_dmach, serial_rk_dma_rxcb)) {\r
                dev_info(up->port.dev, "rk29_dma_set_buffdone_fn rx fail\n");\r
                return -1;\r
        }\r
-       if (rk29_dma_devconfig(prk29_uart_dma_t->rx_dmach, RK29_DMASRC_HW, (unsigned long)(port->iobase + UART_RX))) {\r
+\r
+       if (rk29_dma_devconfig(uart_dma->rx_dmach, RK29_DMASRC_HW, (unsigned long)(port->iobase + UART_RX))) {\r
                dev_info(up->port.dev, "rk29_dma_devconfig rx fail\n");\r
                return -1;\r
        }\r
 \r
-       if (rk29_dma_config(prk29_uart_dma_t->rx_dmach, 1, 1)) {\r
-               dev_info(up->port.dev, "rk29_dma_config rx fail\n");\r
+       if (rk29_dma_config(uart_dma->rx_dmach, 1, 1)) {\r
+               dev_info(up->port.dev, "rk29_dma_config rx fail 1 1 \n");\r
                return -1;\r
        }\r
 \r
-       rk29_dma_setflags(prk29_uart_dma_t->rx_dmach, RK29_DMAF_CIRCULAR);\r
+       rk29_dma_setflags(uart_dma->rx_dmach, RK29_DMAF_CIRCULAR);\r
 \r
-       prk29_uart_dma_t->rx_dma_inited = 1;\r
+       uart_dma->rx_dma_inited = 1;\r
        dev_info(up->port.dev, "serial_rk_init_dma_rx sucess\n");\r
        return 0;\r
 \r
@@ -625,38 +660,34 @@ static int serial_rk_start_rx_dma(struct uart_port *port)
 {\r
        struct uart_rk_port *up =\r
                                container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       if(0 == prk29_uart_dma_t->use_dma){\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       if(!uart_dma->use_dma)\r
                return 0;\r
-       }\r
 \r
-       if(prk29_uart_dma_t->rx_dma_start == 1){\r
+       if(uart_dma->rx_dma_used == 1)\r
                return 0;\r
-       }\r
 \r
        if(-1 == serial_rk_init_dma_rx(port)){\r
                dev_info(up->port.dev, "*******serial_rk_init_dma_rx*******error*******\n");\r
                return -1;\r
        }\r
 \r
-       if (rk29_dma_enqueue(prk29_uart_dma_t->rx_dmach, (void *)up, prk29_uart_dma_t->rx_phy_addr,\r
-                       prk29_uart_dma_t->rx_buffer_size/2)) {\r
+       if (rk29_dma_enqueue(uart_dma->rx_dmach, (void *)up, uart_dma->rx_phy_addr,\r
+                       uart_dma->rb_size/2)) {\r
                dev_info(up->port.dev, "*******rk29_dma_enqueue fail*****\n");\r
                return -1;\r
        }\r
 \r
-       if (rk29_dma_enqueue(prk29_uart_dma_t->rx_dmach, (void *)up,\r
-                       prk29_uart_dma_t->rx_phy_addr+prk29_uart_dma_t->rx_buffer_size/2,\r
-               prk29_uart_dma_t->rx_buffer_size/2)) {\r
+       if (rk29_dma_enqueue(uart_dma->rx_dmach, (void *)up,\r
+                       uart_dma->rx_phy_addr+uart_dma->rb_size/2, uart_dma->rb_size/2)) {\r
                dev_info(up->port.dev, "*******rk29_dma_enqueue fail*****\n");\r
                return -1;\r
        }\r
 \r
-       rk29_dma_ctrl(prk29_uart_dma_t->rx_dmach, RK29_DMAOP_START);\r
-       prk29_uart_dma_t->rx_dma_start = 1;\r
-       if(prk29_uart_dma_t->use_timer == 1){\r
-               mod_timer(&prk29_uart_dma_t->rx_timer, jiffies +\r
-                               msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
+       rk29_dma_ctrl(uart_dma->rx_dmach, RK29_DMAOP_START);\r
+       uart_dma->rx_dma_used = 1;\r
+       if(uart_dma->use_timer == 1){\r
+               mod_timer(&uart_dma->rx_timer, jiffies + msecs_to_jiffies(uart_dma->rx_timeout));\r
        }\r
        up->port_activity = jiffies;\r
        return 1;\r
@@ -665,113 +696,76 @@ static int serial_rk_start_rx_dma(struct uart_port *port)
 static void serial_rk_update_rb_addr(struct uart_rk_port *up){\r
        dma_addr_t current_pos = 0;\r
        dma_addr_t rx_current_pos = 0;\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       spin_lock(&(up->prk29_uart_dma_t->rx_lock));\r
-       rk29_dma_getposition(prk29_uart_dma_t->rx_dmach, &current_pos, &rx_current_pos);\r
-\r
-       prk29_uart_dma_t->rb_cur_pos = (rx_current_pos - prk29_uart_dma_t->rx_phy_addr);\r
-       prk29_uart_dma_t->rx_size = CIRC_CNT(prk29_uart_dma_t->rb_cur_pos,\r
-                       prk29_uart_dma_t->rb_pre_pos, prk29_uart_dma_t->rx_buffer_size);\r
-\r
-       spin_unlock(&(up->prk29_uart_dma_t->rx_lock));\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       //spin_lock(&(up->dma->rx_lock));\r
+       uart_dma->rx_size = 0;\r
+       if(uart_dma->rx_dma_used == 1){\r
+               rk29_dma_getposition(uart_dma->rx_dmach, &current_pos, &rx_current_pos);\r
+               uart_dma->rb_head = (rx_current_pos - uart_dma->rx_phy_addr);\r
+               uart_dma->rx_size = CIRC_CNT(uart_dma->rb_head, uart_dma->rb_tail, uart_dma->rb_size);\r
+       }\r
+       //spin_unlock(&(up->dma->rx_lock));\r
 }\r
 \r
 static void serial_rk_report_dma_rx(unsigned long uart)\r
 {\r
+       int count, flip = 0;\r
        struct uart_rk_port *up = (struct uart_rk_port *)uart;\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       if(prk29_uart_dma_t->use_timer == 1){\r
-               serial_rk_update_rb_addr(up);\r
-       }\r
-       if(prk29_uart_dma_t->rx_size > 0) {\r
-               spin_lock(&(up->prk29_uart_dma_t->rx_lock));\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
 \r
-               if(prk29_uart_dma_t->rb_cur_pos > prk29_uart_dma_t->rb_pre_pos){\r
-                       tty_insert_flip_string(up->port.state->port.tty, prk29_uart_dma_t->rx_buffer\r
-                                       + prk29_uart_dma_t->rb_pre_pos, prk29_uart_dma_t->rx_size);\r
-                       tty_flip_buffer_push(up->port.state->port.tty);\r
-               }\r
-               else if(prk29_uart_dma_t->rb_cur_pos < prk29_uart_dma_t->rb_pre_pos){\r
-\r
-                       tty_insert_flip_string(up->port.state->port.tty, prk29_uart_dma_t->rx_buffer\r
-                                       + prk29_uart_dma_t->rb_pre_pos, CIRC_CNT_TO_END(prk29_uart_dma_t->rb_cur_pos,\r
-                                       prk29_uart_dma_t->rb_pre_pos, prk29_uart_dma_t->rx_buffer_size));\r
-                       tty_flip_buffer_push(up->port.state->port.tty);\r
+       if(!uart_dma->rx_dma_used || !up->port.state->port.tty)\r
+               return;\r
 \r
-                       if(prk29_uart_dma_t->rb_cur_pos != 0){\r
-                               tty_insert_flip_string(up->port.state->port.tty, prk29_uart_dma_t->rx_buffer,\r
-                                               prk29_uart_dma_t->rb_cur_pos);\r
-                               tty_flip_buffer_push(up->port.state->port.tty);\r
-                       }\r
-               }\r
+       serial_rk_update_rb_addr(up);\r
 \r
-               prk29_uart_dma_t->rb_pre_pos = (prk29_uart_dma_t->rb_pre_pos + prk29_uart_dma_t->rx_size)\r
-                               & (prk29_uart_dma_t->rx_buffer_size - 1);\r
-               up->port.icount.rx += prk29_uart_dma_t->rx_size;\r
-               spin_unlock(&(up->prk29_uart_dma_t->rx_lock));\r
-               prk29_uart_dma_t->rx_timeout = 7;\r
+       while(1) {\r
+               count = CIRC_CNT_TO_END(uart_dma->rb_head, uart_dma->rb_tail, uart_dma->rb_size);\r
+               if(count <= 0)\r
+                       break;\r
+               up->port.icount.rx += count;\r
+               flip = tty_insert_flip_string(up->port.state->port.tty, uart_dma->rx_buffer\r
+                               + uart_dma->rb_tail, count);\r
+               tty_flip_buffer_push(up->port.state->port.tty);\r
+               uart_dma->rb_tail = (uart_dma->rb_tail + count) & (uart_dma->rb_size - 1);\r
                up->port_activity = jiffies;\r
        }\r
 \r
+       //if (uart_dma->rx_size > 0)\r
+       //      printk("rx_size:%d ADDR:%x\n", uart_dma->rx_size, uart_dma->rb_head);\r
 \r
-#if 1\r
-       if (jiffies_to_msecs(jiffies - up->port_activity) < RX_TIMEOUT) {\r
-               if(prk29_uart_dma_t->use_timer == 1){\r
-                       mod_timer(&prk29_uart_dma_t->rx_timer, jiffies + msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
-               }\r
-       } else {\r
-\r
-#if 1\r
-\r
-\r
-               prk29_uart_dma_t->rx_timeout = 20;\r
-               mod_timer(&prk29_uart_dma_t->rx_timer, jiffies + msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
-#else\r
-//             serial_out(up, 0x2a, 0x01);\r
-               serial_rk_release_dma_rx(&up->port);\r
-               serial_out(up, 0x2a, 0x01);\r
-               up->ier |= (UART_IER_RDI | UART_IER_RLSI);\r
-               serial_out(up, UART_IER, up->ier);\r
-//             serial_out(up, 0x22, 0x01);\r
-               dev_info(up->port.dev, "*****enable recv int*****\n");\r
-\r
-               //serial_rk_start_rx_dma(&up->port);\r
-#endif\r
-       }\r
-\r
-\r
-#else\r
-       if(prk29_uart_dma_t->use_timer == 1){\r
-               mod_timer(&prk29_uart_dma_t->rx_timer, jiffies + msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
+       if(uart_dma->use_timer == 1){\r
+               mod_timer(&uart_dma->rx_timer, jiffies + msecs_to_jiffies(uart_dma->rx_timeout));\r
        }\r
-#endif\r
 \r
 }\r
-\r
+#if 0\r
 static void serial_rk_rx_timeout(unsigned long uart)\r
 {\r
        struct uart_rk_port *up = (struct uart_rk_port *)uart;\r
 \r
-       //serial_rk_report_dma_rx(up);\r
-       queue_work(up->uart_wq, &up->uart_work);\r
+       serial_rk_report_dma_rx(up);\r
+       //queue_work(up->uart_wq, &up->uart_work);\r
 }\r
 \r
 static void serial_rk_report_revdata_workfunc(struct work_struct *work)\r
 {\r
        struct uart_rk_port *up =\r
                                container_of(work, struct uart_rk_port, uart_work);\r
+\r
        serial_rk_report_dma_rx((unsigned long)up);\r
-       spin_lock(&(up->prk29_uart_dma_t->rx_lock));\r
 \r
-       if(up->prk29_uart_dma_t->use_timer == 1){\r
+       //spin_lock(&(up->dma->rx_lock));\r
+\r
+       if(up->port.state->port.tty && up->dma->use_timer != 1 && up->fifo_size > 0){\r
 \r
-       }else{\r
                tty_insert_flip_string(up->port.state->port.tty, up->fifo, up->fifo_size);\r
                tty_flip_buffer_push(up->port.state->port.tty);\r
                up->port.icount.rx += up->fifo_size;\r
+               up->ier |= UART_IER_RDI;\r
+               serial_out(up, UART_IER, up->ier);\r
        }\r
 \r
-       spin_unlock(&(up->prk29_uart_dma_t->rx_lock));\r
+       //spin_unlock(&(up->dma->rx_lock));\r
 \r
 }\r
 \r
@@ -780,10 +774,15 @@ static void serial_rk_start_dma_rx(struct work_struct *work)
 {\r
        struct uart_rk_port *up =\r
                                        container_of(work, struct uart_rk_port, uart_work_rx);\r
-       serial_rk_start_rx_dma(&up->port);\r
+\r
+       //mod_timer(&up->dma->rx_timer, jiffies + msecs_to_jiffies(up->dma->rx_timeout));\r
+       //rk29_dma_ctrl(up->dma->rx_dmach, RK29_DMAOP_START);\r
+       //serial_rk_start_rx_dma(&up->port);\r
+\r
 }\r
-#endif /* USE_DMA */\r
+#endif\r
 \r
+#endif /* USE_DMA */\r
 \r
 \r
 static void\r
@@ -883,8 +882,16 @@ static void transmit_chars(struct uart_rk_port *up)
                __stop_tx(up);\r
                return;\r
        }\r
-\r
-       count = up->tx_loadsz;\r
+#if USE_DMA\r
+       //hhb\r
+       if(up->dma->use_dma & TX_DMA){\r
+               if(SERIAL_CIRC_CNT_TO_END(xmit) >= DMA_TX_TRRIGE_LEVEL){\r
+                       serial_rk_start_tx_dma(&up->port);\r
+                       return;\r
+               }\r
+       }\r
+#endif\r
+       count = up->port.fifosize - serial_in(up , 0x20);\r
        do {\r
                serial_out(up, UART_TX, xmit->buf[xmit->tail]);\r
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);\r
@@ -897,7 +904,9 @@ static void transmit_chars(struct uart_rk_port *up)
                uart_write_wakeup(&up->port);\r
 \r
        DEBUG_INTR("THRE...");\r
-\r
+#if USE_DMA\r
+       up->port_activity = jiffies;\r
+#endif\r
        if (uart_circ_empty(xmit))\r
                __stop_tx(up);\r
 }\r
@@ -940,29 +949,33 @@ static void serial_rk_handle_port(struct uart_rk_port *up)
        /* reading UART_LSR can automatically clears PE FE OE bits, except receive fifo error bit*/\r
        status = serial_in(up, UART_LSR);\r
 \r
-       DEBUG_INTR("status = %x...", status);\r
+       DEBUG_INTR("status = %x...\n", status);\r
 #if USE_DMA\r
        /* DMA mode enable */\r
-       if(up->prk29_uart_dma_t->use_dma == 1) {\r
-\r
-               if(up->iir & UART_IIR_RLSI){\r
-                       if (status & (UART_LSR_DR | UART_LSR_BI)) {\r
-                               up->port_activity = jiffies;\r
-                               up->ier &= ~UART_IER_RLSI;\r
-                               up->ier &= ~UART_IER_RDI;\r
-                               serial_out(up, UART_IER, up->ier);\r
-                               //receive_chars(up, &status);\r
-                               //mod_timer(&up->prk29_uart_dma_t->rx_timer, jiffies +\r
-                               //msecs_to_jiffies(up->prk29_uart_dma_t->rx_timeout));\r
-                               if(serial_rk_start_rx_dma(&up->port) == -1){\r
-                                       receive_chars(up, &status);\r
-                               }\r
+       if(up->dma->use_dma) {\r
+\r
+               if (status & UART_LSR_RFE) {\r
+                       if(up->port.line != DBG_PORT){\r
+                               dev_info(up->port.dev, "error:lsr=0x%x\n", status);\r
+                               status = serial_in(up, UART_LSR);\r
+                               DEBUG_INTR("error:lsr=0x%x\n", status);\r
                        }\r
                }\r
 \r
-       } else\r
+               if (status & 0x02) {\r
+                       if(up->port.line != DBG_PORT){\r
+                               dev_info(up->port.dev, "error:lsr=0x%x\n", status);\r
+                               status = serial_in(up, UART_LSR);\r
+                               DEBUG_INTR("error:lsr=0x%x\n", status);\r
+                       }\r
+               }\r
+\r
+               if ((up->iir & 0x0f) == 0x02) {\r
+                       transmit_chars(up);\r
+               }\r
+       } else \r
 #endif\r
-       {       //dma mode disable\r
+       {   //dma mode disable\r
 \r
                /*\r
                 * when uart receive a serial of data which doesn't have stop bit and so on, that causes frame error,and\r
@@ -972,25 +985,25 @@ static void serial_rk_handle_port(struct uart_rk_port *up)
                 */\r
 \r
                if (status & UART_LSR_RFE) {\r
-                       \r
                        if(up->port.line != DBG_PORT){\r
-                               status = serial_in(up, UART_LSR);\r
                                dev_info(up->port.dev, "error:lsr=0x%x\n", status);\r
+                               status = serial_in(up, UART_LSR);\r
+                               DEBUG_INTR("error:lsr=0x%x\n", status);\r
+                               rk29_uart_dump_register(up);\r
                        }\r
-                       \r
-                       \r
-               //      rk29_uart_dump_register(up);\r
                }\r
 \r
                if (status & (UART_LSR_DR | UART_LSR_BI)) {\r
                        receive_chars(up, &status);\r
                }\r
                check_modem_status(up);\r
-               if (status & UART_LSR_THRE) {\r
+               //hhb@rock-chips.com when FIFO and THRE mode both are enabled,and FIFO TX empty trigger is set to larger than 1,\r
+               //,we need to add ((up->iir & 0x0f) == 0x02) to transmit_chars,because when entering interrupt,the FIFO and THR\r
+               //might not be 1.\r
+               if ((up->iir & 0x0f) == 0x02) {\r
                        transmit_chars(up);\r
                }\r
        }\r
-\r
        spin_unlock_irqrestore(&up->port.lock, flags);\r
 }\r
 \r
@@ -1007,7 +1020,6 @@ static irqreturn_t serial_rk_interrupt(int irq, void *dev_id)
        iir = serial_in(up, UART_IIR);\r
 \r
        DEBUG_INTR("%s(%d) iir = 0x%02x\n", __func__, irq, iir);\r
-\r
        up->iir = iir;\r
 \r
        if (!(iir & UART_IIR_NO_INT)) {\r
@@ -1190,8 +1202,8 @@ static int serial_rk_startup(struct uart_port *port)
        struct uart_rk_port *up =\r
                container_of(port, struct uart_rk_port, port);\r
        unsigned long flags;\r
-       int retval;\r
-\r
+       int retval, fifosize = 0;\r
+       \r
 \r
        dev_dbg(port->dev, "%s\n", __func__);\r
 \r
@@ -1214,6 +1226,13 @@ static int serial_rk_startup(struct uart_port *port)
         */\r
        serial_rk_clear_fifos(up);\r
 \r
+       //read uart fifo size  hhb@rock-chips.com\r
+       fifosize = __raw_readl(up->port.membase + 0xf4);\r
+       up->port.fifosize = ((fifosize >> 16) & 0xff) << 4;\r
+       if(up->port.fifosize <= 0)\r
+               up->port.fifosize = 32;\r
+       //printk("fifo size:%d :%08x\n", up->port.fifosize, fifosize);\r
+\r
        /*\r
         * Clear the interrupt registers.\r
         */\r
@@ -1253,26 +1272,14 @@ static int serial_rk_startup(struct uart_port *port)
 #if 0\r
        up->msr_saved_flags = 0;\r
 #endif\r
-\r
 #if USE_DMA\r
-       if (1 == up->prk29_uart_dma_t->use_dma) {\r
-\r
-               if(up->port.state->xmit.buf != up->prk29_uart_dma_t->tx_buffer){\r
+       if (up->dma->use_dma & TX_DMA) {\r
+               if(up->port.state->xmit.buf != up->dma->tx_buffer){\r
                        free_page((unsigned long)up->port.state->xmit.buf);\r
-                       up->port.state->xmit.buf = up->prk29_uart_dma_t->tx_buffer;\r
+                       up->port.state->xmit.buf = up->dma->tx_buffer;\r
                }\r
-\r
-#if 1\r
-               serial_rk_start_rx_dma(&up->port);\r
-#else\r
-               up->ier |= UART_IER_RDI;\r
-               up->ier |= UART_IER_RLSI;\r
-               serial_out(up, UART_IER, up->ier);\r
+       } else \r
 #endif\r
-               up->port_activity = jiffies;\r
-\r
-       } else\r
-#endif /* USE_DMA */\r
        {\r
                up->ier = 0;\r
                serial_out(up, UART_IER, up->ier);\r
@@ -1316,7 +1323,10 @@ static void serial_rk_shutdown(struct uart_port *port)
         * Read data port to reset things, and then free the irq\r
         */\r
        (void) serial_in(up, UART_RX);\r
-\r
+#if USE_DMA\r
+       //if (up->dma->use_dma & TX_DMA)\r
+       //      up->port.state->xmit.buf = NULL;\r
+#endif\r
        free_irq(up->port.irq, up);\r
        clk_disable(up->clk);\r
        clk_disable(up->pclk);\r
@@ -1328,10 +1338,9 @@ serial_rk_set_termios(struct uart_port *port, struct ktermios *termios,
 {\r
        struct uart_rk_port *up =\r
                container_of(port, struct uart_rk_port, port);\r
-       unsigned char cval, fcr = 0;\r
+       unsigned char cval = 0, fcr = 0, mcr = 0;\r
        unsigned long flags;\r
        unsigned int baud, quot;\r
-       int timeout = 1000000;\r
        dev_dbg(port->dev, "+%s\n", __func__);\r
 \r
        switch (termios->c_cflag & CSIZE) {\r
@@ -1373,44 +1382,36 @@ serial_rk_set_termios(struct uart_port *port, struct ktermios *termios,
                                  port->uartclk / 16);\r
 \r
        quot = uart_get_divisor(port, baud);\r
-\r
-       dev_info(up->port.dev, "baud:%d\n", baud);\r
-//     dev_info(up->port.dev, "quot:%d\n", quot);\r
-\r
-       /*\r
-        * To wait long enough to avoid writting lcr when the uart is busy\r
-        * because of data communication, so that we can set lcr and baud rate\r
-        * successfully. added by hhb@rock-chips.com\r
-        */\r
-\r
-       while(serial_in(up, UART_USR) & UART_USR_BUSY){\r
-               if(--timeout == 0){\r
-                       if(port->line != DBG_PORT){\r
-                               serial_out(up, UART_SRR, UART_RESET);\r
-                       }\r
-                       dbg("rk_serial_set_termios uart.%d timeout,irq=%d,ret=0x%x  AND uart is reseted\n",\r
-                                       port->line, port->irq, serial_in(up, UART_USR));\r
-                       break;\r
-               }\r
-               cpu_relax();\r
-       }\r
-\r
-\r
-       printk("serial.%d timeout:%d\n", up->port.line,timeout);\r
-\r
+       //dev_info(up->port.dev, "uartclk:%d\n", port->uartclk/16);\r
+       //dev_info(up->port.dev, "baud:%d\n", baud);\r
+       //dev_info(up->port.dev, "quot:%d\n", quot);\r
 \r
        if (baud < 2400){\r
                fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;\r
        }\r
        else{\r
+               fcr = UART_FCR_ENABLE_FIFO;\r
 #if USE_DMA\r
                //added by hhb@rock-chips.com\r
-               if(up->prk29_uart_dma_t->use_timer == 1){\r
-                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_01;\r
+               if(up->dma->use_dma & TX_DMA){\r
+                       fcr |= UART_FCR_T_TRIG_01;\r
                } else\r
 #endif\r
                {\r
-                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | UART_FCR_T_TRIG_01;\r
+                       fcr |= UART_FCR_T_TRIG_01;\r
+               }\r
+\r
+#if USE_DMA\r
+               //added by hhb@rock-chips.com\r
+               if(up->dma->use_dma & RX_DMA){  \r
+                       fcr |= UART_FCR_R_TRIG_00;\r
+               } else\r
+#endif\r
+               {\r
+                       if (termios->c_cflag & CRTSCTS)\r
+                               fcr |= UART_FCR_R_TRIG_11;\r
+                       else\r
+                               fcr |= UART_FCR_R_TRIG_00;\r
                }\r
        }\r
 \r
@@ -1475,44 +1476,65 @@ serial_rk_set_termios(struct uart_port *port, struct ktermios *termios,
                up->ier |= UART_IER_MSI;\r
 #endif\r
 \r
+       //to avoid uart busy when set baud rate  hhb@rock-chips.com\r
+       serial_out(up, UART_SRR, UART_RESET);\r
+       mcr = serial_in(up, UART_MCR);\r
+       serial_out(up, UART_MCR, mcr | 0x10);  //loopback mode\r
+       \r
        up->lcr = cval;                         /* Save LCR */\r
        /* set DLAB */\r
-       if(serial_lcr_write(up, cval | UART_LCR_DLAB)){\r
-               dbg("serial.%d set DLAB fail\n", up->port.line);\r
+       if(serial_lcr_write(up, cval | UART_LCR_DLAB)) {\r
+               if(up->port.line != DBG_PORT)\r
+                       dbg("serial.%d set DLAB fail\n", up->port.line);\r
                serial_out(up, UART_SRR, UART_RESET);\r
                goto fail;\r
        }\r
 \r
        /* set uart baud rate */\r
-       if(serial_dl_write(up, quot)){\r
-               dbg("serial.%d set dll fail\n", up->port.line);\r
+       if(serial_dl_write(up, quot)) {\r
+               if(up->port.line != DBG_PORT)\r
+                       dbg("serial.%d set dll fail\n", up->port.line);\r
                serial_out(up, UART_SRR, UART_RESET);\r
                goto fail;\r
        }\r
 \r
        /* reset DLAB */\r
-       if(serial_lcr_write(up, cval)){\r
-               dbg("serial.%d reset DLAB fail\n", up->port.line);\r
+       if(serial_lcr_write(up, cval)) {\r
+               if(up->port.line != DBG_PORT)\r
+                       dbg("serial.%d reset DLAB fail\n", up->port.line);\r
                serial_out(up, UART_SRR, UART_RESET);\r
                goto fail;\r
        }\r
-       else{\r
+       else {\r
                serial_rk_set_mctrl(&up->port, up->port.mctrl);\r
-               serial_out(up, UART_FCR, fcr);          /* set fcr */\r
                up->fcr = fcr;\r
-               /* enable the uart interrupt last */\r
-               up->ier |= UART_IER_RDI;\r
-               up->ier |= UART_IER_RLSI;\r
+               serial_out(up, UART_FCR, up->fcr);              /* set fcr */\r
+               up->ier = 0;\r
+               //start serial receive data\r
+#if USE_DMA\r
+               if (up->dma->use_dma) {\r
+                       up->ier |= UART_IER_RLSI;\r
+                       up->ier |= UART_IER_PTIME;   //Programmable THRE Interrupt Mode Enable\r
+                       serial_rk_start_rx_dma(&up->port);\r
+               } else\r
+#endif\r
+               {\r
+                       //  not use dma receive\r
+                       up->ier |= UART_IER_RDI;\r
+                       up->ier |= UART_IER_RLSI;\r
+                       if(up->port.line != DBG_PORT)\r
+                               up->ier |= UART_IER_PTIME;   //Programmable THRE Interrupt Mode Enable\r
+\r
+               }\r
                serial_out(up, UART_IER, up->ier);\r
        }\r
-\r
+       \r
        spin_unlock_irqrestore(&up->port.lock, flags);\r
 \r
        /* Don't rewrite B0 */\r
        if (tty_termios_baud_rate(termios))\r
                tty_termios_encode_baud_rate(termios, baud, baud);\r
        dev_dbg(port->dev, "-%s baud %d\n", __func__, baud);\r
-\r
        return;\r
 \r
 fail:\r
@@ -1743,6 +1765,7 @@ static int __devinit serial_rk_probe(struct platform_device *pdev)
        struct resource         *mem;\r
        int irq;\r
        int ret = -ENOSPC;\r
+       \r
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
        if (!mem) {\r
                dev_err(&pdev->dev, "no mem resource?\n");\r
@@ -1777,7 +1800,7 @@ static int __devinit serial_rk_probe(struct platform_device *pdev)
        }\r
        up->tx_loadsz = 30;\r
 #if USE_DMA\r
-       up->prk29_uart_dma_t = &rk29_uart_ports_dma_t[pdev->id];\r
+       up->dma = &rk29_uart_ports_dma[pdev->id];\r
 #endif\r
        up->port.dev = &pdev->dev;\r
        up->port.type = PORT_RK;\r
@@ -1785,6 +1808,7 @@ static int __devinit serial_rk_probe(struct platform_device *pdev)
        up->port.iotype = UPIO_DWAPB;\r
 \r
        up->port.regshift = 2;\r
+       //fifo size default is 32, but it will be updated later when start_up\r
        up->port.fifosize = 32;\r
        up->port.ops = &serial_rk_pops;\r
        up->port.line = pdev->id;\r
@@ -1800,54 +1824,56 @@ static int __devinit serial_rk_probe(struct platform_device *pdev)
 \r
 #if USE_DMA\r
        /* set dma config */\r
-       if(1 == up->prk29_uart_dma_t->use_dma) {\r
+       if(up->dma->use_dma & RX_DMA) {\r
                pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);\r
-\r
                //timer\r
-               up->prk29_uart_dma_t->use_timer = USE_TIMER;\r
-               up->prk29_uart_dma_t->rx_timer.function = serial_rk_rx_timeout;\r
-               up->prk29_uart_dma_t->rx_timer.data = (unsigned long)up;\r
-               up->prk29_uart_dma_t->rx_timeout = 7;\r
-               up->prk29_uart_dma_t->rx_timer.expires = jiffies + msecs_to_jiffies(up->prk29_uart_dma_t->rx_timeout);\r
-               init_timer(&up->prk29_uart_dma_t->rx_timer);\r
-               //tx buffer\r
-               up->prk29_uart_dma_t->tx_buffer_size = UART_XMIT_SIZE;\r
-               up->prk29_uart_dma_t->tx_buffer = dmam_alloc_coherent(up->port.dev, up->prk29_uart_dma_t->tx_buffer_size,\r
-                               &up->prk29_uart_dma_t->tx_phy_addr, DMA_MEMORY_MAP);\r
-               if(!up->prk29_uart_dma_t->tx_buffer){\r
-                       dev_info(up->port.dev, "dmam_alloc_coherent dma_tx_buffer fail\n");\r
-               }\r
-               else{\r
-                       dev_info(up->port.dev, "dma_tx_buffer 0x%08x\n", (unsigned) up->prk29_uart_dma_t->tx_buffer);\r
-                       dev_info(up->port.dev, "dma_tx_phy 0x%08x\n", (unsigned) up->prk29_uart_dma_t->tx_phy_addr);\r
-               }\r
+               up->dma->use_timer = USE_TIMER;\r
+               up->dma->rx_timer.function = serial_rk_report_dma_rx;\r
+               up->dma->rx_timer.data = (unsigned long)up;\r
+               up->dma->rx_timeout = 10;\r
+               up->dma->rx_timer.expires = jiffies + msecs_to_jiffies(up->dma->rx_timeout);\r
+               init_timer(&up->dma->rx_timer);\r
+\r
                //rx buffer\r
-               up->prk29_uart_dma_t->rx_buffer_size = UART_XMIT_SIZE*32;\r
-               up->prk29_uart_dma_t->rx_buffer = dmam_alloc_coherent(up->port.dev, up->prk29_uart_dma_t->rx_buffer_size,\r
-                               &up->prk29_uart_dma_t->rx_phy_addr, DMA_MEMORY_MAP);\r
-               up->prk29_uart_dma_t->rb_pre_pos = 0;\r
-               if(!up->prk29_uart_dma_t->rx_buffer){\r
+               up->dma->rb_size =  UART_XMIT_SIZE*8;\r
+               up->dma->rx_buffer = dmam_alloc_coherent(up->port.dev, up->dma->rb_size,\r
+                               &up->dma->rx_phy_addr, DMA_MEMORY_MAP);\r
+               up->dma->rb_tail = 0;\r
+\r
+               if(!up->dma->rx_buffer){\r
                        dev_info(up->port.dev, "dmam_alloc_coherent dma_rx_buffer fail\n");\r
                }\r
                else {\r
-                       dev_info(up->port.dev, "dma_rx_buffer 0x%08x\n", (unsigned) up->prk29_uart_dma_t->rx_buffer);\r
-                       dev_info(up->port.dev, "up 0x%08x\n", (unsigned)up->prk29_uart_dma_t);\r
+                       dev_info(up->port.dev, "dma_rx_buffer 0x%08x\n", (unsigned) up->dma->rx_buffer);\r
+                       dev_info(up->port.dev, "up 0x%08x\n", (unsigned)up->dma);\r
                }\r
 \r
                // work queue\r
-               INIT_WORK(&up->uart_work, serial_rk_report_revdata_workfunc);\r
-               INIT_WORK(&up->uart_work_rx, serial_rk_start_dma_rx);\r
-               up->uart_wq = create_singlethread_workqueue("uart_workqueue");\r
-               up->prk29_uart_dma_t->rx_dma_start = 0;\r
-               spin_lock_init(&(up->prk29_uart_dma_t->tx_lock));\r
-               spin_lock_init(&(up->prk29_uart_dma_t->rx_lock));\r
+               //INIT_WORK(&up->uart_work, serial_rk_report_revdata_workfunc);\r
+               //INIT_WORK(&up->uart_work_rx, serial_rk_start_dma_rx);\r
+               //up->uart_wq = create_singlethread_workqueue("uart_workqueue");\r
+               up->dma->rx_dma_used = 0;\r
+               spin_lock_init(&(up->dma->rx_lock));\r
                serial_rk_init_dma_rx(&up->port);\r
+       }\r
+\r
+       if(up->dma->use_dma & TX_DMA){\r
+               //tx buffer\r
+               up->dma->tb_size = UART_XMIT_SIZE;\r
+               up->dma->tx_buffer = dmam_alloc_coherent(up->port.dev, up->dma->tb_size,\r
+                               &up->dma->tx_phy_addr, DMA_MEMORY_MAP);\r
+               if(!up->dma->tx_buffer){\r
+                       dev_info(up->port.dev, "dmam_alloc_coherent dma_tx_buffer fail\n");\r
+               }\r
+               else{\r
+                       dev_info(up->port.dev, "dma_tx_buffer 0x%08x\n", (unsigned) up->dma->tx_buffer);\r
+                       dev_info(up->port.dev, "dma_tx_phy 0x%08x\n", (unsigned) up->dma->tx_phy_addr);\r
+               }\r
+               spin_lock_init(&(up->dma->tx_lock));\r
                serial_rk_init_dma_tx(&up->port);\r
-               up->ier |= THRE_MODE;                   // enable THRE interrupt mode\r
-               serial_out(up, UART_IER, up->ier);\r
        }\r
-#endif\r
 \r
+#endif\r
        serial_rk_add_console_port(up);\r
        ret = uart_add_one_port(&serial_rk_reg, &up->port);\r
        if (ret != 0)\r
@@ -1939,6 +1965,8 @@ static struct platform_driver serial_rk_driver = {
 static int __init serial_rk_init(void)\r
 {\r
        int ret;\r
+       //hhb@rock-chips.com\r
+       printk("%s\n", VERSION_AND_TIME);\r
 \r
        ret = uart_register_driver(&serial_rk_reg);\r
        if (ret)\r