ENGR00181395-1: Add UART MISC functions support for Faraday
authorJingchang Lu <b35083@freescale.com>
Wed, 12 Sep 2012 05:56:45 +0000 (13:56 +0800)
committerJason Jin <Jason.jin@freescale.com>
Thu, 11 Oct 2012 09:49:48 +0000 (17:49 +0800)
Add hardware flow control support,
Add transmit DMA support,
Add FIFO operation support,
Add MSB/LSB on data support,
Add 9-bits MARK/SPACE support.

Signed-off-by: Jingchang Lu <b35083@freescale.com>
arch/arm/mach-mvf/board-twr-vf700.c
arch/arm/plat-mxc/include/mach/imx-uart.h
drivers/tty/serial/mvf.c
include/asm-generic/ioctls.h

index b79b40e2ffb78a9aefb19efb2dce0ada0fd4f71f..a796fde9a562d88c286529220a13a56ecc1c38a5 100644 (file)
@@ -228,9 +228,15 @@ static struct platform_device mvf_twr_audio_device = {
        .name = "mvf-sgtl5000",
 };
 
+static struct imxuart_platform_data mvf_uart1_pdata = {
+       .flags = IMXUART_FIFO | IMXUART_EDMA,
+       .dma_req_rx = DMA_MUX03_UART1_RX,
+       .dma_req_tx = DMA_MUX03_UART1_TX,
+};
+
 static inline void mvf_vf700_init_uart(void)
 {
-       mvf_add_imx_uart(1, NULL);
+       mvf_add_imx_uart(1, &mvf_uart1_pdata);
 }
 
 static int mvf_vf700_fec_phy_init(struct phy_device *phydev)
index 48dc29a4f1d67c7e34b3ce8879e11f7bb1dd84c3..4e43ee1a0e3157c5c9551820aa6fee8be720eccd 100644 (file)
@@ -24,6 +24,7 @@
 #define IMXUART_USE_DCEDTE  (1<<2)
 #define IMXUART_SDMA        (1<<3)
 #define IMXUART_EDMA   (1<<4)
+#define IMXUART_FIFO   (1 << 5)
 
 struct imxuart_platform_data {
        int (*init)(struct platform_device *pdev);
index 13aa8a9eef8a274444a2c9231d1b3ac97628932e..a65a275c7c98b0fc7038c485690886de2c0d63be 100644 (file)
@@ -49,8 +49,9 @@
 #include <mach/imx-uart.h>
 #include <mach/mxc_uart.h>
 #include <mach/mvf.h>
+#include <mach/mcf_edma.h>
 
-
+#define CONFIG_MVF_SERIAL_DMA
 /* We've been assigned a range on the "Low-density serial ports" major */
 #define SERIAL_IMX_MAJOR        207
 #define MINOR_START            16
@@ -79,19 +80,27 @@ struct imx_port {
        unsigned int            use_irda:1;
        unsigned int            irda_inv_rx:1;
        unsigned int            irda_inv_tx:1;
+       unsigned int            fifo_en:1; /* enable FIFO mode */
+       unsigned int            mark_en:1; /* enable Mark address match */
+       unsigned int            format_9bits:1; /* 9bits data format */
        unsigned short          trcv_delay; /* transceiver delay */
+       unsigned char           ma_addr; /* Match address */
        struct clk              *clk;
 
+       unsigned int            tx_fifo_size, rx_fifo_size;
+
        /* DMA fields */
        int                     enable_dma;
+       unsigned long           dma_tx_ch; /* configured eDMA channel */
        struct imx_dma_data     dma_data;
        struct dma_chan         *dma_chan_rx, *dma_chan_tx;
-       struct scatterlist      rx_sgl, tx_sgl[2];
+       struct scatterlist      rx_sgl, tx_sgl;
        void                    *rx_buf;
+       unsigned char           *tx_buf;
        unsigned int            rx_bytes, tx_bytes;
        struct work_struct      tsk_dma_rx, tsk_dma_tx;
        unsigned int            dma_tx_nents;
-       bool                    dma_is_rxing;
+       bool                    dma_is_rxing, dma_is_txing;
        wait_queue_head_t       dma_wait;
 };
 
@@ -194,8 +203,10 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
 {
        struct circ_buf *xmit = &sport->port.state->xmit;
 
-       while (!uart_circ_empty(xmit) &&
-               (readb(sport->port.membase + MXC_UARTSR1) & MXC_UARTSR1_TDRE)) {
+       while (!uart_circ_empty(xmit) && (sport->fifo_en == 1 ?
+       (readb(sport->port.membase + MXC_UARTTCFIFO) < sport->tx_fifo_size) :
+               (readb(sport->port.membase + MXC_UARTSR1) & MXC_UARTSR1_TDRE)
+               )) {
                /* send xmit->buf[xmit->tail]
                 * out the port here */
                writeb(xmit->buf[xmit->tail], sport->port.membase + MXC_UARTDR);
@@ -211,12 +222,91 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
 }
 
 #ifdef CONFIG_MVF_SERIAL_DMA
-static void dma_tx_callback(void *data)
+/****************************************************************************/
+/* Configure and start DMA engine. */
+static void tx_uart_dmarun(struct imx_port *sport)
+{
+       if (sport->dma_tx_nents == 0)
+               return;
+
+       mcf_edma_set_tcd_params(sport->dma_tx_ch,
+                       (u32)sg_phys(&sport->tx_sgl),
+                       (u32)(sport->port.mapbase + MXC_UARTDR),
+                       MCF_EDMA_TCD_ATTR_SSIZE_8BIT |
+                       MCF_EDMA_TCD_ATTR_DSIZE_8BIT,
+                       1,
+                       1,
+                       0,
+                       sport->tx_bytes,
+                       0,
+                       0,
+                       0,
+                       1, /* major_int */
+                       1, /* disable_req */
+                       0
+                       );
+       sport->dma_is_txing = 1;
+       mcf_edma_enable_transfer(sport->dma_tx_ch);
+}
+
+/****************************************************************************/
+static irqreturn_t dma_tx_callback(int ch, void *data)
 {
+       struct imx_port *sport = data;
+       struct circ_buf *xmit = &sport->port.state->xmit;
+
+       mcf_edma_stop_transfer(sport->dma_tx_ch);
+
+       dma_unmap_sg(sport->port.dev, &sport->tx_sgl, 1, DMA_TO_DEVICE);
+
+       spin_lock(&sport->port.lock);
+       xmit->tail = (xmit->tail + sport->tx_bytes) & (UART_XMIT_SIZE - 1);
+       sport->port.icount.tx += sport->tx_bytes;
+       spin_unlock(&sport->port.lock);
+
+       sport->dma_is_txing = 0;
+
+       schedule_work(&sport->tsk_dma_tx);
+
+       return IRQ_HANDLED;
 }
 
 static void dma_tx_work(struct work_struct *w)
 {
+       struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_tx);
+       struct circ_buf *xmit = &sport->port.state->xmit;
+       unsigned long flags;
+
+       if (sport->dma_is_txing)
+               return;
+
+       spin_lock_irqsave(&sport->port.lock, flags);
+       sport->tx_bytes = uart_circ_chars_pending(xmit);
+
+       if (sport->tx_bytes > 0) {
+               sport->dma_tx_nents = 0;
+               if (xmit->tail > xmit->head) {
+                       sg_init_one(&sport->tx_sgl, xmit->buf + xmit->tail,
+                                       UART_XMIT_SIZE - xmit->tail);
+                       sport->dma_tx_nents = UART_XMIT_SIZE - xmit->tail;
+                       sport->tx_bytes = sport->dma_tx_nents;
+               } else {
+                       sg_init_one(&sport->tx_sgl, xmit->buf + xmit->tail,
+                                       sport->tx_bytes);
+                       sport->dma_tx_nents = sport->tx_bytes;
+               }
+
+               dma_map_sg(sport->port.dev, &sport->tx_sgl, 1, DMA_TO_DEVICE);
+               /* fire it */
+               tx_uart_dmarun(sport);
+       }
+
+       spin_unlock_irqrestore(&sport->port.lock, flags);
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&sport->port);
+
+       return;
 }
 #endif
 
@@ -239,9 +329,11 @@ static void imx_start_tx(struct uart_port *port)
                writel(temp, sport->port.membase + UCR1);
        }
 #endif
