drm/rockchip: add rk3399 vop big csc support
[firefly-linux-kernel-4.4.55.git] / drivers / tty / serial / rk_serial.c
index 682e62c043096ec1feee21a71265972c8f9c8f6f..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
 #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
 *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.3 2012-12-14"\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
 \r
 \r
 //#define BOTH_EMPTY   (UART_LSR_TEMT | UART_LSR_THRE)\r
-\r
-#define UART_NR        4   //uart port number\r
+#define UART_NR        5   //uart port number\r
 \r
 \r
 /* configurate whether the port transmit-receive by DMA in menuconfig*/\r
 \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
+#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
-#ifdef CONFIG_UART1_DMA_RK29\r
-#define UART1_USE_DMA CONFIG_UART1_DMA_RK29\r
+#ifdef CONFIG_UART1_WAKEUP_RK29\r
+#define UART1_USE_WAKEUP CONFIG_UART1_WAKEUP_RK29\r
 #else\r
-#define UART1_USE_DMA CLOSE_DMA\r
+#define UART1_USE_WAKEUP 0\r
 #endif\r
-#ifdef CONFIG_UART2_DMA_RK29\r
-#define UART2_USE_DMA CONFIG_UART2_DMA_RK29\r
+#ifdef CONFIG_UART2_WAKEUP_RK29\r
+#define UART2_USE_WAKEUP CONFIG_UART2_WAKEUP_RK29\r
 #else\r
-#define UART2_USE_DMA CLOSE_DMA\r
+#define UART2_USE_WAKEUP 0\r
 #endif\r
-#ifdef CONFIG_UART3_DMA_RK29\r
-#define UART3_USE_DMA CONFIG_UART3_DMA_RK29\r
+#ifdef CONFIG_UART3_WAKEUP_RK29\r
+#define UART3_USE_WAKEUP CONFIG_UART3_WAKEUP_RK29\r
 #else\r
-#define UART3_USE_DMA CLOSE_DMA\r
+#define UART3_USE_WAKEUP 0\r
 #endif\r
 \r
 #define USE_TIMER    1           // use timer for dma transport\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_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
-#else\r
-#include <plat/dma-pl330.h>\r
-#endif\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
 \r
@@ -135,8 +148,13 @@ static struct uart_driver serial_rk_reg;
 #ifdef CONFIG_ARCH_RK29\r
 #define DBG_PORT 1   //DBG_PORT which uart is used to print log message\r
 #else\r
-#define DBG_PORT -1   //DBG_PORT which uart is used to print log message\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
 #else\r
@@ -154,11 +172,13 @@ 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 1\r
+#define DEBUG 0\r
 static int log_port = -1;\r
 module_param(log_port, int, S_IRUGO|S_IWUSR);\r
 \r
@@ -174,8 +194,8 @@ module_param(log_port, int, S_IRUGO|S_IWUSR);
 \r
 struct rk_uart_dma {\r
        u32 use_dma;            //1:used\r
-       enum dma_ch rx_dmach;\r
-       enum dma_ch tx_dmach;\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
@@ -202,9 +222,37 @@ struct rk_uart_dma {
        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
@@ -228,24 +276,28 @@ struct uart_rk_port {
        unsigned char           msr_saved_flags;\r
 #endif\r
 \r
-       char                    name[12];\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 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_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_port *port);\r
-static int serial_rk_start_rx_dma(struct uart_port *port);\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
@@ -254,7 +306,8 @@ static int serial_rk_startup(struct uart_port *port);
 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
@@ -275,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
@@ -400,11 +453,10 @@ static void serial_rk_stop_tx(struct uart_port *port)
 #if 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
+               serial_rk_stop_dma_tx(up);\r
        }\r
 #endif\r
        __stop_tx(up);\r
-\r
 }\r
 \r
 \r
@@ -433,7 +485,7 @@ static void serial_rk_stop_rx(struct uart_port *port)
 #if 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
+               serial_rk_stop_dma_rx(up);\r
        }\r
 #endif\r
        up->ier &= ~UART_IER_RLSI;\r
