[PATCH 3/4] serial: 8250-mtk: add uart DMA support

2018-09-20 Thread Long Cheng
Modify uart register to support DMA function.

Signed-off-by: Long Cheng 
---
 drivers/tty/serial/8250/8250_mtk.c |  211 +++-
 1 file changed, 210 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c 
b/drivers/tty/serial/8250/8250_mtk.c
index dd5e1ce..9da9db4 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -14,6 +14,10 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include "8250.h"
 
@@ -22,12 +26,173 @@
 #define UART_MTK_SAMPLE_POINT  0x0b/* Sample point register */
 #define MTK_UART_RATE_FIX  0x0d/* UART Rate Fix Register */
 
+#define MTK_UART_DMA_EN0x13/* DMA Enable register */
+#define MTK_UART_DMA_EN_TX 0x2
+#define MTK_UART_DMA_EN_RX 0x5
+
+#define MTK_UART_TX_SIZE   UART_XMIT_SIZE
+#define MTK_UART_RX_SIZE   0x8000
+#define MTK_UART_TX_TRIGGER1
+#define MTK_UART_RX_TRIGGERMTK_UART_RX_SIZE
+
+#ifdef CONFIG_SERIAL_8250_DMA
+enum dma_rx_status {
+   DMA_RX_START = 0,
+   DMA_RX_RUNNING = 1,
+   DMA_RX_SHUTDOWN = 2,
+};
+#endif
+
 struct mtk8250_data {
int line;
+   unsigned intrx_pos;
struct clk  *uart_clk;
struct clk  *bus_clk;
+   struct uart_8250_dma*dma;
+#ifdef CONFIG_SERIAL_8250_DMA
+   enum dma_rx_status  rx_status;
+#endif
 };
 
+#ifdef CONFIG_SERIAL_8250_DMA
+static void mtk8250_rx_dma(struct uart_8250_port *up);
+
+static void mtk8250_dma_rx_complete(void *param)
+{
+   struct uart_8250_port *up = param;
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   struct tty_port *tty_port = >port.state->port;
+   struct dma_tx_state state;
+   unsigned char *ptr;
+   int copied;
+
+   dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
+   dma->rx_size, DMA_FROM_DEVICE);
+
+   dmaengine_tx_status(dma->rxchan, dma->rx_cookie, );
+   dmaengine_terminate_all(dma->rxchan);
+
+   if (data->rx_status == DMA_RX_SHUTDOWN)
+   return;
+
+   if ((data->rx_pos + state.residue) <= dma->rx_size) {
+   ptr = (unsigned char *)(data->rx_pos + dma->rx_buf);
+   copied = tty_insert_flip_string(tty_port, ptr, state.residue);
+   } else {
+   ptr = (unsigned char *)(data->rx_pos + dma->rx_buf);
+   copied = tty_insert_flip_string(tty_port, ptr,
+   dma->rx_size - data->rx_pos);
+   ptr = (unsigned char *)(dma->rx_buf);
+   copied += tty_insert_flip_string(tty_port, ptr,
+   data->rx_pos + state.residue - dma->rx_size);
+   }
+   up->port.icount.rx += copied;
+
+   tty_flip_buffer_push(tty_port);
+
+   mtk8250_rx_dma(up);
+}
+
+static void mtk8250_rx_dma(struct uart_8250_port *up)
+{
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   struct dma_async_tx_descriptor  *desc;
+   struct dma_tx_state  state;
+
+   desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
+  dma->rx_size, DMA_DEV_TO_MEM,
+  DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!desc) {
+   pr_err("failed to prepare rx slave single\n");
+   return;
+   }
+
+   desc->callback = mtk8250_dma_rx_complete;
+   desc->callback_param = up;
+
+   dma->rx_cookie = dmaengine_submit(desc);
+
+   dmaengine_tx_status(dma->rxchan, dma->rx_cookie, );
+   data->rx_pos = state.residue;
+
+   dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr,
+  dma->rx_size, DMA_FROM_DEVICE);
+
+   dma_async_issue_pending(dma->rxchan);
+}
+
+static void mtk8250_dma_enable(struct uart_8250_port *up)
+{
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   int lcr = serial_in(up, UART_LCR);
+
+   if (data->rx_status != DMA_RX_START)
+   return;
+
+   dma->rxconf.direction   = DMA_DEV_TO_MEM;
+   dma->rxconf.src_addr_width  = dma->rx_size / 1024;
+   dma->rxconf.src_addr= dma->rx_addr;
+
+   dma->txconf.direction   = DMA_MEM_TO_DEV;
+   dma->txconf.dst_addr_width  = MTK_UART_TX_SIZE / 1024;
+   dma->txconf.dst_addr= dma->tx_addr;
+
+   serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
+   UART_FCR_CLEAR_XMIT);
+   serial_out(up, MTK_UART_DMA_EN,
+  MTK_UART_DMA_EN_RX | MTK_UART_DMA_EN_TX);
+
+   serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+   serial_out(up, UART_EFR, UART_EFR_ECB);
+   serial_out(up, 

[PATCH 3/4] serial: 8250-mtk: add uart DMA support

2018-09-20 Thread Long Cheng
Modify uart register to support DMA function.

Signed-off-by: Long Cheng 
---
 drivers/tty/serial/8250/8250_mtk.c |  211 +++-
 1 file changed, 210 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c 
b/drivers/tty/serial/8250/8250_mtk.c
index dd5e1ce..9da9db4 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -14,6 +14,10 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include "8250.h"
 
@@ -22,12 +26,173 @@
 #define UART_MTK_SAMPLE_POINT  0x0b/* Sample point register */
 #define MTK_UART_RATE_FIX  0x0d/* UART Rate Fix Register */
 
+#define MTK_UART_DMA_EN0x13/* DMA Enable register */
+#define MTK_UART_DMA_EN_TX 0x2
+#define MTK_UART_DMA_EN_RX 0x5
+
+#define MTK_UART_TX_SIZE   UART_XMIT_SIZE
+#define MTK_UART_RX_SIZE   0x8000
+#define MTK_UART_TX_TRIGGER1
+#define MTK_UART_RX_TRIGGERMTK_UART_RX_SIZE
+
+#ifdef CONFIG_SERIAL_8250_DMA
+enum dma_rx_status {
+   DMA_RX_START = 0,
+   DMA_RX_RUNNING = 1,
+   DMA_RX_SHUTDOWN = 2,
+};
+#endif
+
 struct mtk8250_data {
int line;
+   unsigned intrx_pos;
struct clk  *uart_clk;
struct clk  *bus_clk;
+   struct uart_8250_dma*dma;
+#ifdef CONFIG_SERIAL_8250_DMA
+   enum dma_rx_status  rx_status;
+#endif
 };
 
+#ifdef CONFIG_SERIAL_8250_DMA
+static void mtk8250_rx_dma(struct uart_8250_port *up);
+
+static void mtk8250_dma_rx_complete(void *param)
+{
+   struct uart_8250_port *up = param;
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   struct tty_port *tty_port = >port.state->port;
+   struct dma_tx_state state;
+   unsigned char *ptr;
+   int copied;
+
+   dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
+   dma->rx_size, DMA_FROM_DEVICE);
+
+   dmaengine_tx_status(dma->rxchan, dma->rx_cookie, );
+   dmaengine_terminate_all(dma->rxchan);
+
+   if (data->rx_status == DMA_RX_SHUTDOWN)
+   return;
+
+   if ((data->rx_pos + state.residue) <= dma->rx_size) {
+   ptr = (unsigned char *)(data->rx_pos + dma->rx_buf);
+   copied = tty_insert_flip_string(tty_port, ptr, state.residue);
+   } else {
+   ptr = (unsigned char *)(data->rx_pos + dma->rx_buf);
+   copied = tty_insert_flip_string(tty_port, ptr,
+   dma->rx_size - data->rx_pos);
+   ptr = (unsigned char *)(dma->rx_buf);
+   copied += tty_insert_flip_string(tty_port, ptr,
+   data->rx_pos + state.residue - dma->rx_size);
+   }
+   up->port.icount.rx += copied;
+
+   tty_flip_buffer_push(tty_port);
+
+   mtk8250_rx_dma(up);
+}
+
+static void mtk8250_rx_dma(struct uart_8250_port *up)
+{
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   struct dma_async_tx_descriptor  *desc;
+   struct dma_tx_state  state;
+
+   desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
+  dma->rx_size, DMA_DEV_TO_MEM,
+  DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!desc) {
+   pr_err("failed to prepare rx slave single\n");
+   return;
+   }
+
+   desc->callback = mtk8250_dma_rx_complete;
+   desc->callback_param = up;
+
+   dma->rx_cookie = dmaengine_submit(desc);
+
+   dmaengine_tx_status(dma->rxchan, dma->rx_cookie, );
+   data->rx_pos = state.residue;
+
+   dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr,
+  dma->rx_size, DMA_FROM_DEVICE);
+
+   dma_async_issue_pending(dma->rxchan);
+}
+
+static void mtk8250_dma_enable(struct uart_8250_port *up)
+{
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   int lcr = serial_in(up, UART_LCR);
+
+   if (data->rx_status != DMA_RX_START)
+   return;
+
+   dma->rxconf.direction   = DMA_DEV_TO_MEM;
+   dma->rxconf.src_addr_width  = dma->rx_size / 1024;
+   dma->rxconf.src_addr= dma->rx_addr;
+
+   dma->txconf.direction   = DMA_MEM_TO_DEV;
+   dma->txconf.dst_addr_width  = MTK_UART_TX_SIZE / 1024;
+   dma->txconf.dst_addr= dma->tx_addr;
+
+   serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
+   UART_FCR_CLEAR_XMIT);
+   serial_out(up, MTK_UART_DMA_EN,
+  MTK_UART_DMA_EN_RX | MTK_UART_DMA_EN_TX);
+
+   serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+   serial_out(up, UART_EFR, UART_EFR_ECB);
+   serial_out(up, 

Re: [PATCH 3/4] serial: 8250-mtk: add uart DMA support

2017-02-16 Thread Arnd Bergmann
On Thursday, February 16, 2017 7:07:30 PM CET Long Cheng wrote:
> Modify uart register to support DMA function.
> 
> Signed-off-by: Long Cheng 
> ---
>  drivers/tty/serial/8250/8250_mtk.c |  194 
> +++-
>  1 file changed, 193 insertions(+), 1 deletion(-)
> 

This code looks a lot like the one in 8250_omap.c and 8250_dma.c.
Could it be made more generic so we can share more of the implementation?

Arnd


Re: [PATCH 3/4] serial: 8250-mtk: add uart DMA support

2017-02-16 Thread Arnd Bergmann
On Thursday, February 16, 2017 7:07:30 PM CET Long Cheng wrote:
> Modify uart register to support DMA function.
> 
> Signed-off-by: Long Cheng 
> ---
>  drivers/tty/serial/8250/8250_mtk.c |  194 
> +++-
>  1 file changed, 193 insertions(+), 1 deletion(-)
> 

This code looks a lot like the one in 8250_omap.c and 8250_dma.c.
Could it be made more generic so we can share more of the implementation?

Arnd


[PATCH 3/4] serial: 8250-mtk: add uart DMA support

2017-02-16 Thread Long Cheng
Modify uart register to support DMA function.

Signed-off-by: Long Cheng 
---
 drivers/tty/serial/8250/8250_mtk.c |  194 +++-
 1 file changed, 193 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c 
b/drivers/tty/serial/8250/8250_mtk.c
index ce0cc47..7d7a864 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -23,6 +23,10 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include "8250.h"
 
@@ -30,13 +34,165 @@
 #define UART_MTK_SAMPLE_COUNT  0x0a/* Sample count register */
 #define UART_MTK_SAMPLE_POINT  0x0b/* Sample point register */
 #define MTK_UART_RATE_FIX  0x0d/* UART Rate Fix Register */
-
+#define UART_MTK_DMA_EN0x13
+#define TX_TRIGGER 1
+#define RX_TRIGGER 8192
+
+#ifdef CONFIG_SERIAL_8250_DMA
+enum dma_rx_status {
+   DMA_RX_START = 0,
+   DMA_RX_RUNNING = 1,
+   DMA_RX_SHUTDOWN = 2,
+};
+#endif
 struct mtk8250_data {
int line;
+   int rxpos;
struct clk  *uart_clk;
struct clk  *bus_clk;
+   struct uart_8250_dma*dma;
+#ifdef CONFIG_SERIAL_8250_DMA
+   enum dma_rx_status  rxstatus;
+#endif
 };
 
+#ifdef CONFIG_SERIAL_8250_DMA
+static int mtk8250_rx_dma(struct uart_8250_port *up);
+
+static void __mtkdma_rx_complete(void *param)
+{
+   struct uart_8250_port *up = param;
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   struct tty_port *tty_port = >port.state->port;
+   struct dma_tx_state state;
+   unsigned char *ptr;
+   int copied;
+
+   dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
+   dma->rx_size, DMA_FROM_DEVICE);
+
+   dmaengine_tx_status(dma->rxchan, dma->rx_cookie, );
+   dmaengine_terminate_all(dma->rxchan);
+
+   if (data->rxstatus == DMA_RX_SHUTDOWN)
+   return;
+
+   if ((data->rxpos + state.residue) <= dma->rx_size) {
+   ptr = (unsigned char *)(data->rxpos + dma->rx_buf);
+   copied = tty_insert_flip_string(tty_port, ptr, state.residue);
+   } else {
+   ptr = (unsigned char *)(data->rxpos + dma->rx_buf);
+   copied = tty_insert_flip_string(tty_port, ptr,
+   (dma->rx_size - data->rxpos));
+   ptr = (unsigned char *)(dma->rx_buf);
+   copied += tty_insert_flip_string(tty_port, ptr,
+   (data->rxpos + state.residue - dma->rx_size));
+   }
+   up->port.icount.rx += copied;
+
+   tty_flip_buffer_push(tty_port);
+
+   mtk8250_rx_dma(up);
+}
+
+static int mtk8250_rx_dma(struct uart_8250_port *up)
+{
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   struct dma_async_tx_descriptor  *desc;
+   struct dma_tx_state  state;
+
+   desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
+  dma->rx_size, DMA_DEV_TO_MEM,
+  DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!desc)
+   return -EBUSY;
+
+   desc->callback = __mtkdma_rx_complete;
+   desc->callback_param = up;
+
+   dma->rx_cookie = dmaengine_submit(desc);
+
+   dmaengine_tx_status(dma->rxchan, dma->rx_cookie, );
+   data->rxpos = state.residue;
+
+   dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr,
+  dma->rx_size, DMA_FROM_DEVICE);
+
+   dma_async_issue_pending(dma->rxchan);
+
+   return 0;
+}
+
+static void mtk_dma_enable(struct uart_8250_port *up)
+{
+   struct uart_port *port = >port;
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   int tmp = 0;
+
+   if (data->rxstatus != DMA_RX_START)
+   return;
+
+   dma->rxconf.direction   = DMA_DEV_TO_MEM;
+   dma->rxconf.src_addr_width  = dma->rx_size/1024;
+   dma->rxconf.src_addr= dma->rx_addr;
+
+   dma->txconf.direction   = DMA_MEM_TO_DEV;
+   dma->txconf.dst_addr_width  = UART_XMIT_SIZE/1024;
+   dma->txconf.dst_addr= dma->tx_addr;
+
+   serial_port_out(port, UART_FCR, ((1 << 0)|(1 << 1)|(1 << 2)));
+   serial_port_out(port, UART_MTK_DMA_EN,
+   (serial_port_in(port, UART_MTK_DMA_EN) |
+   ((1 << 0) | (1 << 2;
+   serial_port_out(port, UART_MTK_DMA_EN,
+   (serial_port_in(port, UART_MTK_DMA_EN) |
+   (1 << 1)));
+
+   tmp = serial_port_in(port, UART_LCR);
+   serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+   serial_port_out(port, UART_EFR, 

[PATCH 3/4] serial: 8250-mtk: add uart DMA support

2017-02-16 Thread Long Cheng
Modify uart register to support DMA function.

Signed-off-by: Long Cheng 
---
 drivers/tty/serial/8250/8250_mtk.c |  194 +++-
 1 file changed, 193 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c 
b/drivers/tty/serial/8250/8250_mtk.c
index ce0cc47..7d7a864 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -23,6 +23,10 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include "8250.h"
 
@@ -30,13 +34,165 @@
 #define UART_MTK_SAMPLE_COUNT  0x0a/* Sample count register */
 #define UART_MTK_SAMPLE_POINT  0x0b/* Sample point register */
 #define MTK_UART_RATE_FIX  0x0d/* UART Rate Fix Register */
-
+#define UART_MTK_DMA_EN0x13
+#define TX_TRIGGER 1
+#define RX_TRIGGER 8192
+
+#ifdef CONFIG_SERIAL_8250_DMA
+enum dma_rx_status {
+   DMA_RX_START = 0,
+   DMA_RX_RUNNING = 1,
+   DMA_RX_SHUTDOWN = 2,
+};
+#endif
 struct mtk8250_data {
int line;
+   int rxpos;
struct clk  *uart_clk;
struct clk  *bus_clk;
+   struct uart_8250_dma*dma;
+#ifdef CONFIG_SERIAL_8250_DMA
+   enum dma_rx_status  rxstatus;
+#endif
 };
 
+#ifdef CONFIG_SERIAL_8250_DMA
+static int mtk8250_rx_dma(struct uart_8250_port *up);
+
+static void __mtkdma_rx_complete(void *param)
+{
+   struct uart_8250_port *up = param;
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   struct tty_port *tty_port = >port.state->port;
+   struct dma_tx_state state;
+   unsigned char *ptr;
+   int copied;
+
+   dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
+   dma->rx_size, DMA_FROM_DEVICE);
+
+   dmaengine_tx_status(dma->rxchan, dma->rx_cookie, );
+   dmaengine_terminate_all(dma->rxchan);
+
+   if (data->rxstatus == DMA_RX_SHUTDOWN)
+   return;
+
+   if ((data->rxpos + state.residue) <= dma->rx_size) {
+   ptr = (unsigned char *)(data->rxpos + dma->rx_buf);
+   copied = tty_insert_flip_string(tty_port, ptr, state.residue);
+   } else {
+   ptr = (unsigned char *)(data->rxpos + dma->rx_buf);
+   copied = tty_insert_flip_string(tty_port, ptr,
+   (dma->rx_size - data->rxpos));
+   ptr = (unsigned char *)(dma->rx_buf);
+   copied += tty_insert_flip_string(tty_port, ptr,
+   (data->rxpos + state.residue - dma->rx_size));
+   }
+   up->port.icount.rx += copied;
+
+   tty_flip_buffer_push(tty_port);
+
+   mtk8250_rx_dma(up);
+}
+
+static int mtk8250_rx_dma(struct uart_8250_port *up)
+{
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   struct dma_async_tx_descriptor  *desc;
+   struct dma_tx_state  state;
+
+   desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
+  dma->rx_size, DMA_DEV_TO_MEM,
+  DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!desc)
+   return -EBUSY;
+
+   desc->callback = __mtkdma_rx_complete;
+   desc->callback_param = up;
+
+   dma->rx_cookie = dmaengine_submit(desc);
+
+   dmaengine_tx_status(dma->rxchan, dma->rx_cookie, );
+   data->rxpos = state.residue;
+
+   dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr,
+  dma->rx_size, DMA_FROM_DEVICE);
+
+   dma_async_issue_pending(dma->rxchan);
+
+   return 0;
+}
+
+static void mtk_dma_enable(struct uart_8250_port *up)
+{
+   struct uart_port *port = >port;
+   struct uart_8250_dma *dma = up->dma;
+   struct mtk8250_data *data = up->port.private_data;
+   int tmp = 0;
+
+   if (data->rxstatus != DMA_RX_START)
+   return;
+
+   dma->rxconf.direction   = DMA_DEV_TO_MEM;
+   dma->rxconf.src_addr_width  = dma->rx_size/1024;
+   dma->rxconf.src_addr= dma->rx_addr;
+
+   dma->txconf.direction   = DMA_MEM_TO_DEV;
+   dma->txconf.dst_addr_width  = UART_XMIT_SIZE/1024;
+   dma->txconf.dst_addr= dma->tx_addr;
+
+   serial_port_out(port, UART_FCR, ((1 << 0)|(1 << 1)|(1 << 2)));
+   serial_port_out(port, UART_MTK_DMA_EN,
+   (serial_port_in(port, UART_MTK_DMA_EN) |
+   ((1 << 0) | (1 << 2;
+   serial_port_out(port, UART_MTK_DMA_EN,
+   (serial_port_in(port, UART_MTK_DMA_EN) |
+   (1 << 1)));
+
+   tmp = serial_port_in(port, UART_LCR);
+   serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+   serial_port_out(port, UART_EFR, UART_EFR_ECB);
+