struct uart_amba_port {
        struct uart_port        port;
        struct clk              *clk;
-       unsigned int            im;     /* interrupt mask */
+       unsigned int            im;             /* interrupt mask */
        unsigned int            old_status;
-       unsigned int            ifls;   /* vendor-specific */
+       unsigned int            ifls;           /* vendor-specific */
+       unsigned int            lcrh_tx;        /* vendor-specific */
+       unsigned int            lcrh_rx;        /* vendor-specific */
        bool                    autorts;
 };
 
 struct vendor_data {
        unsigned int            ifls;
        unsigned int            fifosize;
+       unsigned int            lcrh_tx;
+       unsigned int            lcrh_rx;
 };
 
 static struct vendor_data vendor_arm = {
        .ifls                   = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
        .fifosize               = 16,
+       .lcrh_tx                = UART011_LCRH,
+       .lcrh_rx                = UART011_LCRH,
 };
 
 static struct vendor_data vendor_st = {
        .ifls                   = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
        .fifosize               = 64,
+       .lcrh_tx                = ST_UART011_LCRH_TX,
+       .lcrh_rx                = ST_UART011_LCRH_RX,
 };
 
 static void pl011_stop_tx(struct uart_port *port)
        unsigned int lcr_h;
 
        spin_lock_irqsave(&uap->port.lock, flags);
-       lcr_h = readw(uap->port.membase + UART011_LCRH);
+       lcr_h = readw(uap->port.membase + uap->lcrh_tx);
        if (break_state == -1)
                lcr_h |= UART01x_LCRH_BRK;
        else
                lcr_h &= ~UART01x_LCRH_BRK;
-       writew(lcr_h, uap->port.membase + UART011_LCRH);
+       writew(lcr_h, uap->port.membase + uap->lcrh_tx);
        spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
        writew(cr, uap->port.membase + UART011_CR);
        writew(0, uap->port.membase + UART011_FBRD);
        writew(1, uap->port.membase + UART011_IBRD);
-       writew(0, uap->port.membase + UART011_LCRH);
+       writew(0, uap->port.membase + uap->lcrh_rx);
+       if (uap->lcrh_tx != uap->lcrh_rx) {
+               int i;
+               /*
+                * Wait 10 PCLKs before writing LCRH_TX register,
+                * to get this delay write read only register 10 times
+                */
+               for (i = 0; i < 10; ++i)
+                       writew(0xff, uap->port.membase + UART011_MIS);
+               writew(0, uap->port.membase + uap->lcrh_tx);
+       }
        writew(0, uap->port.membase + UART01x_DR);
        while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
                barrier();
        return retval;
 }
 
+static void pl011_shutdown_channel(struct uart_amba_port *uap,
+                                       unsigned int lcrh)
+{
+      unsigned long val;
+
+      val = readw(uap->port.membase + lcrh);
+      val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
+      writew(val, uap->port.membase + lcrh);
+}
+
 static void pl011_shutdown(struct uart_port *port)
 {
        struct uart_amba_port *uap = (struct uart_amba_port *)port;
-       unsigned long val;
 
        /*
         * disable all interrupts
        /*
         * disable break condition and fifos
         */
-       val = readw(uap->port.membase + UART011_LCRH);
-       val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
-       writew(val, uap->port.membase + UART011_LCRH);
+       pl011_shutdown_channel(uap, uap->lcrh_rx);
+       if (uap->lcrh_rx != uap->lcrh_tx)
+               pl011_shutdown_channel(uap, uap->lcrh_tx);
 
        /*
         * Shut down the clock producer
         * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
         * ----------^----------^----------^----------^-----
         */
-       writew(lcr_h, port->membase + UART011_LCRH);
+       writew(lcr_h, port->membase + uap->lcrh_rx);
+       if (uap->lcrh_rx != uap->lcrh_tx) {
+               int i;
+               /*
+                * Wait 10 PCLKs before writing LCRH_TX register,
+                * to get this delay write read only register 10 times
+                */
+               for (i = 0; i < 10; ++i)
+                       writew(0xff, uap->port.membase + UART011_MIS);
+               writew(lcr_h, port->membase + uap->lcrh_tx);
+       }
        writew(old_cr, port->membase + UART011_CR);
 
        spin_unlock_irqrestore(&port->lock, flags);
        if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {
                unsigned int lcr_h, ibrd, fbrd;
 
-               lcr_h = readw(uap->port.membase + UART011_LCRH);
+               lcr_h = readw(uap->port.membase + uap->lcrh_tx);
 
                *parity = 'n';
                if (lcr_h & UART01x_LCRH_PEN) {
        }
 
        uap->ifls = vendor->ifls;
+       uap->lcrh_rx = vendor->lcrh_rx;
+       uap->lcrh_tx = vendor->lcrh_tx;
        uap->port.dev = &dev->dev;
        uap->port.mapbase = dev->res.start;
        uap->port.membase = base;