@@ -455,77 +507,71 @@ 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 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
+#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 = "rk-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 rk_uart_dma *uart_dma = up->dma;\r
-       if(!port){\r
-               return;\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
+}\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
-               rk29_dma_free(uart_dma->tx_dmach, &rk29_uart_dma_client);\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
-               uart_dma->tx_dma_used = 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
-               printk(">>>>%s:%d result:%d\n", __func__, __LINE__, result);\r
-               up->dma->tx_dma_used = 0;\r
-               return;\r
-       }\r
+       dma_unmap_sg(up->port.dev, sgl, 1, DMA_TO_DEVICE);\r
 \r
-       //spin_lock(&(up->dma->rx_lock));\r
-       xmit->tail = (xmit->tail + size) & (UART_XMIT_SIZE - 1);\r
-       port->icount.tx += size;\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
+               uart_write_wakeup(port);\r
 \r
        //spin_lock(&(up->dma->tx_lock));\r
-       up->dma->tx_dma_used = 0;\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_port *port) {\r
+}\r
+static int serial_rk_init_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 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
-       if(!port || !uart_dma){\r
+       if(!uart_dma){\r
                dev_info(up->port.dev, "serial_rk_init_dma_tx fail\n");\r
                return -1;\r
        }\r
@@ -534,43 +580,41 @@ static int serial_rk_init_dma_tx(struct uart_port *port) {
                return 0;\r
        }\r
 \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
+       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(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
-       \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
-       \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
+       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
        uart_dma->tx_dma_inited = 1;\r
-       dev_info(up->port.dev, "serial_rk_init_dma_tx sucess\n");\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
        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 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(!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
        if (1 == uart_dma->tx_dma_used)\r
@@ -582,55 +626,79 @@ static int serial_rk_start_tx_dma(struct uart_port *port)
        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
+               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
 /*RX*/\r
+#if 0\r
 static void serial_rk_dma_rxcb(void *buf, int size, enum rk29_dma_buffresult result) {\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 rk_uart_dma *uart_dma = up->dma;\r
        \r
-       if(!port){\r
-               return;\r
-       }\r
-       \r
-       if(uart_dma && uart_dma->rx_dma_inited) {\r
+       if(uart_dma && uart_dma->rx_dma_used) {\r
                del_timer(&uart_dma->rx_timer);\r
-               rk29_dma_free(uart_dma->rx_dmach, &rk29_uart_dma_client);\r
+               dmaengine_terminate_all(uart_dma->dma_chan_rx); \r
                uart_dma->rb_tail = 0;\r
-               uart_dma->rx_dma_inited = 0;\r
                uart_dma->rx_dma_used = 0;\r
        }\r
 }\r
 \r
 \r
-static int serial_rk_init_dma_rx(struct uart_port *port) {\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
-       struct uart_rk_port *up =\r
-                               container_of(port, struct uart_rk_port, port);\r
+\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
-       if(!port || !uart_dma){\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
 \r
@@ -638,67 +706,56 @@ static int serial_rk_init_dma_rx(struct uart_port *port) {
                return 0;\r
        }\r
 \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(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
-\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
+       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(uart_dma->rx_dmach, 1, 1)) {\r
-               dev_info(up->port.dev, "rk29_dma_config rx fail 1 1 \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(uart_dma->rx_dmach, RK29_DMAF_CIRCULAR);\r
-\r
        uart_dma->rx_dma_inited = 1;\r
-       dev_info(up->port.dev, "serial_rk_init_dma_rx sucess\n");\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 rk_uart_dma *uart_dma = up->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
        if(uart_dma->rx_dma_used == 1)\r
                return 0;\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
-       \r
-#if 0  \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
+       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(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
+       if (!desc) {\r
+               dev_err(port->dev, "We cannot prepare for the RX slave dma!\n");                \r
+               return -EINVAL; \r
+       }\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
-#else\r
-       rk29_dma_enqueue_ring(uart_dma->rx_dmach, (void *)up, uart_dma->rx_phy_addr, uart_dma->rb_size/4, 4, false);\r
-#endif\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
@@ -707,15 +764,15 @@ static int serial_rk_start_rx_dma(struct uart_port *port)
        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
+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
-               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
+       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
@@ -725,77 +782,30 @@ static void serial_rk_report_dma_rx(unsigned long uart)
 {\r
        int count, flip = 0;\r
        struct uart_rk_port *up = (struct uart_rk_port *)uart;\r
+       struct uart_port *port = &up->port;\r
        struct rk_uart_dma *uart_dma = up->dma;\r
 \r
-       if(!uart_dma->rx_dma_used || !up->port.state->port.tty)\r
+       if(!uart_dma->rx_dma_used || !port->state->port.tty)\r
                return;\r
 \r
        serial_rk_update_rb_addr(up);\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
        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
+               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
-       //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(uart_dma->use_timer == 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
-\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
-}\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
-\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
-               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->dma->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
-\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\r
-\r
 #endif /* USE_DMA */\r
 \r
 \r
@@ -872,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
@@ -900,7 +910,7 @@ static void transmit_chars(struct uart_rk_port *up)
        //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
+                       serial_rk_start_dma_tx(up);\r
                        return;\r
                }\r
        }\r
@@ -987,7 +997,9 @@ static void serial_rk_handle_port(struct uart_rk_port *up)
                if(!(up->dma->use_dma & RX_DMA)) {\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
                }\r
 \r
                if ((up->iir & 0x0f) == 0x02) {\r
@@ -1015,7 +1027,9 @@ static void serial_rk_handle_port(struct uart_rk_port *up)
 \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
                //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
@@ -1142,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
@@ -1236,10 +1250,10 @@ 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
@@ -1344,12 +1358,14 @@ static void serial_rk_shutdown(struct uart_port *port)
         */\r
        (void) serial_in(up, UART_RX);\r
 #if USE_DMA\r
-       //if (up->dma->use_dma & TX_DMA)\r
-       //      up->port.state->xmit.buf = NULL;\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
@@ -1361,8 +1377,16 @@ serial_rk_set_termios(struct uart_port *port, struct ktermios *termios,
        unsigned char cval = 0, fcr = 0, mcr = 0;\r
        unsigned long flags;\r
        unsigned int baud, quot;\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
@@ -1536,7 +1560,7 @@ serial_rk_set_termios(struct uart_port *port, struct ktermios *termios,
                        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_rx_dma(&up->port);\r
+                               serial_rk_start_dma_rx(up);\r
                        else\r
                                up->ier |= UART_IER_RDI;\r
                } else\r
@@ -1581,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
@@ -1656,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
@@ -1727,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
@@ -1745,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
@@ -1774,26 +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 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 __devinit serial_rk_probe(struct platform_device *pdev)\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
-       \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
@@ -1801,49 +2016,53 @@ 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->dma = &rk29_uart_ports_dma[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
@@ -1858,16 +2077,18 @@ static int __devinit serial_rk_probe(struct platform_device *pdev)
                init_timer(&up->dma->rx_timer);\r
 \r
                //rx buffer\r
-               up->dma->rb_size =  UART_XMIT_SIZE*2;\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->dma->rx_buffer);\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
@@ -1875,9 +2096,8 @@ static int __devinit serial_rk_probe(struct platform_device *pdev)
                //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
+               serial_rk_init_dma_rx(up);\r
        }\r
 \r
        if(up->dma->use_dma & TX_DMA){\r
@@ -1889,53 +2109,43 @@ static int __devinit serial_rk_probe(struct platform_device *pdev)
                        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_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->port);\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
@@ -1951,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
@@ -1967,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
@@ -1990,15 +2206,12 @@ static int __init serial_rk_init(void)
        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
                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
@@ -2013,4 +2226,3 @@ module_exit(serial_rk_exit);
 \r
 MODULE_LICENSE("GPL");\r
 MODULE_DESCRIPTION("RK UART driver");\r
-\r