+       if (!sport->enable_dma) {
                temp = readb(sport->port.membase + MXC_UARTCR2);
                writeb(temp | MXC_UARTCR2_TIE,
                                sport->port.membase + MXC_UARTCR2);
+       }
 #if 0
        if (USE_IRDA(sport)) {
                temp = readl(sport->port.membase + UCR1);
@@ -254,26 +346,15 @@ static void imx_start_tx(struct uart_port *port)
        }
 #endif
 
+       if (sport->enable_dma) {
+               schedule_work(&sport->tsk_dma_tx);
+               return;
+       }
+
        if (readb(sport->port.membase + MXC_UARTSR1) & MXC_UARTSR1_TDRE)
                imx_transmit_buffer(sport);
 }
 
-static irqreturn_t imx_rtsint(int irq, void *dev_id)
-{
-#if 0
-       struct imx_port *sport = dev_id;
-       unsigned int val;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sport->port.lock, flags);
-
-       writeb(MXC_UARTMODEM_RXRTS, sport->port.membase + MXC_UARTMODEM);
-       wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
-
-       spin_unlock_irqrestore(&sport->port.lock, flags);
-#endif
-       return IRQ_HANDLED;
-}
 
 static irqreturn_t imx_txint(int irq, void *dev_id)
 {
@@ -306,10 +387,10 @@ out:
 static irqreturn_t imx_rxint(int irq, void *dev_id)
 {
        struct imx_port *sport = dev_id;
-       unsigned int rx, flg, ignored = 0;
+       unsigned int flg, ignored = 0;
        struct tty_struct *tty = sport->port.state->port.tty;
        unsigned long flags;
-       unsigned char sr;
+       unsigned char r8, rx, sr;
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
@@ -323,8 +404,12 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
                 */
                sr = readb(sport->port.membase + MXC_UARTSR1);
 
+               r8 = readb(sport->port.membase + MXC_UARTCR3) & MXC_UARTCR3_R8;
                rx = readb(sport->port.membase + MXC_UARTDR);
 
+               if (sport->mark_en &&
+                       (sport->format_9bits ? r8 : (rx == sport->ma_addr)))
+                               continue;
 
                if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
                        continue;
@@ -458,12 +543,13 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
 
 static int imx_setup_watermark(struct imx_port *sport, unsigned int mode)
 {
-       unsigned char val, cr2;
+       unsigned char val, old_cr2, cr2;
 
        /* set receiver / transmitter trigger level.
         */
-       cr2 = readb(sport->port.membase + MXC_UARTCR2);
-       cr2 &= ~(MXC_UARTCR2_TE | MXC_UARTCR2_RE);
+       old_cr2 = cr2 = readb(sport->port.membase + MXC_UARTCR2);
+       cr2 &= ~(MXC_UARTCR2_TIE | MXC_UARTCR2_TCIE | MXC_UARTCR2_TE |
+                       MXC_UARTCR2_RIE | MXC_UARTCR2_RE);
        writeb(cr2, sport->port.membase + MXC_UARTCR2);
 
        val = TXTL;
@@ -473,7 +559,10 @@ static int imx_setup_watermark(struct imx_port *sport, unsigned int mode)
 
        /* Enable Tx and Rx FIFO */
        val = readb(sport->port.membase + MXC_UARTPFIFO);
-
+       sport->tx_fifo_size = 0x1 << (((val >> MXC_UARTPFIFO_TXFIFOSIZE_OFF) &
+               MXC_UARTPFIFO_TXFIFOSIZE_MASK) + 1);
+       sport->rx_fifo_size = 0x1 << (((val >> MXC_UARTPFIFO_RXFIFOSIZE_OFF) &
+               MXC_UARTPFIFO_RXFIFOSIZE_MASK) + 1);
        writeb(val | MXC_UARTPFIFO_TXFE | MXC_UARTPFIFO_RXFE,
                        sport->port.membase + MXC_UARTPFIFO);
 
@@ -481,63 +570,12 @@ static int imx_setup_watermark(struct imx_port *sport, unsigned int mode)
        writeb(MXC_UARTCFIFO_TXFLUSH | MXC_UARTCFIFO_RXFLUSH,
                        sport->port.membase + MXC_UARTCFIFO);
 
-       /* enable Tx and Rx */
-       writeb(cr2 | MXC_UARTCR2_TE | MXC_UARTCR2_RE,
-                               sport->port.membase + MXC_UARTCR2);
-
-       return 0;
-}
-
-static bool imx_uart_filter(struct dma_chan *chan, void *param)
-{
-       struct imx_port *sport = param;
-
-       if (!imx_dma_is_general_purpose(chan))
-               return false;
-       chan->private = &sport->dma_data;
-       return true;
-}
-
-#ifdef CONFIG_MVF_SERIAL_DMA
-#define RX_BUF_SIZE    (PAGE_SIZE)
-static int start_rx_dma(struct imx_port *sport);
-
-static void dma_rx_work(struct work_struct *w)
-{
-}
-
-static void imx_finish_dma(struct imx_port *sport)
-{
-}
-
-/*
- * There are three kinds of RX DMA interrupts:
- *   [1] the RX DMA buffer is full.
- *   [2] the Aging timer expires(wait for 8 bytes long)
- *   [3] the Idle Condition Detect(enabled the UCR4_IDDMAEN).
- *
- * The [2] and [3] are similar, but [3] is better.
- * [3] can wait for 32 bytes long, so we do not use [2].
- */
-static void dma_rx_callback(void *data)
-{
-}
+       /* restore CR2 */
+       writeb(old_cr2, sport->port.membase + MXC_UARTCR2);
 
-static int start_rx_dma(struct imx_port *sport)
-{
        return 0;
 }
 
-static void imx_uart_dma_exit(struct imx_port *sport)
-{
-}
-
-/* see the "i.MX61 SDMA Scripts User Manual.doc" for the parameters */
-static int imx_uart_dma_init(struct imx_port *sport)
-{
-       return 0;
-}
-#endif
 
 /* half the RX buffer size */
 #define CTSTL 16
@@ -548,9 +586,11 @@ static int imx_startup(struct uart_port *port)
        int retval;
        unsigned long flags, temp;
        struct tty_struct *tty;
+       struct imxuart_platform_data *pdata = port->dev->platform_data;
 
 #ifndef CONFIG_SERIAL_CORE_CONSOLE
-       /*imx_setup_watermark(sport, 0);*/
+       if (sport->fifo_en)
+               imx_setup_watermark(sport, 0);
 #endif
 
        /* disable the DREN bit (Data Ready interrupt enable) before
@@ -575,8 +615,8 @@ static int imx_startup(struct uart_port *port)
        }
 
        /*
-        * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
-        * chips only have one interrupt.
+        * Allocate the IRQ(s)
+        * Vybrid chips only have one interrupt.
         */
                retval = request_irq(sport->port.irq, imx_int, 0,
                                DRIVER_NAME, sport);
@@ -584,20 +624,27 @@ static int imx_startup(struct uart_port *port)
                        free_irq(sport->port.irq, sport);
                        goto error_out1;
                }
-#if 0
-       /* Enable the SDMA for uart. */
+
+       /* Enable the DMA ops for uart. */
        if (sport->enable_dma) {
-               int ret;
-               ret = imx_uart_dma_init(sport);
-               if (ret)
-                       goto error_out3;
+               /* request eDMA channel and buffer */
+               sport->dma_tx_ch = mcf_edma_request_channel(pdata->dma_req_tx,
+                       dma_tx_callback, NULL, 1, sport, NULL, "ttymxc");
+
+               sport->dma_is_txing = 0;
+
+               /* enable DMA request generation */
+               temp = readb(sport->port.membase + MXC_UARTCR5);
+               temp |= MXC_UARTCR5_TDMAS;
+               writeb(temp, sport->port.membase + MXC_UARTCR5);
 
                sport->port.flags |= UPF_LOW_LATENCY;
                INIT_WORK(&sport->tsk_dma_tx, dma_tx_work);
-               INIT_WORK(&sport->tsk_dma_rx, dma_rx_work);
+               /*INIT_WORK(&sport->tsk_dma_rx, dma_rx_work);*/
                init_waitqueue_head(&sport->dma_wait);
+
        }
-#endif
+
        spin_lock_irqsave(&sport->port.lock, flags);
        /*
         * Finally, clear and enable interrupts
@@ -616,12 +663,6 @@ static int imx_startup(struct uart_port *port)
 
        return 0;
 
-error_out3:
-       if (sport->txirq)
-               free_irq(sport->txirq, sport);
-error_out2:
-       if (sport->rxirq)
-               free_irq(sport->rxirq, sport);
 error_out1:
        return retval;
 }
@@ -634,6 +675,11 @@ static void imx_shutdown(struct uart_port *port)
 
        if (sport->enable_dma) {
                /* We have to wait for the DMA to finish. */
+               if (sport->dma_tx_ch) {
+                       mcf_edma_stop_transfer(sport->dma_tx_ch);
+                       mcf_edma_free_channel(sport->dma_tx_ch, sport);
+                       sport->dma_tx_ch = 0;
+               }
        }
 
        spin_lock_irqsave(&sport->port.lock, flags);
