drm/rockchip: add rk3399 vop big csc support
[firefly-linux-kernel-4.4.55.git] / drivers / tty / serial / rk_serial.c
index b4d4756c80fda251b6348c16cb4fbe3770f52d89..2f9d8de00ac2d66f66d0c240e1a170f8cbfbf8fb 100644 (file)
  * Date: 2011.06.18\r
  */\r
 \r
-#ifndef CONFIG_SERIAL_RK_CONSOLE\r
-#if defined(CONFIG_SERIAL_RK29_CONSOLE)\r
-#define CONFIG_SERIAL_RK_CONSOLE\r
-#endif\r
-#endif\r
-\r
-#if defined(CONFIG_SERIAL_RK_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)\r
+#if defined(CONFIG_SERIAL_ROCKCHIP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)\r
 #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 +31,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 <linux/timer.h>\r
 #include <linux/workqueue.h>\r
 #include <linux/dma-mapping.h>\r
-\r
 #include <asm/io.h>\r
 #include <asm/irq.h>\r
 \r
+#include <linux/dmaengine.h>\r
+\r
+#ifdef CONFIG_OF\r
+#include <linux/of.h>\r
+#endif\r
+\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 : 2012-08-09\r
+*              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
+*v1.1 : 2012-08-23\r
+*              1. dma driver:make "when tx dma is only enable" work functionally  \r
+*v1.2 : 2012-08-28\r
+*              1. dma driver:serial rx use new dma interface  rk29_dma_enqueue_ring \r
+*v1.3 : 2012-12-14\r
+*              1. When enable Programmable THRE Interrupt Mode, in lsr register, only UART_LSR_TEMT means transmit empty, but\r
+                UART_LSR_THRE doesn't. So, the macro BOTH_EMPTY should be replaced with UART_LSR_TEMT.\r
+*v1.4 : 2013-04-16\r
+*              1.fix bug dma buffer free error\r
+*v1.5 : 2013-10-17\r
+*              1.in some case, set uart rx as gpio interrupt to wake up arm, when arm suspends \r
+*v1.6 : 2013-11-29\r
+               migrate to kernel3.10,and fit device tree\r
+*v1.7 : 2014-03-03\r
+               DMA use new interfaces, and use some interfaces with devm_ prefix \r
+*v1.8 : 2014-03-04\r
+*              1.clear receive time out interrupt request in irq handler       \r
+*/\r
+#define VERSION_AND_TIME  "rk_serial.c v1.8 2014-03-04"\r
 \r
 #define PORT_RK                90\r
 #define UART_USR       0x1F    /* UART Status Register */\r
+#define UART_USR_TX_FIFO_EMPTY         0x04 /* Transmit FIFO empty */\r
+#define UART_USR_TX_FIFO_NOT_FULL      0x02 /* Transmit FIFO not full */\r
 #define UART_USR_BUSY (1)\r
 #define UART_IER_PTIME 0x80    /* Programmable THRE Interrupt Mode Enable */\r
 #define UART_LSR_RFE   0x80    /* receive fifo error */\r
 #define UART_SRR               0x22    /* software reset register */\r
+#define UART_SFE       0x26    /* Shadow FIFO Enable */\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
+//#define BOTH_EMPTY   (UART_LSR_TEMT | UART_LSR_THRE)\r
+#define UART_NR        5   //uart port number\r
 \r
-/* configurate whether the port transmit-receive by DMA */\r
+\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
+#define DMA_SERIAL_BUFFER_SIZE     (UART_XMIT_SIZE*2)\r
+#define CONFIG_CLOCK_CTRL  1\r
+//serial wake up \r
+#ifdef CONFIG_UART0_WAKEUP_RK29 \r
+#define UART0_USE_WAKEUP CONFIG_UART0_WAKEUP_RK29\r
 #else\r
-#define UART0_USE_DMA CLOSE_DMA\r
+#define UART0_USE_WAKEUP 0\r
 #endif\r
-\r
-#ifdef CONFIG_UART2_DMA_RK29\r
-#define UART2_USE_DMA OPEN_DMA\r
+#ifdef CONFIG_UART1_WAKEUP_RK29\r
+#define UART1_USE_WAKEUP CONFIG_UART1_WAKEUP_RK29\r
 #else\r
-#define UART2_USE_DMA CLOSE_DMA\r
+#define UART1_USE_WAKEUP 0\r
 #endif\r
-\r
-#ifdef CONFIG_UART3_DMA_RK29\r
-#define UART3_USE_DMA OPEN_DMA\r
+#ifdef CONFIG_UART2_WAKEUP_RK29\r
+#define UART2_USE_WAKEUP CONFIG_UART2_WAKEUP_RK29\r
 #else\r
-#define UART3_USE_DMA CLOSE_DMA\r
+#define UART2_USE_WAKEUP 0\r
 #endif\r
-\r
-#define UART1_USE_DMA CLOSE_DMA\r
-\r
-#define USE_DMA (UART0_USE_DMA | UART1_USE_DMA | UART2_USE_DMA | UART3_USE_DMA)\r
-#if USE_DMA\r
-#ifdef CONFIG_ARCH_RK29\r
-#include <mach/dma-pl330.h>\r
+#ifdef CONFIG_UART3_WAKEUP_RK29\r
+#define UART3_USE_WAKEUP CONFIG_UART3_WAKEUP_RK29\r
 #else\r
-#include <plat/dma-pl330.h>\r
+#define UART3_USE_WAKEUP 0\r
 #endif\r
+\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
+#define USE_DMA  OPEN_DMA\r
+\r
+#define USE_WAKEUP (UART0_USE_WAKEUP | UART1_USE_WAKEUP | UART2_USE_WAKEUP | UART3_USE_WAKEUP)\r
+\r
+#if USE_WAKEUP\r
+#include <mach/iomux.h>\r
+#include <linux/wakelock.h>\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
+#else\r
+#ifndef CONFIG_RK_DEBUG_UART   //DBG_PORT which uart is used to print log message\r
+#define DBG_PORT 2\r
+#else\r
+#define DBG_PORT CONFIG_RK_DEBUG_UART\r
+#endif\r
+#endif\r
 \r
 #ifdef CONFIG_SERIAL_CORE_CONSOLE\r
 #define uart_console(port)     ((port)->cons && (port)->cons->index == (port)->line)\r
