Re: [PATCH v3 1/2] uart: pl011: support registers offset with LUT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jun,

Some comments below.

On 03/30/15 11:16, Jun Nie wrote:
> Both ARM and ST uart use the same pl011 IP, but some registers
> have different offset. Support the different offset with look
> up table.
> 
> Signed-off-by: Jun Nie <jun.nie@xxxxxxxxxx>
> ---
>  drivers/tty/serial/amba-pl011.c | 339 ++++++++++++++++++++++++----------------
>  include/linux/amba/serial.h     |   2 +
>  2 files changed, 203 insertions(+), 138 deletions(-)
> 
> diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
> index 8d94c19..2047dcd 100644
> --- a/drivers/tty/serial/amba-pl011.c
> +++ b/drivers/tty/serial/amba-pl011.c
> @@ -29,7 +29,6 @@
>   * and hooked into this driver.
>   */
> 
> -
>  #if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>  #define SUPPORT_SYSRQ
>  #endif
> @@ -73,8 +72,7 @@
>  /* There is by now at least one vendor with differing details, so handle it */
>  struct vendor_data {
>         unsigned int            ifls;
> -       unsigned int            lcrh_tx;
> -       unsigned int            lcrh_rx;
> +       u8                      *reg_lut;
>         bool                    oversampling;
>         bool                    dma_threshold;
>         bool                    cts_event_workaround;
> @@ -87,10 +85,32 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
>         return amba_rev(dev) < 3 ? 16 : 32;
>  }
> 
> +static u8 arm_reg[] = {

The size of the LUT is fixed for all UART types isn't it, so it should be specified in this, and other, declarations.  Then, for the completely paranoid, the index could be checked in the accessor functions.

> +       /*  All registers offset are in order except LCRH as comment */
> +       [0] = UART01x_DR,
> +       [1] = UART01x_RSR,
> +       [2] = ST_UART011_DMAWM,
> +       [3] = UART010_LCRM,
> +       [4] = UART010_LCRL,
> +       [5] = UART010_CR,
> +       [6] = UART01x_FR,
> +       [7] = UART011_LCRH_TX, /* remapped */
> +       [8] = UART01x_ILPR,
> +       [9] = UART011_IBRD,
> +       [10] = UART011_FBRD,
> +       [11] = UART011_LCRH_TX,
> +       [12] = UART011_CR,
> +       [13] = UART011_IFLS,
> +       [14] = UART011_IMSC,
> +       [15] = UART011_RIS,
> +       [16] = UART011_MIS,
> +       [17] = UART011_ICR,
> +       [18] = UART011_DMACR,

The offset indexes are all magic numbers but later on they are referenced by symbol. So you probably want something of the form:

#define UART_REG_IDX(r)	((r) >> 2)

...

	[UART_REG_IDX(UART01x_DR)] = UART01x_DR;

then it's clear what is being mapped where and things are easier to maintain.

	Andrew

> +};
> +
>  static struct vendor_data vendor_arm = {
>         .ifls                   = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
> -       .lcrh_tx                = UART011_LCRH,
> -       .lcrh_rx                = UART011_LCRH,
> +       .reg_lut                = arm_reg,
>         .oversampling           = false,
>         .dma_threshold          = false,
>         .cts_event_workaround   = false,
> @@ -102,10 +122,32 @@ static unsigned int get_fifosize_st(struct amba_device *dev)
>         return 64;
>  }
> 
> +static u8 st_reg[] = {
> +       /* All registers offset are in order */
> +       [0] = UART01x_DR,
> +       [1] = UART01x_RSR,
> +       [2] = ST_UART011_DMAWM,
> +       [3] = UART010_LCRM,
> +       [4] = UART010_LCRL,
> +       [5] = UART010_CR,
> +       [6] = UART01x_FR,
> +       [7] = UART011_LCRH_RX,
> +       [8] = UART01x_ILPR,
> +       [9] = UART011_IBRD,
> +       [10] = UART011_FBRD,
> +       [11] = UART011_LCRH_TX,
> +       [12] = UART011_CR,
> +       [13] = UART011_IFLS,
> +       [14] = UART011_IMSC,
> +       [15] = UART011_RIS,
> +       [16] = UART011_MIS,
> +       [17] = UART011_ICR,
> +       [18] = UART011_DMACR,
> +};
> +
>  static struct vendor_data vendor_st = {
>         .ifls                   = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
> -       .lcrh_tx                = ST_UART011_LCRH_TX,
> -       .lcrh_rx                = ST_UART011_LCRH_RX,
> +       .reg_lut                = st_reg,
>         .oversampling           = true,
>         .dma_threshold          = true,
>         .cts_event_workaround   = true,
> @@ -148,13 +190,12 @@ struct pl011_dmatx_data {
>  struct uart_amba_port {
>         struct uart_port        port;
>         struct clk              *clk;
> +       u8                      *reg_lut;
>         const struct vendor_data *vendor;
>         unsigned int            dmacr;          /* dma control reg */
>         unsigned int            im;             /* interrupt mask */
>         unsigned int            old_status;
>         unsigned int            fifosize;       /* vendor-specific */
> -       unsigned int            lcrh_tx;        /* vendor-specific */
> -       unsigned int            lcrh_rx;        /* vendor-specific */
>         unsigned int            old_cr;         /* state during shutdown */
>         bool                    autorts;
>         char                    type[12];
> @@ -167,6 +208,21 @@ struct uart_amba_port {
>  #endif
>  };
> 
> +static unsigned int pl011_readw(struct uart_amba_port *uap, int index)
> +{
> +       return readw_relaxed(uap->port.membase + uap->reg_lut[index >> 2]);
> +}
> +
> +static void pl011_writew(struct uart_amba_port *uap, int val, int index)
> +{
> +       writew_relaxed(val, uap->port.membase + uap->reg_lut[index >> 2]);
> +}
> +
> +static void pl011_writeb(struct uart_amba_port *uap, u8 val, int index)
> +{
> +       writeb_relaxed(val, uap->port.membase + uap->reg_lut[index >> 2]);
> +}
> +
>  /*
>   * Reads up to 256 characters from the FIFO or until it's empty and
>   * inserts them into the TTY layer. Returns the number of characters
> @@ -179,12 +235,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
>         int fifotaken = 0;
> 
>         while (max_count--) {
> -               status = readw(uap->port.membase + UART01x_FR);
> +               status = pl011_readw(uap, UART01x_FR);
>                 if (status & UART01x_FR_RXFE)
>                         break;
> 
>                 /* Take chars from the FIFO and update status */
> -               ch = readw(uap->port.membase + UART01x_DR) |
> +               ch = pl011_readw(uap, UART01x_DR) |
>                         UART_DUMMY_DR_RX;
>                 flag = TTY_NORMAL;
>                 uap->port.icount.rx++;
> @@ -266,7 +322,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
>         /* DMA is the sole user of the platform data right now */
>         struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
>         struct dma_slave_config tx_conf = {
> -               .dst_addr = uap->port.mapbase + UART01x_DR,
> +               .dst_addr = uap->port.mapbase + uap->reg_lut[UART01x_DR],
>                 .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
>                 .direction = DMA_MEM_TO_DEV,
>                 .dst_maxburst = uap->fifosize >> 1,
> @@ -316,7 +372,8 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
> 
>         if (chan) {
>                 struct dma_slave_config rx_conf = {
> -                       .src_addr = uap->port.mapbase + UART01x_DR,
> +                       .src_addr = uap->port.mapbase
> +                                       + uap->reg_lut[UART01x_DR],
>                         .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
>                         .direction = DMA_DEV_TO_MEM,
>                         .src_maxburst = uap->fifosize >> 2,
> @@ -461,7 +518,7 @@ static void pl011_dma_tx_callback(void *data)
> 
>         dmacr = uap->dmacr;
>         uap->dmacr = dmacr & ~UART011_TXDMAE;
> -       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
> +       pl011_writew(uap, uap->dmacr, UART011_DMACR);
> 
>         /*
>          * If TX DMA was disabled, it means that we've stopped the DMA for
> @@ -485,7 +542,7 @@ static void pl011_dma_tx_callback(void *data)
>                  * have data pending to be sent.  Re-enable the TX IRQ.
>                  */
>                 uap->im |= UART011_TXIM;
> -               writew(uap->im, uap->port.membase + UART011_IMSC);
> +               pl011_writew(uap, uap->im, UART011_IMSC);
>         }
>         spin_unlock_irqrestore(&uap->port.lock, flags);
>  }
> @@ -576,7 +633,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
>         dma_dev->device_issue_pending(chan);
> 
>         uap->dmacr |= UART011_TXDMAE;
> -       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
> +       pl011_writew(uap, uap->dmacr, UART011_DMACR);
>         uap->dmatx.queued = true;
> 
>         /*
> @@ -612,9 +669,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
>          */
>         if (uap->dmatx.queued) {
>                 uap->dmacr |= UART011_TXDMAE;
> -               writew(uap->dmacr, uap->port.membase + UART011_DMACR);
> +               pl011_writew(uap, uap->dmacr, UART011_DMACR);
>                 uap->im &= ~UART011_TXIM;
> -               writew(uap->im, uap->port.membase + UART011_IMSC);
> +               pl011_writew(uap, uap->im, UART011_IMSC);
>                 return true;
>         }
> 
> @@ -624,7 +681,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
>          */
>         if (pl011_dma_tx_refill(uap) > 0) {
>                 uap->im &= ~UART011_TXIM;
> -               writew(uap->im, uap->port.membase + UART011_IMSC);
> +               pl011_writew(uap, uap->im, UART011_IMSC);
>                 return true;
>         }
>         return false;
> @@ -638,7 +695,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
>  {
>         if (uap->dmatx.queued) {
>                 uap->dmacr &= ~UART011_TXDMAE;
> -               writew(uap->dmacr, uap->port.membase + UART011_DMACR);
> +               pl011_writew(uap, uap->dmacr, UART011_DMACR);
>         }
>  }
> 
> @@ -669,11 +726,10 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
>                                 uap->im |= UART011_TXIM;
>                                 ret = false;
>                         }
> -                       writew(uap->im, uap->port.membase + UART011_IMSC);
> +                       pl011_writew(uap, uap->im, UART011_IMSC);
>                 } else if (!(uap->dmacr & UART011_TXDMAE)) {
>                         uap->dmacr |= UART011_TXDMAE;
> -                       writew(uap->dmacr,
> -                                      uap->port.membase + UART011_DMACR);
> +                       pl011_writew(uap, uap->dmacr, UART011_DMACR);
>                 }
>                 return ret;
>         }
> @@ -684,9 +740,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
>          */
>         dmacr = uap->dmacr;
>         uap->dmacr &= ~UART011_TXDMAE;
> -       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
> +       pl011_writew(uap, uap->dmacr, UART011_DMACR);
> 
> -       if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) {
> +       if (pl011_readw(uap, UART01x_FR) & UART01x_FR_TXFF) {
>                 /*
>                  * No space in the FIFO, so enable the transmit interrupt
>                  * so we know when there is space.  Note that once we've
> @@ -695,13 +751,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
>                 return false;
>         }
> 
> -       writew(uap->port.x_char, uap->port.membase + UART01x_DR);
> +       pl011_writew(uap, uap->port.x_char, UART01x_DR);
>         uap->port.icount.tx++;
>         uap->port.x_char = 0;
> 
>         /* Success - restore the DMA state */
>         uap->dmacr = dmacr;
> -       writew(dmacr, uap->port.membase + UART011_DMACR);
> +       pl011_writew(uap, dmacr, UART011_DMACR);
> 
>         return true;
>  }
> @@ -729,7 +785,7 @@ __acquires(&uap->port.lock)
>                              DMA_TO_DEVICE);
>                 uap->dmatx.queued = false;
>                 uap->dmacr &= ~UART011_TXDMAE;
> -               writew(uap->dmacr, uap->port.membase + UART011_DMACR);
> +               pl011_writew(uap, uap->dmacr, UART011_DMACR);
>         }
>  }
> 
> @@ -769,11 +825,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
>         dma_async_issue_pending(rxchan);
> 
>         uap->dmacr |= UART011_RXDMAE;
> -       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
> +       pl011_writew(uap, uap->dmacr, UART011_DMACR);
>         uap->dmarx.running = true;
> 
>         uap->im &= ~UART011_RXIM;
> -       writew(uap->im, uap->port.membase + UART011_IMSC);
> +       pl011_writew(uap, uap->im, UART011_IMSC);
> 
>         return 0;
>  }
> @@ -831,8 +887,9 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
>          */
>         if (dma_count == pending && readfifo) {
>                 /* Clear any error flags */
> -               writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
> -                      uap->port.membase + UART011_ICR);
> +               pl011_writew(uap,
> +                   UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
> +                   UART011_ICR);
> 
>                 /*
>                  * If we read all the DMA'd characters, and we had an
> @@ -880,7 +937,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap)
> 
>         /* Disable RX DMA - incoming data will wait in the FIFO */
>         uap->dmacr &= ~UART011_RXDMAE;
> -       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
> +       pl011_writew(uap, uap->dmacr, UART011_DMACR);
>         uap->dmarx.running = false;
> 
>         pending = sgbuf->sg.length - state.residue;
> @@ -900,7 +957,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap)
>                 dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
>                         "fall back to interrupt mode\n");
>                 uap->im |= UART011_RXIM;
> -               writew(uap->im, uap->port.membase + UART011_IMSC);
> +               pl011_writew(uap, uap->im, UART011_IMSC);
>         }
>  }
> 
> @@ -948,7 +1005,7 @@ static void pl011_dma_rx_callback(void *data)
>                 dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
>                         "fall back to interrupt mode\n");
>                 uap->im |= UART011_RXIM;
> -               writew(uap->im, uap->port.membase + UART011_IMSC);
> +               pl011_writew(uap, uap->im, UART011_IMSC);
>         }
>  }
> 
> @@ -961,7 +1018,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
>  {
>         /* FIXME.  Just disable the DMA enable */
>         uap->dmacr &= ~UART011_RXDMAE;
> -       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
> +       pl011_writew(uap, uap->dmacr, UART011_DMACR);
>  }
> 
>  /*
> @@ -1005,7 +1062,7 @@ static void pl011_dma_rx_poll(unsigned long args)
>                 spin_lock_irqsave(&uap->port.lock, flags);
>                 pl011_dma_rx_stop(uap);
>                 uap->im |= UART011_RXIM;
> -               writew(uap->im, uap->port.membase + UART011_IMSC);
> +               pl011_writew(uap, uap->im, UART011_IMSC);
>                 spin_unlock_irqrestore(&uap->port.lock, flags);
> 
>                 uap->dmarx.running = false;
> @@ -1064,7 +1121,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
>  skip_rx:
>         /* Turn on DMA error (RX/TX will be enabled on demand) */
>         uap->dmacr |= UART011_DMAONERR;
> -       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
> +       pl011_writew(uap, uap->dmacr, UART011_DMACR);
> 
>         /*
>          * ST Micro variants has some specific dma burst threshold
> @@ -1072,8 +1129,9 @@ skip_rx:
>          * be issued above/below 16 bytes.
>          */
>         if (uap->vendor->dma_threshold)
> -               writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
> -                              uap->port.membase + ST_UART011_DMAWM);
> +               pl011_writew(uap,
> +                       ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
> +                       ST_UART011_DMAWM);
> 
>         if (uap->using_rx_dma) {
>                 if (pl011_dma_rx_trigger_dma(uap))
> @@ -1098,12 +1156,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
>                 return;
> 
>         /* Disable RX and TX DMA */
> -       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
> +       while (pl011_readw(uap, UART01x_FR) & UART01x_FR_BUSY)
>                 barrier();
> 
>         spin_lock_irq(&uap->port.lock);
>         uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
> -       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
> +       pl011_writew(uap, uap->dmacr, UART011_DMACR);
>         spin_unlock_irq(&uap->port.lock);
> 
>         if (uap->using_tx_dma) {
> @@ -1204,7 +1262,7 @@ static void pl011_stop_tx(struct uart_port *port)
>             container_of(port, struct uart_amba_port, port);
> 
>         uap->im &= ~UART011_TXIM;
> -       writew(uap->im, uap->port.membase + UART011_IMSC);
> +       pl011_writew(uap, uap->im, UART011_IMSC);
>         pl011_dma_tx_stop(uap);
>  }
> 
> @@ -1215,7 +1273,7 @@ static void pl011_start_tx(struct uart_port *port)
> 
>         if (!pl011_dma_tx_start(uap)) {
>                 uap->im |= UART011_TXIM;
> -               writew(uap->im, uap->port.membase + UART011_IMSC);
> +               pl011_writew(uap, uap->im, UART011_IMSC);
>         }
>  }
> 
> @@ -1226,7 +1284,7 @@ static void pl011_stop_rx(struct uart_port *port)
> 
>         uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
>                      UART011_PEIM|UART011_BEIM|UART011_OEIM);
> -       writew(uap->im, uap->port.membase + UART011_IMSC);
> +       pl011_writew(uap, uap->im, UART011_IMSC);
> 
>         pl011_dma_rx_stop(uap);
>  }
> @@ -1237,7 +1295,7 @@ static void pl011_enable_ms(struct uart_port *port)
>             container_of(port, struct uart_amba_port, port);
> 
>         uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM;
> -       writew(uap->im, uap->port.membase + UART011_IMSC);
> +       pl011_writew(uap, uap->im, UART011_IMSC);
>  }
> 
>  static void pl011_rx_chars(struct uart_amba_port *uap)
> @@ -1257,7 +1315,7 @@ __acquires(&uap->port.lock)
>                         dev_dbg(uap->port.dev, "could not trigger RX DMA job "
>                                 "fall back to interrupt mode again\n");
>                         uap->im |= UART011_RXIM;
> -                       writew(uap->im, uap->port.membase + UART011_IMSC);
> +                       pl011_writew(uap, uap->im, UART011_IMSC);
>                 } else {
>  #ifdef CONFIG_DMA_ENGINE
>                         /* Start Rx DMA poll */
> @@ -1280,7 +1338,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap)
>         int count;
> 
>         if (uap->port.x_char) {
> -               writew(uap->port.x_char, uap->port.membase + UART01x_DR);
> +               pl011_writew(uap, uap->port.x_char, UART01x_DR);
>                 uap->port.icount.tx++;
>                 uap->port.x_char = 0;
>                 return;
> @@ -1296,7 +1354,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap)
> 
>         count = uap->fifosize >> 1;
>         do {
> -               writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
> +               pl011_writew(uap, xmit->buf[xmit->tail], UART01x_DR);
>                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>                 uap->port.icount.tx++;
>                 if (uart_circ_empty(xmit))
> @@ -1314,7 +1372,7 @@ static void pl011_modem_status(struct uart_amba_port *uap)
>  {
>         unsigned int status, delta;
> 
> -       status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
> +       status = pl011_readw(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
> 
>         delta = status ^ uap->old_status;
>         uap->old_status = status;
> @@ -1343,25 +1401,27 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
>         unsigned int dummy_read;
> 
>         spin_lock_irqsave(&uap->port.lock, flags);
> -       status = readw(uap->port.membase + UART011_MIS);
> +       status = pl011_readw(uap, UART011_MIS);
>         if (status) {
>                 do {
>                         if (uap->vendor->cts_event_workaround) {
>                                 /* workaround to make sure that all bits are unlocked.. */
> -                               writew(0x00, uap->port.membase + UART011_ICR);
> +                               pl011_writew(uap, 0x00, UART011_ICR);
> 
>                                 /*
>                                  * WA: introduce 26ns(1 uart clk) delay before W1C;
>                                  * single apb access will incur 2 pclk(133.12Mhz) delay,
>                                  * so add 2 dummy reads
>                                  */
> -                               dummy_read = readw(uap->port.membase + UART011_ICR);
> -                               dummy_read = readw(uap->port.membase + UART011_ICR);
> +                               dummy_read = pl011_readw(uap,
> +                                                       UART011_ICR);
> +                               dummy_read = pl011_readw(uap,
> +                                                       UART011_ICR);
>                         }
> 
> -                       writew(status & ~(UART011_TXIS|UART011_RTIS|
> -                                         UART011_RXIS),
> -                              uap->port.membase + UART011_ICR);
> +                       pl011_writew(uap,
> +                           status & ~(UART011_TXIS|UART011_RTIS|UART011_RXIS),
> +                           UART011_ICR);
> 
>                         if (status & (UART011_RTIS|UART011_RXIS)) {
>                                 if (pl011_dma_rx_running(uap))
> @@ -1378,7 +1438,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
>                         if (pass_counter-- == 0)
>                                 break;
> 
> -                       status = readw(uap->port.membase + UART011_MIS);
> +                       status = pl011_readw(uap, UART011_MIS);
>                 } while (status != 0);
>                 handled = 1;
>         }
> @@ -1392,16 +1452,17 @@ static unsigned int pl011_tx_empty(struct uart_port *port)
>  {
>         struct uart_amba_port *uap =
>             container_of(port, struct uart_amba_port, port);
> -       unsigned int status = readw(uap->port.membase + UART01x_FR);
> +
> +       unsigned int status = pl011_readw(uap, UART01x_FR);
>         return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
>  }
> 
>  static unsigned int pl011_get_mctrl(struct uart_port *port)
>  {
> +       unsigned int result = 0;
>         struct uart_amba_port *uap =
>             container_of(port, struct uart_amba_port, port);
> -       unsigned int result = 0;
> -       unsigned int status = readw(uap->port.membase + UART01x_FR);
> +       unsigned int status = pl011_readw(uap, UART01x_FR);
> 
>  #define TIOCMBIT(uartbit, tiocmbit)    \
>         if (status & uartbit)           \
> @@ -1421,7 +1482,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
>             container_of(port, struct uart_amba_port, port);
>         unsigned int cr;
> 
> -       cr = readw(uap->port.membase + UART011_CR);
> +       cr = pl011_readw(uap, UART011_CR);
> 
>  #define        TIOCMBIT(tiocmbit, uartbit)             \
>         if (mctrl & tiocmbit)           \
> @@ -1441,7 +1502,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
>         }
>  #undef TIOCMBIT
> 
> -       writew(cr, uap->port.membase + UART011_CR);
> +       pl011_writew(uap, cr, UART011_CR);
>  }
> 
>  static void pl011_break_ctl(struct uart_port *port, int break_state)
> @@ -1452,12 +1513,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
>         unsigned int lcr_h;
> 
>         spin_lock_irqsave(&uap->port.lock, flags);
> -       lcr_h = readw(uap->port.membase + uap->lcrh_tx);
> +       lcr_h = pl011_readw(uap, UART011_LCRH_TX);
>         if (break_state == -1)
>                 lcr_h |= UART01x_LCRH_BRK;
>         else
>                 lcr_h &= ~UART01x_LCRH_BRK;
> -       writew(lcr_h, uap->port.membase + uap->lcrh_tx);
> +       pl011_writew(uap, lcr_h, UART011_LCRH_TX);
>         spin_unlock_irqrestore(&uap->port.lock, flags);
>  }
> 
> @@ -1467,9 +1528,8 @@ static void pl011_quiesce_irqs(struct uart_port *port)
>  {
>         struct uart_amba_port *uap =
>             container_of(port, struct uart_amba_port, port);
> -       unsigned char __iomem *regs = uap->port.membase;
> 
> -       writew(readw(regs + UART011_MIS), regs + UART011_ICR);
> +       pl011_writew(uap, pl011_readw(uap, UART011_MIS), UART011_ICR);
>         /*
>          * There is no way to clear TXIM as this is "ready to transmit IRQ", so
>          * we simply mask it. start_tx() will unmask it.
> @@ -1483,14 +1543,15 @@ static void pl011_quiesce_irqs(struct uart_port *port)
>          * (including tx queue), so we're also fine with start_tx()'s caller
>          * side.
>          */
> -       writew(readw(regs + UART011_IMSC) & ~UART011_TXIM, regs + UART011_IMSC);
> +       pl011_writew(uap,
> +               pl011_readw(uap, UART011_IMSC) & ~UART011_TXIM, UART011_IMSC);
>  }
> 
>  static int pl011_get_poll_char(struct uart_port *port)
>  {
> +       unsigned int status;
>         struct uart_amba_port *uap =
>             container_of(port, struct uart_amba_port, port);
> -       unsigned int status;
> 
>         /*
>          * The caller might need IRQs lowered, e.g. if used with KDB NMI
> @@ -1498,11 +1559,11 @@ static int pl011_get_poll_char(struct uart_port *port)
>          */
>         pl011_quiesce_irqs(port);
> 
> -       status = readw(uap->port.membase + UART01x_FR);
> +       status = pl011_readw(uap, UART01x_FR);
>         if (status & UART01x_FR_RXFE)
>                 return NO_POLL_CHAR;
> 
> -       return readw(uap->port.membase + UART01x_DR);
> +       return pl011_readw(uap, UART01x_DR);
>  }
> 
>  static void pl011_put_poll_char(struct uart_port *port,
> @@ -1511,10 +1572,10 @@ static void pl011_put_poll_char(struct uart_port *port,
>         struct uart_amba_port *uap =
>             container_of(port, struct uart_amba_port, port);
> 
> -       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
> +       while (pl011_readw(uap, UART01x_FR) & UART01x_FR_TXFF)
>                 barrier();
> 
> -       writew(ch, uap->port.membase + UART01x_DR);
> +       pl011_writew(uap, ch, UART01x_DR);
>  }
> 
>  #endif /* CONFIG_CONSOLE_POLL */
> @@ -1538,15 +1599,16 @@ static int pl011_hwinit(struct uart_port *port)
>         uap->port.uartclk = clk_get_rate(uap->clk);
> 
>         /* Clear pending error and receive interrupts */
> -       writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
> -              UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
> +       pl011_writew(uap,
> +               UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
> +               UART011_RTIS | UART011_RXIS, UART011_ICR);
> 
>         /*
>          * Save interrupts enable mask, and enable RX interrupts in case if
>          * the interrupt is used for NMI entry.
>          */
> -       uap->im = readw(uap->port.membase + UART011_IMSC);
> -       writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC);
> +       uap->im = pl011_readw(uap, UART011_IMSC);
> +       pl011_writew(uap, UART011_RTIM | UART011_RXIM, UART011_IMSC);
> 
>         if (dev_get_platdata(uap->port.dev)) {
>                 struct amba_pl011_data *plat;
> @@ -1560,16 +1622,16 @@ static int pl011_hwinit(struct uart_port *port)
> 
>  static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
>  {
> -       writew(lcr_h, uap->port.membase + uap->lcrh_rx);
> -       if (uap->lcrh_rx != uap->lcrh_tx) {
> +       pl011_writew(uap, lcr_h, UART011_LCRH_TX);
> +       if (uap->reg_lut[UART011_LCRH_TX] != uap->reg_lut[UART011_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(lcr_h, uap->port.membase + uap->lcrh_tx);
> +                       pl011_writew(uap, 0xff, UART011_MIS);
> +               pl011_writew(uap, lcr_h, UART011_LCRH_TX);
>         }
>  }
> 
> @@ -1584,7 +1646,7 @@ static int pl011_startup(struct uart_port *port)
>         if (retval)
>                 goto clk_dis;
> 
> -       writew(uap->im, uap->port.membase + UART011_IMSC);
> +       pl011_writew(uap, uap->im, UART011_IMSC);
> 
>         /*
>          * Allocate the IRQ
> @@ -1593,7 +1655,7 @@ static int pl011_startup(struct uart_port *port)
>         if (retval)
>                 goto clk_dis;
> 
> -       writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
> +       pl011_writew(uap, uap->vendor->ifls, UART011_IFLS);
> 
>         /*
>          * Provoke TX FIFO interrupt into asserting. Taking care to preserve
> @@ -1602,34 +1664,34 @@ static int pl011_startup(struct uart_port *port)
>          */
>         spin_lock_irq(&uap->port.lock);
> 
> -       fbrd = readw(uap->port.membase + UART011_FBRD);
> -       ibrd = readw(uap->port.membase + UART011_IBRD);
> -       lcr_h = readw(uap->port.membase + uap->lcrh_rx);
> +       fbrd = pl011_readw(uap, UART011_FBRD);
> +       ibrd = pl011_readw(uap, UART011_IBRD);
> +       lcr_h = pl011_readw(uap, UART011_LCRH_RX);
> 
>         cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE;
> -       writew(cr, uap->port.membase + UART011_CR);
> -       writew(0, uap->port.membase + UART011_FBRD);
> -       writew(1, uap->port.membase + UART011_IBRD);
> +       pl011_writew(uap, cr, UART011_CR);
> +       pl011_writew(uap, 0, UART011_FBRD);
> +       pl011_writew(uap, 1, UART011_IBRD);
>         pl011_write_lcr_h(uap, 0);
> -       writew(0, uap->port.membase + UART01x_DR);
> -       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
> +       pl011_writew(uap, 0, UART01x_DR);
> +       while (pl011_readw(uap, UART01x_FR) & UART01x_FR_BUSY)
>                 barrier();
> 
> -       writew(fbrd, uap->port.membase + UART011_FBRD);
> -       writew(ibrd, uap->port.membase + UART011_IBRD);
> +       pl011_writew(uap, fbrd, UART011_FBRD);
> +       pl011_writew(uap, ibrd, UART011_IBRD);
>         pl011_write_lcr_h(uap, lcr_h);
> 
>         /* restore RTS and DTR */
>         cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
>         cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
> -       writew(cr, uap->port.membase + UART011_CR);
> +       pl011_writew(uap, cr, UART011_CR);
> 
>         spin_unlock_irq(&uap->port.lock);
> 
>         /*
>          * initialise the old status of the modem signals
>          */
> -       uap->old_status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
> +       uap->old_status = pl011_readw(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
> 
>         /* Startup DMA */
>         pl011_dma_startup(uap);
> @@ -1641,29 +1703,33 @@ static int pl011_startup(struct uart_port *port)
>          */
>         spin_lock_irq(&uap->port.lock);
>         /* Clear out any spuriously appearing RX interrupts */
> -        writew(UART011_RTIS | UART011_RXIS,
> -               uap->port.membase + UART011_ICR);
> +        pl011_writew(uap, UART011_RTIS | UART011_RXIS, UART011_ICR);
>         uap->im = UART011_RTIM;
>         if (!pl011_dma_rx_running(uap))
>                 uap->im |= UART011_RXIM;
> -       writew(uap->im, uap->port.membase + UART011_IMSC);
> +       pl011_writew(uap, uap->im, UART011_IMSC);
>         spin_unlock_irq(&uap->port.lock);
> 
>         return 0;
> 
> - clk_dis:
> +clk_dis:
>         clk_disable_unprepare(uap->clk);
>         return retval;
>  }
> 
> -static void pl011_shutdown_channel(struct uart_amba_port *uap,
> -                                       unsigned int lcrh)
> +static void pl011_shutdown_channel(struct uart_amba_port *uap)
>  {
> -      unsigned long val;
> +       unsigned long val;
> +
> +       val = pl011_readw(uap, UART011_LCRH_RX);
> +       val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
> +       pl011_writew(uap, val, UART011_LCRH_RX);
> 
> -      val = readw(uap->port.membase + lcrh);
> -      val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
> -      writew(val, uap->port.membase + lcrh);
> +       if (uap->reg_lut[UART011_LCRH_RX] != uap->reg_lut[UART011_LCRH_TX]) {
> +               val = pl011_readw(uap, UART011_LCRH_TX);
> +               val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
> +               pl011_writew(uap, val, UART011_LCRH_TX);
> +       }
>  }
> 
>  static void pl011_shutdown(struct uart_port *port)
> @@ -1677,8 +1743,8 @@ static void pl011_shutdown(struct uart_port *port)
>          */
>         spin_lock_irq(&uap->port.lock);
>         uap->im = 0;
> -       writew(uap->im, uap->port.membase + UART011_IMSC);
> -       writew(0xffff, uap->port.membase + UART011_ICR);
> +       pl011_writew(uap, uap->im, UART011_IMSC);
> +       pl011_writew(uap, 0xffff, UART011_ICR);
>         spin_unlock_irq(&uap->port.lock);
> 
>         pl011_dma_shutdown(uap);
> @@ -1696,19 +1762,17 @@ static void pl011_shutdown(struct uart_port *port)
>          */
>         uap->autorts = false;
>         spin_lock_irq(&uap->port.lock);
> -       cr = readw(uap->port.membase + UART011_CR);
> +       cr = pl011_readw(uap, UART011_CR);
>         uap->old_cr = cr;
>         cr &= UART011_CR_RTS | UART011_CR_DTR;
>         cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
> -       writew(cr, uap->port.membase + UART011_CR);
> +       pl011_writew(uap, cr, UART011_CR);
>         spin_unlock_irq(&uap->port.lock);
> 
>         /*
>          * disable break condition and fifos
>          */
> -       pl011_shutdown_channel(uap, uap->lcrh_rx);
> -       if (uap->lcrh_rx != uap->lcrh_tx)
> -               pl011_shutdown_channel(uap, uap->lcrh_tx);
> +       pl011_shutdown_channel(uap);
> 
>         /*
>          * Shut down the clock producer
> @@ -1825,8 +1889,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
>                 pl011_enable_ms(port);
> 
>         /* first, disable everything */
> -       old_cr = readw(port->membase + UART011_CR);
> -       writew(0, port->membase + UART011_CR);
> +       old_cr = pl011_readw(uap, UART011_CR);
> +       pl011_writew(uap, 0, UART011_CR);
> 
>         if (termios->c_cflag & CRTSCTS) {
>                 if (old_cr & UART011_CR_RTS)
> @@ -1859,8 +1923,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
>                         quot -= 2;
>         }
>         /* Set baud rate */
> -       writew(quot & 0x3f, port->membase + UART011_FBRD);
> -       writew(quot >> 6, port->membase + UART011_IBRD);
> +       pl011_writew(uap, quot & 0x3f, UART011_FBRD);
> +       pl011_writew(uap, quot >> 6, UART011_IBRD);
> 
>         /*
>          * ----------v----------v----------v----------v-----
> @@ -1869,7 +1933,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
>          * ----------^----------^----------^----------^-----
>          */
>         pl011_write_lcr_h(uap, lcr_h);
> -       writew(old_cr, port->membase + UART011_CR);
> +       pl011_writew(uap, old_cr, UART011_CR);
> 
>         spin_unlock_irqrestore(&port->lock, flags);
>  }
> @@ -1955,12 +2019,9 @@ static struct uart_amba_port *amba_ports[UART_NR];
> 
>  static void pl011_console_putchar(struct uart_port *port, int ch)
>  {
> -       struct uart_amba_port *uap =
> -           container_of(port, struct uart_amba_port, port);
> -
> -       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
> +       while (pl011_readw(uap, UART01x_FR) & UART01x_FR_TXFF)
>                 barrier();
> -       writew(ch, uap->port.membase + UART01x_DR);
> +       pl011_writew(uap, ch, UART01x_DR);
>  }
> 
>  static void
> @@ -1984,10 +2045,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
>         /*
>          *      First save the CR then disable the interrupts
>          */
> -       old_cr = readw(uap->port.membase + UART011_CR);
> +       old_cr = pl011_readw(uap, UART011_CR);
>         new_cr = old_cr & ~UART011_CR_CTSEN;
>         new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
> -       writew(new_cr, uap->port.membase + UART011_CR);
> +       pl011_writew(uap, new_cr, UART011_CR);
> 
>         uart_console_write(&uap->port, s, count, pl011_console_putchar);
> 
> @@ -1996,9 +2057,9 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
>          *      and restore the TCR
>          */
>         do {
> -               status = readw(uap->port.membase + UART01x_FR);
> +               status = pl011_readw(uap, UART01x_FR);
>         } while (status & UART01x_FR_BUSY);
> -       writew(old_cr, uap->port.membase + UART011_CR);
> +       pl011_writew(uap, old_cr, UART011_CR);
> 
>         if (locked)
>                 spin_unlock(&uap->port.lock);
> @@ -2011,10 +2072,10 @@ static void __init
>  pl011_console_get_options(struct uart_amba_port *uap, int *baud,
>                              int *parity, int *bits)
>  {
> -       if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {
> +       if (pl011_readw(uap, UART011_CR) & UART01x_CR_UARTEN) {
>                 unsigned int lcr_h, ibrd, fbrd;
> 
> -               lcr_h = readw(uap->port.membase + uap->lcrh_tx);
> +               lcr_h = pl011_readw(uap, UART011_LCRH_TX);
> 
>                 *parity = 'n';
>                 if (lcr_h & UART01x_LCRH_PEN) {
> @@ -2029,13 +2090,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
>                 else
>                         *bits = 8;
> 
> -               ibrd = readw(uap->port.membase + UART011_IBRD);
> -               fbrd = readw(uap->port.membase + UART011_FBRD);
> +               ibrd = pl011_readw(uap, UART011_IBRD);
> +               fbrd = pl011_readw(uap, UART011_FBRD);
> 
>                 *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
> 
>                 if (uap->vendor->oversampling) {
> -                       if (readw(uap->port.membase + UART011_CR)
> +                       if (pl011_readw(uap, UART011_CR)
>                                   & ST_UART011_CR_OVSFACT)
>                                 *baud *= 2;
>                 }
> @@ -2102,10 +2163,13 @@ static struct console amba_console = {
> 
>  static void pl011_putc(struct uart_port *port, int c)
>  {
> -       while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
> +       struct uart_amba_port *uap =
> +           container_of(port, struct uart_amba_port, port);
> +
> +       while (pl011_readw(uap, UART01x_FR) & UART01x_FR_TXFF)
>                 ;
> -       writeb(c, port->membase + UART01x_DR);
> -       while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY)
> +       pl011_writeb(uap, c, UART01x_DR);
> +       while (pl011_readw(uap, UART01x_FR) & UART01x_FR_BUSY)
>                 ;
>  }
> 
> @@ -2204,9 +2268,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
>         if (IS_ERR(uap->clk))
>                 return PTR_ERR(uap->clk);
> 
> +       uap->reg_lut = vendor->reg_lut;
>         uap->vendor = vendor;
> -       uap->lcrh_rx = vendor->lcrh_rx;
> -       uap->lcrh_tx = vendor->lcrh_tx;
>         uap->old_cr = 0;
>         uap->fifosize = vendor->get_fifosize(dev);
>         uap->port.dev = &dev->dev;
> @@ -2221,8 +2284,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
>         pl011_dma_probe(&dev->dev, uap);
> 
>         /* Ensure interrupts from this UART are masked and cleared */
> -       writew(0, uap->port.membase + UART011_IMSC);
> -       writew(0xffff, uap->port.membase + UART011_ICR);
> +       pl011_writew(uap, 0, UART011_IMSC);
> +       pl011_writew(uap, 0xffff, UART011_ICR);
> 
>         snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
> 
> diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
> index 0ddb5c0..f243461 100644
> --- a/include/linux/amba/serial.h
> +++ b/include/linux/amba/serial.h
> @@ -42,11 +42,13 @@
>  #define UART01x_FR             0x18    /* Flag register (Read only). */
>  #define UART010_IIR            0x1C    /* Interrupt identification register (Read). */
>  #define UART010_ICR            0x1C    /* Interrupt clear register (Write). */
> +#define UART011_LCRH_RX                0x1C    /* Rx line control register. */
>  #define ST_UART011_LCRH_RX     0x1C    /* Rx line control register. */
>  #define UART01x_ILPR           0x20    /* IrDA low power counter register. */
>  #define UART011_IBRD           0x24    /* Integer baud rate divisor register. */
>  #define UART011_FBRD           0x28    /* Fractional baud rate divisor register. */
>  #define UART011_LCRH           0x2c    /* Line control register. */
> +#define UART011_LCRH_TX                0x2c    /* Line control register. */
>  #define ST_UART011_LCRH_TX     0x2c    /* Tx Line control register. */
>  #define UART011_CR             0x30    /* Control register. */
>  #define UART011_IFLS           0x34    /* Interrupt fifo level select. */
> --
> 1.9.1
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux