regulator: Fix check of unsigned return value and transmit errors in wm831x_gp_ldo_ge...
[safe/jmp/linux-2.6] / drivers / serial / bfin_5xx.c
index f9b5a72..50abb7e 100644 (file)
 #include <asm/cacheflush.h>
 #endif
 
+#ifdef CONFIG_SERIAL_BFIN_MODULE
+# undef CONFIG_EARLY_PRINTK
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_MODULE
+# undef CONFIG_EARLY_PRINTK
+#endif
+
 /* UART name and device definitions */
 #define BFIN_SERIAL_NAME       "ttyBF"
 #define BFIN_SERIAL_MAJOR      204
@@ -63,7 +71,6 @@ static int kgdboc_break_enabled;
 #define DMA_RX_YCOUNT          (PAGE_SIZE / DMA_RX_XCOUNT)
 
 #define DMA_RX_FLUSH_JIFFIES   (HZ / 50)
-#define CTS_CHECK_JIFFIES      (HZ / 50)
 
 #ifdef CONFIG_SERIAL_BFIN_DMA
 static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart);
@@ -71,10 +78,65 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart);
 static void bfin_serial_tx_chars(struct bfin_serial_port *uart);
 #endif
 
-static void bfin_serial_mctrl_check(struct bfin_serial_port *uart);
-
 static void bfin_serial_reset_irda(struct uart_port *port);
 
+#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
+       defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
+static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+       if (uart->cts_pin < 0)
+               return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+
+       /* CTS PIN is negative assertive. */
+       if (UART_GET_CTS(uart))
+               return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+       else
+               return TIOCM_DSR | TIOCM_CAR;
+}
+
+static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+       if (uart->rts_pin < 0)
+               return;
+
+       /* RTS PIN is negative assertive. */
+       if (mctrl & TIOCM_RTS)
+               UART_ENABLE_RTS(uart);
+       else
+               UART_DISABLE_RTS(uart);
+}
+
+/*
+ * Handle any change of modem status signal.
+ */
+static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id)
+{
+       struct bfin_serial_port *uart = dev_id;
+       unsigned int status;
+
+       status = bfin_serial_get_mctrl(&uart->port);
+       uart_handle_cts_change(&uart->port, status & TIOCM_CTS);
+#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+       uart->scts = 1;
+       UART_CLEAR_SCTS(uart);
+       UART_CLEAR_IER(uart, EDSSI);
+#endif
+
+       return IRQ_HANDLED;
+}
+#else
+static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
+{
+       return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+#endif
+
 /*
  * interrupts are disabled on entry
  */
@@ -82,7 +144,7 @@ static void bfin_serial_stop_tx(struct uart_port *port)
 {
        struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
 #ifdef CONFIG_SERIAL_BFIN_DMA
-       struct circ_buf *xmit = &uart->port.info->xmit;
+       struct circ_buf *xmit = &uart->port.state->xmit;
 #endif
 
        while (!(UART_GET_LSR(uart) & TEMT))
@@ -109,7 +171,14 @@ static void bfin_serial_stop_tx(struct uart_port *port)
 static void bfin_serial_start_tx(struct uart_port *port)
 {
        struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-       struct tty_struct *tty = uart->port.info->port.tty;
+       struct tty_struct *tty = uart->port.state->port.tty;
+
+#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+       if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) {
+               uart->scts = 0;
+               uart_handle_cts_change(&uart->port, uart->scts);
+       }
+#endif
 
        /*
         * To avoid losting RX interrupt, we reset IR function
@@ -174,10 +243,10 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
                        return;
                }
 
-       if (!uart->port.info || !uart->port.info->port.tty)
+       if (!uart->port.state || !uart->port.state->port.tty)
                return;
 #endif
-       tty = uart->port.info->port.tty;
+       tty = uart->port.state->port.tty;
 
        if (ANOMALY_05000363) {
                /* The BF533 (and BF561) family of processors have a nice anomaly
@@ -262,19 +331,18 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
 
 static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
 {
-       struct circ_buf *xmit = &uart->port.info->xmit;
-
-       /*
-        * Check the modem control lines before
-        * transmitting anything.
-        */
-       bfin_serial_mctrl_check(uart);
+       struct circ_buf *xmit = &uart->port.state->xmit;
 
        if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
 #ifdef CONFIG_BF54x
                /* Clear TFI bit */
                UART_PUT_LSR(uart, TFI);
 #endif
+               /* Anomaly notes:
+                *  05000215 -  we always clear ETBEI within last UART TX
+                *              interrupt to end a string. It is always set
+                *              when start a new tx.
+                */
                UART_CLEAR_IER(uart, ETBEI);
                return;
        }
@@ -312,6 +380,12 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
 {
        struct bfin_serial_port *uart = dev_id;
 
+#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+       if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) {
+               uart->scts = 0;
+               uart_handle_cts_change(&uart->port, uart->scts);
+       }
+#endif
        spin_lock(&uart->port.lock);
        if (UART_GET_LSR(uart) & THRE)
                bfin_serial_tx_chars(uart);
@@ -324,16 +398,10 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
 #ifdef CONFIG_SERIAL_BFIN_DMA
 static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
 {
-       struct circ_buf *xmit = &uart->port.info->xmit;
+       struct circ_buf *xmit = &uart->port.state->xmit;
 
        uart->tx_done = 0;
 
-       /*
-        * Check the modem control lines before
-        * transmitting anything.
-        */
-       bfin_serial_mctrl_check(uart);
-
        if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
                uart->tx_count = 0;
                uart->tx_done = 1;
@@ -360,6 +428,7 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
        set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail));
        set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
        set_dma_x_modify(uart->tx_dma_channel, 1);
+       SSYNC();
        enable_dma(uart->tx_dma_channel);
 
        UART_SET_IER(uart, ETBEI);
@@ -367,7 +436,7 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
 
 static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
 {
-       struct tty_struct *tty = uart->port.info->port.tty;
+       struct tty_struct *tty = uart->port.state->port.tty;
        int i, flg, status;
 
        status = UART_GET_LSR(uart);
@@ -418,27 +487,41 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
 void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
 {
        int x_pos, pos;
-       unsigned long flags;
-
-       spin_lock_irqsave(&uart->port.lock, flags);
 
+       dma_disable_irq(uart->rx_dma_channel);
+       spin_lock_bh(&uart->port.lock);
+
+       /* 2D DMA RX buffer ring is used. Because curr_y_count and
+        * curr_x_count can't be read as an atomic operation,
+        * curr_y_count should be read before curr_x_count. When
+        * curr_x_count is read, curr_y_count may already indicate
+        * next buffer line. But, the position calculated here is
+        * still indicate the old line. The wrong position data may
+        * be smaller than current buffer tail, which cause garbages
+        * are received if it is not prohibit.
+        */
        uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
        x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
        uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
-       if (uart->rx_dma_nrows == DMA_RX_YCOUNT)
+       if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0)
                uart->rx_dma_nrows = 0;
        x_pos = DMA_RX_XCOUNT - x_pos;
        if (x_pos == DMA_RX_XCOUNT)
                x_pos = 0;
 
        pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos;
-       if (pos != uart->rx_dma_buf.tail) {
+       /* Ignore receiving data if new position is in the same line of
+        * current buffer tail and small.
+        */
+       if (pos > uart->rx_dma_buf.tail ||
+               uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) {
                uart->rx_dma_buf.head = pos;
                bfin_serial_dma_rx_chars(uart);
                uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
        }
 
-       spin_unlock_irqrestore(&uart->port.lock, flags);
+       spin_unlock_bh(&uart->port.lock);
+       dma_enable_irq(uart->rx_dma_channel);
 
        mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
 }
@@ -446,12 +529,24 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
 static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
 {
        struct bfin_serial_port *uart = dev_id;
-       struct circ_buf *xmit = &uart->port.info->xmit;
+       struct circ_buf *xmit = &uart->port.state->xmit;
+
+#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+       if (uart->scts && !(bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) {
+               uart->scts = 0;
+               uart_handle_cts_change(&uart->port, uart->scts);
+       }
+#endif
 
        spin_lock(&uart->port.lock);
        if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
                disable_dma(uart->tx_dma_channel);
                clear_dma_irqstat(uart->tx_dma_channel);
+               /* Anomaly notes:
+                *  05000215 -  we always clear ETBEI within last UART TX
+                *              interrupt to end a string. It is always set
+                *              when start a new tx.
+                */
                UART_CLEAR_IER(uart, ETBEI);
                xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1);
                uart->port.icount.tx += uart->tx_count;