@@ -116,7 +161,6 @@ static struct uart_driver serial_rk_reg;
 #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
@@ -128,11 +172,18 @@ static void dbg(const char *fmt, ...)
        vsprintf(buff, fmt, va);\r
        va_end(va);\r
 \r
+#if defined(CONFIG_DEBUG_LL) || defined(CONFIG_RK_EARLY_PRINTK)\r
        printascii(buff);\r
+#endif\r
 }\r
 \r
+//enable log output\r
+#define DEBUG 0\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,34 +192,67 @@ 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
+       //enum dma_ch rx_dmach;\r
+       //enum dma_ch tx_dmach;\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
+\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
-       struct timer_list       rx_timer;\r
-       int                     rx_timeout;\r
+       char use_timer;\r
+       int      rx_timeout;\r
+       struct timer_list rx_timer;\r
+\r
+       struct dma_chan         *dma_chan_rx, *dma_chan_tx;\r
+       struct scatterlist      rx_sgl, tx_sgl;\r
+       unsigned int            rx_bytes, tx_bytes;\r
+};\r
+#endif\r
 \r
+#if USE_WAKEUP \r
+struct uart_wake_up {\r
+       unsigned int enable;\r
+       unsigned int rx_mode;\r
+       unsigned int tx_mode;\r
+       unsigned int rx_pin;\r
+       char rx_pin_name[32];\r
+       unsigned int tx_pin;\r
+       unsigned int rx_irq;\r
+       char rx_irq_name[32];\r
+       struct wake_lock wakelock;\r
+       char wakelock_name[32];\r
 };\r
 #endif\r
 \r
+#ifdef CONFIG_OF\r
+struct of_rk_serial {\r
+       unsigned int id;\r
+       unsigned int use_dma;   \r
+       unsigned int uartclk;\r
+};\r
+#endif\r
+\r
+\r
 struct uart_rk_port {\r
        struct uart_port        port;\r
        struct platform_device  *pdev;\r
@@ -192,32 +276,38 @@ struct uart_rk_port {
        unsigned char           msr_saved_flags;\r
 #endif\r
 \r
-       char                    name[12];\r
-       char                    fifo[32];\r
+       char                    name[16];\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
+#if USE_WAKEUP\r
+       struct uart_wake_up *wakeup;\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_release_dma_rx(struct uart_port *port);\r
-static int serial_rk_start_rx_dma(struct uart_port *port);\r
+static void serial_rk_release_dma_tx(struct uart_rk_port *up);\r
+static int serial_rk_start_dma_tx(struct uart_rk_port *up);\r
+//static void serial_rk_rx_timeout(unsigned long uart);\r
+static void serial_rk_release_dma_rx(struct uart_rk_port *up);\r
+static int serial_rk_start_dma_rx(struct uart_rk_port *up);\r
+static void serial_rk_stop_dma_tx(struct uart_rk_port *up);\r
+static void serial_rk_stop_dma_rx(struct uart_rk_port *up);\r
+\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
-       return __raw_readb(up->port.membase + offset);\r
+\r
+       return __raw_readl(up->port.membase + offset);\r
 }\r
 \r
 /* Save the LCR value so it can be re-written when a Busy Detect IRQ occurs. */\r
@@ -238,9 +328,9 @@ static inline void dwapb_check_clear_ier(struct uart_rk_port *up, int offset)
 static inline void serial_out(struct uart_rk_port *up, int offset, unsigned char value)\r
 {\r
        dwapb_save_out_value(up, offset, value);\r
-       __raw_writeb(value, up->port.membase + (offset << 2));\r
+       __raw_writel(value, up->port.membase + (offset << 2));\r
        if (offset != UART_TX)\r
-               dsb();\r
+               dsb(sy);\r
        dwapb_check_clear_ier(up, offset);\r
 }\r
 \r
@@ -254,22 +344,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 +374,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 +404,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 +426,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,10 +451,9 @@ 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
-               serial_rk_release_dma_tx(port);\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       if(uart_dma->use_dma & TX_DMA){\r
+               serial_rk_stop_dma_tx(up);\r
        }\r
 #endif\r
        __stop_tx(up);\r
@@ -379,11 +465,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,10 +483,9 @@ 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
-               serial_rk_release_dma_rx(port);\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       if(uart_dma->use_dma & RX_DMA){\r
+               serial_rk_stop_dma_rx(up);\r
        }\r
 #endif\r
        up->ier &= ~UART_IER_RLSI;\r
@@ -417,375 +507,308 @@ static void serial_rk_enable_ms(struct uart_port *port)
 #endif\r
 }\r
 \r
-\r
-#if USE_DMA\r
-/*\r
- * Start transmitting by dma.\r
- */\r
-#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
+#if USE_WAKEUP\r
+static struct uart_wake_up rk29_uart_ports_wakeup[] = {\r
+               {UART0_USE_WAKEUP, UART0_SIN, UART0_SOUT},\r
+               {UART1_USE_WAKEUP, UART1_SIN, UART1_SOUT},\r
+               {UART2_USE_WAKEUP, UART2_SIN, UART2_SOUT},\r
+               {UART3_USE_WAKEUP, UART3_SIN, UART3_SOUT},\r
 };\r
+#endif\r
 \r
-\r
+#if USE_DMA\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
-};\r
-\r
-/*TX*/\r
 \r
