Hi Greg, 

On Mon, 2013-07-01 at 12:11 +0300, Ivan T. Ivanov wrote:
> From: "Ivan T. Ivanov" <iiva...@mm-sol.com>
> 
> This is a tty driver with console support for Qualcomm's UART
> controllers found in the MSM8974 chipsets. Driver is completely
> based on implementation found in codeaurora.org msm_serial_hs_lite
> with Android dependences removed. Other changes include, moved to
> device managed resources and few cleanups.
> 
> Driver functionality was tested in LEGACY_HSUART mode.
> 

Please, could you take a look at this driver. It have been 
tested on these new Snapdragon 8074 based DragonBoards. 

If there is something that I have to fix or improve in 
the code please let me know.

Regards,
Ivan


> Signed-off-by: Ivan T. Ivanov <iiva...@mm-sol.com>
> ---
>  .../bindings/tty/serial/msm_serial_hsl.txt         |   52 +
>  drivers/tty/serial/Kconfig                         |   18 +
>  drivers/tty/serial/Makefile                        |    1 +
>  drivers/tty/serial/msm_serial_hsl.c                | 1399 
> ++++++++++++++++++++
>  drivers/tty/serial/msm_serial_hsl.h                |  294 ++++
>  5 files changed, 1764 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/tty/serial/msm_serial_hsl.txt
>  create mode 100644 drivers/tty/serial/msm_serial_hsl.c
>  create mode 100644 drivers/tty/serial/msm_serial_hsl.h
> 
> diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial_hsl.txt 
> b/Documentation/devicetree/bindings/tty/serial/msm_serial_hsl.txt
> new file mode 100644
> index 0000000..972552f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/tty/serial/msm_serial_hsl.txt
> @@ -0,0 +1,52 @@
> +* Qualcomm MSM HSUART Lite
> +
> +Required properties:
> +- compatible :
> +     "qcom,msm-lsuart-v14" to be used for UARTDM Core v1.4
> +
> +- reg :
> +     offset and length of the register set for both the device,
> +     UART core and GBSI core
> +
> +- reg-names :
> +     "uart_mem" to be used as name of the UART core
> +     "gbsi_mem" to be used as name of the GBSI core
> +
> +The registers for the "qcom,msm-lsuart-v14" device have specify
> +UART core block. GSBI reg is optional if specified driver will use
> +GSBI specific functionality.
> +
> +- interrupts : interrupts for UART core
> +
> +- clocks : Must contain an entry for each entry in clock-names.
> +
> +- clock-names : Must include the following entries:
> +  "core_clk" - mandatory
> +  "iface_clk" - optional
> +
> +For details see:
> +Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Example:
> +
> +     serial@f991e000 {
> +             compatible = "qcom,msm-lsuart-v14";
> +             reg = <0xf991e000 0x1000>;
> +             reg-names = "uart_mem";
> +             interrupts = <0 108 0>;
> +             clocks = <&blsp1_uart2_apps_cxc>, <&blsp1_ahb_cxc>;
> +             clock-names = "core_clk", "iface_clk";
> +     };
> +
> +Aliases :
> +An alias may be optionally used to bind the UART device to a TTY device
> +(ttyHSL<alias_num>) with a given alias number. Aliases are of the form
> +uart<n> where <n> is an integer representing the alias number to use.
> +On systems with multiple UART devices present, an alias may optionally be
> +defined for such devices. The alias value should be from 0 to 255.
> +
> +Example:
> +
> +     aliases {
> +             uart4 = &uart7; // This device will be enumerated as ttyHSL4
> +     };
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index 7e7006f..4482bc7 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -1046,6 +1046,24 @@ config SERIAL_MSM_HS
>         Choose M here to compile it as a module. The module will be
>         called msm_serial_hs.
>  
> +config SERIAL_MSM_HSL
> +     tristate "MSM High speed serial lite mode driver"
> +     depends on ARM && ARCH_MSM
> +     select SERIAL_CORE
> +     default n
> +     help
> +       Select this module to enable MSM high speed lite mode driver
> +       for UART controllers found in MSM8974 SoC's
> +
> +       Choose M here to compile it as a module. The module will be
> +       called msm_serial_hsl.
> +
> +config SERIAL_MSM_HSL_CONSOLE
> +     bool "MSM High speed serial lite mode console support"
> +     depends on SERIAL_MSM_HSL=y
> +     select SERIAL_CORE_CONSOLE
> +     default n
> +
>  config SERIAL_VT8500
>       bool "VIA VT8500 on-chip serial port support"
>       depends on ARCH_VT8500
> diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
> index eedfec4..86c023b 100644
> --- a/drivers/tty/serial/Makefile
> +++ b/drivers/tty/serial/Makefile
> @@ -58,6 +58,7 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
>  obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
>  obj-$(CONFIG_SERIAL_MSM) += msm_serial.o
>  obj-$(CONFIG_SERIAL_MSM_HS) += msm_serial_hs.o
> +obj-$(CONFIG_SERIAL_MSM_HSL) += msm_serial_hsl.o
>  obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
>  obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
>  obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
> diff --git a/drivers/tty/serial/msm_serial_hsl.c 
> b/drivers/tty/serial/msm_serial_hsl.c
> new file mode 100644
> index 0000000..56c15a8
> --- /dev/null
> +++ b/drivers/tty/serial/msm_serial_hsl.c
> @@ -0,0 +1,1399 @@
> +/*
> + * drivers/tty/serial/msm_serial_hsl.c - driver for serial device and console
> + *
> + * Copyright (C) 2007 Google, Inc.
> + * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +/* Acknowledgements:
> + * This file is based on msm_serial.c, originally
> + * Written by Robert Love <rl...@google.com>  */
> +
> +#include <linux/clk.h>
> +#include <linux/console.h>
> +#include <linux/debugfs.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/nmi.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/serial_core.h>
> +#include <linux/tty.h>
> +#include <linux/tty_flip.h>
> +
> +#include "msm_serial_hsl.h"
> +
> +/*
> + * There are 3 different kind of UART Core available on MSM.
> + * High Speed UART (i.e. Legacy HSUART), GSBI based HSUART
> + * and BSLP based HSUART.
> + */
> +enum uart_core_type {
> +     LEGACY_HSUART,
> +     GSBI_HSUART,
> +     BLSP_HSUART,
> +};
> +
> +/*
> + * @uart: uart port instance
> + * @name: name of the port
> + * @clk: reference to core clock
> + * @pclk: reference to interface clock
> + * @imr: shadow interrupt mask register
> + * @mapped_gsbi: GSBI contol memory
> + * @old_snap_state: How many data still left in the FIFO
> + * @tx_timeout - transmit timout ~600x the character transmit time
> + * @uart_type - see enum uart_core_type
> + * @regmap - Register map based on controller version
> + * It is mainly required where same UART is used across different processor.
> + * Make sure that Clock driver for platform support setting clock rate to 
> zero.
> + */
> +struct msm_hsl_port {
> +     struct uart_port        uart;
> +     char                    name[16];
> +     struct clk              *clk;
> +     struct clk              *pclk;
> +     struct dentry           *loopback_dir;
> +     unsigned int            imr;
> +     unsigned int            *mapped_gsbi;
> +     unsigned int            old_snap_state;
> +     int                     tx_timeout;
> +     enum uart_core_type     uart_type;
> +     const unsigned int      *regmap;
> +};
> +
> +#define UARTDM_VERSION_11_13 0
> +#define UARTDM_VERSION_14    1
> +#define UART_NR                      3
> +
> +#define to_hsl_port(p)               (container_of(p, struct msm_hsl_port, 
> uart))
> +#define is_console(port)     ((port)->cons && \
> +                             (port)->cons->index == (port)->line)
> +
> +static const unsigned int regmap[][UARTDM_LAST] = {
> +     [UARTDM_VERSION_11_13] = {
> +             [UARTDM_MR1] = UARTDM_MR1_ADDR,
> +             [UARTDM_MR2] = UARTDM_MR2_ADDR,
> +             [UARTDM_IMR] = UARTDM_IMR_ADDR,
> +             [UARTDM_SR] = UARTDM_SR_ADDR,
> +             [UARTDM_CR] = UARTDM_CR_ADDR,
> +             [UARTDM_CSR] = UARTDM_CSR_ADDR,
> +             [UARTDM_IPR] = UARTDM_IPR_ADDR,
> +             [UARTDM_ISR] = UARTDM_ISR_ADDR,
> +             [UARTDM_RX_TOTAL_SNAP] = UARTDM_RX_TOTAL_SNAP_ADDR,
> +             [UARTDM_TFWR] = UARTDM_TFWR_ADDR,
> +             [UARTDM_RFWR] = UARTDM_RFWR_ADDR,
> +             [UARTDM_RF] = UARTDM_RF_ADDR,
> +             [UARTDM_TF] = UARTDM_TF_ADDR,
> +             [UARTDM_MISR] = UARTDM_MISR_ADDR,
> +             [UARTDM_DMRX] = UARTDM_DMRX_ADDR,
> +             [UARTDM_NCF_TX] = UARTDM_NCF_TX_ADDR,
> +             [UARTDM_DMEN] = UARTDM_DMEN_ADDR,
> +             [UARTDM_TXFS] = UARTDM_TXFS_ADDR,
> +             [UARTDM_RXFS] = UARTDM_RXFS_ADDR,
> +     },
> +     [UARTDM_VERSION_14] = {
> +             [UARTDM_MR1] = UARTDM_MR1_ADDR,
> +             [UARTDM_MR2] = UARTDM_MR2_ADDR,
> +             [UARTDM_IMR] = UARTDM_IMR_ADDR_V14,
> +             [UARTDM_SR] = UARTDM_SR_ADDR_V14,
> +             [UARTDM_CR] = UARTDM_CR_ADDR_V14,
> +             [UARTDM_CSR] = UARTDM_CSR_ADDR_V14,
> +             [UARTDM_IPR] = UARTDM_IPR_ADDR,
> +             [UARTDM_ISR] = UARTDM_ISR_ADDR_V14,
> +             [UARTDM_RX_TOTAL_SNAP] = UARTDM_RX_TOTAL_SNAP_ADDR_V14,
> +             [UARTDM_TFWR] = UARTDM_TFWR_ADDR,
> +             [UARTDM_RFWR] = UARTDM_RFWR_ADDR,
> +             [UARTDM_RF] = UARTDM_RF_ADDR_V14,
> +             [UARTDM_TF] = UARTDM_TF_ADDR_V14,
> +             [UARTDM_MISR] = UARTDM_MISR_ADDR_V14,
> +             [UARTDM_DMRX] = UARTDM_DMRX_ADDR,
> +             [UARTDM_NCF_TX] = UARTDM_NCF_TX_ADDR,
> +             [UARTDM_DMEN] = UARTDM_DMEN_ADDR,
> +             [UARTDM_TXFS] = UARTDM_TXFS_ADDR,
> +             [UARTDM_RXFS] = UARTDM_RXFS_ADDR,
> +     },
> +};
> +
> +/*
> + * get_console_state - check the per-port serial console state.
> + * @port: uart_port structure describing the port
> + *
> + * Return the state of serial console availability on port.
> + * return 1: If serial console is enabled on particular UART port.
> + * return 0: If serial console is disabled on particular UART port.
> + */
> +static int get_console_state(struct uart_port *port)
> +{
> +#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
> +     if (is_console(port) && (port->cons->flags & CON_ENABLED))
> +             return 1;
> +     else
> +             return 0;
> +#else
> +     return -ENODEV;
> +#endif
> +}
> +
> +static inline void msm_hsl_write(struct uart_port *port,
> +                              unsigned int val, unsigned int off)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +
> +     iowrite32(val, port->membase + hslp->regmap[off]);
> +}
> +
> +static inline unsigned int msm_hsl_read(struct uart_port *port,
> +                                     unsigned int off)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +
> +     return ioread32(port->membase + hslp->regmap[off]);
> +}
> +
> +static unsigned int msm_serial_hsl_has_gsbi(struct uart_port *port)
> +{
> +     return (to_hsl_port(port)->uart_type == GSBI_HSUART);
> +}
> +
> +/*
> + * set_gsbi_uart_func_mode: Check the currently used GSBI UART mode
> + * and set the new required GSBI UART Mode if it is different.
> + * @port: uart port
> + */
> +static void set_gsbi_uart_func_mode(struct uart_port *port)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +     unsigned int set_mode = GSBI_PROTOCOL_I2C_UART;
> +     unsigned int cur_mode;
> +
> +     if (hslp->pclk)
> +             clk_prepare_enable(hslp->pclk);
> +
> +     /* Read current used GSBI UART Mode and set only if it is different. */
> +     cur_mode = ioread32(hslp->mapped_gsbi + GSBI_CONTROL_ADDR);
> +     if ((cur_mode & GSBI_PROTOCOL_CODE_MASK) != set_mode)
> +             /*
> +              * Programmed GSBI based UART protocol mode i.e. I2C/UART
> +              * Shared Mode or UART Mode.
> +              */
> +             iowrite32(set_mode, hslp->mapped_gsbi + GSBI_CONTROL_ADDR);
> +
> +     if (hslp->pclk)
> +             clk_disable_unprepare(hslp->pclk);
> +}
> +
> +static int msm_hsl_clock_enable(struct uart_port *port, int enable)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +     int ret = 0;
> +
> +     if (enable) {
> +             ret = clk_prepare_enable(hslp->clk);
> +             if (ret)
> +                     return ret;
> +             if (hslp->pclk) {
> +                     ret = clk_prepare_enable(hslp->pclk);
> +                     if (ret)
> +                             clk_disable_unprepare(hslp->clk);
> +             }
> +     } else {
> +             clk_disable_unprepare(hslp->clk);
> +             if (hslp->pclk)
> +                     clk_disable_unprepare(hslp->pclk);
> +     }
> +
> +     return ret;
> +}
> +
> +static int msm_hsl_loopback_set(void *data, u64 val)
> +{
> +     struct msm_hsl_port *hslp = data;
> +     struct uart_port *port = &(hslp->uart);
> +     unsigned long flags;
> +     int ret = 0;
> +
> +     ret = clk_set_rate(hslp->clk, port->uartclk);
> +     if (!ret)
> +             msm_hsl_clock_enable(port, 1);
> +     else
> +             return -EINVAL;
> +
> +     if (val) {
> +             spin_lock_irqsave(&port->lock, flags);
> +             ret = msm_hsl_read(port, UARTDM_MR2);
> +             ret |= UARTDM_MR2_LOOP_MODE_BMSK;
> +             msm_hsl_write(port, ret, UARTDM_MR2);
> +             spin_unlock_irqrestore(&port->lock, flags);
> +     } else {
> +             spin_lock_irqsave(&port->lock, flags);
> +             ret = msm_hsl_read(port, UARTDM_MR2);
> +             ret &= ~UARTDM_MR2_LOOP_MODE_BMSK;
> +             msm_hsl_write(port, ret, UARTDM_MR2);
> +             spin_unlock_irqrestore(&port->lock, flags);
> +     }
> +
> +     msm_hsl_clock_enable(port, 0);
> +     return 0;
> +}
> +
> +static int msm_hsl_loopback_get(void *data, u64 *val)
> +{
> +     struct msm_hsl_port *hslp = data;
> +     struct uart_port *port = &hslp->uart;
> +     unsigned long flags;
> +     int ret = 0;
> +
> +     ret = clk_set_rate(hslp->clk, port->uartclk);
> +     if (!ret)
> +             msm_hsl_clock_enable(port, 1);
> +     else
> +             return -EINVAL;
> +
> +     spin_lock_irqsave(&port->lock, flags);
> +     ret = msm_hsl_read(port, UARTDM_MR2);
> +     spin_unlock_irqrestore(&port->lock, flags);
> +     msm_hsl_clock_enable(port, 0);
> +
> +     *val = (ret & UARTDM_MR2_LOOP_MODE_BMSK) ? 1 : 0;
> +     return 0;
> +}
> +
> +static void msm_hsl_stop_tx(struct uart_port *port)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +
> +     hslp->imr &= ~UARTDM_ISR_TXLEV_BMSK;
> +     msm_hsl_write(port, hslp->imr, UARTDM_IMR);
> +}
> +
> +static void msm_hsl_start_tx(struct uart_port *port)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +
> +     hslp->imr |= UARTDM_ISR_TXLEV_BMSK;
> +     msm_hsl_write(port, hslp->imr, UARTDM_IMR);
> +}
> +
> +static void msm_hsl_stop_rx(struct uart_port *port)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +
> +     hslp->imr &= ~(UARTDM_ISR_RXLEV_BMSK | UARTDM_ISR_RXSTALE_BMSK);
> +     msm_hsl_write(port, hslp->imr, UARTDM_IMR);
> +}
> +
> +static void msm_hsl_enable_ms(struct uart_port *port)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +
> +     hslp->imr |= UARTDM_ISR_DELTA_CTS_BMSK;
> +     msm_hsl_write(port, hslp->imr, UARTDM_IMR);
> +}
> +
> +static void msm_hsl_handle_rx(struct uart_port *port, unsigned int misr)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +     struct tty_port *tty = &port->state->port;
> +     unsigned int sr;
> +     int count = 0;
> +
> +     /*
> +      * Handle overrun. My understanding of the hardware is that overrun
> +      * is not tied to the RX buffer, so we handle the case out of band.
> +      */
> +     sr = msm_hsl_read(port, UARTDM_SR);
> +     if (sr & UARTDM_SR_OVERRUN_BMSK) {
> +             port->icount.overrun++;
> +             tty_insert_flip_char(tty, 0, TTY_OVERRUN);
> +             msm_hsl_write(port, RESET_ERROR_STATUS, UARTDM_CR);
> +     }
> +
> +     if (misr & UARTDM_ISR_RXSTALE_BMSK) {
> +             count = msm_hsl_read(port, UARTDM_RX_TOTAL_SNAP) -
> +                                  hslp->old_snap_state;
> +             hslp->old_snap_state = 0;
> +     } else {
> +             count = 4 * (msm_hsl_read(port, UARTDM_RFWR));
> +             hslp->old_snap_state += count;
> +     }
> +
> +     /* and now the main RX loop */
> +     while (count > 0) {
> +             unsigned int c;
> +             char flag = TTY_NORMAL;
> +
> +             sr = msm_hsl_read(port, UARTDM_SR);
> +             if ((sr & UARTDM_SR_RXRDY_BMSK) == 0) {
> +                     hslp->old_snap_state -= count;
> +                     break;
> +             }
> +             c = msm_hsl_read(port, UARTDM_RF);
> +             if (sr & UARTDM_SR_RX_BREAK_BMSK) {
> +                     port->icount.brk++;
> +                     if (uart_handle_break(port))
> +                             continue;
> +             } else if (sr & UARTDM_SR_PAR_FRAME_BMSK) {
> +                     port->icount.frame++;
> +             } else {
> +                     port->icount.rx++;
> +             }
> +
> +             /* Mask conditions we're ignorning. */
> +             sr &= port->read_status_mask;
> +             if (sr & UARTDM_SR_RX_BREAK_BMSK)
> +                     flag = TTY_BREAK;
> +             else if (sr & UARTDM_SR_PAR_FRAME_BMSK)
> +                     flag = TTY_FRAME;
> +
> +             /* TODO: handle sysrq */
> +             /* if (!uart_handle_sysrq_char(port, c)) */
> +             tty_insert_flip_string(tty, (char *)&c,
> +                                    (count > 4) ? 4 : count);
> +             count -= 4;
> +     }
> +
> +     tty_flip_buffer_push(tty);
> +}
> +
> +static void msm_hsl_dump_regs(struct uart_port *port)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +     unsigned int sr, isr, mr1, mr2, ncf, txfs, rxfs, con_state;
> +
> +     sr = msm_hsl_read(port, UARTDM_SR);
> +     isr = msm_hsl_read(port, UARTDM_ISR);
> +     mr1 = msm_hsl_read(port, UARTDM_MR1);
> +     mr2 = msm_hsl_read(port, UARTDM_MR2);
> +     ncf = msm_hsl_read(port, UARTDM_NCF_TX);
> +     txfs = msm_hsl_read(port, UARTDM_TXFS);
> +     rxfs = msm_hsl_read(port, UARTDM_RXFS);
> +     con_state = get_console_state(port);
> +
> +     pr_info("Timeout: %d uS\n", hslp->tx_timeout);
> +     pr_info("SR:  %08x\n", sr);
> +     pr_info("ISR: %08x\n", isr);
> +     pr_info("MR1: %08x\n", mr1);
> +     pr_info("MR2: %08x\n", mr2);
> +     pr_info("NCF: %08x\n", ncf);
> +     pr_info("TXFS: %08x\n", txfs);
> +     pr_info("RXFS: %08x\n", rxfs);
> +     pr_info("Console state: %d\n", con_state);
> +}
> +
> +/*
> + *  Wait for transmitter & holding register to empty
> + *  Derived from msm_hsl_wait_for_xmitr in 8250 serial driver by Russell King
> + */
> +static void msm_hsl_wait_for_xmitr(struct uart_port *port)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +     int count = 0;
> +     int sr;
> +     int isr;
> +
> +     sr = msm_hsl_read(port, UARTDM_SR);
> +     if (sr & UARTDM_SR_TXEMT_BMSK)
> +             return;
> +
> +     do {
> +             isr = msm_hsl_read(port, UARTDM_ISR);
> +             sr = msm_hsl_read(port, UARTDM_SR);
> +
> +             if ((isr & UARTDM_ISR_TX_READY_BMSK) ||
> +                 (sr & UARTDM_SR_TXEMT_BMSK))
> +                     break;
> +
> +             udelay(1);
> +             touch_nmi_watchdog();
> +             cpu_relax();
> +
> +             if (++count == hslp->tx_timeout) {
> +                     msm_hsl_dump_regs(port);
> +                     panic("MSM HSL msm_hsl_wait_for_xmitr is stuck!");
> +             }
> +
> +     } while (true);
> +
> +     msm_hsl_write(port, CLEAR_TX_READY, UARTDM_CR);
> +
> +}
> +
> +static void msm_hsl_handle_tx(struct uart_port *port)
> +{
> +     struct circ_buf *xmit = &port->state->xmit;
> +     unsigned int tf_pointer = 0;
> +     int sent_tx;
> +     int tx_count;
> +     int x;
> +     int sr;
> +
> +     tx_count = uart_circ_chars_pending(xmit);
> +
> +     if (tx_count > (UART_XMIT_SIZE - xmit->tail))
> +             tx_count = UART_XMIT_SIZE - xmit->tail;
> +     if (tx_count >= port->fifosize)
> +             tx_count = port->fifosize;
> +
> +     /* Handle x_char */
> +     if (port->x_char) {
> +             msm_hsl_wait_for_xmitr(port);
> +             msm_hsl_write(port, tx_count + 1, UARTDM_NCF_TX);
> +             msm_hsl_read(port, UARTDM_NCF_TX);
> +             msm_hsl_write(port, port->x_char, UARTDM_TF);
> +             port->icount.tx++;
> +             port->x_char = 0;
> +     } else if (tx_count) {
> +             msm_hsl_wait_for_xmitr(port);
> +             msm_hsl_write(port, tx_count, UARTDM_NCF_TX);
> +             msm_hsl_read(port, UARTDM_NCF_TX);
> +     }
> +     if (!tx_count) {
> +             msm_hsl_stop_tx(port);
> +             return;
> +     }
> +
> +     while (tf_pointer < tx_count) {
> +             sr = msm_hsl_read(port, UARTDM_SR);
> +             if (!(sr & UARTDM_SR_TXRDY_BMSK))
> +                     continue;
> +             switch (tx_count - tf_pointer) {
> +             case 1:
> +                     x = xmit->buf[xmit->tail];
> +                     port->icount.tx++;
> +                     break;
> +             case 2:
> +                     x = xmit->buf[xmit->tail]
> +                         | xmit->buf[xmit->tail + 1] << 8;
> +                     port->icount.tx += 2;
> +                     break;
> +             case 3:
> +                     x = xmit->buf[xmit->tail]
> +                         | xmit->buf[xmit->tail + 1] << 8
> +                         | xmit->buf[xmit->tail + 2] << 16;
> +                     port->icount.tx += 3;
> +                     break;
> +             default:
> +                     x = *((int *)&(xmit->buf[xmit->tail]));
> +                     port->icount.tx += 4;
> +                     break;
> +             }
> +             msm_hsl_write(port, x, UARTDM_TF);
> +             xmit->tail = ((tx_count - tf_pointer < 4) ?
> +                           (tx_count - tf_pointer + xmit->tail) :
> +                           (xmit->tail + 4)) & (UART_XMIT_SIZE - 1);
> +             tf_pointer += 4;
> +             sent_tx = 1;
> +     }
> +
> +     if (uart_circ_empty(xmit))
> +             msm_hsl_stop_tx(port);
> +
> +     if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
> +             uart_write_wakeup(port);
> +
> +}
> +
> +static void msm_hsl_handle_delta_cts(struct uart_port *port)
> +{
> +     msm_hsl_write(port, RESET_CTS, UARTDM_CR);
> +     port->icount.cts++;
> +     wake_up_interruptible(&port->state->port.delta_msr_wait);
> +}
> +
> +static irqreturn_t msm_hsl_irq(int irq, void *dev_id)
> +{
> +     struct uart_port *port = dev_id;
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +     unsigned int misr;
> +     unsigned long flags;
> +
> +     spin_lock_irqsave(&port->lock, flags);
> +     misr = msm_hsl_read(port, UARTDM_MISR);
> +     /* disable interrupt */
> +     msm_hsl_write(port, 0, UARTDM_IMR);
> +
> +     if (misr & (UARTDM_ISR_RXSTALE_BMSK | UARTDM_ISR_RXLEV_BMSK)) {
> +             msm_hsl_handle_rx(port, misr);
> +             if (misr & (UARTDM_ISR_RXSTALE_BMSK))
> +                     msm_hsl_write(port, RESET_STALE_INT,
> +                                   UARTDM_CR);
> +             msm_hsl_write(port, 6500, UARTDM_DMRX);
> +             msm_hsl_write(port, STALE_EVENT_ENABLE, UARTDM_CR);
> +     }
> +     if (misr & UARTDM_ISR_TXLEV_BMSK)
> +             msm_hsl_handle_tx(port);
> +
> +     if (misr & UARTDM_ISR_DELTA_CTS_BMSK)
> +             msm_hsl_handle_delta_cts(port);
> +
> +     /* restore interrupt */
> +     msm_hsl_write(port, hslp->imr, UARTDM_IMR);
> +     spin_unlock_irqrestore(&port->lock, flags);
> +
> +     return IRQ_HANDLED;
> +}
> +
> +static unsigned int msm_hsl_tx_empty(struct uart_port *port)
> +{
> +     unsigned int ret;
> +
> +     ret = msm_hsl_read(port, UARTDM_SR);
> +     ret &= UARTDM_SR_TXEMT_BMSK;
> +
> +     if (ret)
> +             ret = TIOCSER_TEMT;
> +
> +     return ret;
> +}
> +
> +static void msm_hsl_reset(struct uart_port *port)
> +{
> +     /* reset everything */
> +     msm_hsl_write(port, RESET_RX, UARTDM_CR);
> +     msm_hsl_write(port, RESET_TX, UARTDM_CR);
> +     msm_hsl_write(port, RESET_ERROR_STATUS, UARTDM_CR);
> +     msm_hsl_write(port, RESET_BREAK_INT, UARTDM_CR);
> +     msm_hsl_write(port, RESET_CTS, UARTDM_CR);
> +     msm_hsl_write(port, RFR_LOW, UARTDM_CR);
> +}
> +
> +static unsigned int msm_hsl_get_mctrl(struct uart_port *port)
> +{
> +     return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR | TIOCM_RTS;
> +}
> +
> +static void msm_hsl_set_mctrl(struct uart_port *port, unsigned int mctrl)
> +{
> +     unsigned int mr;
> +     unsigned int loop_mode;
> +
> +     mr = msm_hsl_read(port, UARTDM_MR1);
> +
> +     if (!(mctrl & TIOCM_RTS)) {
> +             mr &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
> +             msm_hsl_write(port, mr, UARTDM_MR1);
> +             msm_hsl_write(port, RFR_HIGH, UARTDM_CR);
> +     } else {
> +             mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
> +             msm_hsl_write(port, mr, UARTDM_MR1);
> +     }
> +
> +     loop_mode = TIOCM_LOOP & mctrl;
> +     if (loop_mode) {
> +             mr = msm_hsl_read(port, UARTDM_MR2);
> +             mr |= UARTDM_MR2_LOOP_MODE_BMSK;
> +             msm_hsl_write(port, mr, UARTDM_MR2);
> +
> +             /* Reset TX */
> +             msm_hsl_reset(port);
> +
> +             /* Turn on Uart Receiver & Transmitter */
> +             msm_hsl_write(port, UARTDM_CR_RX_EN_BMSK | UARTDM_CR_TX_EN_BMSK,
> +                           UARTDM_CR);
> +     }
> +}
> +
> +static void msm_hsl_break_ctl(struct uart_port *port, int break_ctl)
> +{
> +
> +     if (break_ctl)
> +             msm_hsl_write(port, START_BREAK, UARTDM_CR);
> +     else
> +             msm_hsl_write(port, STOP_BREAK, UARTDM_CR);
> +}
> +
> +/*
> + * msm_hsl_set_baud_rate: set requested baud rate
> + * @port: uart port
> + * @baud: baud rate to set (in bps)
> + */
> +static void msm_hsl_set_baud_rate(struct uart_port *port, unsigned int baud)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +     unsigned int baud_code, rxstale, watermark;
> +     unsigned int data;
> +
> +     switch (baud) {
> +     case 300:
> +             baud_code = 0x00;
> +             rxstale = 1;
> +             break;
> +     case 600:
> +             baud_code = 0x11;
> +             rxstale = 1;
> +             break;
> +     case 1200:
> +             baud_code = 0x22;
> +             rxstale = 1;
> +             break;
> +     case 2400:
> +             baud_code = 0x33;
> +             rxstale = 1;
> +             break;
> +     case 4800:
> +             baud_code = 0x44;
> +             rxstale = 1;
> +             break;
> +     case 9600:
> +             baud_code = 0x55;
> +             rxstale = 2;
> +             break;
> +     case 14400:
> +             baud_code = 0x66;
> +             rxstale = 3;
> +             break;
> +     case 19200:
> +             baud_code = 0x77;
> +             rxstale = 4;
> +             break;
> +     case 28800:
> +             baud_code = 0x88;
> +             rxstale = 6;
> +             break;
> +     case 38400:
> +             baud_code = 0x99;
> +             rxstale = 8;
> +             break;
> +     case 57600:
> +             baud_code = 0xaa;
> +             rxstale = 16;
> +             break;
> +     case 115200:
> +             baud_code = 0xcc;
> +             rxstale = 31;
> +             break;
> +     case 230400:
> +             baud_code = 0xee;
> +             rxstale = 31;
> +             break;
> +     case 460800:
> +             baud_code = 0xff;
> +             rxstale = 31;
> +             break;
> +     default:                /*115200 baud rate */
> +             baud_code = 0xcc;
> +             rxstale = 31;
> +             break;
> +     }
> +
> +     msm_hsl_write(port, baud_code, UARTDM_CSR);
> +
> +     /*
> +      * uart baud rate depends on CSR and MND Values
> +      * we are updating CSR before and then calling
> +      * clk_set_rate which updates MND Values. Hence
> +      * dsb requires here.
> +      */
> +     mb();
> +
> +     /*
> +      * Check requested baud rate and for higher baud rate than 460800,
> +      * calculate required uart clock frequency and set the same.
> +      */
> +     if (baud > 460800)
> +             port->uartclk = baud * 16;
> +     else
> +             port->uartclk = 7372800;
> +
> +     if (clk_set_rate(hslp->clk, port->uartclk)) {
> +             WARN_ON(1);
> +             return;
> +     }
> +
> +     /* Set timeout to be ~600x the character transmit time */
> +     hslp->tx_timeout = (1000000000 / baud) * 6;
> +
> +     /* RX stale watermark */
> +     watermark = UARTDM_IPR_STALE_LSB_BMSK & rxstale;
> +     watermark |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2);
> +     msm_hsl_write(port, watermark, UARTDM_IPR);
> +
> +     /* Set RX watermark
> +      * Configure Rx Watermark as 3/4 size of Rx FIFO.
> +      * RFWR register takes value in Words for UARTDM Core
> +      * whereas it is consider to be in Bytes for UART Core.
> +      * Hence configuring Rx Watermark as 48 Words.
> +      */
> +     watermark = (port->fifosize * 3) / 4;
> +     msm_hsl_write(port, watermark, UARTDM_RFWR);
> +
> +     /* set TX watermark */
> +     msm_hsl_write(port, 0, UARTDM_TFWR);
> +
> +     msm_hsl_write(port, CR_PROTECTION_EN, UARTDM_CR);
> +     msm_hsl_reset(port);
> +
> +     data = UARTDM_CR_TX_EN_BMSK;
> +     data |= UARTDM_CR_RX_EN_BMSK;
> +     /* enable TX & RX */
> +     msm_hsl_write(port, data, UARTDM_CR);
> +
> +     msm_hsl_write(port, RESET_STALE_INT, UARTDM_CR);
> +     /* turn on RX and CTS interrupts */
> +     hslp->imr = UARTDM_ISR_RXSTALE_BMSK | UARTDM_ISR_DELTA_CTS_BMSK |
> +                 UARTDM_ISR_RXLEV_BMSK;
> +     msm_hsl_write(port, hslp->imr, UARTDM_IMR);
> +     msm_hsl_write(port, 6500, UARTDM_DMRX);
> +     msm_hsl_write(port, STALE_EVENT_ENABLE, UARTDM_CR);
> +}
> +
> +static int msm_hsl_startup(struct uart_port *port)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +     unsigned int data, rfr_level;
> +     int ret;
> +     unsigned long flags;
> +
> +     snprintf(hslp->name, sizeof(hslp->name),
> +              "msm_serial_hsl%d", port->line);
> +
> +     if (!(is_console(port)) || (!port->cons) ||
> +         (port->cons && (!(port->cons->flags & CON_ENABLED)))) {
> +
> +             if (msm_serial_hsl_has_gsbi(port))
> +                     set_gsbi_uart_func_mode(port);
> +     }
> +
> +     /*
> +      * Set RFR Level as 3/4 of UARTDM FIFO Size
> +      * i.e. 48 Words = 192 bytes as Rx FIFO is 64 words ( 256 bytes).
> +      */
> +     if (port->fifosize > 48)
> +             rfr_level = port->fifosize - 16;
> +     else
> +             rfr_level = port->fifosize;
> +
> +     spin_lock_irqsave(&port->lock, flags);
> +
> +     /* set automatic RFR level */
> +     data = msm_hsl_read(port, UARTDM_MR1);
> +     data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
> +     data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK;
> +     data |= UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2);
> +     data |= UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level;
> +     msm_hsl_write(port, data, UARTDM_MR1);
> +     spin_unlock_irqrestore(&port->lock, flags);
> +
> +     ret = request_irq(port->irq, msm_hsl_irq, IRQF_TRIGGER_HIGH,
> +                       hslp->name, port);
> +     if (ret)
> +             dev_err(port->dev, "Failed to request irq\n");
> +
> +     return ret;
> +}
> +
> +static void msm_hsl_shutdown(struct uart_port *port)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +
> +     hslp->imr = 0;
> +     /* disable interrupts */
> +     msm_hsl_write(port, 0, UARTDM_IMR);
> +
> +     free_irq(port->irq, port);
> +}
> +
> +static void msm_hsl_set_termios(struct uart_port *port,
> +                             struct ktermios *termios, struct ktermios *old)
> +{
> +     unsigned int baud, mr;
> +     unsigned long flags;
> +
> +     if (!termios->c_cflag)
> +             return;
> +
> +     /*
> +      * Calculate and set baud rate
> +      * 300 is the minimum and 4 Mbps is the maximum baud rate
> +      * supported by driver.
> +      */
> +     baud = uart_get_baud_rate(port, termios, old, 200, 4000000);
> +
> +     /*
> +      * Due to non-availability of 3.2 Mbps baud rate as standard baud rate
> +      * with TTY/serial core. Map 200 BAUD to 3.2 Mbps
> +      */
> +     if (baud == 200)
> +             baud = 3200000;
> +
> +     spin_lock_irqsave(&port->lock, flags);
> +
> +     msm_hsl_set_baud_rate(port, baud);
> +
> +     /* calculate parity */
> +     mr = msm_hsl_read(port, UARTDM_MR2);
> +     mr &= ~UARTDM_MR2_PARITY_MODE_BMSK;
> +     if (termios->c_cflag & PARENB) {
> +             if (termios->c_cflag & PARODD)
> +                     mr |= ODD_PARITY;
> +             else if (termios->c_cflag & CMSPAR)
> +                     mr |= SPACE_PARITY;
> +             else
> +                     mr |= EVEN_PARITY;
> +     }
> +
> +     /* calculate bits per char */
> +     mr &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK;
> +     switch (termios->c_cflag & CSIZE) {
> +     case CS5:
> +             mr |= FIVE_BPC;
> +             break;
> +     case CS6:
> +             mr |= SIX_BPC;
> +             break;
> +     case CS7:
> +             mr |= SEVEN_BPC;
> +             break;
> +     case CS8:
> +     default:
> +             mr |= EIGHT_BPC;
> +             break;
> +     }
> +
> +     /* calculate stop bits */
> +     mr &= ~(STOP_BIT_ONE | STOP_BIT_TWO);
> +     if (termios->c_cflag & CSTOPB)
> +             mr |= STOP_BIT_TWO;
> +     else
> +             mr |= STOP_BIT_ONE;
> +
> +     /* set parity, bits per char, and stop bit */
> +     msm_hsl_write(port, mr, UARTDM_MR2);
> +
> +     /* calculate and set hardware flow control */
> +     mr = msm_hsl_read(port, UARTDM_MR1);
> +     mr &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
> +     if (termios->c_cflag & CRTSCTS) {
> +             mr |= UARTDM_MR1_CTS_CTL_BMSK;
> +             mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
> +     }
> +     msm_hsl_write(port, mr, UARTDM_MR1);
> +
> +     /* Configure status bits to ignore based on termio flags. */
> +     port->read_status_mask = 0;
> +     if (termios->c_iflag & INPCK)
> +             port->read_status_mask |= UARTDM_SR_PAR_FRAME_BMSK;
> +     if (termios->c_iflag & (BRKINT | PARMRK))
> +             port->read_status_mask |= UARTDM_SR_RX_BREAK_BMSK;
> +
> +     uart_update_timeout(port, termios->c_cflag, baud);
> +
> +     spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static const char *msm_hsl_type(struct uart_port *port)
> +{
> +     return "MSM";
> +}
> +
> +static void msm_hsl_release_port(struct uart_port *port)
> +{
> +}
> +
> +static int msm_hsl_request_port(struct uart_port *port)
> +{
> +     return 0;
> +}
> +
> +static void msm_hsl_config_port(struct uart_port *port, int flags)
> +{
> +     if (flags & UART_CONFIG_TYPE)
> +             port->type = PORT_MSM;
> +
> +     /* Configure required GSBI based UART protocol. */
> +     if (msm_serial_hsl_has_gsbi(port))
> +             set_gsbi_uart_func_mode(port);
> +}
> +
> +static int msm_hsl_verify_port(struct uart_port *port,
> +                            struct serial_struct *ser)
> +{
> +     if (ser->type != PORT_UNKNOWN && ser->type != PORT_MSM)
> +             return -EINVAL;
> +     if (port->irq != ser->irq)
> +             return -EINVAL;
> +     return 0;
> +}
> +
> +static void msm_hsl_power(struct uart_port *port, unsigned int state,
> +                       unsigned int oldstate)
> +{
> +     struct msm_hsl_port *hslp = to_hsl_port(port);
> +     int ret;
> +
> +     switch (state) {
> +     case UART_PM_STATE_ON:
> +             ret = clk_set_rate(hslp->clk, port->uartclk);
> +             if (ret)
> +                     dev_err(port->dev, "Can't change rate to %u\n",
> +                             port->uartclk);
> +             msm_hsl_clock_enable(port, 1);
> +             break;
> +     case UART_PM_STATE_OFF:
> +             msm_hsl_clock_enable(port, 0);
> +             break;
> +     default:
> +             dev_err(port->dev, "Unknown PM state %d\n", state);
> +     }
> +}
> +
> +static struct uart_ops msm_hsl_uart_pops = {
> +     .tx_empty       = msm_hsl_tx_empty,
> +     .set_mctrl      = msm_hsl_set_mctrl,
> +     .get_mctrl      = msm_hsl_get_mctrl,
> +     .stop_tx        = msm_hsl_stop_tx,
> +     .start_tx       = msm_hsl_start_tx,
> +     .stop_rx        = msm_hsl_stop_rx,
> +     .enable_ms      = msm_hsl_enable_ms,
> +     .break_ctl      = msm_hsl_break_ctl,
> +     .startup        = msm_hsl_startup,
> +     .shutdown       = msm_hsl_shutdown,
> +     .set_termios    = msm_hsl_set_termios,
> +     .type           = msm_hsl_type,
> +     .release_port   = msm_hsl_release_port,
> +     .request_port   = msm_hsl_request_port,
> +     .config_port    = msm_hsl_config_port,
> +     .verify_port    = msm_hsl_verify_port,
> +     .pm             = msm_hsl_power,
> +};
> +
> +#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
> +
> +static struct msm_hsl_port *msm_hsl_uart_ports[UART_NR];
> +
> +static void msm_hsl_console_putchar(struct uart_port *port, int ch)
> +{
> +     msm_hsl_wait_for_xmitr(port);
> +     msm_hsl_write(port, 1, UARTDM_NCF_TX);
> +     /*
> +      * Dummy read to add 1 AHB clock delay to fix UART hardware bug.
> +      * Bug: Delay required on TX-transfer-init. after writing to
> +      * NO_CHARS_FOR_TX register.
> +      */
> +     msm_hsl_read(port, UARTDM_SR);
> +     msm_hsl_write(port, ch, UARTDM_TF);
> +}
> +
> +static void msm_hsl_console_write(struct console *co, const char *s,
> +                               unsigned int count)
> +{
> +     struct uart_port *port;
> +     struct msm_hsl_port *hslp;
> +     int locked;
> +
> +     BUG_ON(co->index < 0 || co->index >= UART_NR);
> +
> +     hslp = msm_hsl_uart_ports[co->index];
> +     port = &hslp->uart;
> +
> +     /* not pretty, but we can end up here via various convoluted paths */
> +     if (port->sysrq || oops_in_progress)
> +             locked = spin_trylock(&port->lock);
> +     else {
> +             locked = 1;
> +             spin_lock(&port->lock);
> +     }
> +     msm_hsl_write(port, 0, UARTDM_IMR);
> +     uart_console_write(port, s, count, msm_hsl_console_putchar);
> +     msm_hsl_write(port, hslp->imr, UARTDM_IMR);
> +     if (locked == 1)
> +             spin_unlock(&port->lock);
> +}
> +
> +static int msm_hsl_console_setup(struct console *co, char *options)
> +{
> +     struct uart_port *port;
> +     int baud = 0, flow, bits, parity, mr2;
> +     int ret;
> +
> +     if (co->index >= UART_NR || co->index < 0)
> +             return -ENXIO;
> +
> +     port = &msm_hsl_uart_ports[co->index]->uart;
> +
> +     if (!port->membase)
> +             return -ENXIO;
> +
> +     port->cons = co;
> +
> +     pm_runtime_get_noresume(port->dev);
> +
> +#ifndef CONFIG_PM_RUNTIME
> +     msm_hsl_clock_enable(port, 1);
> +#endif
> +     pm_runtime_resume(port->dev);
> +
> +     if (options)
> +             uart_parse_options(options, &baud, &parity, &bits, &flow);
> +
> +     bits = 8;
> +     parity = 'n';
> +     flow = 'n';
> +     msm_hsl_write(port, UARTDM_MR2_BITS_PER_CHAR_8 |
> +                   STOP_BIT_ONE, UARTDM_MR2);        /* 8N1 */
> +
> +     if (baud < 300 || baud > 115200)
> +             baud = 115200;
> +
> +     msm_hsl_set_baud_rate(port, baud);
> +
> +     ret = uart_set_options(port, co, baud, parity, bits, flow);
> +
> +     mr2 = msm_hsl_read(port, UARTDM_MR2);
> +     mr2 |= UARTDM_MR2_RX_ERROR_CHAR_OFF;
> +     mr2 |= UARTDM_MR2_RX_BREAK_ZERO_CHAR_OFF;
> +     msm_hsl_write(port, mr2, UARTDM_MR2);
> +
> +     msm_hsl_reset(port);
> +     /* Enable transmitter */
> +     msm_hsl_write(port, CR_PROTECTION_EN, UARTDM_CR);
> +     msm_hsl_write(port, UARTDM_CR_TX_EN_BMSK, UARTDM_CR);
> +
> +     msm_hsl_write(port, 1, UARTDM_NCF_TX);
> +     msm_hsl_read(port, UARTDM_NCF_TX);
> +
> +     dev_dbg(port->dev, "Console setup on port #%d\n", port->line);
> +
> +     return ret;
> +}
> +
> +static struct uart_driver msm_hsl_uart_driver;
> +
> +static struct console msm_hsl_console = {
> +     .name = "ttyHSL",
> +     .write = msm_hsl_console_write,
> +     .device = uart_console_device,
> +     .setup = msm_hsl_console_setup,
> +     .flags = CON_PRINTBUFFER,
> +     .index = -1,
> +     .data = &msm_hsl_uart_driver,
> +};
> +
> +#define MSM_HSL_CONSOLE      (&msm_hsl_console)
> +
> +#else
> +#define MSM_HSL_CONSOLE      NULL
> +#endif
> +
> +static struct uart_driver msm_hsl_uart_driver = {
> +     .owner = THIS_MODULE,
> +     .driver_name = "msm_serial_hsl",
> +     .dev_name = "ttyHSL",
> +     .nr = UART_NR,
> +     .cons = MSM_HSL_CONSOLE,
> +};
> +
> +static struct dentry *debug_base;
> +
> +DEFINE_SIMPLE_ATTRIBUTE(loopback_enable_fops, msm_hsl_loopback_get,
> +                     msm_hsl_loopback_set, "%llu\n");
> +/*
> + * msm_serial_hsl debugfs node: <debugfs_root>/msm_serial_hsl/loopback.<id>
> + * writing 1 turns on internal loopback mode in HW. Useful for automation
> + * test scripts.
> + * writing 0 disables the internal loopback mode. Default is disabled.
> + */
> +static void msm_hsl_debugfs_init(struct msm_hsl_port *hslp, int id)
> +{
> +     char node_name[15];
> +
> +     snprintf(node_name, sizeof(node_name), "loopback.%d", id);
> +     hslp->loopback_dir = debugfs_create_file(node_name,
> +                                              S_IRUGO | S_IWUSR,
> +                                              debug_base, hslp,
> +                                              &loopback_enable_fops);
> +}
> +
> +static atomic_t msm_serial_hsl_next_id = ATOMIC_INIT(0);
> +
> +static struct of_device_id msm_hsl_match_table[] = {
> +     {.compatible = "qcom,msm-lsuart-v14"},
> +     { /* Sentinel */ }
> +};
> +
> +MODULE_DEVICE_TABLE(of, msm_hsl_match_table);
> +
> +static int msm_serial_hsl_probe(struct platform_device *pdev)
> +{
> +     struct device_node *node = pdev->dev.of_node;
> +     struct msm_hsl_port *hslp;
> +     struct resource *mem;
> +     struct uart_port *port;
> +     const struct of_device_id *match;
> +     u32 line;
> +     int ret;
> +
> +     if (pdev->id == -1)
> +             pdev->id = atomic_inc_return(&msm_serial_hsl_next_id) - 1;
> +
> +     line = pdev->id;
> +
> +     /* Use line number from device tree alias if present */
> +     if (!node)
> +             return -EINVAL;
> +
> +     ret = of_alias_get_id(node, "serial");
> +     if (ret >= 0)
> +             line = ret;
> +
> +     if (line < 0 || line >= UART_NR)
> +             return -ENXIO;
> +
> +     pr_info("detected port #%d (ttyHSL%d)\n", pdev->id, line);
> +
> +     hslp = devm_kzalloc(&pdev->dev, sizeof(*hslp), GFP_KERNEL);
> +     if (!hslp)
> +             return -ENOMEM;
> +
> +     port = &hslp->uart;
> +     port->dev = &pdev->dev;
> +     port->uartclk = 7372800;
> +     port->iotype = UPIO_MEM;
> +     port->ops = &msm_hsl_uart_pops;
> +     port->flags = UPF_BOOT_AUTOCONF;
> +     port->fifosize = 64;
> +     port->line = line;
> +
> +     hslp->clk = devm_clk_get(&pdev->dev, "core_clk");
> +     if (IS_ERR(hslp->clk)) {
> +             ret = PTR_ERR(hslp->clk);
> +             if (ret != -EPROBE_DEFER)
> +                     dev_err(&pdev->dev, "Error getting core clk\n");
> +             return ret;
> +     }
> +
> +     /*
> +      * Interface clock is not required by all UART configurations.
> +      * GSBI UART and BLSP UART needs interface clock but Legacy UART
> +      * do not require interface clock. Hence, do not fail probe with
> +      * iface of_clk_get_by_name failure.
> +      */
> +     hslp->pclk = devm_clk_get(&pdev->dev, "iface_clk");
> +     if (IS_ERR(hslp->pclk)) {
> +             ret = PTR_ERR(hslp->pclk);
> +             if (ret == -EPROBE_DEFER)
> +                     return ret;
> +             else
> +                     hslp->pclk = NULL;
> +     }
> +
> +     hslp->uart_type = LEGACY_HSUART;
> +
> +     match = of_match_device(msm_hsl_match_table, &pdev->dev);
> +     if (!match) {
> +             hslp->regmap = regmap[UARTDM_VERSION_11_13];
> +     } else {
> +             hslp->regmap = regmap[UARTDM_VERSION_14];
> +             /*
> +              * BLSP based UART configuration is available with
> +              * UARTDM v14 Revision. Hence set uart_type as UART_BLSP.
> +              */
> +             hslp->uart_type = BLSP_HSUART;
> +     }
> +
> +     mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gbsi_mem");
> +     if (mem) {
> +             hslp->mapped_gsbi = devm_request_and_ioremap(&pdev->dev, mem);
> +             if (!hslp->mapped_gsbi)
> +                     dev_warn(&pdev->dev, "GSBI region already claimed\n");
> +             else
> +                     hslp->uart_type = GSBI_HSUART;
> +     }
> +
> +     mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uart_mem");
> +     if (!mem) {
> +             dev_err(&pdev->dev, "Getting UART mem failed\n");
> +             return -ENXIO;
> +     }
> +
> +     port->mapbase = mem->start;
> +
> +     port->irq = platform_get_irq(pdev, 0);
> +     if ((int)port->irq < 0) {
> +             dev_err(&pdev->dev, "Getting irq failed\n");
> +             return -ENXIO;
> +     }
> +
> +     port->membase = devm_request_and_ioremap(&pdev->dev, mem);
> +     if (!port->membase) {
> +             dev_err(&pdev->dev, "UART region already claimed\n");
> +             return -EADDRNOTAVAIL;
> +     }
> +
> +     device_set_wakeup_capable(&pdev->dev, 1);
> +     platform_set_drvdata(pdev, port);
> +     pm_runtime_enable(port->dev);
> +#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
> +     msm_hsl_uart_ports[line] = hslp;
> +#endif
> +     msm_hsl_debugfs_init(hslp, hslp->uart.line);
> +
> +     /* Temporarily increase the refcount on the GSBI clock to avoid a race
> +      * condition with the earlyprintk handover mechanism.
> +      */
> +     if (hslp->pclk)
> +             clk_prepare_enable(hslp->pclk);
> +     ret = uart_add_one_port(&msm_hsl_uart_driver, port);
> +     if (hslp->pclk)
> +             clk_disable_unprepare(hslp->pclk);
> +
> +     if (!ret)
> +             platform_set_drvdata(pdev, hslp);
> +
> +     return ret;
> +}
> +
> +static int msm_serial_hsl_remove(struct platform_device *pdev)
> +{
> +     struct msm_hsl_port *hslp = platform_get_drvdata(pdev);
> +     struct uart_port *port;
> +
> +     port = &hslp->uart;
> +
> +     pm_runtime_put_sync(&pdev->dev);
> +     pm_runtime_disable(&pdev->dev);
> +
> +     device_set_wakeup_capable(&pdev->dev, 0);
> +     platform_set_drvdata(pdev, NULL);
> +
> +     uart_remove_one_port(&msm_hsl_uart_driver, port);
> +
> +     debugfs_remove(hslp->loopback_dir);
> +     return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int msm_serial_hsl_suspend(struct device *dev)
> +{
> +     struct msm_hsl_port *hslp = dev_get_drvdata(dev);
> +     struct uart_port *port;
> +
> +     port = &hslp->uart;
> +
> +     if (port)
> +             return 0;
> +
> +     if (is_console(port))
> +             msm_hsl_clock_enable(port, 0);
> +
> +     uart_suspend_port(&msm_hsl_uart_driver, port);
> +     if (device_may_wakeup(dev))
> +             enable_irq_wake(port->irq);
> +
> +     return 0;
> +}
> +
> +static int msm_serial_hsl_resume(struct device *dev)
> +{
> +     struct msm_hsl_port *hslp = dev_get_drvdata(dev);
> +     struct uart_port *port;
> +
> +     port = &hslp->uart;
> +
> +     if (!port)
> +             return 0;
> +
> +     uart_resume_port(&msm_hsl_uart_driver, port);
> +     if (device_may_wakeup(dev))
> +             disable_irq_wake(port->irq);
> +
> +     if (is_console(port))
> +             msm_hsl_clock_enable(port, 1);
> +
> +     return 0;
> +}
> +#else
> +#define msm_serial_hsl_suspend NULL
> +#define msm_serial_hsl_resume NULL
> +#endif
> +
> +static int msm_hsl_runtime_suspend(struct device *dev)
> +{
> +     struct msm_hsl_port *hslp = dev_get_drvdata(dev);
> +     struct uart_port *port;
> +
> +     port = &hslp->uart;
> +
> +     dev_dbg(dev, "pm_runtime: suspending\n");
> +     msm_hsl_clock_enable(port, 0);
> +     return 0;
> +}
> +
> +static int msm_hsl_runtime_resume(struct device *dev)
> +{
> +     struct msm_hsl_port *hslp = dev_get_drvdata(dev);
> +     struct uart_port *port;
> +
> +     port = &hslp->uart;
> +
> +     dev_dbg(dev, "pm_runtime: resuming\n");
> +     msm_hsl_clock_enable(port, 1);
> +     return 0;
> +}
> +
> +static const struct dev_pm_ops msm_hsl_dev_pm_ops = {
> +     .suspend = msm_serial_hsl_suspend,
> +     .resume = msm_serial_hsl_resume,
> +     .runtime_suspend = msm_hsl_runtime_suspend,
> +     .runtime_resume = msm_hsl_runtime_resume,
> +};
> +
> +static struct platform_driver msm_hsl_platform_driver = {
> +     .probe = msm_serial_hsl_probe,
> +     .remove = msm_serial_hsl_remove,
> +     .driver = {
> +                .name = "msm_serial_hsl",
> +                .owner = THIS_MODULE,
> +                .pm = &msm_hsl_dev_pm_ops,
> +                .of_match_table = msm_hsl_match_table,
> +     },
> +};
> +
> +static int __init msm_serial_hsl_init(void)
> +{
> +     int ret;
> +
> +     ret = uart_register_driver(&msm_hsl_uart_driver);
> +     if (ret)
> +             return ret;
> +
> +     debug_base = debugfs_create_dir("msm_serial_hsl", NULL);
> +     if (IS_ERR_OR_NULL(debug_base))
> +             pr_err("Cannot create debugfs dir\n");
> +
> +     ret = platform_driver_register(&msm_hsl_platform_driver);
> +     if (ret)
> +             uart_unregister_driver(&msm_hsl_uart_driver);
> +
> +     pr_debug("Driver initialized\n");
> +     return ret;
> +}
> +
> +static void __exit msm_serial_hsl_exit(void)
> +{
> +     debugfs_remove_recursive(debug_base);
> +#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
> +     unregister_console(&msm_hsl_console);
> +#endif
> +     platform_driver_unregister(&msm_hsl_platform_driver);
> +     uart_unregister_driver(&msm_hsl_uart_driver);
> +}
> +
> +module_init(msm_serial_hsl_init);
> +module_exit(msm_serial_hsl_exit);
> +
> +MODULE_DESCRIPTION("Driver for MSM HSUART UART serial device");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/tty/serial/msm_serial_hsl.h 
> b/drivers/tty/serial/msm_serial_hsl.h
> new file mode 100644
> index 0000000..beb97d4
> --- /dev/null
> +++ b/drivers/tty/serial/msm_serial_hsl.h
> @@ -0,0 +1,294 @@
> +/* drivers/tty/serial/msm_serial_hsl.h
> + *
> + * Copyright (c) 2007-2009, 2012-2013,The Linux Foundation. All rights 
> reserved.
> + *
> + * All source code in this file is licensed under the following license
> + * except where indicated.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> + * See the GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, you can find it at http://www.fsf.org
> + */
> +
> +#ifndef MSM_SERIAL_HSL_H
> +#define MSM_SERIAL_HSL_H
> +
> +#define GSBI_CONTROL_ADDR              0x0
> +#define GSBI_PROTOCOL_CODE_MASK        0x30
> +#define GSBI_PROTOCOL_I2C_UART         0x60
> +#define GSBI_PROTOCOL_UART             0x40
> +#define GSBI_PROTOCOL_IDLE             0x0
> +
> +#define TCSR_ADM_1_A_CRCI_MUX_SEL      0x78
> +#define TCSR_ADM_1_B_CRCI_MUX_SEL      0x7c
> +#define ADM1_CRCI_GSBI6_RX_SEL         0x800
> +#define ADM1_CRCI_GSBI6_TX_SEL         0x400
> +
> +enum msm_hsl_regs {
> +     UARTDM_MR1,
> +     UARTDM_MR2,
> +     UARTDM_IMR,
> +     UARTDM_SR,
> +     UARTDM_CR,
> +     UARTDM_CSR,
> +     UARTDM_IPR,
> +     UARTDM_ISR,
> +     UARTDM_RX_TOTAL_SNAP,
> +     UARTDM_RFWR,
> +     UARTDM_TFWR,
> +     UARTDM_RF,
> +     UARTDM_TF,
> +     UARTDM_MISR,
> +     UARTDM_DMRX,
> +     UARTDM_NCF_TX,
> +     UARTDM_DMEN,
> +     UARTDM_BCR,
> +     UARTDM_TXFS,
> +     UARTDM_RXFS,
> +     UARTDM_LAST,
> +};
> +
> +#define UARTDM_MR1_ADDR 0x0
> +#define UARTDM_MR2_ADDR 0x4
> +
> +/* Backward Compatability Register for UARTDM Core v1.4 */
> +#define UARTDM_BCR_ADDR      0xc8
> +
> +/*
> + * UARTDM Core v1.4 STALE_IRQ_EMPTY bit defination
> + * Stale interrupt will fire if bit is set when RX-FIFO is empty
> + */
> +#define UARTDM_BCR_STALE_IRQ_EMPTY   0x2
> +
> +/* TRANSFER_CONTROL Register for UARTDM Core v1.4 */
> +#define UARTDM_RX_TRANS_CTRL_ADDR      0xcc
> +
> +/* TRANSFER_CONTROL Register bits */
> +#define RX_STALE_AUTO_RE_EN          0x1
> +#define RX_TRANS_AUTO_RE_ACTIVATE    0x2
> +#define RX_DMRX_CYCLIC_EN            0x4
> +
> +/* write only register */
> +#define UARTDM_IPR_ADDR 0x18
> +#define UARTDM_TFWR_ADDR 0x1c
> +#define UARTDM_RFWR_ADDR 0x20
> +#define UARTDM_HCR_ADDR 0x24
> +#define UARTDM_DMRX_ADDR 0x34
> +#define UARTDM_DMEN_ADDR 0x3c
> +
> +/* UART_DM_NO_CHARS_FOR_TX */
> +#define UARTDM_NCF_TX_ADDR 0x40
> +
> +#define UARTDM_BADR_ADDR 0x44
> +
> +#define UARTDM_SIM_CFG_ADDR 0x80
> +
> +/* Read Only register */
> +#define UARTDM_TXFS_ADDR 0x4c
> +#define UARTDM_RXFS_ADDR 0x50
> +
> +/* Register field Mask Mapping */
> +#define UARTDM_SR_RX_BREAK_BMSK              BIT(6)
> +#define UARTDM_SR_PAR_FRAME_BMSK     BIT(5)
> +#define UARTDM_SR_OVERRUN_BMSK               BIT(4)
> +#define UARTDM_SR_TXEMT_BMSK         BIT(3)
> +#define UARTDM_SR_TXRDY_BMSK         BIT(2)
> +#define UARTDM_SR_RXRDY_BMSK         BIT(0)
> +
> +#define UARTDM_CR_TX_DISABLE_BMSK    BIT(3)
> +#define UARTDM_CR_RX_DISABLE_BMSK    BIT(1)
> +#define UARTDM_CR_TX_EN_BMSK         BIT(2)
> +#define UARTDM_CR_RX_EN_BMSK         BIT(0)
> +
> +/* UARTDM_CR channel_comman bit value (register field is bits 8:4) */
> +#define RESET_RX             0x10
> +#define RESET_TX             0x20
> +#define RESET_ERROR_STATUS   0x30
> +#define RESET_BREAK_INT              0x40
> +#define START_BREAK          0x50
> +#define STOP_BREAK           0x60
> +#define RESET_CTS            0x70
> +#define RESET_STALE_INT              0x80
> +#define RFR_LOW                      0xD0
> +#define RFR_HIGH             0xE0
> +#define CR_PROTECTION_EN     0x100
> +#define STALE_EVENT_ENABLE   0x500
> +#define STALE_EVENT_DISABLE  0x600
> +#define FORCE_STALE_EVENT    0x400
> +#define CLEAR_TX_READY               0x300
> +#define RESET_TX_ERROR               0x800
> +#define RESET_TX_DONE                0x810
> +
> +/*
> + * UARTDM_CR BAM IFC comman bit value
> + * for UARTDM Core v1.4
> + */
> +#define START_RX_BAM_IFC     0x850
> +#define START_TX_BAM_IFC     0x860
> +
> +#define UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK 0xffffff00
> +#define UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK 0x3f
> +#define UARTDM_MR1_CTS_CTL_BMSK 0x40
> +#define UARTDM_MR1_RX_RDY_CTL_BMSK 0x80
> +
> +/*
> + * UARTDM Core v1.4 MR2_RFR_CTS_LOOP bitmask
> + * Enables internal loopback between RFR_N of
> + * RX channel and CTS_N of TX channel.
> + */
> +#define UARTDM_MR2_RFR_CTS_LOOP_MODE_BMSK    0x400
> +
> +#define UARTDM_MR2_LOOP_MODE_BMSK            0x80
> +#define UARTDM_MR2_ERROR_MODE_BMSK           0x40
> +#define UARTDM_MR2_BITS_PER_CHAR_BMSK                0x30
> +#define UARTDM_MR2_RX_ZERO_CHAR_OFF          0x100
> +#define UARTDM_MR2_RX_ERROR_CHAR_OFF         0x200
> +#define UARTDM_MR2_RX_BREAK_ZERO_CHAR_OFF    0x100
> +
> +#define UARTDM_MR2_BITS_PER_CHAR_8   (0x3 << 4)
> +
> +/* bits per character configuration */
> +#define FIVE_BPC  (0 << 4)
> +#define SIX_BPC   (1 << 4)
> +#define SEVEN_BPC (2 << 4)
> +#define EIGHT_BPC (3 << 4)
> +
> +#define UARTDM_MR2_STOP_BIT_LEN_BMSK 0xc
> +#define STOP_BIT_ONE (1 << 2)
> +#define STOP_BIT_TWO (3 << 2)
> +
> +#define UARTDM_MR2_PARITY_MODE_BMSK 0x3
> +
> +/* Parity configuration */
> +#define NO_PARITY 0x0
> +#define EVEN_PARITY 0x2
> +#define ODD_PARITY 0x1
> +#define SPACE_PARITY 0x3
> +
> +#define UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK 0xffffff80
> +#define UARTDM_IPR_STALE_LSB_BMSK 0x1f
> +
> +/* These can be used for both ISR and IMR register */
> +#define UARTDM_ISR_TX_READY_BMSK     BIT(7)
> +#define UARTDM_ISR_CURRENT_CTS_BMSK  BIT(6)
> +#define UARTDM_ISR_DELTA_CTS_BMSK    BIT(5)
> +#define UARTDM_ISR_RXLEV_BMSK                BIT(4)
> +#define UARTDM_ISR_RXSTALE_BMSK              BIT(3)
> +#define UARTDM_ISR_RXBREAK_BMSK              BIT(2)
> +#define UARTDM_ISR_RXHUNT_BMSK               BIT(1)
> +#define UARTDM_ISR_TXLEV_BMSK                BIT(0)
> +
> +/* Field definitions for UART_DM_DMEN*/
> +#define UARTDM_TX_DM_EN_BMSK 0x1
> +#define UARTDM_RX_DM_EN_BMSK 0x2
> +
> +/*
> + * UARTDM Core v1.4 bitmask
> + * Bitmasks for enabling Rx and Tx BAM Interface
> + */
> +#define UARTDM_TX_BAM_ENABLE_BMSK 0x4
> +#define UARTDM_RX_BAM_ENABLE_BMSK 0x8
> +
> +/*
> + * Some of the BLSP Based UART Core(v14) existing register offsets
> + * are different compare to GSBI based UART Core(v13)
> + * Hence add the changed register offsets for UART Core v14
> + */
> +
> +/* write only register */
> +#define UARTDM_CSR_ADDR_V14    0xa0
> +
> +/* write only register */
> +#define UARTDM_TF_ADDR_V14   0x100
> +#define UARTDM_TF2_ADDR_V14  0x104
> +#define UARTDM_TF3_ADDR_V14  0x108
> +#define UARTDM_TF4_ADDR_V14  0x10c
> +#define UARTDM_TF5_ADDR_V14  0x110
> +#define UARTDM_TF6_ADDR_V14  0x114
> +#define UARTDM_TF7_ADDR_V14  0x118
> +#define UARTDM_TF8_ADDR_V14  0x11c
> +#define UARTDM_TF9_ADDR_V14  0x120
> +#define UARTDM_TF10_ADDR_V14 0x124
> +#define UARTDM_TF11_ADDR_V14 0x128
> +#define UARTDM_TF12_ADDR_V14 0x12c
> +#define UARTDM_TF13_ADDR_V14 0x130
> +#define UARTDM_TF14_ADDR_V14 0x134
> +#define UARTDM_TF15_ADDR_V14 0x138
> +#define UARTDM_TF16_ADDR_V14 0x13c
> +
> +/* write only register */
> +#define UARTDM_CR_ADDR_V14 0xa8
> +/* write only register */
> +#define UARTDM_IMR_ADDR_V14 0xb0
> +#define UARTDM_IRDA_ADDR_V14 0xb8
> +
> +/* Read Only register */
> +#define UARTDM_SR_ADDR_V14 0xa4
> +
> +/* Read Only register */
> +#define UARTDM_RF_ADDR_V14   0x140
> +#define UARTDM_RF2_ADDR_V14  0x144
> +#define UARTDM_RF3_ADDR_V14  0x148
> +#define UARTDM_RF4_ADDR_V14  0x14c
> +#define UARTDM_RF5_ADDR_V14  0x150
> +#define UARTDM_RF6_ADDR_V14  0x154
> +#define UARTDM_RF7_ADDR_V14  0x158
> +#define UARTDM_RF8_ADDR_V14  0x15c
> +#define UARTDM_RF9_ADDR_V14  0x160
> +#define UARTDM_RF10_ADDR_V14 0x164
> +#define UARTDM_RF11_ADDR_V14 0x168
> +#define UARTDM_RF12_ADDR_V14 0x16c
> +#define UARTDM_RF13_ADDR_V14 0x170
> +#define UARTDM_RF14_ADDR_V14 0x174
> +#define UARTDM_RF15_ADDR_V14 0x178
> +#define UARTDM_RF16_ADDR_V14 0x17c
> +
> +/* Read Only register */
> +#define UARTDM_MISR_ADDR_V14 0xac
> +
> +/* Read Only register */
> +#define UARTDM_ISR_ADDR_V14 0xb4
> +#define UARTDM_RX_TOTAL_SNAP_ADDR_V14 0xbc
> +
> +/* Register offsets for UART Core v13 */
> +
> +/* write only register */
> +#define UARTDM_CSR_ADDR    0x8
> +
> +/* write only register */
> +#define UARTDM_TF_ADDR   0x70
> +#define UARTDM_TF2_ADDR  0x74
> +#define UARTDM_TF3_ADDR  0x78
> +#define UARTDM_TF4_ADDR  0x7c
> +
> +/* write only register */
> +#define UARTDM_CR_ADDR 0x10
> +/* write only register */
> +#define UARTDM_IMR_ADDR 0x14
> +#define UARTDM_IRDA_ADDR 0x38
> +
> +/* Read Only register */
> +#define UARTDM_SR_ADDR 0x8
> +
> +/* Read Only register */
> +#define UARTDM_RF_ADDR   0x70
> +#define UARTDM_RF2_ADDR  0x74
> +#define UARTDM_RF3_ADDR  0x78
> +#define UARTDM_RF4_ADDR  0x7c
> +
> +/* Read Only register */
> +#define UARTDM_MISR_ADDR 0x10
> +
> +/* Read Only register */
> +#define UARTDM_ISR_ADDR 0x14
> +#define UARTDM_RX_TOTAL_SNAP_ADDR 0x38
> +
> +#endif /* MSM_SERIAL_HSL_H */


_______________________________________________
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

Reply via email to