@@ -470,11 +565,26 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
 {
        struct bfin_serial_port *uart = dev_id;
        unsigned short irqstat;
+       int x_pos, pos;
 
        spin_lock(&uart->port.lock);
        irqstat = get_dma_curr_irqstat(uart->rx_dma_channel);
        clear_dma_irqstat(uart->rx_dma_channel);
-       bfin_serial_dma_rx_chars(uart);
+
+       uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
+       x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
+       uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
+       if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0)
+               uart->rx_dma_nrows = 0;
+
+       pos = uart->rx_dma_nrows * DMA_RX_XCOUNT;
+       if (pos > uart->rx_dma_buf.tail ||
+               uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) {
+               uart->rx_dma_buf.head = pos;
+               bfin_serial_dma_rx_chars(uart);
+               uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
+       }
+
        spin_unlock(&uart->port.lock);
 
        return IRQ_HANDLED;
@@ -496,61 +606,6 @@ static unsigned int bfin_serial_tx_empty(struct uart_port *port)
                return 0;
 }
 
-static unsigned int bfin_serial_get_mctrl(struct uart_port *port)
-{
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
-       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-       if (uart->cts_pin < 0)
-               return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-
-       if (UART_GET_CTS(uart))
-               return TIOCM_DSR | TIOCM_CAR;
-       else
-#endif
-               return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-}
-
-static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
-       struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-       if (uart->rts_pin < 0)
-               return;
-
-       if (mctrl & TIOCM_RTS)
-               UART_CLEAR_RTS(uart);
-       else
-               UART_SET_RTS(uart);
-#endif
-}
-
-/*
- * Handle any change of modem status signal since we were last called.
- */
-static void bfin_serial_mctrl_check(struct bfin_serial_port *uart)
-{
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
-       unsigned int status;
-       struct uart_info *info = uart->port.info;
-       struct tty_struct *tty = info->port.tty;
-
-       status = bfin_serial_get_mctrl(&uart->port);
-       uart_handle_cts_change(&uart->port, status & TIOCM_CTS);
-       if (!(status & TIOCM_CTS)) {
-               tty->hw_stopped = 1;
-               uart->cts_timer.data = (unsigned long)(uart);
-               uart->cts_timer.function = (void *)bfin_serial_mctrl_check;
-               uart->cts_timer.expires = jiffies + CTS_CHECK_JIFFIES;
-               add_timer(&(uart->cts_timer));
-       } else {
-               tty->hw_stopped = 0;
-       }
-#endif
-}
-
-/*
- * Interrupts are always disabled.
- */
 static void bfin_serial_break_ctl(struct uart_port *port, int break_state)
 {
        struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
@@ -606,7 +661,7 @@ static int bfin_serial_startup(struct uart_port *port)
        uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
        add_timer(&(uart->rx_dma_timer));
 #else
-#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
+# if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
        defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
        if (kgdboc_port_line == uart->port.line && kgdboc_break_enabled)
                kgdboc_break_enabled = 0;
@@ -661,11 +716,50 @@ static int bfin_serial_startup(struct uart_port *port)
                }
        }
 # endif
-#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
+# if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
        defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
        }
 # endif
 #endif
+
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       if (uart->cts_pin >= 0) {
+               if (request_irq(gpio_to_irq(uart->cts_pin),
+                       bfin_serial_mctrl_cts_int,
+                       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+                       IRQF_DISABLED, "BFIN_UART_CTS", uart)) {
+                       uart->cts_pin = -1;
+                       pr_info("Unable to attach BlackFin UART CTS interrupt.\
+                                So, disable it.\n");
+               }
+       }
+       if (uart->rts_pin >= 0) {
+               gpio_request(uart->rts_pin, DRIVER_NAME);
+               gpio_direction_output(uart->rts_pin, 0);
+       }
+#endif
+#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+       if (request_irq(uart->status_irq,
+               bfin_serial_mctrl_cts_int,
+               IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) {
+               pr_info("Unable to attach BlackFin UART Modem \
+                       Status interrupt.\n");
+       }
+
+       if (uart->cts_pin >= 0) {
+               gpio_request(uart->cts_pin, DRIVER_NAME);
+               gpio_direction_output(uart->cts_pin, 1);
+       }
+       if (uart->rts_pin >= 0) {
+               gpio_request(uart->rts_pin, DRIVER_NAME);
+               gpio_direction_output(uart->rts_pin, 0);
+       }
+
+       /* CTS RTS PINs are negative assertive. */
+       UART_PUT_MCR(uart, ACTS);
+       UART_SET_IER(uart, EDSSI);
+#endif
+
        UART_SET_IER(uart, ERBFI);
        return 0;
 }