-static void serial_rk_release_dma_tx(struct uart_port *port)\r
+static void serial_rk_stop_dma_tx(struct uart_rk_port *up)\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
-       if(!port){\r
-               return;\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       \r
+       if(uart_dma && uart_dma->tx_dma_used) {\r
+               dmaengine_terminate_all(uart_dma->dma_chan_tx);\r
+               uart_dma->tx_dma_used = 0;\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
+}\r
+\r
+static void serial_rk_release_dma_tx(struct uart_rk_port *up)\r
+{\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+\r
+       if(uart_dma && uart_dma->tx_dma_inited) {\r
+               serial_rk_stop_dma_tx(up);\r
+               dma_release_channel(uart_dma->dma_chan_tx);\r
+               uart_dma->dma_chan_tx = NULL;\r
+               uart_dma->tx_dma_inited = 0;\r
        }\r
 }\r
 \r
-/*this function will be called every time after rk29_dma_enqueue() be invoked*/\r
-static void serial_rk_dma_txcb(void *buf, int size, enum rk29_dma_buffresult result) {\r
-       struct uart_port *port = buf;\r
+static void dma_tx_callback(void *data)\r
+{\r
+       struct uart_port *port = data;\r
        struct uart_rk_port *up = container_of(port, struct uart_rk_port, port);\r
        struct circ_buf *xmit = &port->state->xmit;\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       struct scatterlist *sgl = &uart_dma->tx_sgl;\r
 \r
-       if(result != RK29_RES_OK){\r
-               return;\r
-       }\r
-\r
-       port->icount.tx += size;\r
-       xmit->tail = (xmit->tail + size) & (UART_XMIT_SIZE - 1);\r
+       dma_unmap_sg(up->port.dev, sgl, 1, DMA_TO_DEVICE);\r
 \r
+       xmit->tail = (xmit->tail + uart_dma->tx_bytes) & (UART_XMIT_SIZE - 1);\r
+       port->icount.tx += uart_dma->tx_bytes;\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
+               uart_write_wakeup(port);\r
 \r
+       //spin_lock(&(up->dma->tx_lock));\r
+       uart_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
 }\r
+static int serial_rk_init_dma_tx(struct uart_rk_port *up) {\r
 \r
-static int serial_rk_init_dma_tx(struct uart_port *port) {\r
+       struct dma_slave_config slave_config;\r
+       struct uart_port *port = &up->port;\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       int ret;\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
-       if(!port || !prk29_uart_dma_t){\r
+       if(!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
-               dev_info(up->port.dev, "rk29_dma_request tx fail\n");\r
-               return -1;\r
+       uart_dma->dma_chan_tx = dma_request_slave_channel(port->dev, "tx");\r
+       if (!uart_dma->dma_chan_tx) {\r
+               dev_err(port->dev, "cannot get the TX DMA channel!\n");\r
+               ret = -EINVAL;\r
        }\r
 \r
-       if (rk29_dma_set_buffdone_fn(prk29_uart_dma_t->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
-               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
-               dev_info(up->port.dev, "rk29_dma_config tx fail\n");\r
-               return -1;\r
+       slave_config.direction = DMA_MEM_TO_DEV;        \r
+       slave_config.dst_addr = port->mapbase + UART_TX;        \r
+       slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;        \r
+       slave_config.dst_maxburst = 16;\r
+       ret = dmaengine_slave_config(uart_dma->dma_chan_tx, &slave_config);     \r
+       if (ret) {\r
+               dev_err(port->dev, "error in TX dma configuration.");   \r
+               return ret;\r
        }\r
 \r
-       prk29_uart_dma_t->tx_dma_inited = 1;\r
-       dev_info(up->port.dev, "serial_rk_init_dma_tx sucess\n");\r
+       uart_dma->tx_dma_inited = 1;\r
+       dev_info(port->dev, "serial_rk_init_dma_tx sucess\n");\r
        return 0;\r
-\r
 }\r
 \r
-static int serial_rk_start_tx_dma(struct uart_port *port)\r
+static int serial_rk_start_dma_tx(struct uart_rk_port *up)\r
 {\r
-\r
+       int count = 0;\r
+       struct uart_port *port = &up->port;\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
+       struct scatterlist *sgl = &uart_dma->tx_sgl;\r
+       struct dma_async_tx_descriptor *desc;\r
+       int ret;\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(up))\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
-                       goto err_out;\r
-               }\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_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
+               uart_dma->tx_bytes = count;\r
+               sg_init_one(sgl, uart_dma->tx_buffer + xmit->tail, count);\r
+               ret = dma_map_sg(port->dev, sgl, 1, DMA_TO_DEVICE);\r
+               \r
+               if (ret == 0) {\r
+                       dev_err(port->dev, "DMA mapping error for TX.\n");      \r
+                       return -1;\r
+               }       \r
+               desc = dmaengine_prep_slave_sg(uart_dma->dma_chan_tx, sgl, 1,\r
+                       DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);    \r
+\r
+               if (!desc) {\r
+                       dev_err(port->dev, "We cannot prepare for the TX slave dma!\n");                \r
+                       return -1;      \r
+               }       \r
+               desc->callback = dma_tx_callback;       \r
+               desc->callback_param = port;    \r
+               dmaengine_submit(desc);\r
+               dma_async_issue_pending(uart_dma->dma_chan_tx);\r
+               uart_dma->tx_dma_used = 1;\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
+       dev_info(up->port.dev, "-serial_rk_start_dma_tx-error-\n");\r
        return -1;\r
-\r
 }\r
 \r
 \r
 \r
 /*RX*/\r
+#if 0\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
+#endif\r
 \r
-static void serial_rk_release_dma_rx(struct uart_port *port)\r
+static void serial_rk_stop_dma_rx(struct uart_rk_port *up)\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
-       if(!port){\r
-               return;\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       \r
+       if(uart_dma && uart_dma->rx_dma_used) {\r
+               del_timer(&uart_dma->rx_timer);\r
+               dmaengine_terminate_all(uart_dma->dma_chan_rx); \r
+               uart_dma->rb_tail = 0;\r
+               uart_dma->rx_dma_used = 0;\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
+\r
+\r
+static void serial_rk_release_dma_rx(struct uart_rk_port *up)\r
+{\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       \r
+       if(uart_dma && uart_dma->rx_dma_inited) {\r
+               serial_rk_stop_dma_rx(up);\r
+               dma_release_channel(uart_dma->dma_chan_rx);\r
+               uart_dma->dma_chan_rx = NULL;   \r
+               uart_dma->rx_dma_inited = 0;\r
        }\r
 }\r
 \r
 \r
-static int serial_rk_init_dma_rx(struct uart_port *port) {\r
+static int serial_rk_init_dma_rx(struct uart_rk_port *up) \r
+{\r
+       int ret;\r
+       struct uart_port *port = &up->port;\r
+       struct dma_slave_config slave_config;\r
+       struct rk_uart_dma *uart_dma = up->dma;\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
-       if(!port || !prk29_uart_dma_t){\r
-               dev_info(up->port.dev, "serial_rk_init_dma_rx: port fail\n");\r
+       if(!uart_dma) {\r
+               dev_info(port->dev, "serial_rk_init_dma_rx: port fail\n");\r
                return -1;\r
        }\r
-       if(prk29_uart_dma_t->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
-               dev_info(up->port.dev, "rk29_dma_request fail rx \n");\r
-               return -1;\r
+       if(uart_dma->rx_dma_inited) {\r
+               return 0;\r
        }\r
 \r
-       if (rk29_dma_set_buffdone_fn(prk29_uart_dma_t->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
-               dev_info(up->port.dev, "rk29_dma_devconfig rx fail\n");\r
+       uart_dma->dma_chan_rx = dma_request_slave_channel(port->dev, "rx");\r
+       if (!uart_dma->dma_chan_rx) {\r
+               dev_err(port->dev, "cannot get the DMA channel.\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
-               return -1;\r
+       slave_config.direction = DMA_DEV_TO_MEM;        \r
+       slave_config.src_addr = port->mapbase + UART_RX;        \r
+       slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;        \r
+       slave_config.src_maxburst = 1;\r
+       ret = dmaengine_slave_config(uart_dma->dma_chan_rx, &slave_config);     \r
+       if (ret) {\r
+               dev_err(port->dev, "error in RX dma configuration.\n");         \r
+               return ret;     \r
        }\r
 \r
-       rk29_dma_setflags(prk29_uart_dma_t->rx_dmach, RK29_DMAF_CIRCULAR);\r
-\r
-       prk29_uart_dma_t->rx_dma_inited = 1;\r
-       dev_info(up->port.dev, "serial_rk_init_dma_rx sucess\n");\r
+       uart_dma->rx_dma_inited = 1;\r
+       dev_info(port->dev, "serial_rk_init_dma_rx sucess\n");\r
        return 0;\r
-\r
 }\r
 \r
-static int serial_rk_start_rx_dma(struct uart_port *port)\r
+static int serial_rk_start_dma_rx(struct uart_rk_port *up)\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
-       if(0 == prk29_uart_dma_t->use_dma){\r
+       struct uart_port *port = &up->port;\r
+       struct rk_uart_dma *uart_dma = up->dma; \r
+       struct dma_async_tx_descriptor *desc;   \r
+       \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
+       if(-1 == serial_rk_init_dma_rx(up)){\r
                dev_info(up->port.dev, "*******serial_rk_init_dma_rx*******error*******\n");\r
                return -1;\r
        }\r
+       desc = dmaengine_prep_dma_cyclic(uart_dma->dma_chan_rx, uart_dma->rx_phy_addr, uart_dma->rb_size, uart_dma->rb_size/2,DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);      \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
-               dev_info(up->port.dev, "*******rk29_dma_enqueue fail*****\n");\r
-               return -1;\r
+       if (!desc) {\r
+               dev_err(port->dev, "We cannot prepare for the RX slave dma!\n");                \r
+               return -EINVAL; \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
-               dev_info(up->port.dev, "*******rk29_dma_enqueue fail*****\n");\r
-               return -1;\r
-       }\r
+       //desc->callback = dma_rx_callback;     \r
+       //desc->callback_param = port;  \r
+       dev_dbg(port->dev, "RX: prepare for the DMA.\n");\r
+       dmaengine_submit(desc); \r
+       dma_async_issue_pending(uart_dma->dma_chan_rx);\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
+       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
 }\r
 \r
-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
+static void serial_rk_update_rb_addr(struct uart_rk_port *up)\r
+{\r
+       struct rk_uart_dma *uart_dma = up->dma;\r
+       struct dma_tx_state state;      \r
+       //spin_lock(&(up->dma->rx_lock));\r
+       uart_dma->rx_size = 0;\r
+       if(uart_dma->rx_dma_used == 1) {\r
+               dmaengine_tx_status(uart_dma->dma_chan_rx, (dma_cookie_t)0, &state);\r
+               uart_dma->rb_head = (state.residue - 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
-\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
+       struct uart_port *port = &up->port;\r
+       struct rk_uart_dma *uart_dma = up->dma;\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
+       if(!uart_dma->rx_dma_used || !port->state->port.tty)\r
+               return;\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
+       serial_rk_update_rb_addr(up);\r
+       //if (uart_dma->rx_size > 0)\r
+       //      printk("rx_size:%d ADDR:%x\n", uart_dma->rx_size, uart_dma->rb_head);\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
+               port->icount.rx += count;\r
+               flip = tty_insert_flip_string(&port->state->port, uart_dma->rx_buffer\r
+                       + uart_dma->rb_tail, count);\r
+               tty_flip_buffer_push(&port->state->port);\r
+               uart_dma->rb_tail = (uart_dma->rb_tail + count) & (uart_dma->rb_size - 1);\r
                up->port_activity = jiffies;\r
        }\r
 \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
-       }\r
-#endif\r
-\r
-}\r
-\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
-}\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
-       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
-\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
-       }\r
-\r
-       spin_unlock(&(up->prk29_uart_dma_t->rx_lock));\r
-\r
-}\r
-\r
-\r
-static void serial_rk_start_dma_rx(struct work_struct *work)\r
-{\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
+       if(uart_dma->use_timer == 1)\r
+               mod_timer(&uart_dma->rx_timer, jiffies + msecs_to_jiffies(uart_dma->rx_timeout));\r
 }\r
 #endif /* USE_DMA */\r
 \r
 \r
-\r
 static void\r
 receive_chars(struct uart_rk_port *up, unsigned int *status)\r
 {\r
@@ -859,7 +882,7 @@ ignore_char:
                lsr = serial_in(up, UART_LSR);\r
        } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));\r
        spin_unlock(&up->port.lock);\r
-       tty_flip_buffer_push(tty);\r
+       tty_flip_buffer_push(tty->port);\r
        spin_lock(&up->port.lock);\r
        *status = lsr;\r
 }\r
@@ -883,8 +906,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_dma_tx(up);\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 +928,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 +973,41 @@ 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
+       if(up->dma->use_dma) {\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 (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->dma->use_dma & RX_DMA)) {\r
+                       if (status & (UART_LSR_DR | UART_LSR_BI)) {\r
+                               receive_chars(up, &status);\r
+                       } else if ((up->iir & 0x0f) == 0x0c) {\r
+               serial_in(up, UART_RX);\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 +1017,27 @@ 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
+               } else if ((up->iir & 0x0f) == 0x0c) {\r
+            serial_in(up, UART_RX);\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 +1054,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
@@ -1044,7 +1090,7 @@ static unsigned int serial_rk_tx_empty(struct uart_port *port)
        up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;\r
        spin_unlock_irqrestore(&up->port.lock, flags);\r
 \r
-       return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;\r
+       return (lsr & UART_LSR_TEMT) == UART_LSR_TEMT ? TIOCSER_TEMT : 0;\r
 }\r
 \r
 static unsigned int serial_rk_get_mctrl(struct uart_port *port)\r
@@ -1110,7 +1156,7 @@ static void serial_rk_break_ctl(struct uart_port *port, int break_state)
        dev_dbg(port->dev, "-%s lcr: 0x%02x\n", __func__, up->lcr);\r
 }\r
 \r
-#if defined(CONFIG_SERIAL_RK_CONSOLE) || defined(CONFIG_CONSOLE_POLL)\r
+#if defined(CONFIG_SERIAL_ROCKCHIP_CONSOLE) || defined(CONFIG_CONSOLE_POLL)\r
 /*\r
  *     Wait for transmitter & holding register to empty\r
  */\r
@@ -1164,14 +1210,14 @@ static void serial_rk_put_poll_char(struct uart_port *port,
        ier = serial_in(up, UART_IER);\r
        serial_out(up, UART_IER, 0);\r
 \r
-       wait_for_xmitr(up, BOTH_EMPTY);\r
+       wait_for_xmitr(up, UART_LSR_TEMT);\r
        /*\r
         *      Send the character out.\r
         *      If a LF, also do CR...\r
         */\r
        serial_out(up, UART_TX, c);\r
        if (c == 10) {\r
-               wait_for_xmitr(up, BOTH_EMPTY);\r
+               wait_for_xmitr(up, UART_LSR_TEMT);\r
                serial_out(up, UART_TX, 13);\r
        }\r
 \r
@@ -1179,7 +1225,7 @@ static void serial_rk_put_poll_char(struct uart_port *port,
         *      Finally, wait for transmitter to become empty\r
         *      and restore the IER\r
         */\r
-       wait_for_xmitr(up, BOTH_EMPTY);\r
+       wait_for_xmitr(up, UART_LSR_TEMT);\r
        serial_out(up, UART_IER, ier);\r
 }\r
 \r
@@ -1190,8 +1236,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
@@ -1204,16 +1250,23 @@ static int serial_rk_startup(struct uart_port *port)
                return retval;\r
 \r
        up->mcr = 0;\r
-\r
-       clk_enable(up->pclk);\r
-       clk_enable(up->clk);  // enable the config uart clock\r
-\r
+#ifdef CONFIG_CLOCK_CTRL\r
+       clk_prepare_enable(up->clk);\r
+       clk_prepare_enable(up->pclk); // enable the config uart clock\r
+#endif\r
        /*\r
         * Clear the FIFO buffers and disable them.\r
         * (they will be reenabled in set_termios())\r
         */\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 +1306,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,10 +1357,15 @@ 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
+#ifdef CONFIG_CLOCK_CTRL\r
+       clk_disable_unprepare(up->clk);\r
+       clk_disable_unprepare(up->pclk); \r
+#endif\r
 }\r
 \r
 static void\r
@@ -1328,12 +1374,19 @@ 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
+\r
        dev_dbg(port->dev, "+%s\n", __func__);\r
 \r
+#if USE_DMA\r
+       //stop dma tx, which might make the uart be busy while some registers are set\r
+       if(up->dma->tx_dma_used) {\r
+               serial_rk_stop_dma_tx(up);\r
+       }\r
+#endif\r
+\r
        switch (termios->c_cflag & CSIZE) {\r
        case CS5:\r
                cval = UART_LCR_WLEN5;\r
@@ -1373,44 +1426,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->dma->use_dma & TX_DMA){\r
+                       fcr |= UART_FCR_T_TRIG_01;\r
+               } else\r
+#endif\r
+               {\r
+                       fcr |= UART_FCR_T_TRIG_01;\r
+               }\r
+\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 & RX_DMA){  \r
+                       fcr |= UART_FCR_R_TRIG_00;\r
                } else\r
 #endif\r
                {\r
-                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | UART_FCR_T_TRIG_01;\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 +1520,68 @@ 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
+                       if (up->dma->use_dma & RX_DMA)\r
+                               serial_rk_start_dma_rx(up);\r
+                       else\r
+                               up->ier |= UART_IER_RDI;\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
@@ -1536,17 +1605,19 @@ static void
 serial_rk_pm(struct uart_port *port, unsigned int state,\r
              unsigned int oldstate)\r
 {\r
+#ifdef CONFIG_CLOCK_CTRL\r
        struct uart_rk_port *up =\r
                container_of(port, struct uart_rk_port, port);\r
 \r
        dev_dbg(port->dev, "%s: %s\n", __func__, state ? "disable" : "enable");\r
        if (state) {\r
-               clk_disable(up->clk);\r
-               clk_disable(up->pclk);\r
+       clk_disable_unprepare(up->clk);\r
+       clk_disable_unprepare(up->pclk); \r
        } else {\r
-               clk_enable(up->pclk);\r
-               clk_enable(up->clk);\r
+       clk_prepare_enable(up->clk);\r
+       clk_prepare_enable(up->pclk); \r
        }\r
+#endif\r
 }\r
 \r
 static void serial_rk_release_port(struct uart_port *port)\r
@@ -1611,7 +1682,7 @@ static struct uart_ops serial_rk_pops = {
 #endif\r
 };\r
 \r
-#ifdef CONFIG_SERIAL_RK_CONSOLE\r
+#ifdef CONFIG_SERIAL_ROCKCHIP_CONSOLE\r
 \r
 static struct uart_rk_port *serial_rk_console_ports[UART_NR];\r
 \r
@@ -1662,7 +1733,7 @@ serial_rk_console_write(struct console *co, const char *s, unsigned int count)
         *      Finally, wait for transmitter to become empty\r
         *      and restore the IER\r
         */\r
-       wait_for_xmitr(up, BOTH_EMPTY);\r
+       wait_for_xmitr(up, UART_LSR_TEMT);\r
        serial_out(up, UART_IER, ier);\r
 \r
 #if 0\r
@@ -1682,6 +1753,85 @@ serial_rk_console_write(struct console *co, const char *s, unsigned int count)
        local_irq_restore(flags);\r
 }\r
 \r
+#ifdef CONFIG_RK_CONSOLE_THREAD\r
+#include <linux/kfifo.h>\r
+#include <linux/kthread.h>\r
+static struct task_struct *console_task;\r
+#define FIFO_SIZE SZ_512K\r
+static DEFINE_KFIFO(fifo, unsigned char, FIFO_SIZE);\r
+static bool console_thread_stop;\r
+\r
+static void console_putc(struct uart_rk_port *up, unsigned int c)\r
+{\r
+       while (!(serial_in(up, UART_USR) & UART_USR_TX_FIFO_NOT_FULL))\r
+               cpu_relax();\r
+       serial_out(up, UART_TX, c);\r
+}\r
+\r
+static void console_flush(struct uart_rk_port *up)\r
+{\r
+       while (!(serial_in(up, UART_USR) & UART_USR_TX_FIFO_EMPTY))\r
+               cpu_relax();\r
+}\r
+\r
+static int console_thread(void *data)\r
+{\r
+       struct uart_rk_port *up = data;\r
+       unsigned char c;\r
+\r
+       while (1) {\r
+               set_current_state(TASK_INTERRUPTIBLE);\r
+               schedule();\r
+               if (kthread_should_stop())\r
+                       break;\r
+               set_current_state(TASK_RUNNING);\r
+               while (!console_thread_stop && serial_in(up, UART_SFE) && kfifo_get(&fifo, &c)) {\r
+                       console_putc(up, c);\r
+               }\r
+               if (!console_thread_stop)\r
+                       console_flush(up);\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static void console_write(struct console *co, const char *s, unsigned int count)\r
+{\r
+       struct uart_rk_port *up = serial_rk_console_ports[co->index];\r
+       unsigned int fifo_count = FIFO_SIZE;\r
+       unsigned char c, r = '\r';\r
+\r
+       if (console_thread_stop ||\r
+           oops_in_progress ||\r
+           system_state == SYSTEM_HALT ||\r
+           system_state == SYSTEM_POWER_OFF ||\r
+           system_state == SYSTEM_RESTART) {\r
+               if (!console_thread_stop) {\r
+                       console_thread_stop = true;\r
+                       smp_wmb();\r
+                       console_flush(up);\r
+                       while (fifo_count-- && kfifo_get(&fifo, &c))\r
+                               console_putc(up, c);\r
+               }\r
+               while (count--) {\r
+                       if (*s == '\n') {\r
+                               console_putc(up, r);\r
+                       }\r
+                       console_putc(up, *s++);\r
+               }\r
+               console_flush(up);\r
+       } else {\r
+               while (count--) {\r
+                       if (*s == '\n') {\r
+                               kfifo_put(&fifo, &r);\r
+                       }\r
+                       kfifo_put(&fifo, s++);\r
+               }\r
+               wake_up_process(console_task);\r
+       }\r
+}\r
+#endif\r
+\r
 static int __init serial_rk_console_setup(struct console *co, char *options)\r
 {\r
        struct uart_rk_port *up;\r
@@ -1700,6 +1850,13 @@ static int __init serial_rk_console_setup(struct console *co, char *options)
        if (options)\r
                uart_parse_options(options, &baud, &parity, &bits, &flow);\r
 \r
+#ifdef CONFIG_RK_CONSOLE_THREAD\r
+       if (!console_task) {\r
+               console_task = kthread_create(console_thread, up, "kconsole");\r
+               if (!IS_ERR(console_task))\r
+                       co->write = console_write;\r
+       }\r
+#endif\r
        return uart_set_options(&up->port, co, baud, parity, bits, flow);\r
 }\r
 \r
@@ -1729,25 +1886,129 @@ static inline void serial_rk_add_console_port(struct uart_rk_port *up)
 \r
 static struct uart_driver serial_rk_reg = {\r
        .owner                  = THIS_MODULE,\r
-       .driver_name            = "rk29_serial",\r
+       .driver_name            = "rk_serial",\r
        .dev_name               = "ttyS",\r
        .major                  = TTY_MAJOR,\r
        .minor                  = 64,\r
        .cons                   = SERIAL_CONSOLE,\r
        .nr                     = UART_NR,\r
 };\r
+#if USE_WAKEUP\r
+static irqreturn_t serial_rk_wakeup_handler(int irq, void *dev) {\r
+       struct uart_rk_port *up = dev;\r
+       struct uart_wake_up *wakeup = up->wakeup;\r
+       if(wakeup->enable == 1) {\r
+               iomux_set(wakeup->rx_mode);\r
+               wake_lock_timeout(&wakeup->wakelock, 3 * HZ);\r
+       }    \r
+       return 0;\r
+}\r
 \r
-static int __devinit serial_rk_probe(struct platform_device *pdev)\r
+static int serial_rk_setup_wakeup_irq(struct uart_rk_port *up)\r
+{\r
+       int ret = 0;\r
+       struct uart_wake_up *wakeup = up->wakeup;\r
+\r
+       if(wakeup->enable == 1) {\r
+               memset(wakeup->wakelock_name, 0, 32);\r
+               sprintf(wakeup->wakelock_name, "serial.%d_wakelock", up->port.line);\r
+               wake_lock_init(&wakeup->wakelock, WAKE_LOCK_SUSPEND, wakeup->wakelock_name);\r
+               memset(wakeup->rx_pin_name, 0, 32);             \r
+               sprintf(wakeup->rx_pin_name, "UART%d_SIN", up->port.line);\r
+               wakeup->rx_pin = iomux_mode_to_gpio(wakeup->rx_mode);\r
+               ret = gpio_request(wakeup->rx_pin, wakeup->rx_pin_name);\r
+               if (ret) {\r
+                       printk("request %s fail ! \n", wakeup->rx_pin_name);\r
+                   return ret;\r
+               }\r
+               gpio_direction_input(wakeup->rx_pin);\r
+               wakeup->rx_irq = gpio_to_irq(wakeup->rx_pin);\r
+               memset(wakeup->rx_irq_name, 0, 32);\r
+               sprintf(wakeup->rx_irq_name, "serial.%d_wake_up_irq", up->port.line);\r
+               ret = request_irq(wakeup->rx_irq, serial_rk_wakeup_handler, IRQF_TRIGGER_FALLING, wakeup->rx_irq_name, up);\r
+               if(ret < 0) {\r
+                       printk("%s request fail\n", wakeup->rx_irq_name);\r
+                   return ret;\r
+               }\r
+               disable_irq_nosync(wakeup->rx_irq);\r
+               enable_irq_wake(wakeup->rx_irq);\r
+               iomux_set(wakeup->rx_mode);\r
+       }\r
+       return ret;\r
+}\r
+\r
+static int serial_rk_enable_wakeup_irq(struct uart_rk_port *up) {\r
+       struct uart_wake_up *wakeup = up->wakeup;\r
+       if(wakeup->enable == 1) {\r
+               iomux_set(wakeup->rx_mode & 0xfff0);\r
+               enable_irq(wakeup->rx_irq);\r
+       }\r
+    return 0;\r
+}\r
+\r
+static int serial_rk_disable_wakeup_irq(struct uart_rk_port *up) {\r
+       struct uart_wake_up *wakeup = up->wakeup;\r
+       if(wakeup->enable == 1) {\r
+               disable_irq_nosync(wakeup->rx_irq);\r
+               iomux_set(wakeup->rx_mode);\r
+       }\r
+    return 0;\r
+}\r
+\r
+static int serial_rk_remove_wakeup_irq(struct uart_rk_port *up) {\r
+       struct uart_wake_up *wakeup = up->wakeup;\r
+       if(wakeup->enable == 1) {\r
+               //disable_irq_nosync(wakeup->rx_irq);\r
+               free_irq(wakeup->rx_irq, NULL);\r
+               gpio_free(wakeup->rx_pin);\r
+               wake_lock_destroy(&wakeup->wakelock);\r
+       }\r
+    return 0;\r
+}\r
+#endif\r
+\r
+#ifdef CONFIG_OF\r
+static int of_rk_serial_parse_dt(struct device_node *np, struct of_rk_serial *rks) \r
+{\r
+       unsigned int val = 0;\r
+       const char *s = NULL;\r
+       int ret, i = 0;\r
+       rks->id = of_alias_get_id(np, "serial");\r
+       if(!of_property_read_u32(np, "clock-frequency", &val))\r
+               rks->uartclk = val;\r
+\r
+#if USE_DMA\r
+       rks->use_dma = 0;\r
+       for(i = 0; i < 2; i++) {\r
+               ret = of_property_read_string_index(np, "dma-names", i, &s);\r
+               if(!ret) {\r
+                       if(!strcmp(s, "tx"))\r
+                               rks->use_dma |= TX_DMA;\r
+                        else if (!strcmp(s, "rx"))\r
+                               rks->use_dma |= RX_DMA;\r
+               }\r
+       }\r
+#endif\r
+       return 0;\r
+}\r
+#endif\r
+\r
+static int serial_rk_probe(struct platform_device *pdev)\r
 {\r
        struct uart_rk_port     *up;\r
        struct resource         *mem;\r
        int irq;\r
        int ret = -ENOSPC;\r
+       struct of_rk_serial rks;\r
+\r
+       up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL);\r
+       if (!up)\r
+               return -ENOMEM;\r
+\r
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
-       if (!mem) {\r
-               dev_err(&pdev->dev, "no mem resource?\n");\r
-               return -ENODEV;\r
-       }\r
+       up->port.membase = devm_request_and_ioremap(&pdev->dev, mem);\r
+       if (!up->port.membase)\r
+               return -ENOMEM;\r
 \r
        irq = platform_get_irq(pdev, 0);\r
        if (irq < 0) {\r
@@ -1755,138 +2016,136 @@ static int __devinit serial_rk_probe(struct platform_device *pdev)
                return irq;\r
        }\r
 \r
-       if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,\r
-                               pdev->dev.driver->name)) {\r
-               dev_err(&pdev->dev, "memory region already claimed\n");\r
-               return -EBUSY;\r
-       }\r
-\r
-       up = kzalloc(sizeof(*up), GFP_KERNEL);\r
-       if (up == NULL) {\r
-               ret = -ENOMEM;\r
-               goto do_release_region;\r
-       }\r
+#ifdef CONFIG_OF\r
+       of_rk_serial_parse_dt(pdev->dev.of_node, &rks);\r
+       pdev->id = rks.id;\r
+#endif\r
 \r
        sprintf(up->name, "rk29_serial.%d", pdev->id);\r
        up->pdev = pdev;\r
-       up->pclk = clk_get(&pdev->dev, "pclk_uart");\r
-       up->clk = clk_get(&pdev->dev, "uart");\r
-       if (unlikely(IS_ERR(up->clk))) {\r
-               ret = PTR_ERR(up->clk);\r
-               goto do_free;\r
+#ifdef CONFIG_CLOCK_CTRL\r
+       up->pclk = devm_clk_get(&pdev->dev, "pclk_uart");\r
+       up->clk = devm_clk_get(&pdev->dev, "sclk_uart");\r
+       if (unlikely(IS_ERR(up->clk)) || unlikely(IS_ERR(up->pclk))) {\r
+               dev_err(&pdev->dev, "get clock fail\n");\r
+               return -EINVAL;\r
        }\r
+#endif\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 = devm_kzalloc(&pdev->dev, sizeof(struct rk_uart_dma), GFP_KERNEL);\r
+       if (!up->dma) {\r
+               dev_err(&pdev->dev, "unable to allocate mem\n");\r
+               return -ENOMEM;\r
+       }\r
+       up->dma->use_dma = rks.use_dma;\r
+#endif\r
+#if USE_WAKEUP\r
+       up->wakeup = &rk29_uart_ports_wakeup[pdev->id];\r
 #endif\r
        up->port.dev = &pdev->dev;\r
        up->port.type = PORT_RK;\r
        up->port.irq = irq;\r
-       up->port.iotype = UPIO_DWAPB;\r
-\r
+       up->port.iotype = UPIO_MEM;\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
        up->port.iobase = mem->start;\r
-       up->port.membase = ioremap_nocache(mem->start, mem->end - mem->start + 1);\r
-       if (!up->port.membase) {\r
-               ret = -ENOMEM;\r
-               goto do_put_clk;\r
-       }\r
        up->port.mapbase = mem->start;\r
        up->port.irqflags = IRQF_DISABLED;\r
+#if defined(CONFIG_CLOCK_CTRL)\r
        up->port.uartclk = clk_get_rate(up->clk);\r
+#elif defined(CONFIG_OF)\r
+       up->port.uartclk = rks.uartclk;\r
+#else\r
+       up->port.uartclk = 24000000;\r
+#endif\r
 \r
 #if USE_DMA\r
        /* set dma config */\r
-       if(1 == up->prk29_uart_dma_t->use_dma) {\r
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);\r
-\r
+       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);\r
+       if(up->dma->use_dma & RX_DMA) {\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 = DMA_SERIAL_BUFFER_SIZE;\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
+               up->dma->rx_dma_inited = 0;\r
+               up->dma->rx_dma_used = 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 %p\n", up->dma->rx_buffer);\r
+                       dev_info(up->port.dev, "dma_rx_phy 0x%08x\n", (unsigned)up->dma->rx_phy_addr);\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
-               serial_rk_init_dma_rx(&up->port);\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
+               //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
+               spin_lock_init(&(up->dma->rx_lock));\r
+               serial_rk_init_dma_rx(up);\r
        }\r
-#endif\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 %p\n", 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);\r
+       }\r
+\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
-               goto do_iounmap;\r
-\r
+               return ret;\r
        platform_set_drvdata(pdev, up);\r
-       dev_info(&pdev->dev, "membase 0x%08x\n", (unsigned) up->port.membase);\r
-\r
+       dev_info(&pdev->dev, "membase %p\n", up->port.membase);\r
+#if USE_WAKEUP\r
+       serial_rk_setup_wakeup_irq(up); \r
+#endif\r
        return 0;\r
-\r
-do_iounmap:\r
-       iounmap(up->port.membase);\r
-       up->port.membase = NULL;\r
-do_put_clk:\r
-       clk_put(up->clk);\r
-       clk_put(up->pclk);\r
-do_free:\r
-       kfree(up);\r
-do_release_region:\r
-       release_mem_region(mem->start, (mem->end - mem->start) + 1);\r
-       return ret;\r
 }\r
 \r
-static int __devexit serial_rk_remove(struct platform_device *pdev)\r
+static int serial_rk_remove(struct platform_device *pdev)\r
 {\r
        struct uart_rk_port *up = platform_get_drvdata(pdev);\r
 \r
        platform_set_drvdata(pdev, NULL);\r
        if (up) {\r
-               struct resource *mem;\r
-               destroy_workqueue(up->uart_wq);\r
+#if USE_DMA\r
+               serial_rk_release_dma_tx(up);\r
+               serial_rk_release_dma_rx(up);\r
+#endif\r
+#if USE_WAKEUP\r
+       serial_rk_remove_wakeup_irq(up);\r
+#endif\r
+               //destroy_workqueue(up->uart_wq);\r
                uart_remove_one_port(&serial_rk_reg, &up->port);\r
-               mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
-               iounmap(up->port.membase);\r
                up->port.membase = NULL;\r
-               clk_put(up->clk);\r
-               clk_put(up->pclk);\r
-               kfree(up);\r
-               release_mem_region(mem->start, (mem->end - mem->start) + 1);\r
        }\r
 \r
        return 0;\r
@@ -1902,14 +2161,18 @@ static int serial_rk_suspend(struct platform_device *dev, pm_message_t state)
        if(up->port.line == DBG_PORT && POWER_MANEGEMENT){\r
                serial_rk_pm(&up->port, 1, 0);\r
        }\r
-\r
+#if USE_WAKEUP\r
+    serial_rk_enable_wakeup_irq(up);\r
+#endif\r
        return 0;\r
 }\r
 \r
 static int serial_rk_resume(struct platform_device *dev)\r
 {\r
        struct uart_rk_port *up = platform_get_drvdata(dev);\r
-\r
+#if USE_WAKEUP\r
+    serial_rk_disable_wakeup_irq(up);\r
+#endif\r
        if (up && up->port.line != DBG_PORT && POWER_MANEGEMENT){\r
                uart_resume_port(&serial_rk_reg, &up->port);\r
        }\r
@@ -1918,19 +2181,21 @@ static int serial_rk_resume(struct platform_device *dev)
        }\r
        return 0;\r
 }\r
-\r
+#ifdef CONFIG_OF\r
+static const struct of_device_id of_rk_serial_match[] = {\r
+       { .compatible = "rockchip,serial" },\r
+       { /* Sentinel */ }\r
+};\r
+#endif\r
 static struct platform_driver serial_rk_driver = {\r
        .probe          = serial_rk_probe,\r
-       .remove         = __devexit_p(serial_rk_remove),\r
+       .remove         = serial_rk_remove,\r
        .suspend        = serial_rk_suspend,\r
        .resume         = serial_rk_resume,\r
        .driver         = {\r
-#if defined(CONFIG_ARCH_RK29)\r
-               .name   = "rk29_serial",\r
-#elif defined(CONFIG_SERIAL_RK2818)\r
-               .name   = "rk2818_serial",\r
-#else\r
-               .name   = "rk_serial",\r
+               .name   = "serial",\r
+#ifdef CONFIG_OF\r
+               .of_match_table = of_rk_serial_match,\r
 #endif\r
                .owner  = THIS_MODULE,\r
        },\r
@@ -1939,15 +2204,14 @@ static struct platform_driver serial_rk_driver = {
 static int __init serial_rk_init(void)\r
 {\r
        int ret;\r
-\r
+       //hhb@rock-chips.com\r
+       printk("%s\n", VERSION_AND_TIME);\r
        ret = uart_register_driver(&serial_rk_reg);\r
        if (ret)\r
                return ret;\r
-\r
        ret = platform_driver_register(&serial_rk_driver);\r
        if (ret != 0)\r
                uart_unregister_driver(&serial_rk_reg);\r
-\r
        return ret;\r
 }\r
 \r
@@ -1962,4 +2226,3 @@ module_exit(serial_rk_exit);
 \r
 MODULE_LICENSE("GPL");\r
 MODULE_DESCRIPTION("RK UART driver");\r
-\r