@@ -672,7 +718,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 {
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long flags;
-       unsigned char cr1, old_cr1, old_cr2, cr4, bdh;
+       unsigned char cr1, old_cr1, old_cr2, cr4, bdh, modem;
        unsigned int  baud;
        unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
        unsigned int sbr, brfa;
@@ -681,6 +727,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        old_cr2 = readb(sport->port.membase + MXC_UARTCR2);
        cr4 = readb(sport->port.membase + MXC_UARTCR4);
        bdh = readb(sport->port.membase + MXC_UARTBDH);
+       modem = readb(sport->port.membase + MXC_UARTMODEM);
        /*
         * If we don't support modem control lines, don't allow
         * these to be set.
@@ -691,29 +738,62 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        }
 
        /*
-        * We only support CS8.
+        * We only support CS8 and CS7,but CS7 must enable PE.
+        * supported mode:
+        *  - (7,e/o,1)
+        *  - (8,n,1)
+        *  - (8,m/s,1)
+        *  - (8,e/o,1)
         */
-       while ((termios->c_cflag & CSIZE) != CS8) {
+       while ((termios->c_cflag & CSIZE) != CS8 &&
+               (termios->c_cflag & CSIZE) != CS7) {
                termios->c_cflag &= ~CSIZE;
                termios->c_cflag |= old_csize;
                old_csize = CS8;
        }
 
-       if ((termios->c_cflag & CSIZE) == CS8)
+       if ((termios->c_cflag & CSIZE) == CS8 ||
+               (termios->c_cflag & CSIZE) == CS7)
                cr1 = old_cr1 & ~MXC_UARTCR1_M;
 
-       if (termios->c_cflag & CRTSCTS)
-                       termios->c_cflag &= ~CRTSCTS;
+       if (termios->c_cflag & CMSPAR) {
+               if ((termios->c_cflag & CSIZE) != CS8) {
+                       termios->c_cflag &= ~CSIZE;
+                       termios->c_cflag |= CS8;
+               }
+               cr1 |= MXC_UARTCR1_M;
+       }
+
+       if (termios->c_cflag & CRTSCTS) {
+               if (sport->have_rtscts)
+                       modem |= (MXC_UARTMODEM_RXRTSE | MXC_UARTMODEM_TXCTSE);
+
+       } else {
+               termios->c_cflag &= ~CRTSCTS;
+               modem &= ~(MXC_UARTMODEM_RXRTSE | MXC_UARTMODEM_TXCTSE);
+       }
 
        if (termios->c_cflag & CSTOPB)
                termios->c_cflag &= ~CSTOPB;
 
-       if (termios->c_cflag & PARENB) {
-               cr1 |= MXC_UARTCR1_PE;
-               if (termios->c_cflag & PARODD)
-                       cr1 |= MXC_UARTCR1_PT;
-               else
-                       cr1 &= ~MXC_UARTCR1_PT;
+       /* parity must enable when CS7 to match 8-bits format */
+       if ((termios->c_cflag & CSIZE) == CS7)
+               termios->c_cflag |= PARENB;
+
+       if ((termios->c_cflag & PARENB)) {
+               if (termios->c_cflag & CMSPAR) {
+                       cr1 &= ~MXC_UARTCR1_PE;
+                       cr1 |= MXC_UARTCR1_M;
+                       sport->format_9bits = 1;
+               } else {
+                       cr1 |= MXC_UARTCR1_PE;
+                       if ((termios->c_cflag & CSIZE) == CS8)
+                               cr1 |= MXC_UARTCR1_M;
+                       if (termios->c_cflag & PARODD)
+                               cr1 |= MXC_UARTCR1_PT;
+                       else
+                               cr1 &= ~MXC_UARTCR1_PT;
+               }
        }
 
        /*
@@ -755,10 +835,10 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        while (!(readb(sport->port.membase + MXC_UARTSR1) & MXC_UARTSR1_TC))
                barrier();
 
-       /* disable transmit and receive */
        writeb(old_cr2 & ~(MXC_UARTCR2_TE | MXC_UARTCR2_RE),
                        sport->port.membase + MXC_UARTCR2);
 
+       /* disable transmit and receive */
        sbr = sport->port.uartclk / (16 * baud);
        brfa = ((sport->port.uartclk - (16 * sbr * baud)) * 2)/baud;
 
@@ -771,6 +851,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        writeb(bdh, sport->port.membase + MXC_UARTBDH);
        writeb(sbr & 0xFF, sport->port.membase + MXC_UARTBDL);
        writeb(cr1, sport->port.membase + MXC_UARTCR1);
+       writeb(modem, sport->port.membase + MXC_UARTMODEM);
 
        /* restore control register */
        writeb(old_cr2, sport->port.membase + MXC_UARTCR2);
@@ -854,6 +935,82 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser)
        return ret;
 }
 
+static int imx_uart_ioctl(struct uart_port *uport, unsigned int cmd,
+                       unsigned long arg)
+{
+       struct imx_port *sport = (struct imx_port *)uport;
+       unsigned char cr1, cr3, cr4, sr2, ma1;
+
+       switch (cmd) {
+       case TIOCSETADDRMODE:
+               sport->mark_en = 1;
+               sport->ma_addr = (unsigned char) arg;
+                       /*
+                        * Enable Mark/Space mode
+                        * Avaliable config for MSB as address bit include:
+                        * 1b start + 7b data + 1b addr + 1b stop (8,n,1)
+                        * 1b start + 8b data + 1b addr + 1b stop (9,n,1)
+                        * 1b start + 8b data + 1b addr + 1b parity + 1b stop
+                        *
+                        * only 9,n,1 mark/space mode is supported
+                        */
+               cr4 = readb(sport->port.membase + MXC_UARTCR4);
+               cr4 |= MXC_UARTCR4_MAEN1;
+               ma1 = (unsigned char) arg;
+               /* Set match address for receive comparation */
+               writeb(ma1, sport->port.membase + MXC_UARTMAR1);
+               /* Enable address match */
+               writeb(cr4, sport->port.membase + MXC_UARTCR4);
+               cr1 = readb(sport->port.membase + MXC_UARTCR1);
+               cr1 |= MXC_UARTCR1_M;
+               sport->format_9bits = 1;
+               writeb(cr1, sport->port.membase + MXC_UARTCR1);
+               return 0;
+
+       case TIOCCLRADDRMODE:
+               cr4 = readb(sport->port.membase + MXC_UARTCR4);
+               cr4 &= ~MXC_UARTCR4_MAEN1;
+               writeb(cr4, sport->port.membase + MXC_UARTCR4);
+               sport->mark_en = 0;
+               return 0;
+
+       case TIOCSETMARK:
+               /* Set Mark flag: following Tx is Address */
+               cr3 = readb(sport->port.membase + MXC_UARTCR3);
+               cr3 |= MXC_UARTCR3_T8;
+               writeb(cr3, sport->port.membase + MXC_UARTCR3);
+               return 0;
+
+       case TIOCCLRMARK:
+               /* clear Mark flag: following Tx is Data */
+               cr3 = readb(sport->port.membase + MXC_UARTCR3);
+               cr3 &= ~MXC_UARTCR3_T8;
+               writeb(cr3, sport->port.membase + MXC_UARTCR3);
+               return 0;
+
+       case TIOCMSBMODE:
+               /* MSB first on line */
+               sr2 = readb(sport->port.membase + MXC_UARTSR2);
+               sr2 |= MXC_UARTSR2_MSBF;
+               writeb(sr2, sport->port.membase + MXC_UARTSR2);
+
+               return 0;
+
+       case TIOCLSBMODE:
+               /* LSB first on line */
+               sr2 = readb(sport->port.membase + MXC_UARTSR2);
+               sr2 &= ~MXC_UARTSR2_MSBF;
+               writeb(sr2, sport->port.membase + MXC_UARTSR2);
+
+               return 0;
+
+       default:
+               break;
+       }
+       return -ENOIOCTLCMD;
+
+}
+
 static struct uart_ops imx_pops = {
        .tx_empty       = imx_tx_empty,
        .set_mctrl      = imx_set_mctrl,
@@ -871,6 +1028,7 @@ static struct uart_ops imx_pops = {
        .request_port   = imx_request_port,
        .config_port    = imx_config_port,
        .verify_port    = imx_verify_port,
+       .ioctl          = imx_uart_ioctl,
 };
 
 static struct imx_port *imx_ports[UART_NR];
@@ -1001,7 +1159,8 @@ imx_console_setup(struct console *co, char *options)
        else
                imx_console_get_options(sport, &baud, &parity, &bits);
 
-       /*imx_setup_watermark(sport, 0);*/
+       if (sport->fifo_en == 1)
+               imx_setup_watermark(sport, 0);
 
        return uart_set_options(&sport->port, co, baud, parity, bits, flow);
 }
@@ -1104,7 +1263,7 @@ static int serial_imx_probe(struct platform_device *pdev)
        sport->port.uartclk = clk_get_rate(sport->clk);
 
        imx_ports[pdev->id] = sport;
-/*
+
        pdata = pdev->dev.platform_data;
        if (pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
                sport->have_rtscts = 1;
@@ -1112,12 +1271,14 @@ static int serial_imx_probe(struct platform_device *pdev)
                sport->use_dcedte = 1;
        if (pdata && (pdata->flags & IMXUART_EDMA))
                sport->enable_dma = 1;
+       if (pdata && (pdata->flags & IMXUART_FIFO))
+               sport->fifo_en = 1;
 
 #ifdef CONFIG_IRDA
        if (pdata && (pdata->flags & IMXUART_IRDA))
                sport->use_irda = 1;
 #endif
-*/
+
        if (pdata && pdata->init) {
                ret = pdata->init(pdev);
                if (ret)
index 199975fac395745342a6cabef1bfb612e73fc1dc..db014dd79a69fdc61278ef06cc0245729d2772c3 100644 (file)
 # define FIOQSIZE      0x5460
 #endif
 
+/* 9bits Mark/Space operation support */
+#define TIOCSETADDRMODE        0x5470 /* enable uart address/data mode */
+#define TIOCCLRADDRMODE        0x5471 /* disable uart address/data mode */
+#define TIOCSETMARK    0x5472 /* address phase: set mark bit */
+#define TIOCCLRMARK    0x5473 /* data phase: clear mark bit */
+#define TIOCMSBMODE    0x5474 /* enable MSB first mode */
+#define TIOCLSBMODE    0x5475 /* enable LSB first mode */
+
 /* Used for packet mode */
 #define TIOCPKT_DATA            0
 #define TIOCPKT_FLUSHREAD       1