@@ -699,6 +793,21 @@ static void bfin_serial_shutdown(struct uart_port *port)
        free_irq(uart->port.irq, uart);
        free_irq(uart->port.irq+1, uart);
 #endif
+
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+       if (uart->cts_pin >= 0)
+               free_irq(gpio_to_irq(uart->cts_pin), uart);
+       if (uart->rts_pin >= 0)
+               gpio_free(uart->rts_pin);
+#endif
+#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+       if (uart->cts_pin >= 0)
+               gpio_free(uart->cts_pin);
+       if (uart->rts_pin >= 0)
+               gpio_free(uart->rts_pin);
+       if (UART_GET_IER(uart) && EDSSI)
+               free_irq(uart->status_irq, uart);
+#endif
 }
 
 static void
@@ -728,8 +837,16 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
                        __func__);
        }
 
-       if (termios->c_cflag & CSTOPB)
-               lcr |= STB;
+       /* Anomaly notes:
+        *  05000231 -  STOP bit is always set to 1 whatever the user is set.
+        */
+       if (termios->c_cflag & CSTOPB) {
+               if (ANOMALY_05000231)
+                       printk(KERN_WARNING "STOP bits other than 1 is not "
+                               "supported in case of anomaly 05000231.\n");
+               else
+                       lcr |= STB;
+       }
        if (termios->c_cflag & PARENB)
                lcr |= PEN;
        if (!(termios->c_cflag & PARODD))
@@ -848,10 +965,10 @@ static void bfin_serial_set_ldisc(struct uart_port *port)
        int line = port->line;
        unsigned short val;
 
-       if (line >= port->info->port.tty->driver->num)
+       if (line >= port->state->port.tty->driver->num)
                return;
 
-       switch (port->info->port.tty->termios->c_line) {
+       switch (port->state->port.tty->termios->c_line) {
        case N_IRDA:
                val = UART_GET_GCTL(&bfin_serial_ports[line]);
                val |= (IREN | RPOLC);
@@ -864,7 +981,25 @@ static void bfin_serial_set_ldisc(struct uart_port *port)
        }
 }
 
+static void bfin_serial_reset_irda(struct uart_port *port)
+{
+       int line = port->line;
+       unsigned short val;
+
+       val = UART_GET_GCTL(&bfin_serial_ports[line]);
+       val &= ~(IREN | RPOLC);
+       UART_PUT_GCTL(&bfin_serial_ports[line], val);
+       SSYNC();
+       val |= (IREN | RPOLC);
+       UART_PUT_GCTL(&bfin_serial_ports[line], val);
+       SSYNC();
+}
+
 #ifdef CONFIG_CONSOLE_POLL
+/* Anomaly notes:
+ *  05000099 -  Because we only use THRE in poll_put and DR in poll_get,
+ *             losing other bits of UART_LSR is not a problem here.
+ */
 static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr)
 {
        struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
@@ -909,20 +1044,6 @@ static int bfin_kgdboc_port_startup(struct uart_port *port)
 }
 #endif
 
-static void bfin_serial_reset_irda(struct uart_port *port)
-{
-       int line = port->line;
-       unsigned short val;
-
-       val = UART_GET_GCTL(&bfin_serial_ports[line]);
-       val &= ~(IREN | RPOLC);
-       UART_PUT_GCTL(&bfin_serial_ports[line], val);
-       SSYNC();
-       val |= (IREN | RPOLC);
-       UART_PUT_GCTL(&bfin_serial_ports[line], val);
-       SSYNC();
-}
-
 static struct uart_ops bfin_serial_pops = {
        .tx_empty       = bfin_serial_tx_empty,
        .set_mctrl      = bfin_serial_set_mctrl,
@@ -952,6 +1073,39 @@ static struct uart_ops bfin_serial_pops = {
 #endif
 };
 
+static void __init bfin_serial_hw_init(void)
+{
+#ifdef CONFIG_SERIAL_BFIN_UART0
+       peripheral_request(P_UART0_TX, DRIVER_NAME);
+       peripheral_request(P_UART0_RX, DRIVER_NAME);
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART1
+       peripheral_request(P_UART1_TX, DRIVER_NAME);
+       peripheral_request(P_UART1_RX, DRIVER_NAME);
+
+# if defined(CONFIG_BFIN_UART1_CTSRTS) && defined(CONFIG_BF54x)
+       peripheral_request(P_UART1_RTS, DRIVER_NAME);
+       peripheral_request(P_UART1_CTS, DRIVER_NAME);
+# endif
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART2
+       peripheral_request(P_UART2_TX, DRIVER_NAME);
+       peripheral_request(P_UART2_RX, DRIVER_NAME);
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART3
+       peripheral_request(P_UART3_TX, DRIVER_NAME);
+       peripheral_request(P_UART3_RX, DRIVER_NAME);
+
+# if defined(CONFIG_BFIN_UART3_CTSRTS) && defined(CONFIG_BF54x)
+       peripheral_request(P_UART3_RTS, DRIVER_NAME);
+       peripheral_request(P_UART3_CTS, DRIVER_NAME);
+# endif
+#endif
+}
+
 static void __init bfin_serial_init_ports(void)
 {
        static int first = 1;
@@ -961,7 +1115,10 @@ static void __init bfin_serial_init_ports(void)
                return;
        first = 0;
 
+       bfin_serial_hw_init();
+
        for (i = 0; i < nr_active_ports; i++) {
+               spin_lock_init(&bfin_serial_ports[i].port.lock);
                bfin_serial_ports[i].port.uartclk   = get_sclk();
                bfin_serial_ports[i].port.fifosize  = BFIN_UART_TX_FIFO_SIZE;
                bfin_serial_ports[i].port.ops       = &bfin_serial_pops;
@@ -973,6 +1130,8 @@ static void __init bfin_serial_init_ports(void)
                        bfin_serial_resource[i].uart_base_addr;
                bfin_serial_ports[i].port.irq       =
                        bfin_serial_resource[i].uart_irq;
+               bfin_serial_ports[i].status_irq     =
+                       bfin_serial_resource[i].uart_status_irq;
                bfin_serial_ports[i].port.flags     = UPF_BOOT_AUTOCONF;
 #ifdef CONFIG_SERIAL_BFIN_DMA
                bfin_serial_ports[i].tx_done        = 1;
@@ -983,16 +1142,14 @@ static void __init bfin_serial_init_ports(void)
                        bfin_serial_resource[i].uart_rx_dma_channel;
                init_timer(&(bfin_serial_ports[i].rx_dma_timer));
 #endif
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
-               init_timer(&(bfin_serial_ports[i].cts_timer));
+#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
+       defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
                bfin_serial_ports[i].cts_pin        =
                        bfin_serial_resource[i].uart_cts_pin;
                bfin_serial_ports[i].rts_pin        =
                        bfin_serial_resource[i].uart_rts_pin;
 #endif
-               bfin_serial_hw_init(&bfin_serial_ports[i]);
        }
-
 }
 
 #if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
@@ -1049,7 +1206,8 @@ bfin_serial_console_setup(struct console *co, char *options)
        int baud = 57600;
        int bits = 8;
        int parity = 'n';
-# ifdef CONFIG_SERIAL_BFIN_CTSRTS
+# if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
+       defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
        int flow = 'r';
 # else
        int flow = 'n';
@@ -1148,12 +1306,17 @@ static __init void early_serial_write(struct console *con, const char *s,
        }
 }
 
+/*
+ * This should have a .setup or .early_setup in it, but then things get called
+ * without the command line options, and the baud rate gets messed up - so
+ * don't let the common infrastructure play with things. (see calls to setup
+ * & earlysetup in ./kernel/printk.c:register_console()
+ */
 static struct __initdata console bfin_early_serial_console = {
        .name = "early_BFuart",
        .write = early_serial_write,
        .device = uart_console_device,
        .flags = CON_PRINTBUFFER,
-       .setup = bfin_serial_console_setup,
        .index = -1,
        .data  = &bfin_serial_reg,
 };
@@ -1246,7 +1409,8 @@ static int bfin_serial_remove(struct platform_device *dev)
                        continue;
                uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
                bfin_serial_ports[i].port.dev = NULL;
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
+       defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
                gpio_free(bfin_serial_ports[i].cts_pin);
                gpio_free(bfin_serial_ports[i].rts_pin);
 #endif