All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH DRAFT 0/2] Sketch for ZTE ZX296702 UART integration
@ 2015-11-02 12:24 ` Andre Przywara
  0 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-02 12:24 UTC (permalink / raw)
  To: Jun Nie, Peter Hurley, Timur Tabi
  Cc: Andrew.Jackson, Russell King, linux-arm-kernel, linux-serial

Hi,

there has been some discussion on how to integrate support for the
ZTE ZX296702 UART, which is very similar to the PL011, but (among
other deviations) has its registers at different offsets from the base
address.
Previous patches on the list [1] were reworking the whole of the PL011
driver, creating extra churn for all architecture compliant
implementations.
This sketch introduces register accessor wrappers in patch 1, which
are useful for other things as well later. Ideally the generated
code should look identical after this one, given the compiler properly
inlines the accessor functions.
Based on that patch 2 then introduces a mapping table just for the
ZTE UART, which redirects the original PL011 register offsets to the
shifted positions on the ZTE UART.
The impact on all other implementations are kept minimal, actually if
the CONFIG_ symbol for that SoC is not defined, there should be no
code difference compared to the state before.

I don't have access to the ZTE UART hardware, so could not test this
(this patch set is not complete anyway), but I quickly tested for
regressions on a Juno, which seems to work fine for me.

I provide these patches as a base for discussion and for future,
proper support patches.
Do these make sense to anyone? Is this the way to go for the ZTE UART
implementation?

Any comments are appreciated.

Cheers,
Andre.

[1] http://marc.info/?l=linux-serial&m=143832897928885&w=2

Andre Przywara (2):
  drivers: serial: PL011: refactor register access
  drivers: serial: PL011: [DRAFT] implement register diverson for ZTE
    UART

 drivers/tty/serial/amba-pl011.c | 246 +++++++++++++++++++++++-----------------
 include/linux/amba/serial.h     |  10 ++
 2 files changed, 155 insertions(+), 101 deletions(-)

-- 
2.5.1

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 0/2] Sketch for ZTE ZX296702 UART integration
@ 2015-11-02 12:24 ` Andre Przywara
  0 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-02 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

there has been some discussion on how to integrate support for the
ZTE ZX296702 UART, which is very similar to the PL011, but (among
other deviations) has its registers at different offsets from the base
address.
Previous patches on the list [1] were reworking the whole of the PL011
driver, creating extra churn for all architecture compliant
implementations.
This sketch introduces register accessor wrappers in patch 1, which
are useful for other things as well later. Ideally the generated
code should look identical after this one, given the compiler properly
inlines the accessor functions.
Based on that patch 2 then introduces a mapping table just for the
ZTE UART, which redirects the original PL011 register offsets to the
shifted positions on the ZTE UART.
The impact on all other implementations are kept minimal, actually if
the CONFIG_ symbol for that SoC is not defined, there should be no
code difference compared to the state before.

I don't have access to the ZTE UART hardware, so could not test this
(this patch set is not complete anyway), but I quickly tested for
regressions on a Juno, which seems to work fine for me.

I provide these patches as a base for discussion and for future,
proper support patches.
Do these make sense to anyone? Is this the way to go for the ZTE UART
implementation?

Any comments are appreciated.

Cheers,
Andre.

[1] http://marc.info/?l=linux-serial&m=143832897928885&w=2

Andre Przywara (2):
  drivers: serial: PL011: refactor register access
  drivers: serial: PL011: [DRAFT] implement register diverson for ZTE
    UART

 drivers/tty/serial/amba-pl011.c | 246 +++++++++++++++++++++++-----------------
 include/linux/amba/serial.h     |  10 ++
 2 files changed, 155 insertions(+), 101 deletions(-)

-- 
2.5.1

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 1/2] drivers: serial: PL011: refactor register access
  2015-11-02 12:24 ` Andre Przywara
@ 2015-11-02 12:24   ` Andre Przywara
  -1 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-02 12:24 UTC (permalink / raw)
  To: Jun Nie, Peter Hurley, Timur Tabi
  Cc: Andrew.Jackson, Russell King, linux-arm-kernel, linux-serial

Currently we call readw/writew directly each time we want to access
a PL011 register.
Wrap these calls in a function to simplify changes later, namely:
* to support UARTs with different register offsets (ZTE)
* to support a different bus access width (16 bits vs. 32 bits)
* to introduce readl_relaxed/writel_relaxed usage

This patch itself does not introduce any functional change.

This is based on code from Jun Nie <jun.nie@linaro.org>.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/tty/serial/amba-pl011.c | 209 +++++++++++++++++++++-------------------
 1 file changed, 108 insertions(+), 101 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index fd27e98..ef5d779 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -184,6 +184,16 @@ struct uart_amba_port {
 #endif
 };
 
+static unsigned int pl011_read(struct uart_amba_port *uap, int offset)
+{
+	return readw(uap->port.membase + offset);
+}
+
+static void pl011_write(struct uart_amba_port *uap, int val, int offset)
+{
+	writew(val, uap->port.membase + offset);
+}
+
 /*
  * 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
@@ -196,13 +206,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_read(uap, UART01x_FR);
 		if (status & UART01x_FR_RXFE)
 			break;
 
 		/* Take chars from the FIFO and update status */
-		ch = readw(uap->port.membase + UART01x_DR) |
-			UART_DUMMY_DR_RX;
+		ch = pl011_read(uap, UART01x_DR) | UART_DUMMY_DR_RX;
 		flag = TTY_NORMAL;
 		uap->port.icount.rx++;
 		fifotaken++;
@@ -438,7 +447,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_write(uap, uap->dmacr, UART011_DMACR);
 
 	/*
 	 * If TX DMA was disabled, it means that we've stopped the DMA for
@@ -552,7 +561,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_write(uap, uap->dmacr, UART011_DMACR);
 	uap->dmatx.queued = true;
 
 	/*
@@ -588,9 +597,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_write(uap, uap->dmacr, UART011_DMACR);
 		uap->im &= ~UART011_TXIM;
-		writew(uap->im, uap->port.membase + UART011_IMSC);
+		pl011_write(uap, uap->im, UART011_IMSC);
 		return true;
 	}
 
@@ -600,7 +609,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_write(uap, uap->im, UART011_IMSC);
 		return true;
 	}
 	return false;
@@ -614,7 +623,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_write(uap, uap->dmacr, UART011_DMACR);
 	}
 }
 
@@ -640,14 +649,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		if (!uap->dmatx.queued) {
 			if (pl011_dma_tx_refill(uap) > 0) {
 				uap->im &= ~UART011_TXIM;
-				writew(uap->im, uap->port.membase +
-				       UART011_IMSC);
+				pl011_write(uap, uap->im, UART011_IMSC);
 			} else
 				ret = false;
 		} else if (!(uap->dmacr & UART011_TXDMAE)) {
 			uap->dmacr |= UART011_TXDMAE;
-			writew(uap->dmacr,
-				       uap->port.membase + UART011_DMACR);
+			pl011_write(uap, uap->dmacr, UART011_DMACR);
 		}
 		return ret;
 	}
@@ -658,9 +665,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_write(uap, uap->dmacr, UART011_DMACR);
 
-	if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) {
+	if (pl011_read(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
@@ -669,13 +676,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_write(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_write(uap, dmacr, UART011_DMACR);
 
 	return true;
 }
@@ -703,7 +710,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_write(uap, uap->dmacr, UART011_DMACR);
 	}
 }
 
@@ -743,11 +750,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_write(uap, uap->dmacr, UART011_DMACR);
 	uap->dmarx.running = true;
 
 	uap->im &= ~UART011_RXIM;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap, uap->im, UART011_IMSC);
 
 	return 0;
 }
@@ -805,8 +812,8 @@ 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_write(uap, UART011_OEIS | UART011_BEIS | UART011_PEIS |
+			    UART011_FEIS, UART011_ICR);
 
 		/*
 		 * If we read all the DMA'd characters, and we had an
@@ -854,7 +861,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_write(uap, uap->dmacr, UART011_DMACR);
 	uap->dmarx.running = false;
 
 	pending = sgbuf->sg.length - state.residue;
@@ -874,7 +881,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_write(uap, uap->im, UART011_IMSC);
 	}
 }
 
@@ -922,7 +929,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_write(uap, uap->im, UART011_IMSC);
 	}
 }
 
@@ -935,7 +942,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_write(uap, uap->dmacr, UART011_DMACR);
 }
 
 /*
@@ -979,7 +986,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_write(uap, uap->im, UART011_IMSC);
 		spin_unlock_irqrestore(&uap->port.lock, flags);
 
 		uap->dmarx.running = false;
@@ -1041,7 +1048,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_write(uap, uap->dmacr, UART011_DMACR);
 
 	/*
 	 * ST Micro variants has some specific dma burst threshold
@@ -1049,8 +1056,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_write(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))
@@ -1075,12 +1083,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_read(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_write(uap, uap->dmacr, UART011_DMACR);
 	spin_unlock_irq(&uap->port.lock);
 
 	if (uap->using_tx_dma) {
@@ -1181,7 +1189,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_write(uap, uap->im, UART011_IMSC);
 	pl011_dma_tx_stop(uap);
 }
 
@@ -1191,7 +1199,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 {
 	uap->im |= UART011_TXIM;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap, uap->im, UART011_IMSC);
 	pl011_tx_chars(uap, false);
 }
 
@@ -1211,7 +1219,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_write(uap, uap->im, UART011_IMSC);
 
 	pl011_dma_rx_stop(uap);
 }
@@ -1222,7 +1230,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_write(uap, uap->im, UART011_IMSC);
 }
 
 static void pl011_rx_chars(struct uart_amba_port *uap)
@@ -1242,7 +1250,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_write(uap, uap->im, UART011_IMSC);
 		} else {
 #ifdef CONFIG_DMA_ENGINE
 			/* Start Rx DMA poll */
@@ -1263,10 +1271,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
 			  bool from_irq)
 {
 	if (unlikely(!from_irq) &&
-	    readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+	    pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		return false; /* unable to transmit character */
 
-	writew(c, uap->port.membase + UART01x_DR);
+	pl011_write(uap, c, UART01x_DR);
 	uap->port.icount.tx++;
 
 	return true;
@@ -1313,7 +1321,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_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
 
 	delta = status ^ uap->old_status;
 	uap->old_status = status;
@@ -1341,15 +1349,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
 		return;
 
 	/* workaround to make sure that all bits are unlocked.. */
-	writew(0x00, uap->port.membase + UART011_ICR);
+	pl011_write(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_read(uap, UART011_ICR);
+	dummy_read = pl011_read(uap, UART011_ICR);
 }
 
 static irqreturn_t pl011_int(int irq, void *dev_id)
@@ -1361,15 +1369,14 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 	int handled = 0;
 
 	spin_lock_irqsave(&uap->port.lock, flags);
-	imsc = readw(uap->port.membase + UART011_IMSC);
-	status = readw(uap->port.membase + UART011_RIS) & imsc;
+	imsc = pl011_read(uap, UART011_IMSC);
+	status = pl011_read(uap, UART011_RIS) & imsc;
 	if (status) {
 		do {
 			check_apply_cts_event_workaround(uap);
 
-			writew(status & ~(UART011_TXIS|UART011_RTIS|
-					  UART011_RXIS),
-			       uap->port.membase + UART011_ICR);
+			pl011_write(uap, status & ~(UART011_TXIS|UART011_RTIS|
+				    UART011_RXIS), UART011_ICR);
 
 			if (status & (UART011_RTIS|UART011_RXIS)) {
 				if (pl011_dma_rx_running(uap))
@@ -1386,7 +1393,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 			if (pass_counter-- == 0)
 				break;
 
-			status = readw(uap->port.membase + UART011_RIS) & imsc;
+			status = pl011_read(uap, UART011_RIS) & imsc;
 		} while (status != 0);
 		handled = 1;
 	}
@@ -1400,7 +1407,7 @@ 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_read(uap, UART01x_FR);
 	return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
 }
 
@@ -1409,7 +1416,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
 	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_read(uap, UART01x_FR);
 
 #define TIOCMBIT(uartbit, tiocmbit)	\
 	if (status & uartbit)		\
@@ -1429,7 +1436,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_read(uap, UART011_CR);
 
 #define	TIOCMBIT(tiocmbit, uartbit)		\
 	if (mctrl & tiocmbit)		\
@@ -1449,7 +1456,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	}
 #undef TIOCMBIT
 
-	writew(cr, uap->port.membase + UART011_CR);
+	pl011_write(uap, cr, UART011_CR);
 }
 
 static void pl011_break_ctl(struct uart_port *port, int break_state)
@@ -1460,12 +1467,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_read(uap, uap->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_write(uap, lcr_h, uap->lcrh_tx);
 	spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
@@ -1477,7 +1484,7 @@ static void pl011_quiesce_irqs(struct uart_port *port)
 	    container_of(port, struct uart_amba_port, port);
 	unsigned char __iomem *regs = uap->port.membase;
 
-	writew(readw(regs + UART011_MIS), regs + UART011_ICR);
+	pl011_write(uap, pl011_read(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.
@@ -1491,7 +1498,7 @@ 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_write(pl011_read(uap, UART011_IMSC) & ~UART011_TXIM, UART011_IMSC);
 }
 
 static int pl011_get_poll_char(struct uart_port *port)
@@ -1506,11 +1513,11 @@ static int pl011_get_poll_char(struct uart_port *port)
 	 */
 	pl011_quiesce_irqs(port);
 
-	status = readw(uap->port.membase + UART01x_FR);
+	status = pl011_read(uap, UART01x_FR);
 	if (status & UART01x_FR_RXFE)
 		return NO_POLL_CHAR;
 
-	return readw(uap->port.membase + UART01x_DR);
+	return pl011_read(uap, UART01x_DR);
 }
 
 static void pl011_put_poll_char(struct uart_port *port,
@@ -1519,10 +1526,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_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
 
-	writew(ch, uap->port.membase + UART01x_DR);
+	pl011_write(uap, ch, UART01x_DR);
 }
 
 #endif /* CONFIG_CONSOLE_POLL */
@@ -1546,15 +1553,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_write(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_read(uap, UART011_IMSC);
+	pl011_write(uap, UART011_RTIM | UART011_RXIM, UART011_IMSC);
 
 	if (dev_get_platdata(uap->port.dev)) {
 		struct amba_pl011_data *plat;
@@ -1568,7 +1576,7 @@ 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);
+	pl011_write(uap, lcr_h, uap->lcrh_rx);
 	if (uap->lcrh_rx != uap->lcrh_tx) {
 		int i;
 		/*
@@ -1576,14 +1584,14 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 		 * 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_write(uap, 0xff, UART011_MIS);
+		pl011_write(uap, lcr_h, uap->lcrh_tx);
 	}
 }
 
 static int pl011_allocate_irq(struct uart_amba_port *uap)
 {
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap, uap->im, UART011_IMSC);
 
 	return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
 }
@@ -1598,12 +1606,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
 	spin_lock_irq(&uap->port.lock);
 
 	/* Clear out any spuriously appearing RX interrupts */
-	writew(UART011_RTIS | UART011_RXIS,
-	       uap->port.membase + UART011_ICR);
+	pl011_write(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_write(uap, uap->im, UART011_IMSC);
 	spin_unlock_irq(&uap->port.lock);
 }
 
@@ -1622,21 +1629,21 @@ static int pl011_startup(struct uart_port *port)
 	if (retval)
 		goto clk_dis;
 
-	writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
+	pl011_write(uap, uap->vendor->ifls, UART011_IFLS);
 
 	spin_lock_irq(&uap->port.lock);
 
 	/* 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_write(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_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
 
 	/* Startup DMA */
 	pl011_dma_startup(uap);
@@ -1675,11 +1682,11 @@ static int sbsa_uart_startup(struct uart_port *port)
 static void pl011_shutdown_channel(struct uart_amba_port *uap,
 					unsigned int lcrh)
 {
-      unsigned long val;
+	unsigned long val;
 
-      val = readw(uap->port.membase + lcrh);
-      val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
-      writew(val, uap->port.membase + lcrh);
+	val = pl011_read(uap, lcrh);
+	val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
+	pl011_write(uap, val, lcrh);
 }
 
 /*
@@ -1693,11 +1700,11 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 
 	uap->autorts = false;
 	spin_lock_irq(&uap->port.lock);
-	cr = readw(uap->port.membase + UART011_CR);
+	cr = pl011_read(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_write(uap, cr, UART011_CR);
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
@@ -1714,8 +1721,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap)
 
 	/* mask all interrupts and clear all pending ones */
 	uap->im = 0;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
-	writew(0xffff, uap->port.membase + UART011_ICR);
+	pl011_write(uap, uap->im, UART011_IMSC);
+	pl011_write(uap, 0xffff, UART011_ICR);
 
 	spin_unlock_irq(&uap->port.lock);
 }
@@ -1867,8 +1874,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_read(uap, UART011_CR);
+	pl011_write(uap, 0, UART011_CR);
 
 	if (termios->c_cflag & CRTSCTS) {
 		if (old_cr & UART011_CR_RTS)
@@ -1901,8 +1908,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_write(uap, quot & 0x3f, UART011_FBRD);
+	pl011_write(uap, quot >> 6, UART011_IBRD);
 
 	/*
 	 * ----------v----------v----------v----------v-----
@@ -1911,7 +1918,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_write(uap, old_cr, UART011_CR);
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -2052,9 +2059,9 @@ 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_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
-	writew(ch, uap->port.membase + UART01x_DR);
+	pl011_write(uap, ch, UART01x_DR);
 }
 
 static void
@@ -2079,10 +2086,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	First save the CR then disable the interrupts
 	 */
 	if (!uap->vendor->always_enabled) {
-		old_cr = readw(uap->port.membase + UART011_CR);
+		old_cr = pl011_read(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_write(uap, new_cr, UART011_CR);
 	}
 
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
@@ -2092,10 +2099,10 @@ 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_read(uap, UART01x_FR);
 	} while (status & UART01x_FR_BUSY);
 	if (!uap->vendor->always_enabled)
-		writew(old_cr, uap->port.membase + UART011_CR);
+		pl011_write(uap, old_cr, UART011_CR);
 
 	if (locked)
 		spin_unlock(&uap->port.lock);
@@ -2108,10 +2115,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_read(uap, UART011_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
 
-		lcr_h = readw(uap->port.membase + uap->lcrh_tx);
+		lcr_h = pl011_read(uap, uap->lcrh_tx);
 
 		*parity = 'n';
 		if (lcr_h & UART01x_LCRH_PEN) {
@@ -2126,13 +2133,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_read(uap, UART011_IBRD);
+		fbrd = pl011_read(uap, UART011_FBRD);
 
 		*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 
 		if (uap->vendor->oversampling) {
-			if (readw(uap->port.membase + UART011_CR)
+			if (pl011_read(uap, UART011_CR)
 				  & ST_UART011_CR_OVSFACT)
 				*baud *= 2;
 		}
@@ -2334,8 +2341,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
 	int ret;
 
 	/* Ensure interrupts from this UART are masked and cleared */
-	writew(0, uap->port.membase + UART011_IMSC);
-	writew(0xffff, uap->port.membase + UART011_ICR);
+	pl011_write(uap, 0, UART011_IMSC);
+	pl011_write(uap, 0xffff, UART011_ICR);
 
 	if (!amba_reg.state) {
 		ret = uart_register_driver(&amba_reg);
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 1/2] drivers: serial: PL011: refactor register access
@ 2015-11-02 12:24   ` Andre Przywara
  0 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-02 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

Currently we call readw/writew directly each time we want to access
a PL011 register.
Wrap these calls in a function to simplify changes later, namely:
* to support UARTs with different register offsets (ZTE)
* to support a different bus access width (16 bits vs. 32 bits)
* to introduce readl_relaxed/writel_relaxed usage

This patch itself does not introduce any functional change.

This is based on code from Jun Nie <jun.nie@linaro.org>.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/tty/serial/amba-pl011.c | 209 +++++++++++++++++++++-------------------
 1 file changed, 108 insertions(+), 101 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index fd27e98..ef5d779 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -184,6 +184,16 @@ struct uart_amba_port {
 #endif
 };
 
+static unsigned int pl011_read(struct uart_amba_port *uap, int offset)
+{
+	return readw(uap->port.membase + offset);
+}
+
+static void pl011_write(struct uart_amba_port *uap, int val, int offset)
+{
+	writew(val, uap->port.membase + offset);
+}
+
 /*
  * 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
@@ -196,13 +206,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_read(uap, UART01x_FR);
 		if (status & UART01x_FR_RXFE)
 			break;
 
 		/* Take chars from the FIFO and update status */
-		ch = readw(uap->port.membase + UART01x_DR) |
-			UART_DUMMY_DR_RX;
+		ch = pl011_read(uap, UART01x_DR) | UART_DUMMY_DR_RX;
 		flag = TTY_NORMAL;
 		uap->port.icount.rx++;
 		fifotaken++;
@@ -438,7 +447,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_write(uap, uap->dmacr, UART011_DMACR);
 
 	/*
 	 * If TX DMA was disabled, it means that we've stopped the DMA for
@@ -552,7 +561,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_write(uap, uap->dmacr, UART011_DMACR);
 	uap->dmatx.queued = true;
 
 	/*
@@ -588,9 +597,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_write(uap, uap->dmacr, UART011_DMACR);
 		uap->im &= ~UART011_TXIM;
-		writew(uap->im, uap->port.membase + UART011_IMSC);
+		pl011_write(uap, uap->im, UART011_IMSC);
 		return true;
 	}
 
@@ -600,7 +609,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_write(uap, uap->im, UART011_IMSC);
 		return true;
 	}
 	return false;
@@ -614,7 +623,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_write(uap, uap->dmacr, UART011_DMACR);
 	}
 }
 
@@ -640,14 +649,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		if (!uap->dmatx.queued) {
 			if (pl011_dma_tx_refill(uap) > 0) {
 				uap->im &= ~UART011_TXIM;
-				writew(uap->im, uap->port.membase +
-				       UART011_IMSC);
+				pl011_write(uap, uap->im, UART011_IMSC);
 			} else
 				ret = false;
 		} else if (!(uap->dmacr & UART011_TXDMAE)) {
 			uap->dmacr |= UART011_TXDMAE;
-			writew(uap->dmacr,
-				       uap->port.membase + UART011_DMACR);
+			pl011_write(uap, uap->dmacr, UART011_DMACR);
 		}
 		return ret;
 	}
@@ -658,9 +665,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_write(uap, uap->dmacr, UART011_DMACR);
 
-	if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) {
+	if (pl011_read(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
@@ -669,13 +676,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_write(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_write(uap, dmacr, UART011_DMACR);
 
 	return true;
 }
@@ -703,7 +710,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_write(uap, uap->dmacr, UART011_DMACR);
 	}
 }
 
@@ -743,11 +750,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_write(uap, uap->dmacr, UART011_DMACR);
 	uap->dmarx.running = true;
 
 	uap->im &= ~UART011_RXIM;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap, uap->im, UART011_IMSC);
 
 	return 0;
 }
@@ -805,8 +812,8 @@ 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_write(uap, UART011_OEIS | UART011_BEIS | UART011_PEIS |
+			    UART011_FEIS, UART011_ICR);
 
 		/*
 		 * If we read all the DMA'd characters, and we had an
@@ -854,7 +861,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_write(uap, uap->dmacr, UART011_DMACR);
 	uap->dmarx.running = false;
 
 	pending = sgbuf->sg.length - state.residue;
@@ -874,7 +881,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_write(uap, uap->im, UART011_IMSC);
 	}
 }
 
@@ -922,7 +929,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_write(uap, uap->im, UART011_IMSC);
 	}
 }
 
@@ -935,7 +942,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_write(uap, uap->dmacr, UART011_DMACR);
 }
 
 /*
@@ -979,7 +986,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_write(uap, uap->im, UART011_IMSC);
 		spin_unlock_irqrestore(&uap->port.lock, flags);
 
 		uap->dmarx.running = false;
@@ -1041,7 +1048,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_write(uap, uap->dmacr, UART011_DMACR);
 
 	/*
 	 * ST Micro variants has some specific dma burst threshold
@@ -1049,8 +1056,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_write(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))
@@ -1075,12 +1083,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_read(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_write(uap, uap->dmacr, UART011_DMACR);
 	spin_unlock_irq(&uap->port.lock);
 
 	if (uap->using_tx_dma) {
@@ -1181,7 +1189,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_write(uap, uap->im, UART011_IMSC);
 	pl011_dma_tx_stop(uap);
 }
 
@@ -1191,7 +1199,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 {
 	uap->im |= UART011_TXIM;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap, uap->im, UART011_IMSC);
 	pl011_tx_chars(uap, false);
 }
 
@@ -1211,7 +1219,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_write(uap, uap->im, UART011_IMSC);
 
 	pl011_dma_rx_stop(uap);
 }
@@ -1222,7 +1230,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_write(uap, uap->im, UART011_IMSC);
 }
 
 static void pl011_rx_chars(struct uart_amba_port *uap)
@@ -1242,7 +1250,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_write(uap, uap->im, UART011_IMSC);
 		} else {
 #ifdef CONFIG_DMA_ENGINE
 			/* Start Rx DMA poll */
@@ -1263,10 +1271,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
 			  bool from_irq)
 {
 	if (unlikely(!from_irq) &&
-	    readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+	    pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		return false; /* unable to transmit character */
 
-	writew(c, uap->port.membase + UART01x_DR);
+	pl011_write(uap, c, UART01x_DR);
 	uap->port.icount.tx++;
 
 	return true;
@@ -1313,7 +1321,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_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
 
 	delta = status ^ uap->old_status;
 	uap->old_status = status;
@@ -1341,15 +1349,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
 		return;
 
 	/* workaround to make sure that all bits are unlocked.. */
-	writew(0x00, uap->port.membase + UART011_ICR);
+	pl011_write(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_read(uap, UART011_ICR);
+	dummy_read = pl011_read(uap, UART011_ICR);
 }
 
 static irqreturn_t pl011_int(int irq, void *dev_id)
@@ -1361,15 +1369,14 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 	int handled = 0;
 
 	spin_lock_irqsave(&uap->port.lock, flags);
-	imsc = readw(uap->port.membase + UART011_IMSC);
-	status = readw(uap->port.membase + UART011_RIS) & imsc;
+	imsc = pl011_read(uap, UART011_IMSC);
+	status = pl011_read(uap, UART011_RIS) & imsc;
 	if (status) {
 		do {
 			check_apply_cts_event_workaround(uap);
 
-			writew(status & ~(UART011_TXIS|UART011_RTIS|
-					  UART011_RXIS),
-			       uap->port.membase + UART011_ICR);
+			pl011_write(uap, status & ~(UART011_TXIS|UART011_RTIS|
+				    UART011_RXIS), UART011_ICR);
 
 			if (status & (UART011_RTIS|UART011_RXIS)) {
 				if (pl011_dma_rx_running(uap))
@@ -1386,7 +1393,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 			if (pass_counter-- == 0)
 				break;
 
-			status = readw(uap->port.membase + UART011_RIS) & imsc;
+			status = pl011_read(uap, UART011_RIS) & imsc;
 		} while (status != 0);
 		handled = 1;
 	}
@@ -1400,7 +1407,7 @@ 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_read(uap, UART01x_FR);
 	return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
 }
 
@@ -1409,7 +1416,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
 	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_read(uap, UART01x_FR);
 
 #define TIOCMBIT(uartbit, tiocmbit)	\
 	if (status & uartbit)		\
@@ -1429,7 +1436,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_read(uap, UART011_CR);
 
 #define	TIOCMBIT(tiocmbit, uartbit)		\
 	if (mctrl & tiocmbit)		\
@@ -1449,7 +1456,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	}
 #undef TIOCMBIT
 
-	writew(cr, uap->port.membase + UART011_CR);
+	pl011_write(uap, cr, UART011_CR);
 }
 
 static void pl011_break_ctl(struct uart_port *port, int break_state)
@@ -1460,12 +1467,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_read(uap, uap->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_write(uap, lcr_h, uap->lcrh_tx);
 	spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
@@ -1477,7 +1484,7 @@ static void pl011_quiesce_irqs(struct uart_port *port)
 	    container_of(port, struct uart_amba_port, port);
 	unsigned char __iomem *regs = uap->port.membase;
 
-	writew(readw(regs + UART011_MIS), regs + UART011_ICR);
+	pl011_write(uap, pl011_read(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.
@@ -1491,7 +1498,7 @@ 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_write(pl011_read(uap, UART011_IMSC) & ~UART011_TXIM, UART011_IMSC);
 }
 
 static int pl011_get_poll_char(struct uart_port *port)
@@ -1506,11 +1513,11 @@ static int pl011_get_poll_char(struct uart_port *port)
 	 */
 	pl011_quiesce_irqs(port);
 
-	status = readw(uap->port.membase + UART01x_FR);
+	status = pl011_read(uap, UART01x_FR);
 	if (status & UART01x_FR_RXFE)
 		return NO_POLL_CHAR;
 
-	return readw(uap->port.membase + UART01x_DR);
+	return pl011_read(uap, UART01x_DR);
 }
 
 static void pl011_put_poll_char(struct uart_port *port,
@@ -1519,10 +1526,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_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
 
-	writew(ch, uap->port.membase + UART01x_DR);
+	pl011_write(uap, ch, UART01x_DR);
 }
 
 #endif /* CONFIG_CONSOLE_POLL */
@@ -1546,15 +1553,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_write(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_read(uap, UART011_IMSC);
+	pl011_write(uap, UART011_RTIM | UART011_RXIM, UART011_IMSC);
 
 	if (dev_get_platdata(uap->port.dev)) {
 		struct amba_pl011_data *plat;
@@ -1568,7 +1576,7 @@ 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);
+	pl011_write(uap, lcr_h, uap->lcrh_rx);
 	if (uap->lcrh_rx != uap->lcrh_tx) {
 		int i;
 		/*
@@ -1576,14 +1584,14 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 		 * 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_write(uap, 0xff, UART011_MIS);
+		pl011_write(uap, lcr_h, uap->lcrh_tx);
 	}
 }
 
 static int pl011_allocate_irq(struct uart_amba_port *uap)
 {
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap, uap->im, UART011_IMSC);
 
 	return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
 }
@@ -1598,12 +1606,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
 	spin_lock_irq(&uap->port.lock);
 
 	/* Clear out any spuriously appearing RX interrupts */
-	writew(UART011_RTIS | UART011_RXIS,
-	       uap->port.membase + UART011_ICR);
+	pl011_write(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_write(uap, uap->im, UART011_IMSC);
 	spin_unlock_irq(&uap->port.lock);
 }
 
@@ -1622,21 +1629,21 @@ static int pl011_startup(struct uart_port *port)
 	if (retval)
 		goto clk_dis;
 
-	writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
+	pl011_write(uap, uap->vendor->ifls, UART011_IFLS);
 
 	spin_lock_irq(&uap->port.lock);
 
 	/* 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_write(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_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
 
 	/* Startup DMA */
 	pl011_dma_startup(uap);
@@ -1675,11 +1682,11 @@ static int sbsa_uart_startup(struct uart_port *port)
 static void pl011_shutdown_channel(struct uart_amba_port *uap,
 					unsigned int lcrh)
 {
-      unsigned long val;
+	unsigned long val;
 
-      val = readw(uap->port.membase + lcrh);
-      val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
-      writew(val, uap->port.membase + lcrh);
+	val = pl011_read(uap, lcrh);
+	val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
+	pl011_write(uap, val, lcrh);
 }
 
 /*
@@ -1693,11 +1700,11 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 
 	uap->autorts = false;
 	spin_lock_irq(&uap->port.lock);
-	cr = readw(uap->port.membase + UART011_CR);
+	cr = pl011_read(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_write(uap, cr, UART011_CR);
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
@@ -1714,8 +1721,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap)
 
 	/* mask all interrupts and clear all pending ones */
 	uap->im = 0;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
-	writew(0xffff, uap->port.membase + UART011_ICR);
+	pl011_write(uap, uap->im, UART011_IMSC);
+	pl011_write(uap, 0xffff, UART011_ICR);
 
 	spin_unlock_irq(&uap->port.lock);
 }
@@ -1867,8 +1874,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_read(uap, UART011_CR);
+	pl011_write(uap, 0, UART011_CR);
 
 	if (termios->c_cflag & CRTSCTS) {
 		if (old_cr & UART011_CR_RTS)
@@ -1901,8 +1908,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_write(uap, quot & 0x3f, UART011_FBRD);
+	pl011_write(uap, quot >> 6, UART011_IBRD);
 
 	/*
 	 * ----------v----------v----------v----------v-----
@@ -1911,7 +1918,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_write(uap, old_cr, UART011_CR);
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -2052,9 +2059,9 @@ 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_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
-	writew(ch, uap->port.membase + UART01x_DR);
+	pl011_write(uap, ch, UART01x_DR);
 }
 
 static void
@@ -2079,10 +2086,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	First save the CR then disable the interrupts
 	 */
 	if (!uap->vendor->always_enabled) {
-		old_cr = readw(uap->port.membase + UART011_CR);
+		old_cr = pl011_read(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_write(uap, new_cr, UART011_CR);
 	}
 
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
@@ -2092,10 +2099,10 @@ 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_read(uap, UART01x_FR);
 	} while (status & UART01x_FR_BUSY);
 	if (!uap->vendor->always_enabled)
-		writew(old_cr, uap->port.membase + UART011_CR);
+		pl011_write(uap, old_cr, UART011_CR);
 
 	if (locked)
 		spin_unlock(&uap->port.lock);
@@ -2108,10 +2115,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_read(uap, UART011_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
 
-		lcr_h = readw(uap->port.membase + uap->lcrh_tx);
+		lcr_h = pl011_read(uap, uap->lcrh_tx);
 
 		*parity = 'n';
 		if (lcr_h & UART01x_LCRH_PEN) {
@@ -2126,13 +2133,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_read(uap, UART011_IBRD);
+		fbrd = pl011_read(uap, UART011_FBRD);
 
 		*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 
 		if (uap->vendor->oversampling) {
-			if (readw(uap->port.membase + UART011_CR)
+			if (pl011_read(uap, UART011_CR)
 				  & ST_UART011_CR_OVSFACT)
 				*baud *= 2;
 		}
@@ -2334,8 +2341,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
 	int ret;
 
 	/* Ensure interrupts from this UART are masked and cleared */
-	writew(0, uap->port.membase + UART011_IMSC);
-	writew(0xffff, uap->port.membase + UART011_ICR);
+	pl011_write(uap, 0, UART011_IMSC);
+	pl011_write(uap, 0xffff, UART011_ICR);
 
 	if (!amba_reg.state) {
 		ret = uart_register_driver(&amba_reg);
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
  2015-11-02 12:24 ` Andre Przywara
@ 2015-11-02 12:24   ` Andre Przywara
  -1 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-02 12:24 UTC (permalink / raw)
  To: Jun Nie, Peter Hurley, Timur Tabi
  Cc: Andrew.Jackson, Russell King, linux-arm-kernel, linux-serial

The ZTE UART looks very much like a PL011, but (among other things)
has its registers at different offsets.
Introduce a translation table which maps PL011 offsets to ZTE specific
offsets and use that when needed.
Additionally guard this translation with a CONFIG_ symbol to avoid
unnecessary churn when one is not in need of the ZTE UART.

This is a DRAFT to sketch a less intrusive approach than the previous
patchsets suggested.
It does not cover the differing flag bits yet and also lacks the whole
probing and wiring-up code.

This is based on code from Jun Nie <jun.nie@linaro.org>.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/tty/serial/amba-pl011.c | 37 +++++++++++++++++++++++++++++++++++++
 include/linux/amba/serial.h     | 10 ++++++++++
 2 files changed, 47 insertions(+)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index ef5d779..e90840b 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -81,6 +81,7 @@ struct vendor_data {
 	bool			cts_event_workaround;
 	bool			always_enabled;
 	bool			fixed_options;
+	int			*reg_table;
 
 	unsigned int (*get_fifosize)(struct amba_device *dev);
 };
@@ -127,6 +128,34 @@ static struct vendor_data vendor_st = {
 	.get_fifosize		= get_fifosize_st,
 };
 
+int reg_table_zte[] = {
+	[UART01x_DR]	= ZX_UART01x_DR,
+	[UART011_LCRH]	= ZX_UART011_LCRH_TX,
+	[UART011_CR]	= ZX_UART011_CR,
+	[UART01x_FR]	= ZX_UART01x_FR,
+	[UART011_ICR]	= ZX_UART011_ICR,
+	[UART011_IBRD]	= UART011_IBRD,
+	[UART011_FBRD]	= UART011_FBRD,
+	[UART011_IFLS]	= ZX_UART011_IFLS,
+	[UART011_IMSC]	= ZX_UART011_IMSC,
+	[UART011_RIS]	= ZX_UART011_RIS,
+	[UART011_MIS]	= ZX_UART011_MIS,
+	[UART011_DMACR]	= ZX_UART011_DMACR,
+};
+
+static struct vendor_data vendor_zte = {
+	.ifls			= UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
+	.lcrh_tx		= UART011_LCRH,
+	.lcrh_rx		= UART011_LCRH,
+	.oversampling		= false,
+	.dma_threshold		= false,
+	.cts_event_workaround	= false,
+	.always_enabled		= false,
+	.fixed_options		= false,
+	.get_fifosize		= get_fifosize_arm,
+	.reg_table		= reg_table_zte,
+};
+
 /* Deals with DMA transactions */
 
 struct pl011_sgbuf {
@@ -186,11 +215,19 @@ struct uart_amba_port {
 
 static unsigned int pl011_read(struct uart_amba_port *uap, int offset)
 {
+#ifdef CONFIG_SOC_ZX296702
+	if (uap->vendor->reg_table)
+		offset = uap->vendor->reg_table[offset];
+#endif
 	return readw(uap->port.membase + offset);
 }
 
 static void pl011_write(struct uart_amba_port *uap, int val, int offset)
 {
+#ifdef CONFIG_SOC_ZX296702
+	if (uap->vendor->reg_table)
+		offset = uap->vendor->reg_table[offset];
+#endif
 	writew(val, uap->port.membase + offset);
 }
 
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
index 0ddb5c0..1c71b83 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -31,6 +31,7 @@
  *  UART Register Offsets.
  */
 #define UART01x_DR		0x00	/* Data read or written from the interface. */
+#define ZX_UART01x_DR		0x04	/* Different offset in the ZTE UART. */
 #define UART01x_RSR		0x04	/* Receive status register (Read). */
 #define UART01x_ECR		0x04	/* Error clear register (Write). */
 #define UART010_LCRH		0x08	/* Line control register, high byte. */
@@ -39,6 +40,7 @@
 #define ST_UART011_TIMEOUT	0x0C    /* Timeout period register. */
 #define UART010_LCRL		0x10	/* Line control register, low byte. */
 #define UART010_CR		0x14	/* Control register. */
+#define ZX_UART01x_FR		0x14	/* Different offset in the ZTE UART. */
 #define UART01x_FR		0x18	/* Flag register (Read only). */
 #define UART010_IIR		0x1C	/* Interrupt identification register (Read). */
 #define UART010_ICR		0x1C	/* Interrupt clear register (Write). */
@@ -48,14 +50,22 @@
 #define UART011_FBRD		0x28	/* Fractional baud rate divisor register. */
 #define UART011_LCRH		0x2c	/* Line control register. */
 #define ST_UART011_LCRH_TX	0x2c    /* Tx Line control register. */
+#define ZX_UART011_LCRH_TX	0x30    /* Different offset in the ZTE UART. */
 #define UART011_CR		0x30	/* Control register. */
 #define UART011_IFLS		0x34	/* Interrupt fifo level select. */
+#define ZX_UART011_CR		0x34	/* Different offset in the ZTE UART. */
+#define ZX_UART011_IFLS		0x38	/* Different offset in the ZTE UART. */
 #define UART011_IMSC		0x38	/* Interrupt mask. */
 #define UART011_RIS		0x3c	/* Raw interrupt status. */
 #define UART011_MIS		0x40	/* Masked interrupt status. */
+#define ZX_UART011_IMSC		0x40	/* Different offset in the ZTE UART. */
 #define UART011_ICR		0x44	/* Interrupt clear register. */
+#define ZX_UART011_RIS		0x44	/* Different offset in the ZTE UART. */
 #define UART011_DMACR		0x48	/* DMA control register. */
+#define ZX_UART011_MIS		0x48	/* Different offset in the ZTE UART. */
+#define ZX_UART011_ICR		0x4c	/* Different offset in the ZTE UART. */
 #define ST_UART011_XFCR		0x50	/* XON/XOFF control register. */
+#define ZX_UART011_DMACR	0x50	/* Different offset in the ZTE UART. */
 #define ST_UART011_XON1		0x54	/* XON1 register. */
 #define ST_UART011_XON2		0x58	/* XON2 register. */
 #define ST_UART011_XOFF1	0x5C	/* XON1 register. */
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
@ 2015-11-02 12:24   ` Andre Przywara
  0 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-02 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

The ZTE UART looks very much like a PL011, but (among other things)
has its registers at different offsets.
Introduce a translation table which maps PL011 offsets to ZTE specific
offsets and use that when needed.
Additionally guard this translation with a CONFIG_ symbol to avoid
unnecessary churn when one is not in need of the ZTE UART.

This is a DRAFT to sketch a less intrusive approach than the previous
patchsets suggested.
It does not cover the differing flag bits yet and also lacks the whole
probing and wiring-up code.

This is based on code from Jun Nie <jun.nie@linaro.org>.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 drivers/tty/serial/amba-pl011.c | 37 +++++++++++++++++++++++++++++++++++++
 include/linux/amba/serial.h     | 10 ++++++++++
 2 files changed, 47 insertions(+)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index ef5d779..e90840b 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -81,6 +81,7 @@ struct vendor_data {
 	bool			cts_event_workaround;
 	bool			always_enabled;
 	bool			fixed_options;
+	int			*reg_table;
 
 	unsigned int (*get_fifosize)(struct amba_device *dev);
 };
@@ -127,6 +128,34 @@ static struct vendor_data vendor_st = {
 	.get_fifosize		= get_fifosize_st,
 };
 
+int reg_table_zte[] = {
+	[UART01x_DR]	= ZX_UART01x_DR,
+	[UART011_LCRH]	= ZX_UART011_LCRH_TX,
+	[UART011_CR]	= ZX_UART011_CR,
+	[UART01x_FR]	= ZX_UART01x_FR,
+	[UART011_ICR]	= ZX_UART011_ICR,
+	[UART011_IBRD]	= UART011_IBRD,
+	[UART011_FBRD]	= UART011_FBRD,
+	[UART011_IFLS]	= ZX_UART011_IFLS,
+	[UART011_IMSC]	= ZX_UART011_IMSC,
+	[UART011_RIS]	= ZX_UART011_RIS,
+	[UART011_MIS]	= ZX_UART011_MIS,
+	[UART011_DMACR]	= ZX_UART011_DMACR,
+};
+
+static struct vendor_data vendor_zte = {
+	.ifls			= UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
+	.lcrh_tx		= UART011_LCRH,
+	.lcrh_rx		= UART011_LCRH,
+	.oversampling		= false,
+	.dma_threshold		= false,
+	.cts_event_workaround	= false,
+	.always_enabled		= false,
+	.fixed_options		= false,
+	.get_fifosize		= get_fifosize_arm,
+	.reg_table		= reg_table_zte,
+};
+
 /* Deals with DMA transactions */
 
 struct pl011_sgbuf {
@@ -186,11 +215,19 @@ struct uart_amba_port {
 
 static unsigned int pl011_read(struct uart_amba_port *uap, int offset)
 {
+#ifdef CONFIG_SOC_ZX296702
+	if (uap->vendor->reg_table)
+		offset = uap->vendor->reg_table[offset];
+#endif
 	return readw(uap->port.membase + offset);
 }
 
 static void pl011_write(struct uart_amba_port *uap, int val, int offset)
 {
+#ifdef CONFIG_SOC_ZX296702
+	if (uap->vendor->reg_table)
+		offset = uap->vendor->reg_table[offset];
+#endif
 	writew(val, uap->port.membase + offset);
 }
 
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
index 0ddb5c0..1c71b83 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -31,6 +31,7 @@
  *  UART Register Offsets.
  */
 #define UART01x_DR		0x00	/* Data read or written from the interface. */
+#define ZX_UART01x_DR		0x04	/* Different offset in the ZTE UART. */
 #define UART01x_RSR		0x04	/* Receive status register (Read). */
 #define UART01x_ECR		0x04	/* Error clear register (Write). */
 #define UART010_LCRH		0x08	/* Line control register, high byte. */
@@ -39,6 +40,7 @@
 #define ST_UART011_TIMEOUT	0x0C    /* Timeout period register. */
 #define UART010_LCRL		0x10	/* Line control register, low byte. */
 #define UART010_CR		0x14	/* Control register. */
+#define ZX_UART01x_FR		0x14	/* Different offset in the ZTE UART. */
 #define UART01x_FR		0x18	/* Flag register (Read only). */
 #define UART010_IIR		0x1C	/* Interrupt identification register (Read). */
 #define UART010_ICR		0x1C	/* Interrupt clear register (Write). */
@@ -48,14 +50,22 @@
 #define UART011_FBRD		0x28	/* Fractional baud rate divisor register. */
 #define UART011_LCRH		0x2c	/* Line control register. */
 #define ST_UART011_LCRH_TX	0x2c    /* Tx Line control register. */
+#define ZX_UART011_LCRH_TX	0x30    /* Different offset in the ZTE UART. */
 #define UART011_CR		0x30	/* Control register. */
 #define UART011_IFLS		0x34	/* Interrupt fifo level select. */
+#define ZX_UART011_CR		0x34	/* Different offset in the ZTE UART. */
+#define ZX_UART011_IFLS		0x38	/* Different offset in the ZTE UART. */
 #define UART011_IMSC		0x38	/* Interrupt mask. */
 #define UART011_RIS		0x3c	/* Raw interrupt status. */
 #define UART011_MIS		0x40	/* Masked interrupt status. */
+#define ZX_UART011_IMSC		0x40	/* Different offset in the ZTE UART. */
 #define UART011_ICR		0x44	/* Interrupt clear register. */
+#define ZX_UART011_RIS		0x44	/* Different offset in the ZTE UART. */
 #define UART011_DMACR		0x48	/* DMA control register. */
+#define ZX_UART011_MIS		0x48	/* Different offset in the ZTE UART. */
+#define ZX_UART011_ICR		0x4c	/* Different offset in the ZTE UART. */
 #define ST_UART011_XFCR		0x50	/* XON/XOFF control register. */
+#define ZX_UART011_DMACR	0x50	/* Different offset in the ZTE UART. */
 #define ST_UART011_XON1		0x54	/* XON1 register. */
 #define ST_UART011_XON2		0x58	/* XON2 register. */
 #define ST_UART011_XOFF1	0x5C	/* XON1 register. */
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* Re: [PATCH DRAFT 1/2] drivers: serial: PL011: refactor register access
  2015-11-02 12:24   ` Andre Przywara
@ 2015-11-02 13:27     ` Timur Tabi
  -1 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-02 13:27 UTC (permalink / raw)
  To: Andre Przywara, Jun Nie, Peter Hurley
  Cc: Andrew.Jackson, Russell King, linux-arm-kernel, linux-serial

Andre Przywara wrote:
> * to support UARTs with different register offsets (ZTE)
> * to support a different bus access width (16 bits vs. 32 bits)

How exactly does this patch provide this?  The code is still calling a 
fixed function.  How will the code dynamically call a 32-bit version 
instead of a 16-bit version on platforms that need it?

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 1/2] drivers: serial: PL011: refactor register access
@ 2015-11-02 13:27     ` Timur Tabi
  0 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-02 13:27 UTC (permalink / raw)
  To: linux-arm-kernel

Andre Przywara wrote:
> * to support UARTs with different register offsets (ZTE)
> * to support a different bus access width (16 bits vs. 32 bits)

How exactly does this patch provide this?  The code is still calling a 
fixed function.  How will the code dynamically call a 32-bit version 
instead of a 16-bit version on platforms that need it?

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH DRAFT 1/2] drivers: serial: PL011: refactor register access
  2015-11-02 13:27     ` Timur Tabi
@ 2015-11-02 13:40       ` Andre Przywara
  -1 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-02 13:40 UTC (permalink / raw)
  To: Timur Tabi, Jun Nie, Peter Hurley
  Cc: Andrew.Jackson, Russell King, linux-arm-kernel, linux-serial

Hi Timur,

On 02/11/15 13:27, Timur Tabi wrote:
> Andre Przywara wrote:
>> * to support UARTs with different register offsets (ZTE)
>> * to support a different bus access width (16 bits vs. 32 bits)
> 
> How exactly does this patch provide this?  The code is still calling a
> fixed function.  How will the code dynamically call a 32-bit version
> instead of a 16-bit version on platforms that need it?

This patch doesn't, I was just enumerating possible extensions which
will become much easier now that we don't have to patch every single
call site for such a change (to give rationale for this refactoring).
Changing the access width is now a simple change in those two functions,
and since you have the struct uart_amba_port available, you can access
any field in there to determine your desired access width.

As it says on the tin: it's a draft. Feel free to extend it to a proper
series ;-)

Cheers,
Andre.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 1/2] drivers: serial: PL011: refactor register access
@ 2015-11-02 13:40       ` Andre Przywara
  0 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-02 13:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Timur,

On 02/11/15 13:27, Timur Tabi wrote:
> Andre Przywara wrote:
>> * to support UARTs with different register offsets (ZTE)
>> * to support a different bus access width (16 bits vs. 32 bits)
> 
> How exactly does this patch provide this?  The code is still calling a
> fixed function.  How will the code dynamically call a 32-bit version
> instead of a 16-bit version on platforms that need it?

This patch doesn't, I was just enumerating possible extensions which
will become much easier now that we don't have to patch every single
call site for such a change (to give rationale for this refactoring).
Changing the access width is now a simple change in those two functions,
and since you have the struct uart_amba_port available, you can access
any field in there to determine your desired access width.

As it says on the tin: it's a draft. Feel free to extend it to a proper
series ;-)

Cheers,
Andre.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH DRAFT 1/2] drivers: serial: PL011: refactor register access
  2015-11-02 13:40       ` Andre Przywara
@ 2015-11-02 13:44         ` Timur Tabi
  -1 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-02 13:44 UTC (permalink / raw)
  To: Andre Przywara, Jun Nie, Peter Hurley
  Cc: Andrew.Jackson, Russell King, linux-arm-kernel, linux-serial

Andre Przywara wrote:
> This patch doesn't, I was just enumerating possible extensions which
> will become much easier now that we don't have to patch every single
> call site for such a change (to give rationale for this refactoring).
> Changing the access width is now a simple change in those two functions,
> and since you have the struct uart_amba_port available, you can access
> any field in there to determine your desired access width.
>
> As it says on the tin: it's a draft. Feel free to extend it to a proper
> series;-)

Actually, we already have a patch that does just that, so I'll post it.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 1/2] drivers: serial: PL011: refactor register access
@ 2015-11-02 13:44         ` Timur Tabi
  0 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-02 13:44 UTC (permalink / raw)
  To: linux-arm-kernel

Andre Przywara wrote:
> This patch doesn't, I was just enumerating possible extensions which
> will become much easier now that we don't have to patch every single
> call site for such a change (to give rationale for this refactoring).
> Changing the access width is now a simple change in those two functions,
> and since you have the struct uart_amba_port available, you can access
> any field in there to determine your desired access width.
>
> As it says on the tin: it's a draft. Feel free to extend it to a proper
> series;-)

Actually, we already have a patch that does just that, so I'll post it.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH DRAFT 0/2] Sketch for ZTE ZX296702 UART integration
  2015-11-02 12:24 ` Andre Przywara
@ 2015-11-03 13:43   ` Russell King - ARM Linux
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 13:43 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Peter Hurley, Andrew.Jackson, Timur Tabi, linux-serial, Jun Nie,
	linux-arm-kernel

NAK for both patches.

I'm not happy with these patches since they totally ignore all the
comments I made during the last rounds of trying to add this.  That
disgusts me.

So, I'm working on a replacement set of patches which does this the
right way, and I'll post them later today or early tomorrow, depending
on when I get them tested on the Versatile / Juno platforms.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 0/2] Sketch for ZTE ZX296702 UART integration
@ 2015-11-03 13:43   ` Russell King - ARM Linux
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

NAK for both patches.

I'm not happy with these patches since they totally ignore all the
comments I made during the last rounds of trying to add this.  That
disgusts me.

So, I'm working on a replacement set of patches which does this the
right way, and I'll post them later today or early tomorrow, depending
on when I get them tested on the Versatile / Juno platforms.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
  2015-11-02 12:24   ` Andre Przywara
@ 2015-11-03 13:46     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 13:46 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Peter Hurley, Andrew.Jackson, Timur Tabi, linux-serial, Jun Nie,
	linux-arm-kernel

On Mon, Nov 02, 2015 at 12:24:02PM +0000, Andre Przywara wrote:
> +int reg_table_zte[] = {
> +	[UART01x_DR]	= ZX_UART01x_DR,

No entry for RSR, so the value will be zero.  That means when we read
the RSR, we'll be reading the register at offset 0.  Maybe that's
intentional, maybe it isn't, but it's totally screwy.

Someone needs to document what the register layout for the ZTE UART
is.  Better still, point to where the spec can be found.

> +	[UART011_LCRH]	= ZX_UART011_LCRH_TX,
> +	[UART011_CR]	= ZX_UART011_CR,
> +	[UART01x_FR]	= ZX_UART01x_FR,
> +	[UART011_ICR]	= ZX_UART011_ICR,
> +	[UART011_IBRD]	= UART011_IBRD,
> +	[UART011_FBRD]	= UART011_FBRD,
> +	[UART011_IFLS]	= ZX_UART011_IFLS,
> +	[UART011_IMSC]	= ZX_UART011_IMSC,
> +	[UART011_RIS]	= ZX_UART011_RIS,
> +	[UART011_MIS]	= ZX_UART011_MIS,
> +	[UART011_DMACR]	= ZX_UART011_DMACR,
> +};
>  static unsigned int pl011_read(struct uart_amba_port *uap, int offset)
>  {
> +#ifdef CONFIG_SOC_ZX296702
> +	if (uap->vendor->reg_table)
> +		offset = uap->vendor->reg_table[offset];
> +#endif
>  	return readw(uap->port.membase + offset);
>  }
>  
>  static void pl011_write(struct uart_amba_port *uap, int val, int offset)
>  {
> +#ifdef CONFIG_SOC_ZX296702
> +	if (uap->vendor->reg_table)
> +		offset = uap->vendor->reg_table[offset];
> +#endif
>  	writew(val, uap->port.membase + offset);
>  }
>  
> diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
> index 0ddb5c0..1c71b83 100644
> --- a/include/linux/amba/serial.h
> +++ b/include/linux/amba/serial.h
> @@ -31,6 +31,7 @@
>   *  UART Register Offsets.
>   */
>  #define UART01x_DR		0x00	/* Data read or written from the interface. */
> +#define ZX_UART01x_DR		0x04	/* Different offset in the ZTE UART. */
>  #define UART01x_RSR		0x04	/* Receive status register (Read). */
>  #define UART01x_ECR		0x04	/* Error clear register (Write). */
>  #define UART010_LCRH		0x08	/* Line control register, high byte. */
> @@ -39,6 +40,7 @@
>  #define ST_UART011_TIMEOUT	0x0C    /* Timeout period register. */
>  #define UART010_LCRL		0x10	/* Line control register, low byte. */
>  #define UART010_CR		0x14	/* Control register. */
> +#define ZX_UART01x_FR		0x14	/* Different offset in the ZTE UART. */
>  #define UART01x_FR		0x18	/* Flag register (Read only). */
>  #define UART010_IIR		0x1C	/* Interrupt identification register (Read). */
>  #define UART010_ICR		0x1C	/* Interrupt clear register (Write). */
> @@ -48,14 +50,22 @@
>  #define UART011_FBRD		0x28	/* Fractional baud rate divisor register. */
>  #define UART011_LCRH		0x2c	/* Line control register. */
>  #define ST_UART011_LCRH_TX	0x2c    /* Tx Line control register. */
> +#define ZX_UART011_LCRH_TX	0x30    /* Different offset in the ZTE UART. */
>  #define UART011_CR		0x30	/* Control register. */
>  #define UART011_IFLS		0x34	/* Interrupt fifo level select. */
> +#define ZX_UART011_CR		0x34	/* Different offset in the ZTE UART. */
> +#define ZX_UART011_IFLS		0x38	/* Different offset in the ZTE UART. */
>  #define UART011_IMSC		0x38	/* Interrupt mask. */
>  #define UART011_RIS		0x3c	/* Raw interrupt status. */
>  #define UART011_MIS		0x40	/* Masked interrupt status. */
> +#define ZX_UART011_IMSC		0x40	/* Different offset in the ZTE UART. */
>  #define UART011_ICR		0x44	/* Interrupt clear register. */
> +#define ZX_UART011_RIS		0x44	/* Different offset in the ZTE UART. */
>  #define UART011_DMACR		0x48	/* DMA control register. */
> +#define ZX_UART011_MIS		0x48	/* Different offset in the ZTE UART. */
> +#define ZX_UART011_ICR		0x4c	/* Different offset in the ZTE UART. */
>  #define ST_UART011_XFCR		0x50	/* XON/XOFF control register. */
> +#define ZX_UART011_DMACR	0x50	/* Different offset in the ZTE UART. */
>  #define ST_UART011_XON1		0x54	/* XON1 register. */
>  #define ST_UART011_XON2		0x58	/* XON2 register. */
>  #define ST_UART011_XOFF1	0x5C	/* XON1 register. */
> -- 
> 2.5.1
> 

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
@ 2015-11-03 13:46     ` Russell King - ARM Linux
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 13:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 02, 2015 at 12:24:02PM +0000, Andre Przywara wrote:
> +int reg_table_zte[] = {
> +	[UART01x_DR]	= ZX_UART01x_DR,

No entry for RSR, so the value will be zero.  That means when we read
the RSR, we'll be reading the register at offset 0.  Maybe that's
intentional, maybe it isn't, but it's totally screwy.

Someone needs to document what the register layout for the ZTE UART
is.  Better still, point to where the spec can be found.

> +	[UART011_LCRH]	= ZX_UART011_LCRH_TX,
> +	[UART011_CR]	= ZX_UART011_CR,
> +	[UART01x_FR]	= ZX_UART01x_FR,
> +	[UART011_ICR]	= ZX_UART011_ICR,
> +	[UART011_IBRD]	= UART011_IBRD,
> +	[UART011_FBRD]	= UART011_FBRD,
> +	[UART011_IFLS]	= ZX_UART011_IFLS,
> +	[UART011_IMSC]	= ZX_UART011_IMSC,
> +	[UART011_RIS]	= ZX_UART011_RIS,
> +	[UART011_MIS]	= ZX_UART011_MIS,
> +	[UART011_DMACR]	= ZX_UART011_DMACR,
> +};
>  static unsigned int pl011_read(struct uart_amba_port *uap, int offset)
>  {
> +#ifdef CONFIG_SOC_ZX296702
> +	if (uap->vendor->reg_table)
> +		offset = uap->vendor->reg_table[offset];
> +#endif
>  	return readw(uap->port.membase + offset);
>  }
>  
>  static void pl011_write(struct uart_amba_port *uap, int val, int offset)
>  {
> +#ifdef CONFIG_SOC_ZX296702
> +	if (uap->vendor->reg_table)
> +		offset = uap->vendor->reg_table[offset];
> +#endif
>  	writew(val, uap->port.membase + offset);
>  }
>  
> diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
> index 0ddb5c0..1c71b83 100644
> --- a/include/linux/amba/serial.h
> +++ b/include/linux/amba/serial.h
> @@ -31,6 +31,7 @@
>   *  UART Register Offsets.
>   */
>  #define UART01x_DR		0x00	/* Data read or written from the interface. */
> +#define ZX_UART01x_DR		0x04	/* Different offset in the ZTE UART. */
>  #define UART01x_RSR		0x04	/* Receive status register (Read). */
>  #define UART01x_ECR		0x04	/* Error clear register (Write). */
>  #define UART010_LCRH		0x08	/* Line control register, high byte. */
> @@ -39,6 +40,7 @@
>  #define ST_UART011_TIMEOUT	0x0C    /* Timeout period register. */
>  #define UART010_LCRL		0x10	/* Line control register, low byte. */
>  #define UART010_CR		0x14	/* Control register. */
> +#define ZX_UART01x_FR		0x14	/* Different offset in the ZTE UART. */
>  #define UART01x_FR		0x18	/* Flag register (Read only). */
>  #define UART010_IIR		0x1C	/* Interrupt identification register (Read). */
>  #define UART010_ICR		0x1C	/* Interrupt clear register (Write). */
> @@ -48,14 +50,22 @@
>  #define UART011_FBRD		0x28	/* Fractional baud rate divisor register. */
>  #define UART011_LCRH		0x2c	/* Line control register. */
>  #define ST_UART011_LCRH_TX	0x2c    /* Tx Line control register. */
> +#define ZX_UART011_LCRH_TX	0x30    /* Different offset in the ZTE UART. */
>  #define UART011_CR		0x30	/* Control register. */
>  #define UART011_IFLS		0x34	/* Interrupt fifo level select. */
> +#define ZX_UART011_CR		0x34	/* Different offset in the ZTE UART. */
> +#define ZX_UART011_IFLS		0x38	/* Different offset in the ZTE UART. */
>  #define UART011_IMSC		0x38	/* Interrupt mask. */
>  #define UART011_RIS		0x3c	/* Raw interrupt status. */
>  #define UART011_MIS		0x40	/* Masked interrupt status. */
> +#define ZX_UART011_IMSC		0x40	/* Different offset in the ZTE UART. */
>  #define UART011_ICR		0x44	/* Interrupt clear register. */
> +#define ZX_UART011_RIS		0x44	/* Different offset in the ZTE UART. */
>  #define UART011_DMACR		0x48	/* DMA control register. */
> +#define ZX_UART011_MIS		0x48	/* Different offset in the ZTE UART. */
> +#define ZX_UART011_ICR		0x4c	/* Different offset in the ZTE UART. */
>  #define ST_UART011_XFCR		0x50	/* XON/XOFF control register. */
> +#define ZX_UART011_DMACR	0x50	/* Different offset in the ZTE UART. */
>  #define ST_UART011_XON1		0x54	/* XON1 register. */
>  #define ST_UART011_XON2		0x58	/* XON2 register. */
>  #define ST_UART011_XOFF1	0x5C	/* XON1 register. */
> -- 
> 2.5.1
> 

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
  2015-11-03 13:46     ` Russell King - ARM Linux
@ 2015-11-03 13:57       ` Andre Przywara
  -1 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-03 13:57 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Peter Hurley, Andrew.Jackson, Timur Tabi, linux-serial, Jun Nie,
	linux-arm-kernel

Hi Russell,

On 03/11/15 13:46, Russell King - ARM Linux wrote:
> On Mon, Nov 02, 2015 at 12:24:02PM +0000, Andre Przywara wrote:
>> +int reg_table_zte[] = {
>> +	[UART01x_DR]	= ZX_UART01x_DR,
> 
> No entry for RSR, so the value will be zero.  That means when we read
> the RSR, we'll be reading the register at offset 0.  Maybe that's
> intentional, maybe it isn't, but it's totally screwy.

Well, as the subject says: it's a draft. And I scanned the file to see
which registers are actually accessed and only entered those into the
array. RSR is not among them. But I agree that we should eventually
enter identity mappings for all PL011 registers in existence to cover
future extensions to the driver. If there would be a clever way to
differentiate uninitialised entries from "0" we could fall back to
identify mapping upon detecting an unused index and only have the
differing registers in the code.

Cheers,
Andre.

> Someone needs to document what the register layout for the ZTE UART
> is.  Better still, point to where the spec can be found.
> 
>> +	[UART011_LCRH]	= ZX_UART011_LCRH_TX,
>> +	[UART011_CR]	= ZX_UART011_CR,
>> +	[UART01x_FR]	= ZX_UART01x_FR,
>> +	[UART011_ICR]	= ZX_UART011_ICR,
>> +	[UART011_IBRD]	= UART011_IBRD,
>> +	[UART011_FBRD]	= UART011_FBRD,
>> +	[UART011_IFLS]	= ZX_UART011_IFLS,
>> +	[UART011_IMSC]	= ZX_UART011_IMSC,
>> +	[UART011_RIS]	= ZX_UART011_RIS,
>> +	[UART011_MIS]	= ZX_UART011_MIS,
>> +	[UART011_DMACR]	= ZX_UART011_DMACR,
>> +};
>>  static unsigned int pl011_read(struct uart_amba_port *uap, int offset)
>>  {
>> +#ifdef CONFIG_SOC_ZX296702
>> +	if (uap->vendor->reg_table)
>> +		offset = uap->vendor->reg_table[offset];
>> +#endif
>>  	return readw(uap->port.membase + offset);
>>  }
>>  
>>  static void pl011_write(struct uart_amba_port *uap, int val, int offset)
>>  {
>> +#ifdef CONFIG_SOC_ZX296702
>> +	if (uap->vendor->reg_table)
>> +		offset = uap->vendor->reg_table[offset];
>> +#endif
>>  	writew(val, uap->port.membase + offset);
>>  }
>>  
>> diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
>> index 0ddb5c0..1c71b83 100644
>> --- a/include/linux/amba/serial.h
>> +++ b/include/linux/amba/serial.h
>> @@ -31,6 +31,7 @@
>>   *  UART Register Offsets.
>>   */
>>  #define UART01x_DR		0x00	/* Data read or written from the interface. */
>> +#define ZX_UART01x_DR		0x04	/* Different offset in the ZTE UART. */
>>  #define UART01x_RSR		0x04	/* Receive status register (Read). */
>>  #define UART01x_ECR		0x04	/* Error clear register (Write). */
>>  #define UART010_LCRH		0x08	/* Line control register, high byte. */
>> @@ -39,6 +40,7 @@
>>  #define ST_UART011_TIMEOUT	0x0C    /* Timeout period register. */
>>  #define UART010_LCRL		0x10	/* Line control register, low byte. */
>>  #define UART010_CR		0x14	/* Control register. */
>> +#define ZX_UART01x_FR		0x14	/* Different offset in the ZTE UART. */
>>  #define UART01x_FR		0x18	/* Flag register (Read only). */
>>  #define UART010_IIR		0x1C	/* Interrupt identification register (Read). */
>>  #define UART010_ICR		0x1C	/* Interrupt clear register (Write). */
>> @@ -48,14 +50,22 @@
>>  #define UART011_FBRD		0x28	/* Fractional baud rate divisor register. */
>>  #define UART011_LCRH		0x2c	/* Line control register. */
>>  #define ST_UART011_LCRH_TX	0x2c    /* Tx Line control register. */
>> +#define ZX_UART011_LCRH_TX	0x30    /* Different offset in the ZTE UART. */
>>  #define UART011_CR		0x30	/* Control register. */
>>  #define UART011_IFLS		0x34	/* Interrupt fifo level select. */
>> +#define ZX_UART011_CR		0x34	/* Different offset in the ZTE UART. */
>> +#define ZX_UART011_IFLS		0x38	/* Different offset in the ZTE UART. */
>>  #define UART011_IMSC		0x38	/* Interrupt mask. */
>>  #define UART011_RIS		0x3c	/* Raw interrupt status. */
>>  #define UART011_MIS		0x40	/* Masked interrupt status. */
>> +#define ZX_UART011_IMSC		0x40	/* Different offset in the ZTE UART. */
>>  #define UART011_ICR		0x44	/* Interrupt clear register. */
>> +#define ZX_UART011_RIS		0x44	/* Different offset in the ZTE UART. */
>>  #define UART011_DMACR		0x48	/* DMA control register. */
>> +#define ZX_UART011_MIS		0x48	/* Different offset in the ZTE UART. */
>> +#define ZX_UART011_ICR		0x4c	/* Different offset in the ZTE UART. */
>>  #define ST_UART011_XFCR		0x50	/* XON/XOFF control register. */
>> +#define ZX_UART011_DMACR	0x50	/* Different offset in the ZTE UART. */
>>  #define ST_UART011_XON1		0x54	/* XON1 register. */
>>  #define ST_UART011_XON2		0x58	/* XON2 register. */
>>  #define ST_UART011_XOFF1	0x5C	/* XON1 register. */
>> -- 
>> 2.5.1
>>
> 

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
@ 2015-11-03 13:57       ` Andre Przywara
  0 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-03 13:57 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

On 03/11/15 13:46, Russell King - ARM Linux wrote:
> On Mon, Nov 02, 2015 at 12:24:02PM +0000, Andre Przywara wrote:
>> +int reg_table_zte[] = {
>> +	[UART01x_DR]	= ZX_UART01x_DR,
> 
> No entry for RSR, so the value will be zero.  That means when we read
> the RSR, we'll be reading the register at offset 0.  Maybe that's
> intentional, maybe it isn't, but it's totally screwy.

Well, as the subject says: it's a draft. And I scanned the file to see
which registers are actually accessed and only entered those into the
array. RSR is not among them. But I agree that we should eventually
enter identity mappings for all PL011 registers in existence to cover
future extensions to the driver. If there would be a clever way to
differentiate uninitialised entries from "0" we could fall back to
identify mapping upon detecting an unused index and only have the
differing registers in the code.

Cheers,
Andre.

> Someone needs to document what the register layout for the ZTE UART
> is.  Better still, point to where the spec can be found.
> 
>> +	[UART011_LCRH]	= ZX_UART011_LCRH_TX,
>> +	[UART011_CR]	= ZX_UART011_CR,
>> +	[UART01x_FR]	= ZX_UART01x_FR,
>> +	[UART011_ICR]	= ZX_UART011_ICR,
>> +	[UART011_IBRD]	= UART011_IBRD,
>> +	[UART011_FBRD]	= UART011_FBRD,
>> +	[UART011_IFLS]	= ZX_UART011_IFLS,
>> +	[UART011_IMSC]	= ZX_UART011_IMSC,
>> +	[UART011_RIS]	= ZX_UART011_RIS,
>> +	[UART011_MIS]	= ZX_UART011_MIS,
>> +	[UART011_DMACR]	= ZX_UART011_DMACR,
>> +};
>>  static unsigned int pl011_read(struct uart_amba_port *uap, int offset)
>>  {
>> +#ifdef CONFIG_SOC_ZX296702
>> +	if (uap->vendor->reg_table)
>> +		offset = uap->vendor->reg_table[offset];
>> +#endif
>>  	return readw(uap->port.membase + offset);
>>  }
>>  
>>  static void pl011_write(struct uart_amba_port *uap, int val, int offset)
>>  {
>> +#ifdef CONFIG_SOC_ZX296702
>> +	if (uap->vendor->reg_table)
>> +		offset = uap->vendor->reg_table[offset];
>> +#endif
>>  	writew(val, uap->port.membase + offset);
>>  }
>>  
>> diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
>> index 0ddb5c0..1c71b83 100644
>> --- a/include/linux/amba/serial.h
>> +++ b/include/linux/amba/serial.h
>> @@ -31,6 +31,7 @@
>>   *  UART Register Offsets.
>>   */
>>  #define UART01x_DR		0x00	/* Data read or written from the interface. */
>> +#define ZX_UART01x_DR		0x04	/* Different offset in the ZTE UART. */
>>  #define UART01x_RSR		0x04	/* Receive status register (Read). */
>>  #define UART01x_ECR		0x04	/* Error clear register (Write). */
>>  #define UART010_LCRH		0x08	/* Line control register, high byte. */
>> @@ -39,6 +40,7 @@
>>  #define ST_UART011_TIMEOUT	0x0C    /* Timeout period register. */
>>  #define UART010_LCRL		0x10	/* Line control register, low byte. */
>>  #define UART010_CR		0x14	/* Control register. */
>> +#define ZX_UART01x_FR		0x14	/* Different offset in the ZTE UART. */
>>  #define UART01x_FR		0x18	/* Flag register (Read only). */
>>  #define UART010_IIR		0x1C	/* Interrupt identification register (Read). */
>>  #define UART010_ICR		0x1C	/* Interrupt clear register (Write). */
>> @@ -48,14 +50,22 @@
>>  #define UART011_FBRD		0x28	/* Fractional baud rate divisor register. */
>>  #define UART011_LCRH		0x2c	/* Line control register. */
>>  #define ST_UART011_LCRH_TX	0x2c    /* Tx Line control register. */
>> +#define ZX_UART011_LCRH_TX	0x30    /* Different offset in the ZTE UART. */
>>  #define UART011_CR		0x30	/* Control register. */
>>  #define UART011_IFLS		0x34	/* Interrupt fifo level select. */
>> +#define ZX_UART011_CR		0x34	/* Different offset in the ZTE UART. */
>> +#define ZX_UART011_IFLS		0x38	/* Different offset in the ZTE UART. */
>>  #define UART011_IMSC		0x38	/* Interrupt mask. */
>>  #define UART011_RIS		0x3c	/* Raw interrupt status. */
>>  #define UART011_MIS		0x40	/* Masked interrupt status. */
>> +#define ZX_UART011_IMSC		0x40	/* Different offset in the ZTE UART. */
>>  #define UART011_ICR		0x44	/* Interrupt clear register. */
>> +#define ZX_UART011_RIS		0x44	/* Different offset in the ZTE UART. */
>>  #define UART011_DMACR		0x48	/* DMA control register. */
>> +#define ZX_UART011_MIS		0x48	/* Different offset in the ZTE UART. */
>> +#define ZX_UART011_ICR		0x4c	/* Different offset in the ZTE UART. */
>>  #define ST_UART011_XFCR		0x50	/* XON/XOFF control register. */
>> +#define ZX_UART011_DMACR	0x50	/* Different offset in the ZTE UART. */
>>  #define ST_UART011_XON1		0x54	/* XON1 register. */
>>  #define ST_UART011_XON2		0x58	/* XON2 register. */
>>  #define ST_UART011_XOFF1	0x5C	/* XON1 register. */
>> -- 
>> 2.5.1
>>
> 

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
  2015-11-02 12:24   ` Andre Przywara
@ 2015-11-03 14:23     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 14:23 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Peter Hurley, Andrew.Jackson, Timur Tabi, linux-serial, Jun Nie,
	linux-arm-kernel

On Mon, Nov 02, 2015 at 12:24:02PM +0000, Andre Przywara wrote:
> +static struct vendor_data vendor_zte = {

This is unreferenced.  What's the detection mechanism for the ZTE UART?
This is the last piece of information I need to finish my set of patches.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
@ 2015-11-03 14:23     ` Russell King - ARM Linux
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 14:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 02, 2015 at 12:24:02PM +0000, Andre Przywara wrote:
> +static struct vendor_data vendor_zte = {

This is unreferenced.  What's the detection mechanism for the ZTE UART?
This is the last piece of information I need to finish my set of patches.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
  2015-11-03 14:23     ` Russell King - ARM Linux
@ 2015-11-03 14:30       ` Andre Przywara
  -1 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-03 14:30 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Peter Hurley, Andrew.Jackson, Timur Tabi, linux-serial, Jun Nie,
	linux-arm-kernel

Hi,

On 03/11/15 14:23, Russell King - ARM Linux wrote:
> On Mon, Nov 02, 2015 at 12:24:02PM +0000, Andre Przywara wrote:
>> +static struct vendor_data vendor_zte = {
> 
> This is unreferenced.  What's the detection mechanism for the ZTE UART?

Guess why I didn't include this ;-)

If I get [1] correctly, then it's a "zte,zx296702-uart" compatible
string for a starter (but no AMBA IDs, if I am not mistaken). I'd let
them fill in other ways of detection like ACPI.

Cheers,
Andre.

[1] http://marc.info/?l=linux-serial&m=143832902328904&w=2

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
@ 2015-11-03 14:30       ` Andre Przywara
  0 siblings, 0 replies; 72+ messages in thread
From: Andre Przywara @ 2015-11-03 14:30 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/11/15 14:23, Russell King - ARM Linux wrote:
> On Mon, Nov 02, 2015 at 12:24:02PM +0000, Andre Przywara wrote:
>> +static struct vendor_data vendor_zte = {
> 
> This is unreferenced.  What's the detection mechanism for the ZTE UART?

Guess why I didn't include this ;-)

If I get [1] correctly, then it's a "zte,zx296702-uart" compatible
string for a starter (but no AMBA IDs, if I am not mistaken). I'd let
them fill in other ways of detection like ACPI.

Cheers,
Andre.

[1] http://marc.info/?l=linux-serial&m=143832902328904&w=2

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH DRAFT 0/2] Sketch for ZTE ZX296702 UART integration
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:48     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 14:48 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Peter Hurley, Andrew.Jackson, Timur Tabi, linux-serial, Jun Nie,
	linux-arm-kernel

On Tue, Nov 03, 2015 at 01:43:49PM +0000, Russell King - ARM Linux wrote:
> So, I'm working on a replacement set of patches which does this the
> right way, and I'll post them later today or early tomorrow, depending
> on when I get them tested on the Versatile / Juno platforms.

Here's my version of the changes required, following the ideas I've put
forward in previous threads.  Build tested, but not boot tested yet.
They're queued for my nightly build and boot test this evening.

The final patch in the series is experimental as it's missing the
detection to make use of the ZTE UART bits.  Also, I'm debating whether
we should make that conditional on a config symbol so that non-ZTE
platforms don't have to suffer the consequences of the conditional 32-bit
accessor.

 drivers/tty/serial/amba-pl011.c | 341 ++++++++++++++++++++++++++--------------
 drivers/tty/serial/amba-pl011.h |  34 ++++
 include/linux/amba/serial.h     |  18 +++
 3 files changed, 272 insertions(+), 121 deletions(-)

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 0/2] Sketch for ZTE ZX296702 UART integration
@ 2015-11-03 14:48     ` Russell King - ARM Linux
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 14:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 03, 2015 at 01:43:49PM +0000, Russell King - ARM Linux wrote:
> So, I'm working on a replacement set of patches which does this the
> right way, and I'll post them later today or early tomorrow, depending
> on when I get them tested on the Versatile / Juno platforms.

Here's my version of the changes required, following the ideas I've put
forward in previous threads.  Build tested, but not boot tested yet.
They're queued for my nightly build and boot test this evening.

The final patch in the series is experimental as it's missing the
detection to make use of the ZTE UART bits.  Also, I'm debating whether
we should make that conditional on a config symbol so that non-ZTE
platforms don't have to suffer the consequences of the conditional 32-bit
accessor.

 drivers/tty/serial/amba-pl011.c | 341 ++++++++++++++++++++++++++--------------
 drivers/tty/serial/amba-pl011.h |  34 ++++
 include/linux/amba/serial.h     |  18 +++
 3 files changed, 272 insertions(+), 121 deletions(-)

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 01/11] tty: amba-pl011: add register accessor functions
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:50     ` Russell King
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:50 UTC (permalink / raw)
  To: linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Add register accessor functions to amba-pl011.  Much of this
transformation was done using the sed expression below, with any
left-overs fixed up manually afterwards, and code formatted to remain
within coding style.

s/readw(\(uap->port.membase\|regs\|port->membase\) +/pl011_read(\1,/g
s/writew(\(.*\) +/pl011_write(\1,/g

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 210 +++++++++++++++++++++-------------------
 1 file changed, 112 insertions(+), 98 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index fd27e986b1dd..b75f750b27ff 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -184,6 +184,16 @@ struct uart_amba_port {
 #endif
 };
 
+static unsigned int pl011_read(void __iomem *base, unsigned int reg)
+{
+	return readw(base + reg);
+}
+
+static void pl011_write(unsigned int val, void __iomem *base, unsigned int reg)
+{
+	writew(val, base + reg);
+}
+
 /*
  * 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
@@ -196,12 +206,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_read(uap->port.membase, 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_read(uap->port.membase, UART01x_DR) |
 			UART_DUMMY_DR_RX;
 		flag = TTY_NORMAL;
 		uap->port.icount.rx++;
@@ -438,7 +448,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 
 	/*
 	 * If TX DMA was disabled, it means that we've stopped the DMA for
@@ -552,7 +562,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	uap->dmatx.queued = true;
 
 	/*
@@ -588,9 +598,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 		uap->im &= ~UART011_TXIM;
-		writew(uap->im, uap->port.membase + UART011_IMSC);
+		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
 		return true;
 	}
 
@@ -600,7 +610,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_write(uap->im, uap->port.membase, UART011_IMSC);
 		return true;
 	}
 	return false;
@@ -614,7 +624,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	}
 }
 
@@ -640,14 +650,14 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		if (!uap->dmatx.queued) {
 			if (pl011_dma_tx_refill(uap) > 0) {
 				uap->im &= ~UART011_TXIM;
-				writew(uap->im, uap->port.membase +
-				       UART011_IMSC);
+				pl011_write(uap->im, uap->port.membase,
+					    UART011_IMSC);
 			} else
 				ret = false;
 		} else if (!(uap->dmacr & UART011_TXDMAE)) {
 			uap->dmacr |= UART011_TXDMAE;
-			writew(uap->dmacr,
-				       uap->port.membase + UART011_DMACR);
+			pl011_write(uap->dmacr, uap->port.membase,
+				    UART011_DMACR);
 		}
 		return ret;
 	}
@@ -658,9 +668,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 
-	if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) {
+	if (pl011_read(uap->port.membase, 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
@@ -669,13 +679,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_write(uap->port.x_char, uap->port.membase, 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_write(dmacr, uap->port.membase, UART011_DMACR);
 
 	return true;
 }
@@ -703,7 +713,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	}
 }
 
@@ -743,11 +753,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	uap->dmarx.running = true;
 
 	uap->im &= ~UART011_RXIM;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
 
 	return 0;
 }
@@ -805,8 +815,8 @@ 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_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
+			    UART011_FEIS, uap->port.membase, UART011_ICR);
 
 		/*
 		 * If we read all the DMA'd characters, and we had an
@@ -854,7 +864,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	uap->dmarx.running = false;
 
 	pending = sgbuf->sg.length - state.residue;
@@ -874,7 +884,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_write(uap->im, uap->port.membase, UART011_IMSC);
 	}
 }
 
@@ -922,7 +932,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_write(uap->im, uap->port.membase, UART011_IMSC);
 	}
 }
 
@@ -935,7 +945,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 }
 
 /*
@@ -979,7 +989,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_write(uap->im, uap->port.membase, UART011_IMSC);
 		spin_unlock_irqrestore(&uap->port.lock, flags);
 
 		uap->dmarx.running = false;
@@ -1041,7 +1051,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 
 	/*
 	 * ST Micro variants has some specific dma burst threshold
@@ -1049,8 +1059,8 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 	 * 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_write(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
+			    uap->port.membase, ST_UART011_DMAWM);
 
 	if (uap->using_rx_dma) {
 		if (pl011_dma_rx_trigger_dma(uap))
@@ -1075,12 +1085,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_read(uap->port.membase, 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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	spin_unlock_irq(&uap->port.lock);
 
 	if (uap->using_tx_dma) {
@@ -1181,7 +1191,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_write(uap->im, uap->port.membase, UART011_IMSC);
 	pl011_dma_tx_stop(uap);
 }
 
@@ -1191,7 +1201,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 {
 	uap->im |= UART011_TXIM;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
 	pl011_tx_chars(uap, false);
 }
 
@@ -1211,7 +1221,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_write(uap->im, uap->port.membase, UART011_IMSC);
 
 	pl011_dma_rx_stop(uap);
 }
@@ -1222,7 +1232,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_write(uap->im, uap->port.membase, UART011_IMSC);
 }
 
 static void pl011_rx_chars(struct uart_amba_port *uap)
@@ -1242,7 +1252,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_write(uap->im, uap->port.membase, UART011_IMSC);
 		} else {
 #ifdef CONFIG_DMA_ENGINE
 			/* Start Rx DMA poll */
@@ -1263,10 +1273,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
 			  bool from_irq)
 {
 	if (unlikely(!from_irq) &&
-	    readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+	    pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
 		return false; /* unable to transmit character */
 
-	writew(c, uap->port.membase + UART01x_DR);
+	pl011_write(c, uap->port.membase, UART01x_DR);
 	uap->port.icount.tx++;
 
 	return true;
@@ -1313,7 +1323,8 @@ 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_read(uap->port.membase, UART01x_FR);
+	status &= UART01x_FR_MODEM_ANY;
 
 	delta = status ^ uap->old_status;
 	uap->old_status = status;
@@ -1341,15 +1352,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
 		return;
 
 	/* workaround to make sure that all bits are unlocked.. */
-	writew(0x00, uap->port.membase + UART011_ICR);
+	pl011_write(0x00, uap->port.membase, 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_read(uap->port.membase, UART011_ICR);
+	dummy_read = pl011_read(uap->port.membase, UART011_ICR);
 }
 
 static irqreturn_t pl011_int(int irq, void *dev_id)
@@ -1361,15 +1372,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 	int handled = 0;
 
 	spin_lock_irqsave(&uap->port.lock, flags);
-	imsc = readw(uap->port.membase + UART011_IMSC);
-	status = readw(uap->port.membase + UART011_RIS) & imsc;
+	imsc = pl011_read(uap->port.membase, UART011_IMSC);
+	status = pl011_read(uap->port.membase, UART011_RIS) & imsc;
 	if (status) {
 		do {
 			check_apply_cts_event_workaround(uap);
 
-			writew(status & ~(UART011_TXIS|UART011_RTIS|
-					  UART011_RXIS),
-			       uap->port.membase + UART011_ICR);
+			pl011_write(status & ~(UART011_TXIS|UART011_RTIS|
+					       UART011_RXIS),
+				    uap->port.membase, UART011_ICR);
 
 			if (status & (UART011_RTIS|UART011_RXIS)) {
 				if (pl011_dma_rx_running(uap))
@@ -1386,7 +1397,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 			if (pass_counter-- == 0)
 				break;
 
-			status = readw(uap->port.membase + UART011_RIS) & imsc;
+			status = pl011_read(uap->port.membase, UART011_RIS) & imsc;
 		} while (status != 0);
 		handled = 1;
 	}
@@ -1400,7 +1411,7 @@ 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_read(uap->port.membase, UART01x_FR);
 	return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
 }
 
@@ -1409,7 +1420,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
 	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_read(uap->port.membase, UART01x_FR);
 
 #define TIOCMBIT(uartbit, tiocmbit)	\
 	if (status & uartbit)		\
@@ -1429,7 +1440,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_read(uap->port.membase, UART011_CR);
 
 #define	TIOCMBIT(tiocmbit, uartbit)		\
 	if (mctrl & tiocmbit)		\
@@ -1449,7 +1460,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	}
 #undef TIOCMBIT
 
-	writew(cr, uap->port.membase + UART011_CR);
+	pl011_write(cr, uap->port.membase, UART011_CR);
 }
 
 static void pl011_break_ctl(struct uart_port *port, int break_state)
@@ -1460,12 +1471,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_read(uap->port.membase, uap->lcrh_tx);
 	if (break_state == -1)
 		lcr_h |= UART01x_LCRH_BRK;
 	else
 		lcr_h &= ~UART01x_LCRH_BRK;
-	writew(lcr_h, uap->port.membase + uap->lcrh_tx);
+	pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx);
 	spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
@@ -1477,7 +1488,7 @@ static void pl011_quiesce_irqs(struct uart_port *port)
 	    container_of(port, struct uart_amba_port, port);
 	unsigned char __iomem *regs = uap->port.membase;
 
-	writew(readw(regs + UART011_MIS), regs + UART011_ICR);
+	pl011_write(pl011_read(regs, UART011_MIS), regs, 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.
@@ -1491,7 +1502,8 @@ 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_write(pl011_read(regs, UART011_IMSC) & ~UART011_TXIM,
+		    regs, UART011_IMSC);
 }
 
 static int pl011_get_poll_char(struct uart_port *port)
@@ -1506,11 +1518,11 @@ static int pl011_get_poll_char(struct uart_port *port)
 	 */
 	pl011_quiesce_irqs(port);
 
-	status = readw(uap->port.membase + UART01x_FR);
+	status = pl011_read(uap->port.membase, UART01x_FR);
 	if (status & UART01x_FR_RXFE)
 		return NO_POLL_CHAR;
 
-	return readw(uap->port.membase + UART01x_DR);
+	return pl011_read(uap->port.membase, UART01x_DR);
 }
 
 static void pl011_put_poll_char(struct uart_port *port,
@@ -1519,10 +1531,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_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
 
-	writew(ch, uap->port.membase + UART01x_DR);
+	pl011_write(ch, uap->port.membase, UART01x_DR);
 }
 
 #endif /* CONFIG_CONSOLE_POLL */
@@ -1546,15 +1558,17 @@ 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_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
+		    UART011_FEIS | UART011_RTIS | UART011_RXIS,
+		    uap->port.membase, 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_read(uap->port.membase, UART011_IMSC);
+	pl011_write(UART011_RTIM | UART011_RXIM, uap->port.membase,
+		    UART011_IMSC);
 
 	if (dev_get_platdata(uap->port.dev)) {
 		struct amba_pl011_data *plat;
@@ -1568,7 +1582,7 @@ 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);
+	pl011_write(lcr_h, uap->port.membase, uap->lcrh_rx);
 	if (uap->lcrh_rx != uap->lcrh_tx) {
 		int i;
 		/*
@@ -1576,14 +1590,14 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 		 * 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_write(0xff, uap->port.membase, UART011_MIS);
+		pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx);
 	}
 }
 
 static int pl011_allocate_irq(struct uart_amba_port *uap)
 {
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
 
 	return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
 }
@@ -1598,12 +1612,12 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
 	spin_lock_irq(&uap->port.lock);
 
 	/* Clear out any spuriously appearing RX interrupts */
-	writew(UART011_RTIS | UART011_RXIS,
-	       uap->port.membase + UART011_ICR);
+	pl011_write(UART011_RTIS | UART011_RXIS, uap->port.membase,
+	            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_write(uap->im, uap->port.membase, UART011_IMSC);
 	spin_unlock_irq(&uap->port.lock);
 }
 
@@ -1622,21 +1636,21 @@ static int pl011_startup(struct uart_port *port)
 	if (retval)
 		goto clk_dis;
 
-	writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
+	pl011_write(uap->vendor->ifls, uap->port.membase, UART011_IFLS);
 
 	spin_lock_irq(&uap->port.lock);
 
 	/* 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_write(cr, uap->port.membase, 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_read(uap->port.membase, UART01x_FR) & UART01x_FR_MODEM_ANY;
 
 	/* Startup DMA */
 	pl011_dma_startup(uap);
@@ -1677,9 +1691,9 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap,
 {
       unsigned long val;
 
-      val = readw(uap->port.membase + lcrh);
+      val = pl011_read(uap->port.membase, lcrh);
       val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
-      writew(val, uap->port.membase + lcrh);
+      pl011_write(val, uap->port.membase, lcrh);
 }
 
 /*
@@ -1693,11 +1707,11 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 
 	uap->autorts = false;
 	spin_lock_irq(&uap->port.lock);
-	cr = readw(uap->port.membase + UART011_CR);
+	cr = pl011_read(uap->port.membase, 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_write(cr, uap->port.membase, UART011_CR);
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
@@ -1714,8 +1728,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap)
 
 	/* mask all interrupts and clear all pending ones */
 	uap->im = 0;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
-	writew(0xffff, uap->port.membase + UART011_ICR);
+	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(0xffff, uap->port.membase, UART011_ICR);
 
 	spin_unlock_irq(&uap->port.lock);
 }
@@ -1867,8 +1881,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_read(port->membase, UART011_CR);
+	pl011_write(0, port->membase, UART011_CR);
 
 	if (termios->c_cflag & CRTSCTS) {
 		if (old_cr & UART011_CR_RTS)
@@ -1901,8 +1915,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_write(quot & 0x3f, port->membase, UART011_FBRD);
+	pl011_write(quot >> 6, port->membase, UART011_IBRD);
 
 	/*
 	 * ----------v----------v----------v----------v-----
@@ -1911,7 +1925,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_write(old_cr, port->membase, UART011_CR);
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -2052,9 +2066,9 @@ 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_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
-	writew(ch, uap->port.membase + UART01x_DR);
+	pl011_write(ch, uap->port.membase, UART01x_DR);
 }
 
 static void
@@ -2079,10 +2093,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	First save the CR then disable the interrupts
 	 */
 	if (!uap->vendor->always_enabled) {
-		old_cr = readw(uap->port.membase + UART011_CR);
+		old_cr = pl011_read(uap->port.membase, 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_write(new_cr, uap->port.membase, UART011_CR);
 	}
 
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
@@ -2092,10 +2106,10 @@ 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_read(uap->port.membase, UART01x_FR);
 	} while (status & UART01x_FR_BUSY);
 	if (!uap->vendor->always_enabled)
-		writew(old_cr, uap->port.membase + UART011_CR);
+		pl011_write(old_cr, uap->port.membase, UART011_CR);
 
 	if (locked)
 		spin_unlock(&uap->port.lock);
@@ -2108,10 +2122,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_read(uap->port.membase, UART011_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
 
-		lcr_h = readw(uap->port.membase + uap->lcrh_tx);
+		lcr_h = pl011_read(uap->port.membase, uap->lcrh_tx);
 
 		*parity = 'n';
 		if (lcr_h & UART01x_LCRH_PEN) {
@@ -2126,13 +2140,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_read(uap->port.membase, UART011_IBRD);
+		fbrd = pl011_read(uap->port.membase, UART011_FBRD);
 
 		*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 
 		if (uap->vendor->oversampling) {
-			if (readw(uap->port.membase + UART011_CR)
+			if (pl011_read(uap->port.membase, UART011_CR)
 				  & ST_UART011_CR_OVSFACT)
 				*baud *= 2;
 		}
@@ -2334,8 +2348,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
 	int ret;
 
 	/* Ensure interrupts from this UART are masked and cleared */
-	writew(0, uap->port.membase + UART011_IMSC);
-	writew(0xffff, uap->port.membase + UART011_ICR);
+	pl011_write(0, uap->port.membase, UART011_IMSC);
+	pl011_write(0xffff, uap->port.membase, UART011_ICR);
 
 	if (!amba_reg.state) {
 		ret = uart_register_driver(&amba_reg);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 01/11] tty: amba-pl011: add register accessor functions
@ 2015-11-03 14:50     ` Russell King
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:50 UTC (permalink / raw)
  To: linux-arm-kernel

Add register accessor functions to amba-pl011.  Much of this
transformation was done using the sed expression below, with any
left-overs fixed up manually afterwards, and code formatted to remain
within coding style.

s/readw(\(uap->port.membase\|regs\|port->membase\) +/pl011_read(\1,/g
s/writew(\(.*\) +/pl011_write(\1,/g

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 210 +++++++++++++++++++++-------------------
 1 file changed, 112 insertions(+), 98 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index fd27e986b1dd..b75f750b27ff 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -184,6 +184,16 @@ struct uart_amba_port {
 #endif
 };
 
+static unsigned int pl011_read(void __iomem *base, unsigned int reg)
+{
+	return readw(base + reg);
+}
+
+static void pl011_write(unsigned int val, void __iomem *base, unsigned int reg)
+{
+	writew(val, base + reg);
+}
+
 /*
  * 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
@@ -196,12 +206,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_read(uap->port.membase, 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_read(uap->port.membase, UART01x_DR) |
 			UART_DUMMY_DR_RX;
 		flag = TTY_NORMAL;
 		uap->port.icount.rx++;
@@ -438,7 +448,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 
 	/*
 	 * If TX DMA was disabled, it means that we've stopped the DMA for
@@ -552,7 +562,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	uap->dmatx.queued = true;
 
 	/*
@@ -588,9 +598,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 		uap->im &= ~UART011_TXIM;
-		writew(uap->im, uap->port.membase + UART011_IMSC);
+		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
 		return true;
 	}
 
@@ -600,7 +610,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_write(uap->im, uap->port.membase, UART011_IMSC);
 		return true;
 	}
 	return false;
@@ -614,7 +624,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	}
 }
 
@@ -640,14 +650,14 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		if (!uap->dmatx.queued) {
 			if (pl011_dma_tx_refill(uap) > 0) {
 				uap->im &= ~UART011_TXIM;
-				writew(uap->im, uap->port.membase +
-				       UART011_IMSC);
+				pl011_write(uap->im, uap->port.membase,
+					    UART011_IMSC);
 			} else
 				ret = false;
 		} else if (!(uap->dmacr & UART011_TXDMAE)) {
 			uap->dmacr |= UART011_TXDMAE;
-			writew(uap->dmacr,
-				       uap->port.membase + UART011_DMACR);
+			pl011_write(uap->dmacr, uap->port.membase,
+				    UART011_DMACR);
 		}
 		return ret;
 	}
@@ -658,9 +668,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 
-	if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) {
+	if (pl011_read(uap->port.membase, 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
@@ -669,13 +679,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_write(uap->port.x_char, uap->port.membase, 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_write(dmacr, uap->port.membase, UART011_DMACR);
 
 	return true;
 }
@@ -703,7 +713,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	}
 }
 
@@ -743,11 +753,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	uap->dmarx.running = true;
 
 	uap->im &= ~UART011_RXIM;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
 
 	return 0;
 }
@@ -805,8 +815,8 @@ 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_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
+			    UART011_FEIS, uap->port.membase, UART011_ICR);
 
 		/*
 		 * If we read all the DMA'd characters, and we had an
@@ -854,7 +864,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	uap->dmarx.running = false;
 
 	pending = sgbuf->sg.length - state.residue;
@@ -874,7 +884,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_write(uap->im, uap->port.membase, UART011_IMSC);
 	}
 }
 
@@ -922,7 +932,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_write(uap->im, uap->port.membase, UART011_IMSC);
 	}
 }
 
@@ -935,7 +945,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 }
 
 /*
@@ -979,7 +989,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_write(uap->im, uap->port.membase, UART011_IMSC);
 		spin_unlock_irqrestore(&uap->port.lock, flags);
 
 		uap->dmarx.running = false;
@@ -1041,7 +1051,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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 
 	/*
 	 * ST Micro variants has some specific dma burst threshold
@@ -1049,8 +1059,8 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 	 * 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_write(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
+			    uap->port.membase, ST_UART011_DMAWM);
 
 	if (uap->using_rx_dma) {
 		if (pl011_dma_rx_trigger_dma(uap))
@@ -1075,12 +1085,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_read(uap->port.membase, 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_write(uap->dmacr, uap->port.membase, UART011_DMACR);
 	spin_unlock_irq(&uap->port.lock);
 
 	if (uap->using_tx_dma) {
@@ -1181,7 +1191,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_write(uap->im, uap->port.membase, UART011_IMSC);
 	pl011_dma_tx_stop(uap);
 }
 
@@ -1191,7 +1201,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 {
 	uap->im |= UART011_TXIM;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
 	pl011_tx_chars(uap, false);
 }
 
@@ -1211,7 +1221,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_write(uap->im, uap->port.membase, UART011_IMSC);
 
 	pl011_dma_rx_stop(uap);
 }
@@ -1222,7 +1232,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_write(uap->im, uap->port.membase, UART011_IMSC);
 }
 
 static void pl011_rx_chars(struct uart_amba_port *uap)
@@ -1242,7 +1252,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_write(uap->im, uap->port.membase, UART011_IMSC);
 		} else {
 #ifdef CONFIG_DMA_ENGINE
 			/* Start Rx DMA poll */
@@ -1263,10 +1273,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
 			  bool from_irq)
 {
 	if (unlikely(!from_irq) &&
-	    readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+	    pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
 		return false; /* unable to transmit character */
 
-	writew(c, uap->port.membase + UART01x_DR);
+	pl011_write(c, uap->port.membase, UART01x_DR);
 	uap->port.icount.tx++;
 
 	return true;
@@ -1313,7 +1323,8 @@ 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_read(uap->port.membase, UART01x_FR);
+	status &= UART01x_FR_MODEM_ANY;
 
 	delta = status ^ uap->old_status;
 	uap->old_status = status;
@@ -1341,15 +1352,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
 		return;
 
 	/* workaround to make sure that all bits are unlocked.. */
-	writew(0x00, uap->port.membase + UART011_ICR);
+	pl011_write(0x00, uap->port.membase, 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_read(uap->port.membase, UART011_ICR);
+	dummy_read = pl011_read(uap->port.membase, UART011_ICR);
 }
 
 static irqreturn_t pl011_int(int irq, void *dev_id)
@@ -1361,15 +1372,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 	int handled = 0;
 
 	spin_lock_irqsave(&uap->port.lock, flags);
-	imsc = readw(uap->port.membase + UART011_IMSC);
-	status = readw(uap->port.membase + UART011_RIS) & imsc;
+	imsc = pl011_read(uap->port.membase, UART011_IMSC);
+	status = pl011_read(uap->port.membase, UART011_RIS) & imsc;
 	if (status) {
 		do {
 			check_apply_cts_event_workaround(uap);
 
-			writew(status & ~(UART011_TXIS|UART011_RTIS|
-					  UART011_RXIS),
-			       uap->port.membase + UART011_ICR);
+			pl011_write(status & ~(UART011_TXIS|UART011_RTIS|
+					       UART011_RXIS),
+				    uap->port.membase, UART011_ICR);
 
 			if (status & (UART011_RTIS|UART011_RXIS)) {
 				if (pl011_dma_rx_running(uap))
@@ -1386,7 +1397,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 			if (pass_counter-- == 0)
 				break;
 
-			status = readw(uap->port.membase + UART011_RIS) & imsc;
+			status = pl011_read(uap->port.membase, UART011_RIS) & imsc;
 		} while (status != 0);
 		handled = 1;
 	}
@@ -1400,7 +1411,7 @@ 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_read(uap->port.membase, UART01x_FR);
 	return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
 }
 
@@ -1409,7 +1420,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
 	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_read(uap->port.membase, UART01x_FR);
 
 #define TIOCMBIT(uartbit, tiocmbit)	\
 	if (status & uartbit)		\
@@ -1429,7 +1440,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_read(uap->port.membase, UART011_CR);
 
 #define	TIOCMBIT(tiocmbit, uartbit)		\
 	if (mctrl & tiocmbit)		\
@@ -1449,7 +1460,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	}
 #undef TIOCMBIT
 
-	writew(cr, uap->port.membase + UART011_CR);
+	pl011_write(cr, uap->port.membase, UART011_CR);
 }
 
 static void pl011_break_ctl(struct uart_port *port, int break_state)
@@ -1460,12 +1471,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_read(uap->port.membase, uap->lcrh_tx);
 	if (break_state == -1)
 		lcr_h |= UART01x_LCRH_BRK;
 	else
 		lcr_h &= ~UART01x_LCRH_BRK;
-	writew(lcr_h, uap->port.membase + uap->lcrh_tx);
+	pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx);
 	spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
@@ -1477,7 +1488,7 @@ static void pl011_quiesce_irqs(struct uart_port *port)
 	    container_of(port, struct uart_amba_port, port);
 	unsigned char __iomem *regs = uap->port.membase;
 
-	writew(readw(regs + UART011_MIS), regs + UART011_ICR);
+	pl011_write(pl011_read(regs, UART011_MIS), regs, 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.
@@ -1491,7 +1502,8 @@ 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_write(pl011_read(regs, UART011_IMSC) & ~UART011_TXIM,
+		    regs, UART011_IMSC);
 }
 
 static int pl011_get_poll_char(struct uart_port *port)
@@ -1506,11 +1518,11 @@ static int pl011_get_poll_char(struct uart_port *port)
 	 */
 	pl011_quiesce_irqs(port);
 
-	status = readw(uap->port.membase + UART01x_FR);
+	status = pl011_read(uap->port.membase, UART01x_FR);
 	if (status & UART01x_FR_RXFE)
 		return NO_POLL_CHAR;
 
-	return readw(uap->port.membase + UART01x_DR);
+	return pl011_read(uap->port.membase, UART01x_DR);
 }
 
 static void pl011_put_poll_char(struct uart_port *port,
@@ -1519,10 +1531,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_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
 
-	writew(ch, uap->port.membase + UART01x_DR);
+	pl011_write(ch, uap->port.membase, UART01x_DR);
 }
 
 #endif /* CONFIG_CONSOLE_POLL */
@@ -1546,15 +1558,17 @@ 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_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
+		    UART011_FEIS | UART011_RTIS | UART011_RXIS,
+		    uap->port.membase, 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_read(uap->port.membase, UART011_IMSC);
+	pl011_write(UART011_RTIM | UART011_RXIM, uap->port.membase,
+		    UART011_IMSC);
 
 	if (dev_get_platdata(uap->port.dev)) {
 		struct amba_pl011_data *plat;
@@ -1568,7 +1582,7 @@ 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);
+	pl011_write(lcr_h, uap->port.membase, uap->lcrh_rx);
 	if (uap->lcrh_rx != uap->lcrh_tx) {
 		int i;
 		/*
@@ -1576,14 +1590,14 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 		 * 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_write(0xff, uap->port.membase, UART011_MIS);
+		pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx);
 	}
 }
 
 static int pl011_allocate_irq(struct uart_amba_port *uap)
 {
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
 
 	return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
 }
@@ -1598,12 +1612,12 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
 	spin_lock_irq(&uap->port.lock);
 
 	/* Clear out any spuriously appearing RX interrupts */
-	writew(UART011_RTIS | UART011_RXIS,
-	       uap->port.membase + UART011_ICR);
+	pl011_write(UART011_RTIS | UART011_RXIS, uap->port.membase,
+	            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_write(uap->im, uap->port.membase, UART011_IMSC);
 	spin_unlock_irq(&uap->port.lock);
 }
 
@@ -1622,21 +1636,21 @@ static int pl011_startup(struct uart_port *port)
 	if (retval)
 		goto clk_dis;
 
-	writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
+	pl011_write(uap->vendor->ifls, uap->port.membase, UART011_IFLS);
 
 	spin_lock_irq(&uap->port.lock);
 
 	/* 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_write(cr, uap->port.membase, 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_read(uap->port.membase, UART01x_FR) & UART01x_FR_MODEM_ANY;
 
 	/* Startup DMA */
 	pl011_dma_startup(uap);
@@ -1677,9 +1691,9 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap,
 {
       unsigned long val;
 
-      val = readw(uap->port.membase + lcrh);
+      val = pl011_read(uap->port.membase, lcrh);
       val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
-      writew(val, uap->port.membase + lcrh);
+      pl011_write(val, uap->port.membase, lcrh);
 }
 
 /*
@@ -1693,11 +1707,11 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 
 	uap->autorts = false;
 	spin_lock_irq(&uap->port.lock);
-	cr = readw(uap->port.membase + UART011_CR);
+	cr = pl011_read(uap->port.membase, 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_write(cr, uap->port.membase, UART011_CR);
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
@@ -1714,8 +1728,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap)
 
 	/* mask all interrupts and clear all pending ones */
 	uap->im = 0;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
-	writew(0xffff, uap->port.membase + UART011_ICR);
+	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(0xffff, uap->port.membase, UART011_ICR);
 
 	spin_unlock_irq(&uap->port.lock);
 }
@@ -1867,8 +1881,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_read(port->membase, UART011_CR);
+	pl011_write(0, port->membase, UART011_CR);
 
 	if (termios->c_cflag & CRTSCTS) {
 		if (old_cr & UART011_CR_RTS)
@@ -1901,8 +1915,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_write(quot & 0x3f, port->membase, UART011_FBRD);
+	pl011_write(quot >> 6, port->membase, UART011_IBRD);
 
 	/*
 	 * ----------v----------v----------v----------v-----
@@ -1911,7 +1925,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_write(old_cr, port->membase, UART011_CR);
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -2052,9 +2066,9 @@ 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_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
-	writew(ch, uap->port.membase + UART01x_DR);
+	pl011_write(ch, uap->port.membase, UART01x_DR);
 }
 
 static void
@@ -2079,10 +2093,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	First save the CR then disable the interrupts
 	 */
 	if (!uap->vendor->always_enabled) {
-		old_cr = readw(uap->port.membase + UART011_CR);
+		old_cr = pl011_read(uap->port.membase, 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_write(new_cr, uap->port.membase, UART011_CR);
 	}
 
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
@@ -2092,10 +2106,10 @@ 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_read(uap->port.membase, UART01x_FR);
 	} while (status & UART01x_FR_BUSY);
 	if (!uap->vendor->always_enabled)
-		writew(old_cr, uap->port.membase + UART011_CR);
+		pl011_write(old_cr, uap->port.membase, UART011_CR);
 
 	if (locked)
 		spin_unlock(&uap->port.lock);
@@ -2108,10 +2122,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_read(uap->port.membase, UART011_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
 
-		lcr_h = readw(uap->port.membase + uap->lcrh_tx);
+		lcr_h = pl011_read(uap->port.membase, uap->lcrh_tx);
 
 		*parity = 'n';
 		if (lcr_h & UART01x_LCRH_PEN) {
@@ -2126,13 +2140,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_read(uap->port.membase, UART011_IBRD);
+		fbrd = pl011_read(uap->port.membase, UART011_FBRD);
 
 		*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 
 		if (uap->vendor->oversampling) {
-			if (readw(uap->port.membase + UART011_CR)
+			if (pl011_read(uap->port.membase, UART011_CR)
 				  & ST_UART011_CR_OVSFACT)
 				*baud *= 2;
 		}
@@ -2334,8 +2348,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
 	int ret;
 
 	/* Ensure interrupts from this UART are masked and cleared */
-	writew(0, uap->port.membase + UART011_IMSC);
-	writew(0xffff, uap->port.membase + UART011_ICR);
+	pl011_write(0, uap->port.membase, UART011_IMSC);
+	pl011_write(0xffff, uap->port.membase, UART011_ICR);
 
 	if (!amba_reg.state) {
 		ret = uart_register_driver(&amba_reg);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 02/11] tty: amba-pl011: convert accessor functions to take uart_amba_port
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:51     ` Russell King
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Convert the new accessor functions to take the uart_amba_port instead
of the port base address.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 199 ++++++++++++++++++++--------------------
 1 file changed, 97 insertions(+), 102 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index b75f750b27ff..61512afb10da 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -184,14 +184,16 @@ struct uart_amba_port {
 #endif
 };
 
-static unsigned int pl011_read(void __iomem *base, unsigned int reg)
+static unsigned int pl011_read(const struct uart_amba_port *uap,
+	unsigned int reg)
 {
-	return readw(base + reg);
+	return readw(uap->port.membase + reg);
 }
 
-static void pl011_write(unsigned int val, void __iomem *base, unsigned int reg)
+static void pl011_write(unsigned int val, const struct uart_amba_port *uap,
+	unsigned int reg)
 {
-	writew(val, base + reg);
+	writew(val, uap->port.membase + reg);
 }
 
 /*
@@ -206,13 +208,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
 	int fifotaken = 0;
 
 	while (max_count--) {
-		status = pl011_read(uap->port.membase, UART01x_FR);
+		status = pl011_read(uap, UART01x_FR);
 		if (status & UART01x_FR_RXFE)
 			break;
 
 		/* Take chars from the FIFO and update status */
-		ch = pl011_read(uap->port.membase, UART01x_DR) |
-			UART_DUMMY_DR_RX;
+		ch = pl011_read(uap, UART01x_DR) | UART_DUMMY_DR_RX;
 		flag = TTY_NORMAL;
 		uap->port.icount.rx++;
 		fifotaken++;
@@ -448,7 +449,7 @@ static void pl011_dma_tx_callback(void *data)
 
 	dmacr = uap->dmacr;
 	uap->dmacr = dmacr & ~UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 
 	/*
 	 * If TX DMA was disabled, it means that we've stopped the DMA for
@@ -562,7 +563,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
 	dma_dev->device_issue_pending(chan);
 
 	uap->dmacr |= UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 	uap->dmatx.queued = true;
 
 	/*
@@ -598,9 +599,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
 	 */
 	if (uap->dmatx.queued) {
 		uap->dmacr |= UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, UART011_DMACR);
 		uap->im &= ~UART011_TXIM;
-		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+		pl011_write(uap->im, uap, UART011_IMSC);
 		return true;
 	}
 
@@ -610,7 +611,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
 	 */
 	if (pl011_dma_tx_refill(uap) > 0) {
 		uap->im &= ~UART011_TXIM;
-		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+		pl011_write(uap->im, uap, UART011_IMSC);
 		return true;
 	}
 	return false;
@@ -624,7 +625,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
 {
 	if (uap->dmatx.queued) {
 		uap->dmacr &= ~UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, UART011_DMACR);
 	}
 }
 
@@ -650,14 +651,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		if (!uap->dmatx.queued) {
 			if (pl011_dma_tx_refill(uap) > 0) {
 				uap->im &= ~UART011_TXIM;
-				pl011_write(uap->im, uap->port.membase,
-					    UART011_IMSC);
+				pl011_write(uap->im, uap, UART011_IMSC);
 			} else
 				ret = false;
 		} else if (!(uap->dmacr & UART011_TXDMAE)) {
 			uap->dmacr |= UART011_TXDMAE;
-			pl011_write(uap->dmacr, uap->port.membase,
-				    UART011_DMACR);
+			pl011_write(uap->dmacr, uap, UART011_DMACR);
 		}
 		return ret;
 	}
@@ -668,9 +667,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 	 */
 	dmacr = uap->dmacr;
 	uap->dmacr &= ~UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 
-	if (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF) {
+	if (pl011_read(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
@@ -679,13 +678,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		return false;
 	}
 
-	pl011_write(uap->port.x_char, uap->port.membase, UART01x_DR);
+	pl011_write(uap->port.x_char, uap, UART01x_DR);
 	uap->port.icount.tx++;
 	uap->port.x_char = 0;
 
 	/* Success - restore the DMA state */
 	uap->dmacr = dmacr;
-	pl011_write(dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(dmacr, uap, UART011_DMACR);
 
 	return true;
 }
@@ -713,7 +712,7 @@ __acquires(&uap->port.lock)
 			     DMA_TO_DEVICE);
 		uap->dmatx.queued = false;
 		uap->dmacr &= ~UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, UART011_DMACR);
 	}
 }
 
@@ -753,11 +752,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
 	dma_async_issue_pending(rxchan);
 
 	uap->dmacr |= UART011_RXDMAE;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 	uap->dmarx.running = true;
 
 	uap->im &= ~UART011_RXIM;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 
 	return 0;
 }
@@ -816,7 +815,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
 	if (dma_count == pending && readfifo) {
 		/* Clear any error flags */
 		pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
-			    UART011_FEIS, uap->port.membase, UART011_ICR);
+			    UART011_FEIS, uap, UART011_ICR);
 
 		/*
 		 * If we read all the DMA'd characters, and we had an
@@ -864,7 +863,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;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 	uap->dmarx.running = false;
 
 	pending = sgbuf->sg.length - state.residue;
@@ -884,7 +883,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;
-		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+		pl011_write(uap->im, uap, UART011_IMSC);
 	}
 }
 
@@ -932,7 +931,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;
-		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+		pl011_write(uap->im, uap, UART011_IMSC);
 	}
 }
 
@@ -945,7 +944,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
 {
 	/* FIXME.  Just disable the DMA enable */
 	uap->dmacr &= ~UART011_RXDMAE;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 }
 
 /*
@@ -989,7 +988,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;
-		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+		pl011_write(uap->im, uap, UART011_IMSC);
 		spin_unlock_irqrestore(&uap->port.lock, flags);
 
 		uap->dmarx.running = false;
@@ -1051,7 +1050,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;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 
 	/*
 	 * ST Micro variants has some specific dma burst threshold
@@ -1060,7 +1059,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 	 */
 	if (uap->vendor->dma_threshold)
 		pl011_write(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
-			    uap->port.membase, ST_UART011_DMAWM);
+			    uap, ST_UART011_DMAWM);
 
 	if (uap->using_rx_dma) {
 		if (pl011_dma_rx_trigger_dma(uap))
@@ -1085,12 +1084,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
 		return;
 
 	/* Disable RX and TX DMA */
-	while (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_BUSY)
+	while (pl011_read(uap, UART01x_FR) & UART01x_FR_BUSY)
 		barrier();
 
 	spin_lock_irq(&uap->port.lock);
 	uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 	spin_unlock_irq(&uap->port.lock);
 
 	if (uap->using_tx_dma) {
@@ -1191,7 +1190,7 @@ static void pl011_stop_tx(struct uart_port *port)
 	    container_of(port, struct uart_amba_port, port);
 
 	uap->im &= ~UART011_TXIM;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 	pl011_dma_tx_stop(uap);
 }
 
@@ -1201,7 +1200,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 {
 	uap->im |= UART011_TXIM;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 	pl011_tx_chars(uap, false);
 }
 
@@ -1221,7 +1220,7 @@ static void pl011_stop_rx(struct uart_port *port)
 
 	uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
 		     UART011_PEIM|UART011_BEIM|UART011_OEIM);
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 
 	pl011_dma_rx_stop(uap);
 }
@@ -1232,7 +1231,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;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 }
 
 static void pl011_rx_chars(struct uart_amba_port *uap)
@@ -1252,7 +1251,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;
-			pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+			pl011_write(uap->im, uap, UART011_IMSC);
 		} else {
 #ifdef CONFIG_DMA_ENGINE
 			/* Start Rx DMA poll */
@@ -1273,10 +1272,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
 			  bool from_irq)
 {
 	if (unlikely(!from_irq) &&
-	    pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
+	    pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		return false; /* unable to transmit character */
 
-	pl011_write(c, uap->port.membase, UART01x_DR);
+	pl011_write(c, uap, UART01x_DR);
 	uap->port.icount.tx++;
 
 	return true;
@@ -1323,8 +1322,7 @@ static void pl011_modem_status(struct uart_amba_port *uap)
 {
 	unsigned int status, delta;
 
-	status = pl011_read(uap->port.membase, UART01x_FR);
-	status &= UART01x_FR_MODEM_ANY;
+	status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
 
 	delta = status ^ uap->old_status;
 	uap->old_status = status;
@@ -1352,15 +1350,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
 		return;
 
 	/* workaround to make sure that all bits are unlocked.. */
-	pl011_write(0x00, uap->port.membase, UART011_ICR);
+	pl011_write(0x00, uap, 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 = pl011_read(uap->port.membase, UART011_ICR);
-	dummy_read = pl011_read(uap->port.membase, UART011_ICR);
+	dummy_read = pl011_read(uap, UART011_ICR);
+	dummy_read = pl011_read(uap, UART011_ICR);
 }
 
 static irqreturn_t pl011_int(int irq, void *dev_id)
@@ -1372,15 +1370,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 	int handled = 0;
 
 	spin_lock_irqsave(&uap->port.lock, flags);
-	imsc = pl011_read(uap->port.membase, UART011_IMSC);
-	status = pl011_read(uap->port.membase, UART011_RIS) & imsc;
+	imsc = pl011_read(uap, UART011_IMSC);
+	status = pl011_read(uap, UART011_RIS) & imsc;
 	if (status) {
 		do {
 			check_apply_cts_event_workaround(uap);
 
 			pl011_write(status & ~(UART011_TXIS|UART011_RTIS|
 					       UART011_RXIS),
-				    uap->port.membase, UART011_ICR);
+				    uap, UART011_ICR);
 
 			if (status & (UART011_RTIS|UART011_RXIS)) {
 				if (pl011_dma_rx_running(uap))
@@ -1397,7 +1395,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 			if (pass_counter-- == 0)
 				break;
 
-			status = pl011_read(uap->port.membase, UART011_RIS) & imsc;
+			status = pl011_read(uap, UART011_RIS) & imsc;
 		} while (status != 0);
 		handled = 1;
 	}
@@ -1411,7 +1409,7 @@ 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 = pl011_read(uap->port.membase, UART01x_FR);
+	unsigned int status = pl011_read(uap, UART01x_FR);
 	return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
 }
 
@@ -1420,7 +1418,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
 	struct uart_amba_port *uap =
 	    container_of(port, struct uart_amba_port, port);
 	unsigned int result = 0;
-	unsigned int status = pl011_read(uap->port.membase, UART01x_FR);
+	unsigned int status = pl011_read(uap, UART01x_FR);
 
 #define TIOCMBIT(uartbit, tiocmbit)	\
 	if (status & uartbit)		\
@@ -1440,7 +1438,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 = pl011_read(uap->port.membase, UART011_CR);
+	cr = pl011_read(uap, UART011_CR);
 
 #define	TIOCMBIT(tiocmbit, uartbit)		\
 	if (mctrl & tiocmbit)		\
@@ -1460,7 +1458,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	}
 #undef TIOCMBIT
 
-	pl011_write(cr, uap->port.membase, UART011_CR);
+	pl011_write(cr, uap, UART011_CR);
 }
 
 static void pl011_break_ctl(struct uart_port *port, int break_state)
@@ -1471,12 +1469,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 = pl011_read(uap->port.membase, uap->lcrh_tx);
+	lcr_h = pl011_read(uap, uap->lcrh_tx);
 	if (break_state == -1)
 		lcr_h |= UART01x_LCRH_BRK;
 	else
 		lcr_h &= ~UART01x_LCRH_BRK;
-	pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx);
+	pl011_write(lcr_h, uap, uap->lcrh_tx);
 	spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
@@ -1486,9 +1484,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;
 
-	pl011_write(pl011_read(regs, UART011_MIS), regs, UART011_ICR);
+	pl011_write(pl011_read(uap, UART011_MIS), uap, 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.
@@ -1502,8 +1499,8 @@ static void pl011_quiesce_irqs(struct uart_port *port)
 	 * (including tx queue), so we're also fine with start_tx()'s caller
 	 * side.
 	 */
-	pl011_write(pl011_read(regs, UART011_IMSC) & ~UART011_TXIM,
-		    regs, UART011_IMSC);
+	pl011_write(pl011_read(uap, UART011_IMSC) & ~UART011_TXIM, uap,
+		    UART011_IMSC);
 }
 
 static int pl011_get_poll_char(struct uart_port *port)
@@ -1518,11 +1515,11 @@ static int pl011_get_poll_char(struct uart_port *port)
 	 */
 	pl011_quiesce_irqs(port);
 
-	status = pl011_read(uap->port.membase, UART01x_FR);
+	status = pl011_read(uap, UART01x_FR);
 	if (status & UART01x_FR_RXFE)
 		return NO_POLL_CHAR;
 
-	return pl011_read(uap->port.membase, UART01x_DR);
+	return pl011_read(uap, UART01x_DR);
 }
 
 static void pl011_put_poll_char(struct uart_port *port,
@@ -1531,10 +1528,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 (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
+	while (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
 
-	pl011_write(ch, uap->port.membase, UART01x_DR);
+	pl011_write(ch, uap, UART01x_DR);
 }
 
 #endif /* CONFIG_CONSOLE_POLL */
@@ -1560,15 +1557,14 @@ static int pl011_hwinit(struct uart_port *port)
 	/* Clear pending error and receive interrupts */
 	pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
 		    UART011_FEIS | UART011_RTIS | UART011_RXIS,
-		    uap->port.membase, UART011_ICR);
+		    uap, UART011_ICR);
 
 	/*
 	 * Save interrupts enable mask, and enable RX interrupts in case if
 	 * the interrupt is used for NMI entry.
 	 */
-	uap->im = pl011_read(uap->port.membase, UART011_IMSC);
-	pl011_write(UART011_RTIM | UART011_RXIM, uap->port.membase,
-		    UART011_IMSC);
+	uap->im = pl011_read(uap, UART011_IMSC);
+	pl011_write(UART011_RTIM | UART011_RXIM, uap, UART011_IMSC);
 
 	if (dev_get_platdata(uap->port.dev)) {
 		struct amba_pl011_data *plat;
@@ -1582,7 +1578,7 @@ static int pl011_hwinit(struct uart_port *port)
 
 static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 {
-	pl011_write(lcr_h, uap->port.membase, uap->lcrh_rx);
+	pl011_write(lcr_h, uap, uap->lcrh_rx);
 	if (uap->lcrh_rx != uap->lcrh_tx) {
 		int i;
 		/*
@@ -1590,14 +1586,14 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 		 * to get this delay write read only register 10 times
 		 */
 		for (i = 0; i < 10; ++i)
-			pl011_write(0xff, uap->port.membase, UART011_MIS);
-		pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx);
+			pl011_write(0xff, uap, UART011_MIS);
+		pl011_write(lcr_h, uap, uap->lcrh_tx);
 	}
 }
 
 static int pl011_allocate_irq(struct uart_amba_port *uap)
 {
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 
 	return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
 }
@@ -1612,12 +1608,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
 	spin_lock_irq(&uap->port.lock);
 
 	/* Clear out any spuriously appearing RX interrupts */
-	pl011_write(UART011_RTIS | UART011_RXIS, uap->port.membase,
-	            UART011_ICR);
+	pl011_write(UART011_RTIS | UART011_RXIS, uap, UART011_ICR);
 	uap->im = UART011_RTIM;
 	if (!pl011_dma_rx_running(uap))
 		uap->im |= UART011_RXIM;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 	spin_unlock_irq(&uap->port.lock);
 }
 
@@ -1636,21 +1631,21 @@ static int pl011_startup(struct uart_port *port)
 	if (retval)
 		goto clk_dis;
 
-	pl011_write(uap->vendor->ifls, uap->port.membase, UART011_IFLS);
+	pl011_write(uap->vendor->ifls, uap, UART011_IFLS);
 
 	spin_lock_irq(&uap->port.lock);
 
 	/* restore RTS and DTR */
 	cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
 	cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
-	pl011_write(cr, uap->port.membase, UART011_CR);
+	pl011_write(cr, uap, UART011_CR);
 
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
 	 * initialise the old status of the modem signals
 	 */
-	uap->old_status = pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_MODEM_ANY;
+	uap->old_status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
 
 	/* Startup DMA */
 	pl011_dma_startup(uap);
@@ -1691,9 +1686,9 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap,
 {
       unsigned long val;
 
-      val = pl011_read(uap->port.membase, lcrh);
+      val = pl011_read(uap, lcrh);
       val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
-      pl011_write(val, uap->port.membase, lcrh);
+      pl011_write(val, uap, lcrh);
 }
 
 /*
@@ -1707,11 +1702,11 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 
 	uap->autorts = false;
 	spin_lock_irq(&uap->port.lock);
-	cr = pl011_read(uap->port.membase, UART011_CR);
+	cr = pl011_read(uap, UART011_CR);
 	uap->old_cr = cr;
 	cr &= UART011_CR_RTS | UART011_CR_DTR;
 	cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-	pl011_write(cr, uap->port.membase, UART011_CR);
+	pl011_write(cr, uap, UART011_CR);
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
@@ -1728,8 +1723,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap)
 
 	/* mask all interrupts and clear all pending ones */
 	uap->im = 0;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
-	pl011_write(0xffff, uap->port.membase, UART011_ICR);
+	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(0xffff, uap, UART011_ICR);
 
 	spin_unlock_irq(&uap->port.lock);
 }
@@ -1881,8 +1876,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 		pl011_enable_ms(port);
 
 	/* first, disable everything */
-	old_cr = pl011_read(port->membase, UART011_CR);
-	pl011_write(0, port->membase, UART011_CR);
+	old_cr = pl011_read(uap, UART011_CR);
+	pl011_write(0, uap, UART011_CR);
 
 	if (termios->c_cflag & CRTSCTS) {
 		if (old_cr & UART011_CR_RTS)
@@ -1915,8 +1910,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 			quot -= 2;
 	}
 	/* Set baud rate */
-	pl011_write(quot & 0x3f, port->membase, UART011_FBRD);
-	pl011_write(quot >> 6, port->membase, UART011_IBRD);
+	pl011_write(quot & 0x3f, uap, UART011_FBRD);
+	pl011_write(quot >> 6, uap, UART011_IBRD);
 
 	/*
 	 * ----------v----------v----------v----------v-----
@@ -1925,7 +1920,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 	 * ----------^----------^----------^----------^-----
 	 */
 	pl011_write_lcr_h(uap, lcr_h);
-	pl011_write(old_cr, port->membase, UART011_CR);
+	pl011_write(old_cr, uap, UART011_CR);
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -2066,9 +2061,9 @@ 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 (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
+	while (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
-	pl011_write(ch, uap->port.membase, UART01x_DR);
+	pl011_write(ch, uap, UART01x_DR);
 }
 
 static void
@@ -2093,10 +2088,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	First save the CR then disable the interrupts
 	 */
 	if (!uap->vendor->always_enabled) {
-		old_cr = pl011_read(uap->port.membase, UART011_CR);
+		old_cr = pl011_read(uap, UART011_CR);
 		new_cr = old_cr & ~UART011_CR_CTSEN;
 		new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-		pl011_write(new_cr, uap->port.membase, UART011_CR);
+		pl011_write(new_cr, uap, UART011_CR);
 	}
 
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
@@ -2106,10 +2101,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	and restore the TCR
 	 */
 	do {
-		status = pl011_read(uap->port.membase, UART01x_FR);
+		status = pl011_read(uap, UART01x_FR);
 	} while (status & UART01x_FR_BUSY);
 	if (!uap->vendor->always_enabled)
-		pl011_write(old_cr, uap->port.membase, UART011_CR);
+		pl011_write(old_cr, uap, UART011_CR);
 
 	if (locked)
 		spin_unlock(&uap->port.lock);
@@ -2122,10 +2117,10 @@ static void __init
 pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 			     int *parity, int *bits)
 {
-	if (pl011_read(uap->port.membase, UART011_CR) & UART01x_CR_UARTEN) {
+	if (pl011_read(uap, UART011_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
 
-		lcr_h = pl011_read(uap->port.membase, uap->lcrh_tx);
+		lcr_h = pl011_read(uap, uap->lcrh_tx);
 
 		*parity = 'n';
 		if (lcr_h & UART01x_LCRH_PEN) {
@@ -2140,13 +2135,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 		else
 			*bits = 8;
 
-		ibrd = pl011_read(uap->port.membase, UART011_IBRD);
-		fbrd = pl011_read(uap->port.membase, UART011_FBRD);
+		ibrd = pl011_read(uap, UART011_IBRD);
+		fbrd = pl011_read(uap, UART011_FBRD);
 
 		*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 
 		if (uap->vendor->oversampling) {
-			if (pl011_read(uap->port.membase, UART011_CR)
+			if (pl011_read(uap, UART011_CR)
 				  & ST_UART011_CR_OVSFACT)
 				*baud *= 2;
 		}
@@ -2348,8 +2343,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
 	int ret;
 
 	/* Ensure interrupts from this UART are masked and cleared */
-	pl011_write(0, uap->port.membase, UART011_IMSC);
-	pl011_write(0xffff, uap->port.membase, UART011_ICR);
+	pl011_write(0, uap, UART011_IMSC);
+	pl011_write(0xffff, uap, UART011_ICR);
 
 	if (!amba_reg.state) {
 		ret = uart_register_driver(&amba_reg);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 02/11] tty: amba-pl011: convert accessor functions to take uart_amba_port
@ 2015-11-03 14:51     ` Russell King
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

Convert the new accessor functions to take the uart_amba_port instead
of the port base address.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 199 ++++++++++++++++++++--------------------
 1 file changed, 97 insertions(+), 102 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index b75f750b27ff..61512afb10da 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -184,14 +184,16 @@ struct uart_amba_port {
 #endif
 };
 
-static unsigned int pl011_read(void __iomem *base, unsigned int reg)
+static unsigned int pl011_read(const struct uart_amba_port *uap,
+	unsigned int reg)
 {
-	return readw(base + reg);
+	return readw(uap->port.membase + reg);
 }
 
-static void pl011_write(unsigned int val, void __iomem *base, unsigned int reg)
+static void pl011_write(unsigned int val, const struct uart_amba_port *uap,
+	unsigned int reg)
 {
-	writew(val, base + reg);
+	writew(val, uap->port.membase + reg);
 }
 
 /*
@@ -206,13 +208,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
 	int fifotaken = 0;
 
 	while (max_count--) {
-		status = pl011_read(uap->port.membase, UART01x_FR);
+		status = pl011_read(uap, UART01x_FR);
 		if (status & UART01x_FR_RXFE)
 			break;
 
 		/* Take chars from the FIFO and update status */
-		ch = pl011_read(uap->port.membase, UART01x_DR) |
-			UART_DUMMY_DR_RX;
+		ch = pl011_read(uap, UART01x_DR) | UART_DUMMY_DR_RX;
 		flag = TTY_NORMAL;
 		uap->port.icount.rx++;
 		fifotaken++;
@@ -448,7 +449,7 @@ static void pl011_dma_tx_callback(void *data)
 
 	dmacr = uap->dmacr;
 	uap->dmacr = dmacr & ~UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 
 	/*
 	 * If TX DMA was disabled, it means that we've stopped the DMA for
@@ -562,7 +563,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
 	dma_dev->device_issue_pending(chan);
 
 	uap->dmacr |= UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 	uap->dmatx.queued = true;
 
 	/*
@@ -598,9 +599,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
 	 */
 	if (uap->dmatx.queued) {
 		uap->dmacr |= UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, UART011_DMACR);
 		uap->im &= ~UART011_TXIM;
-		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+		pl011_write(uap->im, uap, UART011_IMSC);
 		return true;
 	}
 
@@ -610,7 +611,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
 	 */
 	if (pl011_dma_tx_refill(uap) > 0) {
 		uap->im &= ~UART011_TXIM;
-		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+		pl011_write(uap->im, uap, UART011_IMSC);
 		return true;
 	}
 	return false;
@@ -624,7 +625,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
 {
 	if (uap->dmatx.queued) {
 		uap->dmacr &= ~UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, UART011_DMACR);
 	}
 }
 
@@ -650,14 +651,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		if (!uap->dmatx.queued) {
 			if (pl011_dma_tx_refill(uap) > 0) {
 				uap->im &= ~UART011_TXIM;
-				pl011_write(uap->im, uap->port.membase,
-					    UART011_IMSC);
+				pl011_write(uap->im, uap, UART011_IMSC);
 			} else
 				ret = false;
 		} else if (!(uap->dmacr & UART011_TXDMAE)) {
 			uap->dmacr |= UART011_TXDMAE;
-			pl011_write(uap->dmacr, uap->port.membase,
-				    UART011_DMACR);
+			pl011_write(uap->dmacr, uap, UART011_DMACR);
 		}
 		return ret;
 	}
@@ -668,9 +667,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 	 */
 	dmacr = uap->dmacr;
 	uap->dmacr &= ~UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 
-	if (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF) {
+	if (pl011_read(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
@@ -679,13 +678,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		return false;
 	}
 
-	pl011_write(uap->port.x_char, uap->port.membase, UART01x_DR);
+	pl011_write(uap->port.x_char, uap, UART01x_DR);
 	uap->port.icount.tx++;
 	uap->port.x_char = 0;
 
 	/* Success - restore the DMA state */
 	uap->dmacr = dmacr;
-	pl011_write(dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(dmacr, uap, UART011_DMACR);
 
 	return true;
 }
@@ -713,7 +712,7 @@ __acquires(&uap->port.lock)
 			     DMA_TO_DEVICE);
 		uap->dmatx.queued = false;
 		uap->dmacr &= ~UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, UART011_DMACR);
 	}
 }
 
@@ -753,11 +752,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
 	dma_async_issue_pending(rxchan);
 
 	uap->dmacr |= UART011_RXDMAE;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 	uap->dmarx.running = true;
 
 	uap->im &= ~UART011_RXIM;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 
 	return 0;
 }
@@ -816,7 +815,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
 	if (dma_count == pending && readfifo) {
 		/* Clear any error flags */
 		pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
-			    UART011_FEIS, uap->port.membase, UART011_ICR);
+			    UART011_FEIS, uap, UART011_ICR);
 
 		/*
 		 * If we read all the DMA'd characters, and we had an
@@ -864,7 +863,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;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 	uap->dmarx.running = false;
 
 	pending = sgbuf->sg.length - state.residue;
@@ -884,7 +883,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;
-		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+		pl011_write(uap->im, uap, UART011_IMSC);
 	}
 }
 
@@ -932,7 +931,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;
-		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+		pl011_write(uap->im, uap, UART011_IMSC);
 	}
 }
 
@@ -945,7 +944,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
 {
 	/* FIXME.  Just disable the DMA enable */
 	uap->dmacr &= ~UART011_RXDMAE;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 }
 
 /*
@@ -989,7 +988,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;
-		pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+		pl011_write(uap->im, uap, UART011_IMSC);
 		spin_unlock_irqrestore(&uap->port.lock, flags);
 
 		uap->dmarx.running = false;
@@ -1051,7 +1050,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;
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 
 	/*
 	 * ST Micro variants has some specific dma burst threshold
@@ -1060,7 +1059,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 	 */
 	if (uap->vendor->dma_threshold)
 		pl011_write(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
-			    uap->port.membase, ST_UART011_DMAWM);
+			    uap, ST_UART011_DMAWM);
 
 	if (uap->using_rx_dma) {
 		if (pl011_dma_rx_trigger_dma(uap))
@@ -1085,12 +1084,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
 		return;
 
 	/* Disable RX and TX DMA */
-	while (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_BUSY)
+	while (pl011_read(uap, UART01x_FR) & UART01x_FR_BUSY)
 		barrier();
 
 	spin_lock_irq(&uap->port.lock);
 	uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
-	pl011_write(uap->dmacr, uap->port.membase, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, UART011_DMACR);
 	spin_unlock_irq(&uap->port.lock);
 
 	if (uap->using_tx_dma) {
@@ -1191,7 +1190,7 @@ static void pl011_stop_tx(struct uart_port *port)
 	    container_of(port, struct uart_amba_port, port);
 
 	uap->im &= ~UART011_TXIM;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 	pl011_dma_tx_stop(uap);
 }
 
@@ -1201,7 +1200,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 {
 	uap->im |= UART011_TXIM;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 	pl011_tx_chars(uap, false);
 }
 
@@ -1221,7 +1220,7 @@ static void pl011_stop_rx(struct uart_port *port)
 
 	uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
 		     UART011_PEIM|UART011_BEIM|UART011_OEIM);
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 
 	pl011_dma_rx_stop(uap);
 }
@@ -1232,7 +1231,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;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 }
 
 static void pl011_rx_chars(struct uart_amba_port *uap)
@@ -1252,7 +1251,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;
-			pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+			pl011_write(uap->im, uap, UART011_IMSC);
 		} else {
 #ifdef CONFIG_DMA_ENGINE
 			/* Start Rx DMA poll */
@@ -1273,10 +1272,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
 			  bool from_irq)
 {
 	if (unlikely(!from_irq) &&
-	    pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
+	    pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		return false; /* unable to transmit character */
 
-	pl011_write(c, uap->port.membase, UART01x_DR);
+	pl011_write(c, uap, UART01x_DR);
 	uap->port.icount.tx++;
 
 	return true;
@@ -1323,8 +1322,7 @@ static void pl011_modem_status(struct uart_amba_port *uap)
 {
 	unsigned int status, delta;
 
-	status = pl011_read(uap->port.membase, UART01x_FR);
-	status &= UART01x_FR_MODEM_ANY;
+	status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
 
 	delta = status ^ uap->old_status;
 	uap->old_status = status;
@@ -1352,15 +1350,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
 		return;
 
 	/* workaround to make sure that all bits are unlocked.. */
-	pl011_write(0x00, uap->port.membase, UART011_ICR);
+	pl011_write(0x00, uap, 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 = pl011_read(uap->port.membase, UART011_ICR);
-	dummy_read = pl011_read(uap->port.membase, UART011_ICR);
+	dummy_read = pl011_read(uap, UART011_ICR);
+	dummy_read = pl011_read(uap, UART011_ICR);
 }
 
 static irqreturn_t pl011_int(int irq, void *dev_id)
@@ -1372,15 +1370,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 	int handled = 0;
 
 	spin_lock_irqsave(&uap->port.lock, flags);
-	imsc = pl011_read(uap->port.membase, UART011_IMSC);
-	status = pl011_read(uap->port.membase, UART011_RIS) & imsc;
+	imsc = pl011_read(uap, UART011_IMSC);
+	status = pl011_read(uap, UART011_RIS) & imsc;
 	if (status) {
 		do {
 			check_apply_cts_event_workaround(uap);
 
 			pl011_write(status & ~(UART011_TXIS|UART011_RTIS|
 					       UART011_RXIS),
-				    uap->port.membase, UART011_ICR);
+				    uap, UART011_ICR);
 
 			if (status & (UART011_RTIS|UART011_RXIS)) {
 				if (pl011_dma_rx_running(uap))
@@ -1397,7 +1395,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 			if (pass_counter-- == 0)
 				break;
 
-			status = pl011_read(uap->port.membase, UART011_RIS) & imsc;
+			status = pl011_read(uap, UART011_RIS) & imsc;
 		} while (status != 0);
 		handled = 1;
 	}
@@ -1411,7 +1409,7 @@ 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 = pl011_read(uap->port.membase, UART01x_FR);
+	unsigned int status = pl011_read(uap, UART01x_FR);
 	return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
 }
 
@@ -1420,7 +1418,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
 	struct uart_amba_port *uap =
 	    container_of(port, struct uart_amba_port, port);
 	unsigned int result = 0;
-	unsigned int status = pl011_read(uap->port.membase, UART01x_FR);
+	unsigned int status = pl011_read(uap, UART01x_FR);
 
 #define TIOCMBIT(uartbit, tiocmbit)	\
 	if (status & uartbit)		\
@@ -1440,7 +1438,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 = pl011_read(uap->port.membase, UART011_CR);
+	cr = pl011_read(uap, UART011_CR);
 
 #define	TIOCMBIT(tiocmbit, uartbit)		\
 	if (mctrl & tiocmbit)		\
@@ -1460,7 +1458,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	}
 #undef TIOCMBIT
 
-	pl011_write(cr, uap->port.membase, UART011_CR);
+	pl011_write(cr, uap, UART011_CR);
 }
 
 static void pl011_break_ctl(struct uart_port *port, int break_state)
@@ -1471,12 +1469,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 = pl011_read(uap->port.membase, uap->lcrh_tx);
+	lcr_h = pl011_read(uap, uap->lcrh_tx);
 	if (break_state == -1)
 		lcr_h |= UART01x_LCRH_BRK;
 	else
 		lcr_h &= ~UART01x_LCRH_BRK;
-	pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx);
+	pl011_write(lcr_h, uap, uap->lcrh_tx);
 	spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
@@ -1486,9 +1484,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;
 
-	pl011_write(pl011_read(regs, UART011_MIS), regs, UART011_ICR);
+	pl011_write(pl011_read(uap, UART011_MIS), uap, 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.
@@ -1502,8 +1499,8 @@ static void pl011_quiesce_irqs(struct uart_port *port)
 	 * (including tx queue), so we're also fine with start_tx()'s caller
 	 * side.
 	 */
-	pl011_write(pl011_read(regs, UART011_IMSC) & ~UART011_TXIM,
-		    regs, UART011_IMSC);
+	pl011_write(pl011_read(uap, UART011_IMSC) & ~UART011_TXIM, uap,
+		    UART011_IMSC);
 }
 
 static int pl011_get_poll_char(struct uart_port *port)
@@ -1518,11 +1515,11 @@ static int pl011_get_poll_char(struct uart_port *port)
 	 */
 	pl011_quiesce_irqs(port);
 
-	status = pl011_read(uap->port.membase, UART01x_FR);
+	status = pl011_read(uap, UART01x_FR);
 	if (status & UART01x_FR_RXFE)
 		return NO_POLL_CHAR;
 
-	return pl011_read(uap->port.membase, UART01x_DR);
+	return pl011_read(uap, UART01x_DR);
 }
 
 static void pl011_put_poll_char(struct uart_port *port,
@@ -1531,10 +1528,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 (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
+	while (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
 
-	pl011_write(ch, uap->port.membase, UART01x_DR);
+	pl011_write(ch, uap, UART01x_DR);
 }
 
 #endif /* CONFIG_CONSOLE_POLL */
@@ -1560,15 +1557,14 @@ static int pl011_hwinit(struct uart_port *port)
 	/* Clear pending error and receive interrupts */
 	pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
 		    UART011_FEIS | UART011_RTIS | UART011_RXIS,
-		    uap->port.membase, UART011_ICR);
+		    uap, UART011_ICR);
 
 	/*
 	 * Save interrupts enable mask, and enable RX interrupts in case if
 	 * the interrupt is used for NMI entry.
 	 */
-	uap->im = pl011_read(uap->port.membase, UART011_IMSC);
-	pl011_write(UART011_RTIM | UART011_RXIM, uap->port.membase,
-		    UART011_IMSC);
+	uap->im = pl011_read(uap, UART011_IMSC);
+	pl011_write(UART011_RTIM | UART011_RXIM, uap, UART011_IMSC);
 
 	if (dev_get_platdata(uap->port.dev)) {
 		struct amba_pl011_data *plat;
@@ -1582,7 +1578,7 @@ static int pl011_hwinit(struct uart_port *port)
 
 static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 {
-	pl011_write(lcr_h, uap->port.membase, uap->lcrh_rx);
+	pl011_write(lcr_h, uap, uap->lcrh_rx);
 	if (uap->lcrh_rx != uap->lcrh_tx) {
 		int i;
 		/*
@@ -1590,14 +1586,14 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 		 * to get this delay write read only register 10 times
 		 */
 		for (i = 0; i < 10; ++i)
-			pl011_write(0xff, uap->port.membase, UART011_MIS);
-		pl011_write(lcr_h, uap->port.membase, uap->lcrh_tx);
+			pl011_write(0xff, uap, UART011_MIS);
+		pl011_write(lcr_h, uap, uap->lcrh_tx);
 	}
 }
 
 static int pl011_allocate_irq(struct uart_amba_port *uap)
 {
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 
 	return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
 }
@@ -1612,12 +1608,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
 	spin_lock_irq(&uap->port.lock);
 
 	/* Clear out any spuriously appearing RX interrupts */
-	pl011_write(UART011_RTIS | UART011_RXIS, uap->port.membase,
-	            UART011_ICR);
+	pl011_write(UART011_RTIS | UART011_RXIS, uap, UART011_ICR);
 	uap->im = UART011_RTIM;
 	if (!pl011_dma_rx_running(uap))
 		uap->im |= UART011_RXIM;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
+	pl011_write(uap->im, uap, UART011_IMSC);
 	spin_unlock_irq(&uap->port.lock);
 }
 
@@ -1636,21 +1631,21 @@ static int pl011_startup(struct uart_port *port)
 	if (retval)
 		goto clk_dis;
 
-	pl011_write(uap->vendor->ifls, uap->port.membase, UART011_IFLS);
+	pl011_write(uap->vendor->ifls, uap, UART011_IFLS);
 
 	spin_lock_irq(&uap->port.lock);
 
 	/* restore RTS and DTR */
 	cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
 	cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
-	pl011_write(cr, uap->port.membase, UART011_CR);
+	pl011_write(cr, uap, UART011_CR);
 
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
 	 * initialise the old status of the modem signals
 	 */
-	uap->old_status = pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_MODEM_ANY;
+	uap->old_status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
 
 	/* Startup DMA */
 	pl011_dma_startup(uap);
@@ -1691,9 +1686,9 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap,
 {
       unsigned long val;
 
-      val = pl011_read(uap->port.membase, lcrh);
+      val = pl011_read(uap, lcrh);
       val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
-      pl011_write(val, uap->port.membase, lcrh);
+      pl011_write(val, uap, lcrh);
 }
 
 /*
@@ -1707,11 +1702,11 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 
 	uap->autorts = false;
 	spin_lock_irq(&uap->port.lock);
-	cr = pl011_read(uap->port.membase, UART011_CR);
+	cr = pl011_read(uap, UART011_CR);
 	uap->old_cr = cr;
 	cr &= UART011_CR_RTS | UART011_CR_DTR;
 	cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-	pl011_write(cr, uap->port.membase, UART011_CR);
+	pl011_write(cr, uap, UART011_CR);
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
@@ -1728,8 +1723,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap)
 
 	/* mask all interrupts and clear all pending ones */
 	uap->im = 0;
-	pl011_write(uap->im, uap->port.membase, UART011_IMSC);
-	pl011_write(0xffff, uap->port.membase, UART011_ICR);
+	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(0xffff, uap, UART011_ICR);
 
 	spin_unlock_irq(&uap->port.lock);
 }
@@ -1881,8 +1876,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 		pl011_enable_ms(port);
 
 	/* first, disable everything */
-	old_cr = pl011_read(port->membase, UART011_CR);
-	pl011_write(0, port->membase, UART011_CR);
+	old_cr = pl011_read(uap, UART011_CR);
+	pl011_write(0, uap, UART011_CR);
 
 	if (termios->c_cflag & CRTSCTS) {
 		if (old_cr & UART011_CR_RTS)
@@ -1915,8 +1910,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 			quot -= 2;
 	}
 	/* Set baud rate */
-	pl011_write(quot & 0x3f, port->membase, UART011_FBRD);
-	pl011_write(quot >> 6, port->membase, UART011_IBRD);
+	pl011_write(quot & 0x3f, uap, UART011_FBRD);
+	pl011_write(quot >> 6, uap, UART011_IBRD);
 
 	/*
 	 * ----------v----------v----------v----------v-----
@@ -1925,7 +1920,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 	 * ----------^----------^----------^----------^-----
 	 */
 	pl011_write_lcr_h(uap, lcr_h);
-	pl011_write(old_cr, port->membase, UART011_CR);
+	pl011_write(old_cr, uap, UART011_CR);
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -2066,9 +2061,9 @@ 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 (pl011_read(uap->port.membase, UART01x_FR) & UART01x_FR_TXFF)
+	while (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
-	pl011_write(ch, uap->port.membase, UART01x_DR);
+	pl011_write(ch, uap, UART01x_DR);
 }
 
 static void
@@ -2093,10 +2088,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	First save the CR then disable the interrupts
 	 */
 	if (!uap->vendor->always_enabled) {
-		old_cr = pl011_read(uap->port.membase, UART011_CR);
+		old_cr = pl011_read(uap, UART011_CR);
 		new_cr = old_cr & ~UART011_CR_CTSEN;
 		new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-		pl011_write(new_cr, uap->port.membase, UART011_CR);
+		pl011_write(new_cr, uap, UART011_CR);
 	}
 
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
@@ -2106,10 +2101,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	and restore the TCR
 	 */
 	do {
-		status = pl011_read(uap->port.membase, UART01x_FR);
+		status = pl011_read(uap, UART01x_FR);
 	} while (status & UART01x_FR_BUSY);
 	if (!uap->vendor->always_enabled)
-		pl011_write(old_cr, uap->port.membase, UART011_CR);
+		pl011_write(old_cr, uap, UART011_CR);
 
 	if (locked)
 		spin_unlock(&uap->port.lock);
@@ -2122,10 +2117,10 @@ static void __init
 pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 			     int *parity, int *bits)
 {
-	if (pl011_read(uap->port.membase, UART011_CR) & UART01x_CR_UARTEN) {
+	if (pl011_read(uap, UART011_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
 
-		lcr_h = pl011_read(uap->port.membase, uap->lcrh_tx);
+		lcr_h = pl011_read(uap, uap->lcrh_tx);
 
 		*parity = 'n';
 		if (lcr_h & UART01x_LCRH_PEN) {
@@ -2140,13 +2135,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 		else
 			*bits = 8;
 
-		ibrd = pl011_read(uap->port.membase, UART011_IBRD);
-		fbrd = pl011_read(uap->port.membase, UART011_FBRD);
+		ibrd = pl011_read(uap, UART011_IBRD);
+		fbrd = pl011_read(uap, UART011_FBRD);
 
 		*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 
 		if (uap->vendor->oversampling) {
-			if (pl011_read(uap->port.membase, UART011_CR)
+			if (pl011_read(uap, UART011_CR)
 				  & ST_UART011_CR_OVSFACT)
 				*baud *= 2;
 		}
@@ -2348,8 +2343,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
 	int ret;
 
 	/* Ensure interrupts from this UART are masked and cleared */
-	pl011_write(0, uap->port.membase, UART011_IMSC);
-	pl011_write(0xffff, uap->port.membase, UART011_ICR);
+	pl011_write(0, uap, UART011_IMSC);
+	pl011_write(0xffff, uap, UART011_ICR);
 
 	if (!amba_reg.state) {
 		ret = uart_register_driver(&amba_reg);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 03/11] tty: amba-pl011: add helper to detect split LCRH register
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:51     ` Russell King
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Add a helper to detect the split LCRH register found on ST variants.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 61512afb10da..63a916bb76f1 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1576,10 +1576,15 @@ static int pl011_hwinit(struct uart_port *port)
 	return 0;
 }
 
+static bool pl011_split_lcrh(const struct uart_amba_port *uap)
+{
+	return uap->lcrh_rx != uap->lcrh_tx;
+}
+
 static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 {
 	pl011_write(lcr_h, uap, uap->lcrh_rx);
-	if (uap->lcrh_rx != uap->lcrh_tx) {
+	if (pl011_split_lcrh(uap)) {
 		int i;
 		/*
 		 * Wait 10 PCLKs before writing LCRH_TX register,
@@ -1713,7 +1718,7 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 	 * disable break condition and fifos
 	 */
 	pl011_shutdown_channel(uap, uap->lcrh_rx);
-	if (uap->lcrh_rx != uap->lcrh_tx)
+	if (pl011_split_lcrh(uap))
 		pl011_shutdown_channel(uap, uap->lcrh_tx);
 }
 
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 03/11] tty: amba-pl011: add helper to detect split LCRH register
@ 2015-11-03 14:51     ` Russell King
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add a helper to detect the split LCRH register found on ST variants.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 61512afb10da..63a916bb76f1 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1576,10 +1576,15 @@ static int pl011_hwinit(struct uart_port *port)
 	return 0;
 }
 
+static bool pl011_split_lcrh(const struct uart_amba_port *uap)
+{
+	return uap->lcrh_rx != uap->lcrh_tx;
+}
+
 static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 {
 	pl011_write(lcr_h, uap, uap->lcrh_rx);
-	if (uap->lcrh_rx != uap->lcrh_tx) {
+	if (pl011_split_lcrh(uap)) {
 		int i;
 		/*
 		 * Wait 10 PCLKs before writing LCRH_TX register,
@@ -1713,7 +1718,7 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 	 * disable break condition and fifos
 	 */
 	pl011_shutdown_channel(uap, uap->lcrh_rx);
-	if (uap->lcrh_rx != uap->lcrh_tx)
+	if (pl011_split_lcrh(uap))
 		pl011_shutdown_channel(uap, uap->lcrh_tx);
 }
 
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 04/11] tty: amba-pl011: prepare REG_* register indexes
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:51     ` Russell King
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Prepare for REG_* register accessors.  This change involves introducing
pl011_reg_to_offset() to convert REG_* to the hardware register offset,
and converting all call sites to use REG_* names.  We need to fix up
locations where we check for equivalence of register offsets as well.

Much of this change was made via these sed expressions:
s/ST_UART01[1x]\(_[^_]*\|_LCRH_[TR]X\)\>/REG_ST\1/
s/UART01[1x]_\(DR\|RSR\|ECR\|FR\|ILPR\|[IF]BRD\|LCRH\|CR\|IFLS\|IMSC\|RIS\|MIS\|ICR\|DMACR\)\>/REG_\1/g

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 205 +++++++++++++++++++++-------------------
 drivers/tty/serial/amba-pl011.h |  32 +++++++
 2 files changed, 140 insertions(+), 97 deletions(-)
 create mode 100644 drivers/tty/serial/amba-pl011.h

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 63a916bb76f1..b3a0956d8883 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -60,6 +60,8 @@
 #include <linux/io.h>
 #include <linux/acpi.h>
 
+#include "amba-pl011.h"
+
 #define UART_NR			14
 
 #define SERIAL_AMBA_MAJOR	204
@@ -92,8 +94,8 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
 
 static struct vendor_data vendor_arm = {
 	.ifls			= UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
-	.lcrh_tx		= UART011_LCRH,
-	.lcrh_rx		= UART011_LCRH,
+	.lcrh_tx		= REG_LCRH,
+	.lcrh_rx		= REG_LCRH,
 	.oversampling		= false,
 	.dma_threshold		= false,
 	.cts_event_workaround	= false,
@@ -117,8 +119,8 @@ static unsigned int get_fifosize_st(struct amba_device *dev)
 
 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,
+	.lcrh_tx		= REG_ST_LCRH_TX,
+	.lcrh_rx		= REG_ST_LCRH_RX,
 	.oversampling		= true,
 	.dma_threshold		= true,
 	.cts_event_workaround	= true,
@@ -184,16 +186,22 @@ struct uart_amba_port {
 #endif
 };
 
+static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap,
+	unsigned int reg)
+{
+	return reg;
+}
+
 static unsigned int pl011_read(const struct uart_amba_port *uap,
 	unsigned int reg)
 {
-	return readw(uap->port.membase + reg);
+	return readw(uap->port.membase + pl011_reg_to_offset(uap, reg));
 }
 
 static void pl011_write(unsigned int val, const struct uart_amba_port *uap,
 	unsigned int reg)
 {
-	writew(val, uap->port.membase + reg);
+	writew(val, uap->port.membase + pl011_reg_to_offset(uap, reg));
 }
 
 /*
@@ -208,12 +216,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
 	int fifotaken = 0;
 
 	while (max_count--) {
-		status = pl011_read(uap, UART01x_FR);
+		status = pl011_read(uap, REG_FR);
 		if (status & UART01x_FR_RXFE)
 			break;
 
 		/* Take chars from the FIFO and update status */
-		ch = pl011_read(uap, UART01x_DR) | UART_DUMMY_DR_RX;
+		ch = pl011_read(uap, REG_DR) | UART_DUMMY_DR_RX;
 		flag = TTY_NORMAL;
 		uap->port.icount.rx++;
 		fifotaken++;
@@ -295,7 +303,8 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
 	struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
 	struct device *dev = uap->port.dev;
 	struct dma_slave_config tx_conf = {
-		.dst_addr = uap->port.mapbase + UART01x_DR,
+		.dst_addr = uap->port.mapbase +
+				 pl011_reg_to_offset(uap, REG_DR),
 		.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
 		.direction = DMA_MEM_TO_DEV,
 		.dst_maxburst = uap->fifosize >> 1,
@@ -350,7 +359,8 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
 
 	if (chan) {
 		struct dma_slave_config rx_conf = {
-			.src_addr = uap->port.mapbase + UART01x_DR,
+			.src_addr = uap->port.mapbase +
+				pl011_reg_to_offset(uap, REG_DR),
 			.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
 			.direction = DMA_DEV_TO_MEM,
 			.src_maxburst = uap->fifosize >> 2,
@@ -449,7 +459,7 @@ static void pl011_dma_tx_callback(void *data)
 
 	dmacr = uap->dmacr;
 	uap->dmacr = dmacr & ~UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 
 	/*
 	 * If TX DMA was disabled, it means that we've stopped the DMA for
@@ -563,7 +573,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
 	dma_dev->device_issue_pending(chan);
 
 	uap->dmacr |= UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 	uap->dmatx.queued = true;
 
 	/*
@@ -599,9 +609,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
 	 */
 	if (uap->dmatx.queued) {
 		uap->dmacr |= UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, REG_DMACR);
 		uap->im &= ~UART011_TXIM;
-		pl011_write(uap->im, uap, UART011_IMSC);
+		pl011_write(uap->im, uap, REG_IMSC);
 		return true;
 	}
 
@@ -611,7 +621,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
 	 */
 	if (pl011_dma_tx_refill(uap) > 0) {
 		uap->im &= ~UART011_TXIM;
-		pl011_write(uap->im, uap, UART011_IMSC);
+		pl011_write(uap->im, uap, REG_IMSC);
 		return true;
 	}
 	return false;
@@ -625,7 +635,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
 {
 	if (uap->dmatx.queued) {
 		uap->dmacr &= ~UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, REG_DMACR);
 	}
 }
 
@@ -651,12 +661,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		if (!uap->dmatx.queued) {
 			if (pl011_dma_tx_refill(uap) > 0) {
 				uap->im &= ~UART011_TXIM;
-				pl011_write(uap->im, uap, UART011_IMSC);
+				pl011_write(uap->im, uap, REG_IMSC);
 			} else
 				ret = false;
 		} else if (!(uap->dmacr & UART011_TXDMAE)) {
 			uap->dmacr |= UART011_TXDMAE;
-			pl011_write(uap->dmacr, uap, UART011_DMACR);
+			pl011_write(uap->dmacr, uap, REG_DMACR);
 		}
 		return ret;
 	}
@@ -667,9 +677,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 	 */
 	dmacr = uap->dmacr;
 	uap->dmacr &= ~UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 
-	if (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF) {
+	if (pl011_read(uap, REG_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
@@ -678,13 +688,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		return false;
 	}
 
-	pl011_write(uap->port.x_char, uap, UART01x_DR);
+	pl011_write(uap->port.x_char, uap, REG_DR);
 	uap->port.icount.tx++;
 	uap->port.x_char = 0;
 
 	/* Success - restore the DMA state */
 	uap->dmacr = dmacr;
-	pl011_write(dmacr, uap, UART011_DMACR);
+	pl011_write(dmacr, uap, REG_DMACR);
 
 	return true;
 }
@@ -712,7 +722,7 @@ __acquires(&uap->port.lock)
 			     DMA_TO_DEVICE);
 		uap->dmatx.queued = false;
 		uap->dmacr &= ~UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, REG_DMACR);
 	}
 }
 
@@ -752,11 +762,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
 	dma_async_issue_pending(rxchan);
 
 	uap->dmacr |= UART011_RXDMAE;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 	uap->dmarx.running = true;
 
 	uap->im &= ~UART011_RXIM;
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 
 	return 0;
 }
@@ -815,7 +825,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
 	if (dma_count == pending && readfifo) {
 		/* Clear any error flags */
 		pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
-			    UART011_FEIS, uap, UART011_ICR);
+			    UART011_FEIS, uap, REG_ICR);
 
 		/*
 		 * If we read all the DMA'd characters, and we had an
@@ -863,7 +873,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;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 	uap->dmarx.running = false;
 
 	pending = sgbuf->sg.length - state.residue;
@@ -883,7 +893,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;
-		pl011_write(uap->im, uap, UART011_IMSC);
+		pl011_write(uap->im, uap, REG_IMSC);
 	}
 }
 
@@ -931,7 +941,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;
-		pl011_write(uap->im, uap, UART011_IMSC);
+		pl011_write(uap->im, uap, REG_IMSC);
 	}
 }
 
@@ -944,7 +954,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
 {
 	/* FIXME.  Just disable the DMA enable */
 	uap->dmacr &= ~UART011_RXDMAE;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 }
 
 /*
@@ -988,7 +998,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;
-		pl011_write(uap->im, uap, UART011_IMSC);
+		pl011_write(uap->im, uap, REG_IMSC);
 		spin_unlock_irqrestore(&uap->port.lock, flags);
 
 		uap->dmarx.running = false;
@@ -1050,7 +1060,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;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 
 	/*
 	 * ST Micro variants has some specific dma burst threshold
@@ -1059,7 +1069,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 	 */
 	if (uap->vendor->dma_threshold)
 		pl011_write(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
-			    uap, ST_UART011_DMAWM);
+			    uap, REG_ST_DMAWM);
 
 	if (uap->using_rx_dma) {
 		if (pl011_dma_rx_trigger_dma(uap))
@@ -1084,12 +1094,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
 		return;
 
 	/* Disable RX and TX DMA */
-	while (pl011_read(uap, UART01x_FR) & UART01x_FR_BUSY)
+	while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY)
 		barrier();
 
 	spin_lock_irq(&uap->port.lock);
 	uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 	spin_unlock_irq(&uap->port.lock);
 
 	if (uap->using_tx_dma) {
@@ -1190,7 +1200,7 @@ static void pl011_stop_tx(struct uart_port *port)
 	    container_of(port, struct uart_amba_port, port);
 
 	uap->im &= ~UART011_TXIM;
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 	pl011_dma_tx_stop(uap);
 }
 
@@ -1200,7 +1210,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 {
 	uap->im |= UART011_TXIM;
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 	pl011_tx_chars(uap, false);
 }
 
@@ -1220,7 +1230,7 @@ static void pl011_stop_rx(struct uart_port *port)
 
 	uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
 		     UART011_PEIM|UART011_BEIM|UART011_OEIM);
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 
 	pl011_dma_rx_stop(uap);
 }
@@ -1231,7 +1241,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;
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 }
 
 static void pl011_rx_chars(struct uart_amba_port *uap)
@@ -1251,7 +1261,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;
-			pl011_write(uap->im, uap, UART011_IMSC);
+			pl011_write(uap->im, uap, REG_IMSC);
 		} else {
 #ifdef CONFIG_DMA_ENGINE
 			/* Start Rx DMA poll */
@@ -1272,10 +1282,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
 			  bool from_irq)
 {
 	if (unlikely(!from_irq) &&
-	    pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
+	    pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
 		return false; /* unable to transmit character */
 
-	pl011_write(c, uap, UART01x_DR);
+	pl011_write(c, uap, REG_DR);
 	uap->port.icount.tx++;
 
 	return true;
@@ -1322,7 +1332,7 @@ static void pl011_modem_status(struct uart_amba_port *uap)
 {
 	unsigned int status, delta;
 
-	status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
+	status = pl011_read(uap, REG_FR) & UART01x_FR_MODEM_ANY;
 
 	delta = status ^ uap->old_status;
 	uap->old_status = status;
@@ -1350,15 +1360,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
 		return;
 
 	/* workaround to make sure that all bits are unlocked.. */
-	pl011_write(0x00, uap, UART011_ICR);
+	pl011_write(0x00, uap, REG_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 = pl011_read(uap, UART011_ICR);
-	dummy_read = pl011_read(uap, UART011_ICR);
+	dummy_read = pl011_read(uap, REG_ICR);
+	dummy_read = pl011_read(uap, REG_ICR);
 }
 
 static irqreturn_t pl011_int(int irq, void *dev_id)
@@ -1370,15 +1380,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 	int handled = 0;
 
 	spin_lock_irqsave(&uap->port.lock, flags);
-	imsc = pl011_read(uap, UART011_IMSC);
-	status = pl011_read(uap, UART011_RIS) & imsc;
+	imsc = pl011_read(uap, REG_IMSC);
+	status = pl011_read(uap, REG_RIS) & imsc;
 	if (status) {
 		do {
 			check_apply_cts_event_workaround(uap);
 
 			pl011_write(status & ~(UART011_TXIS|UART011_RTIS|
 					       UART011_RXIS),
-				    uap, UART011_ICR);
+				    uap, REG_ICR);
 
 			if (status & (UART011_RTIS|UART011_RXIS)) {
 				if (pl011_dma_rx_running(uap))
@@ -1395,7 +1405,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 			if (pass_counter-- == 0)
 				break;
 
-			status = pl011_read(uap, UART011_RIS) & imsc;
+			status = pl011_read(uap, REG_RIS) & imsc;
 		} while (status != 0);
 		handled = 1;
 	}
@@ -1409,7 +1419,7 @@ 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 = pl011_read(uap, UART01x_FR);
+	unsigned int status = pl011_read(uap, REG_FR);
 	return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
 }
 
@@ -1418,7 +1428,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
 	struct uart_amba_port *uap =
 	    container_of(port, struct uart_amba_port, port);
 	unsigned int result = 0;
-	unsigned int status = pl011_read(uap, UART01x_FR);
+	unsigned int status = pl011_read(uap, REG_FR);
 
 #define TIOCMBIT(uartbit, tiocmbit)	\
 	if (status & uartbit)		\
@@ -1438,7 +1448,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 = pl011_read(uap, UART011_CR);
+	cr = pl011_read(uap, REG_CR);
 
 #define	TIOCMBIT(tiocmbit, uartbit)		\
 	if (mctrl & tiocmbit)		\
@@ -1458,7 +1468,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	}
 #undef TIOCMBIT
 
-	pl011_write(cr, uap, UART011_CR);
+	pl011_write(cr, uap, REG_CR);
 }
 
 static void pl011_break_ctl(struct uart_port *port, int break_state)
@@ -1485,7 +1495,7 @@ static void pl011_quiesce_irqs(struct uart_port *port)
 	struct uart_amba_port *uap =
 	    container_of(port, struct uart_amba_port, port);
 
-	pl011_write(pl011_read(uap, UART011_MIS), uap, UART011_ICR);
+	pl011_write(pl011_read(uap, REG_MIS), uap, REG_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.
@@ -1499,8 +1509,8 @@ static void pl011_quiesce_irqs(struct uart_port *port)
 	 * (including tx queue), so we're also fine with start_tx()'s caller
 	 * side.
 	 */
-	pl011_write(pl011_read(uap, UART011_IMSC) & ~UART011_TXIM, uap,
-		    UART011_IMSC);
+	pl011_write(pl011_read(uap, REG_IMSC) & ~UART011_TXIM, uap,
+		    REG_IMSC);
 }
 
 static int pl011_get_poll_char(struct uart_port *port)
@@ -1515,11 +1525,11 @@ static int pl011_get_poll_char(struct uart_port *port)
 	 */
 	pl011_quiesce_irqs(port);
 
-	status = pl011_read(uap, UART01x_FR);
+	status = pl011_read(uap, REG_FR);
 	if (status & UART01x_FR_RXFE)
 		return NO_POLL_CHAR;
 
-	return pl011_read(uap, UART01x_DR);
+	return pl011_read(uap, REG_DR);
 }
 
 static void pl011_put_poll_char(struct uart_port *port,
@@ -1528,10 +1538,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 (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
+	while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
 		barrier();
 
-	pl011_write(ch, uap, UART01x_DR);
+	pl011_write(ch, uap, REG_DR);
 }
 
 #endif /* CONFIG_CONSOLE_POLL */
@@ -1557,14 +1567,14 @@ static int pl011_hwinit(struct uart_port *port)
 	/* Clear pending error and receive interrupts */
 	pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
 		    UART011_FEIS | UART011_RTIS | UART011_RXIS,
-		    uap, UART011_ICR);
+		    uap, REG_ICR);
 
 	/*
 	 * Save interrupts enable mask, and enable RX interrupts in case if
 	 * the interrupt is used for NMI entry.
 	 */
-	uap->im = pl011_read(uap, UART011_IMSC);
-	pl011_write(UART011_RTIM | UART011_RXIM, uap, UART011_IMSC);
+	uap->im = pl011_read(uap, REG_IMSC);
+	pl011_write(UART011_RTIM | UART011_RXIM, uap, REG_IMSC);
 
 	if (dev_get_platdata(uap->port.dev)) {
 		struct amba_pl011_data *plat;
@@ -1578,7 +1588,8 @@ static int pl011_hwinit(struct uart_port *port)
 
 static bool pl011_split_lcrh(const struct uart_amba_port *uap)
 {
-	return uap->lcrh_rx != uap->lcrh_tx;
+	return pl011_reg_to_offset(uap, uap->lcrh_rx) !=
+	       pl011_reg_to_offset(uap, uap->lcrh_tx);
 }
 
 static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
@@ -1591,14 +1602,14 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 		 * to get this delay write read only register 10 times
 		 */
 		for (i = 0; i < 10; ++i)
-			pl011_write(0xff, uap, UART011_MIS);
+			pl011_write(0xff, uap, REG_MIS);
 		pl011_write(lcr_h, uap, uap->lcrh_tx);
 	}
 }
 
 static int pl011_allocate_irq(struct uart_amba_port *uap)
 {
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 
 	return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
 }
@@ -1613,11 +1624,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
 	spin_lock_irq(&uap->port.lock);
 
 	/* Clear out any spuriously appearing RX interrupts */
-	pl011_write(UART011_RTIS | UART011_RXIS, uap, UART011_ICR);
+	pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR);
 	uap->im = UART011_RTIM;
 	if (!pl011_dma_rx_running(uap))
 		uap->im |= UART011_RXIM;
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 	spin_unlock_irq(&uap->port.lock);
 }
 
@@ -1636,21 +1647,21 @@ static int pl011_startup(struct uart_port *port)
 	if (retval)
 		goto clk_dis;
 
-	pl011_write(uap->vendor->ifls, uap, UART011_IFLS);
+	pl011_write(uap->vendor->ifls, uap, REG_IFLS);
 
 	spin_lock_irq(&uap->port.lock);
 
 	/* restore RTS and DTR */
 	cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
 	cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
-	pl011_write(cr, uap, UART011_CR);
+	pl011_write(cr, uap, REG_CR);
 
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
 	 * initialise the old status of the modem signals
 	 */
-	uap->old_status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
+	uap->old_status = pl011_read(uap, REG_FR) & UART01x_FR_MODEM_ANY;
 
 	/* Startup DMA */
 	pl011_dma_startup(uap);
@@ -1707,11 +1718,11 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 
 	uap->autorts = false;
 	spin_lock_irq(&uap->port.lock);
-	cr = pl011_read(uap, UART011_CR);
+	cr = pl011_read(uap, REG_CR);
 	uap->old_cr = cr;
 	cr &= UART011_CR_RTS | UART011_CR_DTR;
 	cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-	pl011_write(cr, uap, UART011_CR);
+	pl011_write(cr, uap, REG_CR);
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
@@ -1728,8 +1739,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap)
 
 	/* mask all interrupts and clear all pending ones */
 	uap->im = 0;
-	pl011_write(uap->im, uap, UART011_IMSC);
-	pl011_write(0xffff, uap, UART011_ICR);
+	pl011_write(uap->im, uap, REG_IMSC);
+	pl011_write(0xffff, uap, REG_ICR);
 
 	spin_unlock_irq(&uap->port.lock);
 }
@@ -1881,8 +1892,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 		pl011_enable_ms(port);
 
 	/* first, disable everything */
-	old_cr = pl011_read(uap, UART011_CR);
-	pl011_write(0, uap, UART011_CR);
+	old_cr = pl011_read(uap, REG_CR);
+	pl011_write(0, uap, REG_CR);
 
 	if (termios->c_cflag & CRTSCTS) {
 		if (old_cr & UART011_CR_RTS)
@@ -1915,17 +1926,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 			quot -= 2;
 	}
 	/* Set baud rate */
-	pl011_write(quot & 0x3f, uap, UART011_FBRD);
-	pl011_write(quot >> 6, uap, UART011_IBRD);
+	pl011_write(quot & 0x3f, uap, REG_FBRD);
+	pl011_write(quot >> 6, uap, REG_IBRD);
 
 	/*
 	 * ----------v----------v----------v----------v-----
 	 * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER
-	 * UART011_FBRD & UART011_IBRD.
+	 * REG_FBRD & REG_IBRD.
 	 * ----------^----------^----------^----------^-----
 	 */
 	pl011_write_lcr_h(uap, lcr_h);
-	pl011_write(old_cr, uap, UART011_CR);
+	pl011_write(old_cr, uap, REG_CR);
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -2066,9 +2077,9 @@ 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 (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
+	while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
 		barrier();
-	pl011_write(ch, uap, UART01x_DR);
+	pl011_write(ch, uap, REG_DR);
 }
 
 static void
@@ -2093,10 +2104,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	First save the CR then disable the interrupts
 	 */
 	if (!uap->vendor->always_enabled) {
-		old_cr = pl011_read(uap, UART011_CR);
+		old_cr = pl011_read(uap, REG_CR);
 		new_cr = old_cr & ~UART011_CR_CTSEN;
 		new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-		pl011_write(new_cr, uap, UART011_CR);
+		pl011_write(new_cr, uap, REG_CR);
 	}
 
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
@@ -2106,10 +2117,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	and restore the TCR
 	 */
 	do {
-		status = pl011_read(uap, UART01x_FR);
+		status = pl011_read(uap, REG_FR);
 	} while (status & UART01x_FR_BUSY);
 	if (!uap->vendor->always_enabled)
-		pl011_write(old_cr, uap, UART011_CR);
+		pl011_write(old_cr, uap, REG_CR);
 
 	if (locked)
 		spin_unlock(&uap->port.lock);
@@ -2122,7 +2133,7 @@ static void __init
 pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 			     int *parity, int *bits)
 {
-	if (pl011_read(uap, UART011_CR) & UART01x_CR_UARTEN) {
+	if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
 
 		lcr_h = pl011_read(uap, uap->lcrh_tx);
@@ -2140,13 +2151,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 		else
 			*bits = 8;
 
-		ibrd = pl011_read(uap, UART011_IBRD);
-		fbrd = pl011_read(uap, UART011_FBRD);
+		ibrd = pl011_read(uap, REG_IBRD);
+		fbrd = pl011_read(uap, REG_FBRD);
 
 		*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 
 		if (uap->vendor->oversampling) {
-			if (pl011_read(uap, UART011_CR)
+			if (pl011_read(uap, REG_CR)
 				  & ST_UART011_CR_OVSFACT)
 				*baud *= 2;
 		}
@@ -2218,10 +2229,10 @@ static struct console amba_console = {
 
 static void pl011_putc(struct uart_port *port, int c)
 {
-	while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
+	while (readl(port->membase + REG_FR) & UART01x_FR_TXFF)
 		;
-	writeb(c, port->membase + UART01x_DR);
-	while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY)
+	writeb(c, port->membase + REG_DR);
+	while (readl(port->membase + REG_FR) & UART01x_FR_BUSY)
 		;
 }
 
@@ -2348,8 +2359,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
 	int ret;
 
 	/* Ensure interrupts from this UART are masked and cleared */
-	pl011_write(0, uap, UART011_IMSC);
-	pl011_write(0xffff, uap, UART011_ICR);
+	pl011_write(0, uap, REG_IMSC);
+	pl011_write(0xffff, uap, REG_ICR);
 
 	if (!amba_reg.state) {
 		ret = uart_register_driver(&amba_reg);
diff --git a/drivers/tty/serial/amba-pl011.h b/drivers/tty/serial/amba-pl011.h
new file mode 100644
index 000000000000..b7eb1bc2fab9
--- /dev/null
+++ b/drivers/tty/serial/amba-pl011.h
@@ -0,0 +1,32 @@
+#ifndef AMBA_PL011_H
+#define AMBA_PL011_H
+
+enum {
+	REG_DR = UART01x_DR,
+	REG_ST_DMAWM = ST_UART011_DMAWM,
+	REG_ST_TIMEOUT = ST_UART011_TIMEOUT,
+	REG_FR = UART01x_FR,
+	REG_ST_LCRH_RX = ST_UART011_LCRH_RX,
+	REG_IBRD = UART011_IBRD,
+	REG_FBRD = UART011_FBRD,
+	REG_LCRH = UART011_LCRH,
+	REG_ST_LCRH_TX = ST_UART011_LCRH_TX,
+	REG_CR = UART011_CR,
+	REG_IFLS = UART011_IFLS,
+	REG_IMSC = UART011_IMSC,
+	REG_RIS = UART011_RIS,
+	REG_MIS = UART011_MIS,
+	REG_ICR = UART011_ICR,
+	REG_DMACR = UART011_DMACR,
+	REG_ST_XFCR = ST_UART011_XFCR,
+	REG_ST_XON1 = ST_UART011_XON1,
+	REG_ST_XON2 = ST_UART011_XON2,
+	REG_ST_XOFF1 = ST_UART011_XOFF1,
+	REG_ST_XOFF2 = ST_UART011_XOFF2,
+	REG_ST_ITCR = ST_UART011_ITCR,
+	REG_ST_ITIP = ST_UART011_ITIP,
+	REG_ST_ABCR = ST_UART011_ABCR,
+	REG_ST_ABIMSC = ST_UART011_ABIMSC,
+};
+
+#endif
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 04/11] tty: amba-pl011: prepare REG_* register indexes
@ 2015-11-03 14:51     ` Russell King
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

Prepare for REG_* register accessors.  This change involves introducing
pl011_reg_to_offset() to convert REG_* to the hardware register offset,
and converting all call sites to use REG_* names.  We need to fix up
locations where we check for equivalence of register offsets as well.

Much of this change was made via these sed expressions:
s/ST_UART01[1x]\(_[^_]*\|_LCRH_[TR]X\)\>/REG_ST\1/
s/UART01[1x]_\(DR\|RSR\|ECR\|FR\|ILPR\|[IF]BRD\|LCRH\|CR\|IFLS\|IMSC\|RIS\|MIS\|ICR\|DMACR\)\>/REG_\1/g

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 205 +++++++++++++++++++++-------------------
 drivers/tty/serial/amba-pl011.h |  32 +++++++
 2 files changed, 140 insertions(+), 97 deletions(-)
 create mode 100644 drivers/tty/serial/amba-pl011.h

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 63a916bb76f1..b3a0956d8883 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -60,6 +60,8 @@
 #include <linux/io.h>
 #include <linux/acpi.h>
 
+#include "amba-pl011.h"
+
 #define UART_NR			14
 
 #define SERIAL_AMBA_MAJOR	204
@@ -92,8 +94,8 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
 
 static struct vendor_data vendor_arm = {
 	.ifls			= UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
-	.lcrh_tx		= UART011_LCRH,
-	.lcrh_rx		= UART011_LCRH,
+	.lcrh_tx		= REG_LCRH,
+	.lcrh_rx		= REG_LCRH,
 	.oversampling		= false,
 	.dma_threshold		= false,
 	.cts_event_workaround	= false,
@@ -117,8 +119,8 @@ static unsigned int get_fifosize_st(struct amba_device *dev)
 
 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,
+	.lcrh_tx		= REG_ST_LCRH_TX,
+	.lcrh_rx		= REG_ST_LCRH_RX,
 	.oversampling		= true,
 	.dma_threshold		= true,
 	.cts_event_workaround	= true,
@@ -184,16 +186,22 @@ struct uart_amba_port {
 #endif
 };
 
+static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap,
+	unsigned int reg)
+{
+	return reg;
+}
+
 static unsigned int pl011_read(const struct uart_amba_port *uap,
 	unsigned int reg)
 {
-	return readw(uap->port.membase + reg);
+	return readw(uap->port.membase + pl011_reg_to_offset(uap, reg));
 }
 
 static void pl011_write(unsigned int val, const struct uart_amba_port *uap,
 	unsigned int reg)
 {
-	writew(val, uap->port.membase + reg);
+	writew(val, uap->port.membase + pl011_reg_to_offset(uap, reg));
 }
 
 /*
@@ -208,12 +216,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
 	int fifotaken = 0;
 
 	while (max_count--) {
-		status = pl011_read(uap, UART01x_FR);
+		status = pl011_read(uap, REG_FR);
 		if (status & UART01x_FR_RXFE)
 			break;
 
 		/* Take chars from the FIFO and update status */
-		ch = pl011_read(uap, UART01x_DR) | UART_DUMMY_DR_RX;
+		ch = pl011_read(uap, REG_DR) | UART_DUMMY_DR_RX;
 		flag = TTY_NORMAL;
 		uap->port.icount.rx++;
 		fifotaken++;
@@ -295,7 +303,8 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
 	struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
 	struct device *dev = uap->port.dev;
 	struct dma_slave_config tx_conf = {
-		.dst_addr = uap->port.mapbase + UART01x_DR,
+		.dst_addr = uap->port.mapbase +
+				 pl011_reg_to_offset(uap, REG_DR),
 		.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
 		.direction = DMA_MEM_TO_DEV,
 		.dst_maxburst = uap->fifosize >> 1,
@@ -350,7 +359,8 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
 
 	if (chan) {
 		struct dma_slave_config rx_conf = {
-			.src_addr = uap->port.mapbase + UART01x_DR,
+			.src_addr = uap->port.mapbase +
+				pl011_reg_to_offset(uap, REG_DR),
 			.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
 			.direction = DMA_DEV_TO_MEM,
 			.src_maxburst = uap->fifosize >> 2,
@@ -449,7 +459,7 @@ static void pl011_dma_tx_callback(void *data)
 
 	dmacr = uap->dmacr;
 	uap->dmacr = dmacr & ~UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 
 	/*
 	 * If TX DMA was disabled, it means that we've stopped the DMA for
@@ -563,7 +573,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
 	dma_dev->device_issue_pending(chan);
 
 	uap->dmacr |= UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 	uap->dmatx.queued = true;
 
 	/*
@@ -599,9 +609,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
 	 */
 	if (uap->dmatx.queued) {
 		uap->dmacr |= UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, REG_DMACR);
 		uap->im &= ~UART011_TXIM;
-		pl011_write(uap->im, uap, UART011_IMSC);
+		pl011_write(uap->im, uap, REG_IMSC);
 		return true;
 	}
 
@@ -611,7 +621,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
 	 */
 	if (pl011_dma_tx_refill(uap) > 0) {
 		uap->im &= ~UART011_TXIM;
-		pl011_write(uap->im, uap, UART011_IMSC);
+		pl011_write(uap->im, uap, REG_IMSC);
 		return true;
 	}
 	return false;
@@ -625,7 +635,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
 {
 	if (uap->dmatx.queued) {
 		uap->dmacr &= ~UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, REG_DMACR);
 	}
 }
 
@@ -651,12 +661,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		if (!uap->dmatx.queued) {
 			if (pl011_dma_tx_refill(uap) > 0) {
 				uap->im &= ~UART011_TXIM;
-				pl011_write(uap->im, uap, UART011_IMSC);
+				pl011_write(uap->im, uap, REG_IMSC);
 			} else
 				ret = false;
 		} else if (!(uap->dmacr & UART011_TXDMAE)) {
 			uap->dmacr |= UART011_TXDMAE;
-			pl011_write(uap->dmacr, uap, UART011_DMACR);
+			pl011_write(uap->dmacr, uap, REG_DMACR);
 		}
 		return ret;
 	}
@@ -667,9 +677,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 	 */
 	dmacr = uap->dmacr;
 	uap->dmacr &= ~UART011_TXDMAE;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 
-	if (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF) {
+	if (pl011_read(uap, REG_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
@@ -678,13 +688,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		return false;
 	}
 
-	pl011_write(uap->port.x_char, uap, UART01x_DR);
+	pl011_write(uap->port.x_char, uap, REG_DR);
 	uap->port.icount.tx++;
 	uap->port.x_char = 0;
 
 	/* Success - restore the DMA state */
 	uap->dmacr = dmacr;
-	pl011_write(dmacr, uap, UART011_DMACR);
+	pl011_write(dmacr, uap, REG_DMACR);
 
 	return true;
 }
@@ -712,7 +722,7 @@ __acquires(&uap->port.lock)
 			     DMA_TO_DEVICE);
 		uap->dmatx.queued = false;
 		uap->dmacr &= ~UART011_TXDMAE;
-		pl011_write(uap->dmacr, uap, UART011_DMACR);
+		pl011_write(uap->dmacr, uap, REG_DMACR);
 	}
 }
 
@@ -752,11 +762,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
 	dma_async_issue_pending(rxchan);
 
 	uap->dmacr |= UART011_RXDMAE;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 	uap->dmarx.running = true;
 
 	uap->im &= ~UART011_RXIM;
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 
 	return 0;
 }
@@ -815,7 +825,7 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
 	if (dma_count == pending && readfifo) {
 		/* Clear any error flags */
 		pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
-			    UART011_FEIS, uap, UART011_ICR);
+			    UART011_FEIS, uap, REG_ICR);
 
 		/*
 		 * If we read all the DMA'd characters, and we had an
@@ -863,7 +873,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;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 	uap->dmarx.running = false;
 
 	pending = sgbuf->sg.length - state.residue;
@@ -883,7 +893,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;
-		pl011_write(uap->im, uap, UART011_IMSC);
+		pl011_write(uap->im, uap, REG_IMSC);
 	}
 }
 
@@ -931,7 +941,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;
-		pl011_write(uap->im, uap, UART011_IMSC);
+		pl011_write(uap->im, uap, REG_IMSC);
 	}
 }
 
@@ -944,7 +954,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
 {
 	/* FIXME.  Just disable the DMA enable */
 	uap->dmacr &= ~UART011_RXDMAE;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 }
 
 /*
@@ -988,7 +998,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;
-		pl011_write(uap->im, uap, UART011_IMSC);
+		pl011_write(uap->im, uap, REG_IMSC);
 		spin_unlock_irqrestore(&uap->port.lock, flags);
 
 		uap->dmarx.running = false;
@@ -1050,7 +1060,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;
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 
 	/*
 	 * ST Micro variants has some specific dma burst threshold
@@ -1059,7 +1069,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 	 */
 	if (uap->vendor->dma_threshold)
 		pl011_write(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
-			    uap, ST_UART011_DMAWM);
+			    uap, REG_ST_DMAWM);
 
 	if (uap->using_rx_dma) {
 		if (pl011_dma_rx_trigger_dma(uap))
@@ -1084,12 +1094,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
 		return;
 
 	/* Disable RX and TX DMA */
-	while (pl011_read(uap, UART01x_FR) & UART01x_FR_BUSY)
+	while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY)
 		barrier();
 
 	spin_lock_irq(&uap->port.lock);
 	uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
-	pl011_write(uap->dmacr, uap, UART011_DMACR);
+	pl011_write(uap->dmacr, uap, REG_DMACR);
 	spin_unlock_irq(&uap->port.lock);
 
 	if (uap->using_tx_dma) {
@@ -1190,7 +1200,7 @@ static void pl011_stop_tx(struct uart_port *port)
 	    container_of(port, struct uart_amba_port, port);
 
 	uap->im &= ~UART011_TXIM;
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 	pl011_dma_tx_stop(uap);
 }
 
@@ -1200,7 +1210,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 {
 	uap->im |= UART011_TXIM;
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 	pl011_tx_chars(uap, false);
 }
 
@@ -1220,7 +1230,7 @@ static void pl011_stop_rx(struct uart_port *port)
 
 	uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
 		     UART011_PEIM|UART011_BEIM|UART011_OEIM);
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 
 	pl011_dma_rx_stop(uap);
 }
@@ -1231,7 +1241,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;
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 }
 
 static void pl011_rx_chars(struct uart_amba_port *uap)
@@ -1251,7 +1261,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;
-			pl011_write(uap->im, uap, UART011_IMSC);
+			pl011_write(uap->im, uap, REG_IMSC);
 		} else {
 #ifdef CONFIG_DMA_ENGINE
 			/* Start Rx DMA poll */
@@ -1272,10 +1282,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
 			  bool from_irq)
 {
 	if (unlikely(!from_irq) &&
-	    pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
+	    pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
 		return false; /* unable to transmit character */
 
-	pl011_write(c, uap, UART01x_DR);
+	pl011_write(c, uap, REG_DR);
 	uap->port.icount.tx++;
 
 	return true;
@@ -1322,7 +1332,7 @@ static void pl011_modem_status(struct uart_amba_port *uap)
 {
 	unsigned int status, delta;
 
-	status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
+	status = pl011_read(uap, REG_FR) & UART01x_FR_MODEM_ANY;
 
 	delta = status ^ uap->old_status;
 	uap->old_status = status;
@@ -1350,15 +1360,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
 		return;
 
 	/* workaround to make sure that all bits are unlocked.. */
-	pl011_write(0x00, uap, UART011_ICR);
+	pl011_write(0x00, uap, REG_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 = pl011_read(uap, UART011_ICR);
-	dummy_read = pl011_read(uap, UART011_ICR);
+	dummy_read = pl011_read(uap, REG_ICR);
+	dummy_read = pl011_read(uap, REG_ICR);
 }
 
 static irqreturn_t pl011_int(int irq, void *dev_id)
@@ -1370,15 +1380,15 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 	int handled = 0;
 
 	spin_lock_irqsave(&uap->port.lock, flags);
-	imsc = pl011_read(uap, UART011_IMSC);
-	status = pl011_read(uap, UART011_RIS) & imsc;
+	imsc = pl011_read(uap, REG_IMSC);
+	status = pl011_read(uap, REG_RIS) & imsc;
 	if (status) {
 		do {
 			check_apply_cts_event_workaround(uap);
 
 			pl011_write(status & ~(UART011_TXIS|UART011_RTIS|
 					       UART011_RXIS),
-				    uap, UART011_ICR);
+				    uap, REG_ICR);
 
 			if (status & (UART011_RTIS|UART011_RXIS)) {
 				if (pl011_dma_rx_running(uap))
@@ -1395,7 +1405,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 			if (pass_counter-- == 0)
 				break;
 
-			status = pl011_read(uap, UART011_RIS) & imsc;
+			status = pl011_read(uap, REG_RIS) & imsc;
 		} while (status != 0);
 		handled = 1;
 	}
@@ -1409,7 +1419,7 @@ 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 = pl011_read(uap, UART01x_FR);
+	unsigned int status = pl011_read(uap, REG_FR);
 	return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
 }
 
@@ -1418,7 +1428,7 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
 	struct uart_amba_port *uap =
 	    container_of(port, struct uart_amba_port, port);
 	unsigned int result = 0;
-	unsigned int status = pl011_read(uap, UART01x_FR);
+	unsigned int status = pl011_read(uap, REG_FR);
 
 #define TIOCMBIT(uartbit, tiocmbit)	\
 	if (status & uartbit)		\
@@ -1438,7 +1448,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 = pl011_read(uap, UART011_CR);
+	cr = pl011_read(uap, REG_CR);
 
 #define	TIOCMBIT(tiocmbit, uartbit)		\
 	if (mctrl & tiocmbit)		\
@@ -1458,7 +1468,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	}
 #undef TIOCMBIT
 
-	pl011_write(cr, uap, UART011_CR);
+	pl011_write(cr, uap, REG_CR);
 }
 
 static void pl011_break_ctl(struct uart_port *port, int break_state)
@@ -1485,7 +1495,7 @@ static void pl011_quiesce_irqs(struct uart_port *port)
 	struct uart_amba_port *uap =
 	    container_of(port, struct uart_amba_port, port);
 
-	pl011_write(pl011_read(uap, UART011_MIS), uap, UART011_ICR);
+	pl011_write(pl011_read(uap, REG_MIS), uap, REG_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.
@@ -1499,8 +1509,8 @@ static void pl011_quiesce_irqs(struct uart_port *port)
 	 * (including tx queue), so we're also fine with start_tx()'s caller
 	 * side.
 	 */
-	pl011_write(pl011_read(uap, UART011_IMSC) & ~UART011_TXIM, uap,
-		    UART011_IMSC);
+	pl011_write(pl011_read(uap, REG_IMSC) & ~UART011_TXIM, uap,
+		    REG_IMSC);
 }
 
 static int pl011_get_poll_char(struct uart_port *port)
@@ -1515,11 +1525,11 @@ static int pl011_get_poll_char(struct uart_port *port)
 	 */
 	pl011_quiesce_irqs(port);
 
-	status = pl011_read(uap, UART01x_FR);
+	status = pl011_read(uap, REG_FR);
 	if (status & UART01x_FR_RXFE)
 		return NO_POLL_CHAR;
 
-	return pl011_read(uap, UART01x_DR);
+	return pl011_read(uap, REG_DR);
 }
 
 static void pl011_put_poll_char(struct uart_port *port,
@@ -1528,10 +1538,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 (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
+	while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
 		barrier();
 
-	pl011_write(ch, uap, UART01x_DR);
+	pl011_write(ch, uap, REG_DR);
 }
 
 #endif /* CONFIG_CONSOLE_POLL */
@@ -1557,14 +1567,14 @@ static int pl011_hwinit(struct uart_port *port)
 	/* Clear pending error and receive interrupts */
 	pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
 		    UART011_FEIS | UART011_RTIS | UART011_RXIS,
-		    uap, UART011_ICR);
+		    uap, REG_ICR);
 
 	/*
 	 * Save interrupts enable mask, and enable RX interrupts in case if
 	 * the interrupt is used for NMI entry.
 	 */
-	uap->im = pl011_read(uap, UART011_IMSC);
-	pl011_write(UART011_RTIM | UART011_RXIM, uap, UART011_IMSC);
+	uap->im = pl011_read(uap, REG_IMSC);
+	pl011_write(UART011_RTIM | UART011_RXIM, uap, REG_IMSC);
 
 	if (dev_get_platdata(uap->port.dev)) {
 		struct amba_pl011_data *plat;
@@ -1578,7 +1588,8 @@ static int pl011_hwinit(struct uart_port *port)
 
 static bool pl011_split_lcrh(const struct uart_amba_port *uap)
 {
-	return uap->lcrh_rx != uap->lcrh_tx;
+	return pl011_reg_to_offset(uap, uap->lcrh_rx) !=
+	       pl011_reg_to_offset(uap, uap->lcrh_tx);
 }
 
 static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
@@ -1591,14 +1602,14 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 		 * to get this delay write read only register 10 times
 		 */
 		for (i = 0; i < 10; ++i)
-			pl011_write(0xff, uap, UART011_MIS);
+			pl011_write(0xff, uap, REG_MIS);
 		pl011_write(lcr_h, uap, uap->lcrh_tx);
 	}
 }
 
 static int pl011_allocate_irq(struct uart_amba_port *uap)
 {
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 
 	return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
 }
@@ -1613,11 +1624,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
 	spin_lock_irq(&uap->port.lock);
 
 	/* Clear out any spuriously appearing RX interrupts */
-	pl011_write(UART011_RTIS | UART011_RXIS, uap, UART011_ICR);
+	pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR);
 	uap->im = UART011_RTIM;
 	if (!pl011_dma_rx_running(uap))
 		uap->im |= UART011_RXIM;
-	pl011_write(uap->im, uap, UART011_IMSC);
+	pl011_write(uap->im, uap, REG_IMSC);
 	spin_unlock_irq(&uap->port.lock);
 }
 
@@ -1636,21 +1647,21 @@ static int pl011_startup(struct uart_port *port)
 	if (retval)
 		goto clk_dis;
 
-	pl011_write(uap->vendor->ifls, uap, UART011_IFLS);
+	pl011_write(uap->vendor->ifls, uap, REG_IFLS);
 
 	spin_lock_irq(&uap->port.lock);
 
 	/* restore RTS and DTR */
 	cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
 	cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
-	pl011_write(cr, uap, UART011_CR);
+	pl011_write(cr, uap, REG_CR);
 
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
 	 * initialise the old status of the modem signals
 	 */
-	uap->old_status = pl011_read(uap, UART01x_FR) & UART01x_FR_MODEM_ANY;
+	uap->old_status = pl011_read(uap, REG_FR) & UART01x_FR_MODEM_ANY;
 
 	/* Startup DMA */
 	pl011_dma_startup(uap);
@@ -1707,11 +1718,11 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 
 	uap->autorts = false;
 	spin_lock_irq(&uap->port.lock);
-	cr = pl011_read(uap, UART011_CR);
+	cr = pl011_read(uap, REG_CR);
 	uap->old_cr = cr;
 	cr &= UART011_CR_RTS | UART011_CR_DTR;
 	cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-	pl011_write(cr, uap, UART011_CR);
+	pl011_write(cr, uap, REG_CR);
 	spin_unlock_irq(&uap->port.lock);
 
 	/*
@@ -1728,8 +1739,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap)
 
 	/* mask all interrupts and clear all pending ones */
 	uap->im = 0;
-	pl011_write(uap->im, uap, UART011_IMSC);
-	pl011_write(0xffff, uap, UART011_ICR);
+	pl011_write(uap->im, uap, REG_IMSC);
+	pl011_write(0xffff, uap, REG_ICR);
 
 	spin_unlock_irq(&uap->port.lock);
 }
@@ -1881,8 +1892,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 		pl011_enable_ms(port);
 
 	/* first, disable everything */
-	old_cr = pl011_read(uap, UART011_CR);
-	pl011_write(0, uap, UART011_CR);
+	old_cr = pl011_read(uap, REG_CR);
+	pl011_write(0, uap, REG_CR);
 
 	if (termios->c_cflag & CRTSCTS) {
 		if (old_cr & UART011_CR_RTS)
@@ -1915,17 +1926,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 			quot -= 2;
 	}
 	/* Set baud rate */
-	pl011_write(quot & 0x3f, uap, UART011_FBRD);
-	pl011_write(quot >> 6, uap, UART011_IBRD);
+	pl011_write(quot & 0x3f, uap, REG_FBRD);
+	pl011_write(quot >> 6, uap, REG_IBRD);
 
 	/*
 	 * ----------v----------v----------v----------v-----
 	 * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER
-	 * UART011_FBRD & UART011_IBRD.
+	 * REG_FBRD & REG_IBRD.
 	 * ----------^----------^----------^----------^-----
 	 */
 	pl011_write_lcr_h(uap, lcr_h);
-	pl011_write(old_cr, uap, UART011_CR);
+	pl011_write(old_cr, uap, REG_CR);
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -2066,9 +2077,9 @@ 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 (pl011_read(uap, UART01x_FR) & UART01x_FR_TXFF)
+	while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
 		barrier();
-	pl011_write(ch, uap, UART01x_DR);
+	pl011_write(ch, uap, REG_DR);
 }
 
 static void
@@ -2093,10 +2104,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	First save the CR then disable the interrupts
 	 */
 	if (!uap->vendor->always_enabled) {
-		old_cr = pl011_read(uap, UART011_CR);
+		old_cr = pl011_read(uap, REG_CR);
 		new_cr = old_cr & ~UART011_CR_CTSEN;
 		new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-		pl011_write(new_cr, uap, UART011_CR);
+		pl011_write(new_cr, uap, REG_CR);
 	}
 
 	uart_console_write(&uap->port, s, count, pl011_console_putchar);
@@ -2106,10 +2117,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	 *	and restore the TCR
 	 */
 	do {
-		status = pl011_read(uap, UART01x_FR);
+		status = pl011_read(uap, REG_FR);
 	} while (status & UART01x_FR_BUSY);
 	if (!uap->vendor->always_enabled)
-		pl011_write(old_cr, uap, UART011_CR);
+		pl011_write(old_cr, uap, REG_CR);
 
 	if (locked)
 		spin_unlock(&uap->port.lock);
@@ -2122,7 +2133,7 @@ static void __init
 pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 			     int *parity, int *bits)
 {
-	if (pl011_read(uap, UART011_CR) & UART01x_CR_UARTEN) {
+	if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
 
 		lcr_h = pl011_read(uap, uap->lcrh_tx);
@@ -2140,13 +2151,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 		else
 			*bits = 8;
 
-		ibrd = pl011_read(uap, UART011_IBRD);
-		fbrd = pl011_read(uap, UART011_FBRD);
+		ibrd = pl011_read(uap, REG_IBRD);
+		fbrd = pl011_read(uap, REG_FBRD);
 
 		*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 
 		if (uap->vendor->oversampling) {
-			if (pl011_read(uap, UART011_CR)
+			if (pl011_read(uap, REG_CR)
 				  & ST_UART011_CR_OVSFACT)
 				*baud *= 2;
 		}
@@ -2218,10 +2229,10 @@ static struct console amba_console = {
 
 static void pl011_putc(struct uart_port *port, int c)
 {
-	while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
+	while (readl(port->membase + REG_FR) & UART01x_FR_TXFF)
 		;
-	writeb(c, port->membase + UART01x_DR);
-	while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY)
+	writeb(c, port->membase + REG_DR);
+	while (readl(port->membase + REG_FR) & UART01x_FR_BUSY)
 		;
 }
 
@@ -2348,8 +2359,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
 	int ret;
 
 	/* Ensure interrupts from this UART are masked and cleared */
-	pl011_write(0, uap, UART011_IMSC);
-	pl011_write(0xffff, uap, UART011_ICR);
+	pl011_write(0, uap, REG_IMSC);
+	pl011_write(0xffff, uap, REG_ICR);
 
 	if (!amba_reg.state) {
 		ret = uart_register_driver(&amba_reg);
diff --git a/drivers/tty/serial/amba-pl011.h b/drivers/tty/serial/amba-pl011.h
new file mode 100644
index 000000000000..b7eb1bc2fab9
--- /dev/null
+++ b/drivers/tty/serial/amba-pl011.h
@@ -0,0 +1,32 @@
+#ifndef AMBA_PL011_H
+#define AMBA_PL011_H
+
+enum {
+	REG_DR = UART01x_DR,
+	REG_ST_DMAWM = ST_UART011_DMAWM,
+	REG_ST_TIMEOUT = ST_UART011_TIMEOUT,
+	REG_FR = UART01x_FR,
+	REG_ST_LCRH_RX = ST_UART011_LCRH_RX,
+	REG_IBRD = UART011_IBRD,
+	REG_FBRD = UART011_FBRD,
+	REG_LCRH = UART011_LCRH,
+	REG_ST_LCRH_TX = ST_UART011_LCRH_TX,
+	REG_CR = UART011_CR,
+	REG_IFLS = UART011_IFLS,
+	REG_IMSC = UART011_IMSC,
+	REG_RIS = UART011_RIS,
+	REG_MIS = UART011_MIS,
+	REG_ICR = UART011_ICR,
+	REG_DMACR = UART011_DMACR,
+	REG_ST_XFCR = ST_UART011_XFCR,
+	REG_ST_XON1 = ST_UART011_XON1,
+	REG_ST_XON2 = ST_UART011_XON2,
+	REG_ST_XOFF1 = ST_UART011_XOFF1,
+	REG_ST_XOFF2 = ST_UART011_XOFF2,
+	REG_ST_ITCR = ST_UART011_ITCR,
+	REG_ST_ITIP = ST_UART011_ITIP,
+	REG_ST_ABCR = ST_UART011_ABCR,
+	REG_ST_ABIMSC = ST_UART011_ABIMSC,
+};
+
+#endif
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 05/11] tty: amba-pl011: add register lookup table
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:51     ` Russell King
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Add a register lookup table, which allows the register offsets to be
adjusted on a per-port basis.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 33 ++++++++++++++++++++++++-
 drivers/tty/serial/amba-pl011.h | 53 ++++++++++++++++++++++-------------------
 2 files changed, 60 insertions(+), 26 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index b3a0956d8883..6269eb9907bd 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -73,6 +73,34 @@
 #define UART_DR_ERROR		(UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
 #define UART_DUMMY_DR_RX	(1 << 16)
 
+static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
+	[REG_DR] = UART01x_DR,
+	[REG_ST_DMAWM] = ST_UART011_DMAWM,
+	[REG_ST_TIMEOUT] = ST_UART011_TIMEOUT,
+	[REG_FR] = UART01x_FR,
+	[REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
+	[REG_IBRD] = UART011_IBRD,
+	[REG_FBRD] = UART011_FBRD,
+	[REG_LCRH] = UART011_LCRH,
+	[REG_ST_LCRH_TX] = ST_UART011_LCRH_TX,
+	[REG_CR] = UART011_CR,
+	[REG_IFLS] = UART011_IFLS,
+	[REG_IMSC] = UART011_IMSC,
+	[REG_RIS] = UART011_RIS,
+	[REG_MIS] = UART011_MIS,
+	[REG_ICR] = UART011_ICR,
+	[REG_DMACR] = UART011_DMACR,
+	[REG_ST_XFCR] = ST_UART011_XFCR,
+	[REG_ST_XON1] = ST_UART011_XON1,
+	[REG_ST_XON2] = ST_UART011_XON2,
+	[REG_ST_XOFF1] = ST_UART011_XOFF1,
+	[REG_ST_XOFF2] = ST_UART011_XOFF2,
+	[REG_ST_ITCR] = ST_UART011_ITCR,
+	[REG_ST_ITIP] = ST_UART011_ITIP,
+	[REG_ST_ABCR] = ST_UART011_ABCR,
+	[REG_ST_ABIMSC] = ST_UART011_ABIMSC,
+};
+
 /* There is by now at least one vendor with differing details, so handle it */
 struct vendor_data {
 	unsigned int		ifls;
@@ -164,6 +192,7 @@ struct pl011_dmatx_data {
  */
 struct uart_amba_port {
 	struct uart_port	port;
+	const u16		*reg_offset;
 	struct clk		*clk;
 	const struct vendor_data *vendor;
 	unsigned int		dmacr;		/* dma control reg */
@@ -189,7 +218,7 @@ struct uart_amba_port {
 static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap,
 	unsigned int reg)
 {
-	return reg;
+	return uap->reg_offset[reg];
 }
 
 static unsigned int pl011_read(const struct uart_amba_port *uap,
@@ -2397,6 +2426,7 @@ 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_offset = pl011_std_offsets;
 	uap->vendor = vendor;
 	uap->lcrh_rx = vendor->lcrh_rx;
 	uap->lcrh_tx = vendor->lcrh_tx;
@@ -2478,6 +2508,7 @@ static int sbsa_uart_probe(struct platform_device *pdev)
 	if (!uap)
 		return -ENOMEM;
 
+	uap->reg_offset	= pl011_std_offsets;
 	uap->vendor	= &vendor_sbsa;
 	uap->fifosize	= 32;
 	uap->port.irq	= platform_get_irq(pdev, 0);
diff --git a/drivers/tty/serial/amba-pl011.h b/drivers/tty/serial/amba-pl011.h
index b7eb1bc2fab9..0c6756dba2fe 100644
--- a/drivers/tty/serial/amba-pl011.h
+++ b/drivers/tty/serial/amba-pl011.h
@@ -2,31 +2,34 @@
 #define AMBA_PL011_H
 
 enum {
-	REG_DR = UART01x_DR,
-	REG_ST_DMAWM = ST_UART011_DMAWM,
-	REG_ST_TIMEOUT = ST_UART011_TIMEOUT,
-	REG_FR = UART01x_FR,
-	REG_ST_LCRH_RX = ST_UART011_LCRH_RX,
-	REG_IBRD = UART011_IBRD,
-	REG_FBRD = UART011_FBRD,
-	REG_LCRH = UART011_LCRH,
-	REG_ST_LCRH_TX = ST_UART011_LCRH_TX,
-	REG_CR = UART011_CR,
-	REG_IFLS = UART011_IFLS,
-	REG_IMSC = UART011_IMSC,
-	REG_RIS = UART011_RIS,
-	REG_MIS = UART011_MIS,
-	REG_ICR = UART011_ICR,
-	REG_DMACR = UART011_DMACR,
-	REG_ST_XFCR = ST_UART011_XFCR,
-	REG_ST_XON1 = ST_UART011_XON1,
-	REG_ST_XON2 = ST_UART011_XON2,
-	REG_ST_XOFF1 = ST_UART011_XOFF1,
-	REG_ST_XOFF2 = ST_UART011_XOFF2,
-	REG_ST_ITCR = ST_UART011_ITCR,
-	REG_ST_ITIP = ST_UART011_ITIP,
-	REG_ST_ABCR = ST_UART011_ABCR,
-	REG_ST_ABIMSC = ST_UART011_ABIMSC,
+	REG_DR,
+	REG_ST_DMAWM,
+	REG_ST_TIMEOUT,
+	REG_FR,
+	REG_ST_LCRH_RX,
+	REG_IBRD,
+	REG_FBRD,
+	REG_LCRH,
+	REG_ST_LCRH_TX,
+	REG_CR,
+	REG_IFLS,
+	REG_IMSC,
+	REG_RIS,
+	REG_MIS,
+	REG_ICR,
+	REG_DMACR,
+	REG_ST_XFCR,
+	REG_ST_XON1,
+	REG_ST_XON2,
+	REG_ST_XOFF1,
+	REG_ST_XOFF2,
+	REG_ST_ITCR,
+	REG_ST_ITIP,
+	REG_ST_ABCR,
+	REG_ST_ABIMSC,
+
+	/* The size of the array - must be last */
+	REG_ARRAY_SIZE,
 };
 
 #endif
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 05/11] tty: amba-pl011: add register lookup table
@ 2015-11-03 14:51     ` Russell King
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add a register lookup table, which allows the register offsets to be
adjusted on a per-port basis.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 33 ++++++++++++++++++++++++-
 drivers/tty/serial/amba-pl011.h | 53 ++++++++++++++++++++++-------------------
 2 files changed, 60 insertions(+), 26 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index b3a0956d8883..6269eb9907bd 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -73,6 +73,34 @@
 #define UART_DR_ERROR		(UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
 #define UART_DUMMY_DR_RX	(1 << 16)
 
+static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
+	[REG_DR] = UART01x_DR,
+	[REG_ST_DMAWM] = ST_UART011_DMAWM,
+	[REG_ST_TIMEOUT] = ST_UART011_TIMEOUT,
+	[REG_FR] = UART01x_FR,
+	[REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
+	[REG_IBRD] = UART011_IBRD,
+	[REG_FBRD] = UART011_FBRD,
+	[REG_LCRH] = UART011_LCRH,
+	[REG_ST_LCRH_TX] = ST_UART011_LCRH_TX,
+	[REG_CR] = UART011_CR,
+	[REG_IFLS] = UART011_IFLS,
+	[REG_IMSC] = UART011_IMSC,
+	[REG_RIS] = UART011_RIS,
+	[REG_MIS] = UART011_MIS,
+	[REG_ICR] = UART011_ICR,
+	[REG_DMACR] = UART011_DMACR,
+	[REG_ST_XFCR] = ST_UART011_XFCR,
+	[REG_ST_XON1] = ST_UART011_XON1,
+	[REG_ST_XON2] = ST_UART011_XON2,
+	[REG_ST_XOFF1] = ST_UART011_XOFF1,
+	[REG_ST_XOFF2] = ST_UART011_XOFF2,
+	[REG_ST_ITCR] = ST_UART011_ITCR,
+	[REG_ST_ITIP] = ST_UART011_ITIP,
+	[REG_ST_ABCR] = ST_UART011_ABCR,
+	[REG_ST_ABIMSC] = ST_UART011_ABIMSC,
+};
+
 /* There is by now@least one vendor with differing details, so handle it */
 struct vendor_data {
 	unsigned int		ifls;
@@ -164,6 +192,7 @@ struct pl011_dmatx_data {
  */
 struct uart_amba_port {
 	struct uart_port	port;
+	const u16		*reg_offset;
 	struct clk		*clk;
 	const struct vendor_data *vendor;
 	unsigned int		dmacr;		/* dma control reg */
@@ -189,7 +218,7 @@ struct uart_amba_port {
 static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap,
 	unsigned int reg)
 {
-	return reg;
+	return uap->reg_offset[reg];
 }
 
 static unsigned int pl011_read(const struct uart_amba_port *uap,
@@ -2397,6 +2426,7 @@ 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_offset = pl011_std_offsets;
 	uap->vendor = vendor;
 	uap->lcrh_rx = vendor->lcrh_rx;
 	uap->lcrh_tx = vendor->lcrh_tx;
@@ -2478,6 +2508,7 @@ static int sbsa_uart_probe(struct platform_device *pdev)
 	if (!uap)
 		return -ENOMEM;
 
+	uap->reg_offset	= pl011_std_offsets;
 	uap->vendor	= &vendor_sbsa;
 	uap->fifosize	= 32;
 	uap->port.irq	= platform_get_irq(pdev, 0);
diff --git a/drivers/tty/serial/amba-pl011.h b/drivers/tty/serial/amba-pl011.h
index b7eb1bc2fab9..0c6756dba2fe 100644
--- a/drivers/tty/serial/amba-pl011.h
+++ b/drivers/tty/serial/amba-pl011.h
@@ -2,31 +2,34 @@
 #define AMBA_PL011_H
 
 enum {
-	REG_DR = UART01x_DR,
-	REG_ST_DMAWM = ST_UART011_DMAWM,
-	REG_ST_TIMEOUT = ST_UART011_TIMEOUT,
-	REG_FR = UART01x_FR,
-	REG_ST_LCRH_RX = ST_UART011_LCRH_RX,
-	REG_IBRD = UART011_IBRD,
-	REG_FBRD = UART011_FBRD,
-	REG_LCRH = UART011_LCRH,
-	REG_ST_LCRH_TX = ST_UART011_LCRH_TX,
-	REG_CR = UART011_CR,
-	REG_IFLS = UART011_IFLS,
-	REG_IMSC = UART011_IMSC,
-	REG_RIS = UART011_RIS,
-	REG_MIS = UART011_MIS,
-	REG_ICR = UART011_ICR,
-	REG_DMACR = UART011_DMACR,
-	REG_ST_XFCR = ST_UART011_XFCR,
-	REG_ST_XON1 = ST_UART011_XON1,
-	REG_ST_XON2 = ST_UART011_XON2,
-	REG_ST_XOFF1 = ST_UART011_XOFF1,
-	REG_ST_XOFF2 = ST_UART011_XOFF2,
-	REG_ST_ITCR = ST_UART011_ITCR,
-	REG_ST_ITIP = ST_UART011_ITIP,
-	REG_ST_ABCR = ST_UART011_ABCR,
-	REG_ST_ABIMSC = ST_UART011_ABIMSC,
+	REG_DR,
+	REG_ST_DMAWM,
+	REG_ST_TIMEOUT,
+	REG_FR,
+	REG_ST_LCRH_RX,
+	REG_IBRD,
+	REG_FBRD,
+	REG_LCRH,
+	REG_ST_LCRH_TX,
+	REG_CR,
+	REG_IFLS,
+	REG_IMSC,
+	REG_RIS,
+	REG_MIS,
+	REG_ICR,
+	REG_DMACR,
+	REG_ST_XFCR,
+	REG_ST_XON1,
+	REG_ST_XON2,
+	REG_ST_XOFF1,
+	REG_ST_XOFF2,
+	REG_ST_ITCR,
+	REG_ST_ITIP,
+	REG_ST_ABCR,
+	REG_ST_ABIMSC,
+
+	/* The size of the array - must be last */
+	REG_ARRAY_SIZE,
 };
 
 #endif
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 06/11] tty: amba-pl011: add register offset table to vendor data
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:51     ` Russell King
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Add the register offset table to the vendor data, allowing vendor
differences to be described in this table.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 6269eb9907bd..b912220bf13e 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -103,6 +103,7 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 
 /* There is by now at least one vendor with differing details, so handle it */
 struct vendor_data {
+	const u16		*reg_offset;
 	unsigned int		ifls;
 	unsigned int		lcrh_tx;
 	unsigned int		lcrh_rx;
@@ -121,6 +122,7 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
 }
 
 static struct vendor_data vendor_arm = {
+	.reg_offset		= pl011_std_offsets,
 	.ifls			= UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
 	.lcrh_tx		= REG_LCRH,
 	.lcrh_rx		= REG_LCRH,
@@ -133,6 +135,7 @@ static struct vendor_data vendor_arm = {
 };
 
 static struct vendor_data vendor_sbsa = {
+	.reg_offset		= pl011_std_offsets,
 	.oversampling		= false,
 	.dma_threshold		= false,
 	.cts_event_workaround	= false,
@@ -146,6 +149,7 @@ static unsigned int get_fifosize_st(struct amba_device *dev)
 }
 
 static struct vendor_data vendor_st = {
+	.reg_offset		= pl011_std_offsets,
 	.ifls			= UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
 	.lcrh_tx		= REG_ST_LCRH_TX,
 	.lcrh_rx		= REG_ST_LCRH_RX,
@@ -2426,7 +2430,7 @@ 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_offset = pl011_std_offsets;
+	uap->reg_offset = vendor->reg_offset;
 	uap->vendor = vendor;
 	uap->lcrh_rx = vendor->lcrh_rx;
 	uap->lcrh_tx = vendor->lcrh_tx;
@@ -2508,7 +2512,7 @@ static int sbsa_uart_probe(struct platform_device *pdev)
 	if (!uap)
 		return -ENOMEM;
 
-	uap->reg_offset	= pl011_std_offsets;
+	uap->reg_offset	= vendor_sbsa.reg_offset;
 	uap->vendor	= &vendor_sbsa;
 	uap->fifosize	= 32;
 	uap->port.irq	= platform_get_irq(pdev, 0);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 06/11] tty: amba-pl011: add register offset table to vendor data
@ 2015-11-03 14:51     ` Russell King
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add the register offset table to the vendor data, allowing vendor
differences to be described in this table.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 6269eb9907bd..b912220bf13e 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -103,6 +103,7 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 
 /* There is by now at least one vendor with differing details, so handle it */
 struct vendor_data {
+	const u16		*reg_offset;
 	unsigned int		ifls;
 	unsigned int		lcrh_tx;
 	unsigned int		lcrh_rx;
@@ -121,6 +122,7 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
 }
 
 static struct vendor_data vendor_arm = {
+	.reg_offset		= pl011_std_offsets,
 	.ifls			= UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
 	.lcrh_tx		= REG_LCRH,
 	.lcrh_rx		= REG_LCRH,
@@ -133,6 +135,7 @@ static struct vendor_data vendor_arm = {
 };
 
 static struct vendor_data vendor_sbsa = {
+	.reg_offset		= pl011_std_offsets,
 	.oversampling		= false,
 	.dma_threshold		= false,
 	.cts_event_workaround	= false,
@@ -146,6 +149,7 @@ static unsigned int get_fifosize_st(struct amba_device *dev)
 }
 
 static struct vendor_data vendor_st = {
+	.reg_offset		= pl011_std_offsets,
 	.ifls			= UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
 	.lcrh_tx		= REG_ST_LCRH_TX,
 	.lcrh_rx		= REG_ST_LCRH_RX,
@@ -2426,7 +2430,7 @@ 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_offset = pl011_std_offsets;
+	uap->reg_offset = vendor->reg_offset;
 	uap->vendor = vendor;
 	uap->lcrh_rx = vendor->lcrh_rx;
 	uap->lcrh_tx = vendor->lcrh_tx;
@@ -2508,7 +2512,7 @@ static int sbsa_uart_probe(struct platform_device *pdev)
 	if (!uap)
 		return -ENOMEM;
 
-	uap->reg_offset	= pl011_std_offsets;
+	uap->reg_offset	= vendor_sbsa.reg_offset;
 	uap->vendor	= &vendor_sbsa;
 	uap->fifosize	= 32;
 	uap->port.irq	= platform_get_irq(pdev, 0);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 07/11] tty: amba-pl011: add ST register offset table
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:51     ` Russell King
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Add the ST variant register offset table to the driver.  Currently,
this is an identical copy of the standard version, but this will be
modified in the following changes.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index b912220bf13e..a13551a5e767 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -143,13 +143,41 @@ static struct vendor_data vendor_sbsa = {
 	.fixed_options		= true,
 };
 
+static u16 pl011_st_offsets[REG_ARRAY_SIZE] = {
+	[REG_DR] = UART01x_DR,
+	[REG_ST_DMAWM] = ST_UART011_DMAWM,
+	[REG_ST_TIMEOUT] = ST_UART011_TIMEOUT,
+	[REG_FR] = UART01x_FR,
+	[REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
+	[REG_IBRD] = UART011_IBRD,
+	[REG_FBRD] = UART011_FBRD,
+	[REG_LCRH] = UART011_LCRH,
+	[REG_ST_LCRH_TX] = ST_UART011_LCRH_TX,
+	[REG_CR] = UART011_CR,
+	[REG_IFLS] = UART011_IFLS,
+	[REG_IMSC] = UART011_IMSC,
+	[REG_RIS] = UART011_RIS,
+	[REG_MIS] = UART011_MIS,
+	[REG_ICR] = UART011_ICR,
+	[REG_DMACR] = UART011_DMACR,
+	[REG_ST_XFCR] = ST_UART011_XFCR,
+	[REG_ST_XON1] = ST_UART011_XON1,
+	[REG_ST_XON2] = ST_UART011_XON2,
+	[REG_ST_XOFF1] = ST_UART011_XOFF1,
+	[REG_ST_XOFF2] = ST_UART011_XOFF2,
+	[REG_ST_ITCR] = ST_UART011_ITCR,
+	[REG_ST_ITIP] = ST_UART011_ITIP,
+	[REG_ST_ABCR] = ST_UART011_ABCR,
+	[REG_ST_ABIMSC] = ST_UART011_ABIMSC,
+};
+
 static unsigned int get_fifosize_st(struct amba_device *dev)
 {
 	return 64;
 }
 
 static struct vendor_data vendor_st = {
-	.reg_offset		= pl011_std_offsets,
+	.reg_offset		= pl011_st_offsets,
 	.ifls			= UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
 	.lcrh_tx		= REG_ST_LCRH_TX,
 	.lcrh_rx		= REG_ST_LCRH_RX,
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 07/11] tty: amba-pl011: add ST register offset table
@ 2015-11-03 14:51     ` Russell King
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add the ST variant register offset table to the driver.  Currently,
this is an identical copy of the standard version, but this will be
modified in the following changes.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index b912220bf13e..a13551a5e767 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -143,13 +143,41 @@ static struct vendor_data vendor_sbsa = {
 	.fixed_options		= true,
 };
 
+static u16 pl011_st_offsets[REG_ARRAY_SIZE] = {
+	[REG_DR] = UART01x_DR,
+	[REG_ST_DMAWM] = ST_UART011_DMAWM,
+	[REG_ST_TIMEOUT] = ST_UART011_TIMEOUT,
+	[REG_FR] = UART01x_FR,
+	[REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
+	[REG_IBRD] = UART011_IBRD,
+	[REG_FBRD] = UART011_FBRD,
+	[REG_LCRH] = UART011_LCRH,
+	[REG_ST_LCRH_TX] = ST_UART011_LCRH_TX,
+	[REG_CR] = UART011_CR,
+	[REG_IFLS] = UART011_IFLS,
+	[REG_IMSC] = UART011_IMSC,
+	[REG_RIS] = UART011_RIS,
+	[REG_MIS] = UART011_MIS,
+	[REG_ICR] = UART011_ICR,
+	[REG_DMACR] = UART011_DMACR,
+	[REG_ST_XFCR] = ST_UART011_XFCR,
+	[REG_ST_XON1] = ST_UART011_XON1,
+	[REG_ST_XON2] = ST_UART011_XON2,
+	[REG_ST_XOFF1] = ST_UART011_XOFF1,
+	[REG_ST_XOFF2] = ST_UART011_XOFF2,
+	[REG_ST_ITCR] = ST_UART011_ITCR,
+	[REG_ST_ITIP] = ST_UART011_ITIP,
+	[REG_ST_ABCR] = ST_UART011_ABCR,
+	[REG_ST_ABIMSC] = ST_UART011_ABIMSC,
+};
+
 static unsigned int get_fifosize_st(struct amba_device *dev)
 {
 	return 64;
 }
 
 static struct vendor_data vendor_st = {
-	.reg_offset		= pl011_std_offsets,
+	.reg_offset		= pl011_st_offsets,
 	.ifls			= UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
 	.lcrh_tx		= REG_ST_LCRH_TX,
 	.lcrh_rx		= REG_ST_LCRH_RX,
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 08/11] tty: amba-pl011: clean up LCR register offsets
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:51     ` Russell King
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

As we can detect when the LCR register is split between TX and RX,
we don't need three entries in the table to deal with this.  Reduce
this down to two entries by converting the REG_ST_LCRH_* entries to
standard REG_LCRH_* and remove REG_LCRH.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 40 ++++++++++++++--------------------------
 drivers/tty/serial/amba-pl011.h |  5 ++---
 2 files changed, 16 insertions(+), 29 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index a13551a5e767..85c455c60e12 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -78,11 +78,10 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 	[REG_ST_DMAWM] = ST_UART011_DMAWM,
 	[REG_ST_TIMEOUT] = ST_UART011_TIMEOUT,
 	[REG_FR] = UART01x_FR,
-	[REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
+	[REG_LCRH_RX] = UART011_LCRH,
+	[REG_LCRH_TX] = UART011_LCRH,
 	[REG_IBRD] = UART011_IBRD,
 	[REG_FBRD] = UART011_FBRD,
-	[REG_LCRH] = UART011_LCRH,
-	[REG_ST_LCRH_TX] = ST_UART011_LCRH_TX,
 	[REG_CR] = UART011_CR,
 	[REG_IFLS] = UART011_IFLS,
 	[REG_IMSC] = UART011_IMSC,
@@ -105,8 +104,6 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 struct vendor_data {
 	const u16		*reg_offset;
 	unsigned int		ifls;
-	unsigned int		lcrh_tx;
-	unsigned int		lcrh_rx;
 	bool			oversampling;
 	bool			dma_threshold;
 	bool			cts_event_workaround;
@@ -124,8 +121,6 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
 static struct vendor_data vendor_arm = {
 	.reg_offset		= pl011_std_offsets,
 	.ifls			= UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
-	.lcrh_tx		= REG_LCRH,
-	.lcrh_rx		= REG_LCRH,
 	.oversampling		= false,
 	.dma_threshold		= false,
 	.cts_event_workaround	= false,
@@ -148,11 +143,10 @@ static u16 pl011_st_offsets[REG_ARRAY_SIZE] = {
 	[REG_ST_DMAWM] = ST_UART011_DMAWM,
 	[REG_ST_TIMEOUT] = ST_UART011_TIMEOUT,
 	[REG_FR] = UART01x_FR,
-	[REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
+	[REG_LCRH_RX] = ST_UART011_LCRH_RX,
+	[REG_LCRH_TX] = ST_UART011_LCRH_TX,
 	[REG_IBRD] = UART011_IBRD,
 	[REG_FBRD] = UART011_FBRD,
-	[REG_LCRH] = UART011_LCRH,
-	[REG_ST_LCRH_TX] = ST_UART011_LCRH_TX,
 	[REG_CR] = UART011_CR,
 	[REG_IFLS] = UART011_IFLS,
 	[REG_IMSC] = UART011_IMSC,
@@ -179,8 +173,6 @@ static unsigned int get_fifosize_st(struct amba_device *dev)
 static struct vendor_data vendor_st = {
 	.reg_offset		= pl011_st_offsets,
 	.ifls			= UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
-	.lcrh_tx		= REG_ST_LCRH_TX,
-	.lcrh_rx		= REG_ST_LCRH_RX,
 	.oversampling		= true,
 	.dma_threshold		= true,
 	.cts_event_workaround	= true,
@@ -231,8 +223,6 @@ struct uart_amba_port {
 	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;
 	unsigned int		fixed_baud;	/* vendor-set fixed baud rate */
@@ -1540,12 +1530,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 = pl011_read(uap, uap->lcrh_tx);
+	lcr_h = pl011_read(uap, REG_LCRH_TX);
 	if (break_state == -1)
 		lcr_h |= UART01x_LCRH_BRK;
 	else
 		lcr_h &= ~UART01x_LCRH_BRK;
-	pl011_write(lcr_h, uap, uap->lcrh_tx);
+	pl011_write(lcr_h, uap, REG_LCRH_TX);
 	spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
@@ -1649,13 +1639,13 @@ static int pl011_hwinit(struct uart_port *port)
 
 static bool pl011_split_lcrh(const struct uart_amba_port *uap)
 {
-	return pl011_reg_to_offset(uap, uap->lcrh_rx) !=
-	       pl011_reg_to_offset(uap, uap->lcrh_tx);
+	return pl011_reg_to_offset(uap, REG_LCRH_RX) !=
+	       pl011_reg_to_offset(uap, REG_LCRH_TX);
 }
 
 static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 {
-	pl011_write(lcr_h, uap, uap->lcrh_rx);
+	pl011_write(lcr_h, uap, REG_LCRH_RX);
 	if (pl011_split_lcrh(uap)) {
 		int i;
 		/*
@@ -1664,7 +1654,7 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 		 */
 		for (i = 0; i < 10; ++i)
 			pl011_write(0xff, uap, REG_MIS);
-		pl011_write(lcr_h, uap, uap->lcrh_tx);
+		pl011_write(lcr_h, uap, REG_LCRH_TX);
 	}
 }
 
@@ -1789,9 +1779,9 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 	/*
 	 * disable break condition and fifos
 	 */
-	pl011_shutdown_channel(uap, uap->lcrh_rx);
+	pl011_shutdown_channel(uap, REG_LCRH_RX);
 	if (pl011_split_lcrh(uap))
-		pl011_shutdown_channel(uap, uap->lcrh_tx);
+		pl011_shutdown_channel(uap, REG_LCRH_TX);
 }
 
 static void pl011_disable_interrupts(struct uart_amba_port *uap)
@@ -1992,7 +1982,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	/*
 	 * ----------v----------v----------v----------v-----
-	 * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER
+	 * NOTE: REG_LCRH_TX and REG_LCRH_RX MUST BE WRITTEN AFTER
 	 * REG_FBRD & REG_IBRD.
 	 * ----------^----------^----------^----------^-----
 	 */
@@ -2197,7 +2187,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 	if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
 
-		lcr_h = pl011_read(uap, uap->lcrh_tx);
+		lcr_h = pl011_read(uap, REG_LCRH_TX);
 
 		*parity = 'n';
 		if (lcr_h & UART01x_LCRH_PEN) {
@@ -2460,8 +2450,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 
 	uap->reg_offset = vendor->reg_offset;
 	uap->vendor = vendor;
-	uap->lcrh_rx = vendor->lcrh_rx;
-	uap->lcrh_tx = vendor->lcrh_tx;
 	uap->fifosize = vendor->get_fifosize(dev);
 	uap->port.irq = dev->irq[0];
 	uap->port.ops = &amba_pl011_pops;
diff --git a/drivers/tty/serial/amba-pl011.h b/drivers/tty/serial/amba-pl011.h
index 0c6756dba2fe..411c60e1f9a4 100644
--- a/drivers/tty/serial/amba-pl011.h
+++ b/drivers/tty/serial/amba-pl011.h
@@ -6,11 +6,10 @@ enum {
 	REG_ST_DMAWM,
 	REG_ST_TIMEOUT,
 	REG_FR,
-	REG_ST_LCRH_RX,
+	REG_LCRH_RX,
+	REG_LCRH_TX,
 	REG_IBRD,
 	REG_FBRD,
-	REG_LCRH,
-	REG_ST_LCRH_TX,
 	REG_CR,
 	REG_IFLS,
 	REG_IMSC,
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 08/11] tty: amba-pl011: clean up LCR register offsets
@ 2015-11-03 14:51     ` Russell King
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

As we can detect when the LCR register is split between TX and RX,
we don't need three entries in the table to deal with this.  Reduce
this down to two entries by converting the REG_ST_LCRH_* entries to
standard REG_LCRH_* and remove REG_LCRH.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 40 ++++++++++++++--------------------------
 drivers/tty/serial/amba-pl011.h |  5 ++---
 2 files changed, 16 insertions(+), 29 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index a13551a5e767..85c455c60e12 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -78,11 +78,10 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 	[REG_ST_DMAWM] = ST_UART011_DMAWM,
 	[REG_ST_TIMEOUT] = ST_UART011_TIMEOUT,
 	[REG_FR] = UART01x_FR,
-	[REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
+	[REG_LCRH_RX] = UART011_LCRH,
+	[REG_LCRH_TX] = UART011_LCRH,
 	[REG_IBRD] = UART011_IBRD,
 	[REG_FBRD] = UART011_FBRD,
-	[REG_LCRH] = UART011_LCRH,
-	[REG_ST_LCRH_TX] = ST_UART011_LCRH_TX,
 	[REG_CR] = UART011_CR,
 	[REG_IFLS] = UART011_IFLS,
 	[REG_IMSC] = UART011_IMSC,
@@ -105,8 +104,6 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 struct vendor_data {
 	const u16		*reg_offset;
 	unsigned int		ifls;
-	unsigned int		lcrh_tx;
-	unsigned int		lcrh_rx;
 	bool			oversampling;
 	bool			dma_threshold;
 	bool			cts_event_workaround;
@@ -124,8 +121,6 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
 static struct vendor_data vendor_arm = {
 	.reg_offset		= pl011_std_offsets,
 	.ifls			= UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
-	.lcrh_tx		= REG_LCRH,
-	.lcrh_rx		= REG_LCRH,
 	.oversampling		= false,
 	.dma_threshold		= false,
 	.cts_event_workaround	= false,
@@ -148,11 +143,10 @@ static u16 pl011_st_offsets[REG_ARRAY_SIZE] = {
 	[REG_ST_DMAWM] = ST_UART011_DMAWM,
 	[REG_ST_TIMEOUT] = ST_UART011_TIMEOUT,
 	[REG_FR] = UART01x_FR,
-	[REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
+	[REG_LCRH_RX] = ST_UART011_LCRH_RX,
+	[REG_LCRH_TX] = ST_UART011_LCRH_TX,
 	[REG_IBRD] = UART011_IBRD,
 	[REG_FBRD] = UART011_FBRD,
-	[REG_LCRH] = UART011_LCRH,
-	[REG_ST_LCRH_TX] = ST_UART011_LCRH_TX,
 	[REG_CR] = UART011_CR,
 	[REG_IFLS] = UART011_IFLS,
 	[REG_IMSC] = UART011_IMSC,
@@ -179,8 +173,6 @@ static unsigned int get_fifosize_st(struct amba_device *dev)
 static struct vendor_data vendor_st = {
 	.reg_offset		= pl011_st_offsets,
 	.ifls			= UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
-	.lcrh_tx		= REG_ST_LCRH_TX,
-	.lcrh_rx		= REG_ST_LCRH_RX,
 	.oversampling		= true,
 	.dma_threshold		= true,
 	.cts_event_workaround	= true,
@@ -231,8 +223,6 @@ struct uart_amba_port {
 	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;
 	unsigned int		fixed_baud;	/* vendor-set fixed baud rate */
@@ -1540,12 +1530,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 = pl011_read(uap, uap->lcrh_tx);
+	lcr_h = pl011_read(uap, REG_LCRH_TX);
 	if (break_state == -1)
 		lcr_h |= UART01x_LCRH_BRK;
 	else
 		lcr_h &= ~UART01x_LCRH_BRK;
-	pl011_write(lcr_h, uap, uap->lcrh_tx);
+	pl011_write(lcr_h, uap, REG_LCRH_TX);
 	spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
@@ -1649,13 +1639,13 @@ static int pl011_hwinit(struct uart_port *port)
 
 static bool pl011_split_lcrh(const struct uart_amba_port *uap)
 {
-	return pl011_reg_to_offset(uap, uap->lcrh_rx) !=
-	       pl011_reg_to_offset(uap, uap->lcrh_tx);
+	return pl011_reg_to_offset(uap, REG_LCRH_RX) !=
+	       pl011_reg_to_offset(uap, REG_LCRH_TX);
 }
 
 static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 {
-	pl011_write(lcr_h, uap, uap->lcrh_rx);
+	pl011_write(lcr_h, uap, REG_LCRH_RX);
 	if (pl011_split_lcrh(uap)) {
 		int i;
 		/*
@@ -1664,7 +1654,7 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 		 */
 		for (i = 0; i < 10; ++i)
 			pl011_write(0xff, uap, REG_MIS);
-		pl011_write(lcr_h, uap, uap->lcrh_tx);
+		pl011_write(lcr_h, uap, REG_LCRH_TX);
 	}
 }
 
@@ -1789,9 +1779,9 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 	/*
 	 * disable break condition and fifos
 	 */
-	pl011_shutdown_channel(uap, uap->lcrh_rx);
+	pl011_shutdown_channel(uap, REG_LCRH_RX);
 	if (pl011_split_lcrh(uap))
-		pl011_shutdown_channel(uap, uap->lcrh_tx);
+		pl011_shutdown_channel(uap, REG_LCRH_TX);
 }
 
 static void pl011_disable_interrupts(struct uart_amba_port *uap)
@@ -1992,7 +1982,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	/*
 	 * ----------v----------v----------v----------v-----
-	 * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER
+	 * NOTE: REG_LCRH_TX and REG_LCRH_RX MUST BE WRITTEN AFTER
 	 * REG_FBRD & REG_IBRD.
 	 * ----------^----------^----------^----------^-----
 	 */
@@ -2197,7 +2187,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 	if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
 
-		lcr_h = pl011_read(uap, uap->lcrh_tx);
+		lcr_h = pl011_read(uap, REG_LCRH_TX);
 
 		*parity = 'n';
 		if (lcr_h & UART01x_LCRH_PEN) {
@@ -2460,8 +2450,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 
 	uap->reg_offset = vendor->reg_offset;
 	uap->vendor = vendor;
-	uap->lcrh_rx = vendor->lcrh_rx;
-	uap->lcrh_tx = vendor->lcrh_tx;
 	uap->fifosize = vendor->get_fifosize(dev);
 	uap->port.irq = dev->irq[0];
 	uap->port.ops = &amba_pl011_pops;
diff --git a/drivers/tty/serial/amba-pl011.h b/drivers/tty/serial/amba-pl011.h
index 0c6756dba2fe..411c60e1f9a4 100644
--- a/drivers/tty/serial/amba-pl011.h
+++ b/drivers/tty/serial/amba-pl011.h
@@ -6,11 +6,10 @@ enum {
 	REG_ST_DMAWM,
 	REG_ST_TIMEOUT,
 	REG_FR,
-	REG_ST_LCRH_RX,
+	REG_LCRH_RX,
+	REG_LCRH_TX,
 	REG_IBRD,
 	REG_FBRD,
-	REG_LCRH,
-	REG_ST_LCRH_TX,
 	REG_CR,
 	REG_IFLS,
 	REG_IMSC,
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 09/11] tty: amba-pl011: remove ST micro registers from standard table
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:51     ` Russell King
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Remove the ST micro registers from the standard table.  These registers
should never be accessed in non-ST micro variants.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 85c455c60e12..4cb282a377c0 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -75,8 +75,6 @@
 
 static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 	[REG_DR] = UART01x_DR,
-	[REG_ST_DMAWM] = ST_UART011_DMAWM,
-	[REG_ST_TIMEOUT] = ST_UART011_TIMEOUT,
 	[REG_FR] = UART01x_FR,
 	[REG_LCRH_RX] = UART011_LCRH,
 	[REG_LCRH_TX] = UART011_LCRH,
@@ -89,15 +87,6 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 	[REG_MIS] = UART011_MIS,
 	[REG_ICR] = UART011_ICR,
 	[REG_DMACR] = UART011_DMACR,
-	[REG_ST_XFCR] = ST_UART011_XFCR,
-	[REG_ST_XON1] = ST_UART011_XON1,
-	[REG_ST_XON2] = ST_UART011_XON2,
-	[REG_ST_XOFF1] = ST_UART011_XOFF1,
-	[REG_ST_XOFF2] = ST_UART011_XOFF2,
-	[REG_ST_ITCR] = ST_UART011_ITCR,
-	[REG_ST_ITIP] = ST_UART011_ITIP,
-	[REG_ST_ABCR] = ST_UART011_ABCR,
-	[REG_ST_ABIMSC] = ST_UART011_ABIMSC,
 };
 
 /* There is by now at least one vendor with differing details, so handle it */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 09/11] tty: amba-pl011: remove ST micro registers from standard table
@ 2015-11-03 14:51     ` Russell King
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

Remove the ST micro registers from the standard table.  These registers
should never be accessed in non-ST micro variants.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 85c455c60e12..4cb282a377c0 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -75,8 +75,6 @@
 
 static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 	[REG_DR] = UART01x_DR,
-	[REG_ST_DMAWM] = ST_UART011_DMAWM,
-	[REG_ST_TIMEOUT] = ST_UART011_TIMEOUT,
 	[REG_FR] = UART01x_FR,
 	[REG_LCRH_RX] = UART011_LCRH,
 	[REG_LCRH_TX] = UART011_LCRH,
@@ -89,15 +87,6 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 	[REG_MIS] = UART011_MIS,
 	[REG_ICR] = UART011_ICR,
 	[REG_DMACR] = UART011_DMACR,
-	[REG_ST_XFCR] = ST_UART011_XFCR,
-	[REG_ST_XON1] = ST_UART011_XON1,
-	[REG_ST_XON2] = ST_UART011_XON2,
-	[REG_ST_XOFF1] = ST_UART011_XOFF1,
-	[REG_ST_XOFF2] = ST_UART011_XOFF2,
-	[REG_ST_ITCR] = ST_UART011_ITCR,
-	[REG_ST_ITIP] = ST_UART011_ITIP,
-	[REG_ST_ABCR] = ST_UART011_ABCR,
-	[REG_ST_ABIMSC] = ST_UART011_ABIMSC,
 };
 
 /* There is by now at least one vendor with differing details, so handle it */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 10/11] tty: amba-pl011: add support for 32-bit register access
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:51     ` Russell King
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Add support for 32-bit register accesses to the AMBA PL011 UART.  This
is needed for ZTE UARTs, which require 32-bit accesses as opposed to
the more normal 16-bit accesses.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 4cb282a377c0..8f5f82039346 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -93,6 +93,7 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 struct vendor_data {
 	const u16		*reg_offset;
 	unsigned int		ifls;
+	bool			access_32b;
 	bool			oversampling;
 	bool			dma_threshold;
 	bool			cts_event_workaround;
@@ -214,6 +215,7 @@ struct uart_amba_port {
 	unsigned int		fifosize;	/* vendor-specific */
 	unsigned int		old_cr;		/* state during shutdown */
 	bool			autorts;
+	bool			access_32b;
 	unsigned int		fixed_baud;	/* vendor-set fixed baud rate */
 	char			type[12];
 #ifdef CONFIG_DMA_ENGINE
@@ -235,13 +237,20 @@ static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap,
 static unsigned int pl011_read(const struct uart_amba_port *uap,
 	unsigned int reg)
 {
-	return readw(uap->port.membase + pl011_reg_to_offset(uap, reg));
+	void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
+
+	return uap->access_32b ? readl(addr) : readw(addr);
 }
 
 static void pl011_write(unsigned int val, const struct uart_amba_port *uap,
 	unsigned int reg)
 {
-	writew(val, uap->port.membase + pl011_reg_to_offset(uap, reg));
+	void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
+
+	if (uap->access_32b)
+		writel(val, addr);
+	else
+		writew(val, addr);
 }
 
 /*
@@ -2438,6 +2447,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 		return PTR_ERR(uap->clk);
 
 	uap->reg_offset = vendor->reg_offset;
+	uap->access_32b = vendor->access_32b;
 	uap->vendor = vendor;
 	uap->fifosize = vendor->get_fifosize(dev);
 	uap->port.irq = dev->irq[0];
@@ -2518,6 +2528,7 @@ static int sbsa_uart_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	uap->reg_offset	= vendor_sbsa.reg_offset;
+	uap->access_32b = vendor_sbsa.access_32b;
 	uap->vendor	= &vendor_sbsa;
 	uap->fifosize	= 32;
 	uap->port.irq	= platform_get_irq(pdev, 0);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 10/11] tty: amba-pl011: add support for 32-bit register access
@ 2015-11-03 14:51     ` Russell King
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add support for 32-bit register accesses to the AMBA PL011 UART.  This
is needed for ZTE UARTs, which require 32-bit accesses as opposed to
the more normal 16-bit accesses.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 4cb282a377c0..8f5f82039346 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -93,6 +93,7 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
 struct vendor_data {
 	const u16		*reg_offset;
 	unsigned int		ifls;
+	bool			access_32b;
 	bool			oversampling;
 	bool			dma_threshold;
 	bool			cts_event_workaround;
@@ -214,6 +215,7 @@ struct uart_amba_port {
 	unsigned int		fifosize;	/* vendor-specific */
 	unsigned int		old_cr;		/* state during shutdown */
 	bool			autorts;
+	bool			access_32b;
 	unsigned int		fixed_baud;	/* vendor-set fixed baud rate */
 	char			type[12];
 #ifdef CONFIG_DMA_ENGINE
@@ -235,13 +237,20 @@ static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap,
 static unsigned int pl011_read(const struct uart_amba_port *uap,
 	unsigned int reg)
 {
-	return readw(uap->port.membase + pl011_reg_to_offset(uap, reg));
+	void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
+
+	return uap->access_32b ? readl(addr) : readw(addr);
 }
 
 static void pl011_write(unsigned int val, const struct uart_amba_port *uap,
 	unsigned int reg)
 {
-	writew(val, uap->port.membase + pl011_reg_to_offset(uap, reg));
+	void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
+
+	if (uap->access_32b)
+		writel(val, addr);
+	else
+		writew(val, addr);
 }
 
 /*
@@ -2438,6 +2447,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 		return PTR_ERR(uap->clk);
 
 	uap->reg_offset = vendor->reg_offset;
+	uap->access_32b = vendor->access_32b;
 	uap->vendor = vendor;
 	uap->fifosize = vendor->get_fifosize(dev);
 	uap->port.irq = dev->irq[0];
@@ -2518,6 +2528,7 @@ static int sbsa_uart_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	uap->reg_offset	= vendor_sbsa.reg_offset;
+	uap->access_32b = vendor_sbsa.access_32b;
 	uap->vendor	= &vendor_sbsa;
 	uap->fifosize	= 32;
 	uap->port.irq	= platform_get_irq(pdev, 0);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 11/11] tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)
  2015-11-03 13:43   ` Russell King - ARM Linux
@ 2015-11-03 14:51     ` Russell King
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Add (incomplete) support for the ZTE UART to the AMBA PL011 driver.
This is similar to the ARM and ST variants, except it has a different
register address layout, and requires 32-bit accesses to the registers.
Use the newly introduced register tables and access size support to
cope with these differences.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 23 +++++++++++++++++++++++
 include/linux/amba/serial.h     | 18 ++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 8f5f82039346..373b1520083f 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -171,6 +171,29 @@ static struct vendor_data vendor_st = {
 	.get_fifosize		= get_fifosize_st,
 };
 
+static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = {
+	[REG_DR] = ZX_UART011_DR,
+	[REG_FR] = ZX_UART011_FR,
+	[REG_LCRH_RX] = ZX_UART011_LCRH,
+	[REG_LCRH_TX] = ZX_UART011_LCRH,
+	[REG_IBRD] = ZX_UART011_IBRD,
+	[REG_FBRD] = ZX_UART011_FBRD,
+	[REG_CR] = ZX_UART011_CR,
+	[REG_IFLS] = ZX_UART011_IFLS,
+	[REG_IMSC] = ZX_UART011_IMSC,
+	[REG_RIS] = ZX_UART011_RIS,
+	[REG_MIS] = ZX_UART011_MIS,
+	[REG_ICR] = ZX_UART011_ICR,
+	[REG_DMACR] = ZX_UART011_DMACR,
+};
+
+static struct vendor_data vendor_zte = {
+	.reg_offset		= pl011_zte_offsets,
+	.access_32b		= true,
+	.ifls			= UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
+	.get_fifosize		= get_fifosize_arm,
+};
+
 /* Deals with DMA transactions */
 
 struct pl011_sgbuf {
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
index 0ddb5c02ad8b..d76a19ba2cff 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -65,6 +65,24 @@
 #define ST_UART011_ABCR		0x100	/* Autobaud control register. */
 #define ST_UART011_ABIMSC	0x15C	/* Autobaud interrupt mask/clear register. */
 
+/*
+ * ZTE UART register offsets.  This UART has a radically different address
+ * allocation from the ARM and ST variants, so we list all registers here.
+ * We assume unlisted registers do not exist.
+ */
+#define ZX_UART011_DR		0x04
+#define ZX_UART011_FR		0x14
+#define ZX_UART011_IBRD		0x24
+#define ZX_UART011_FBRD		0x28
+#define ZX_UART011_LCRH		0x30
+#define ZX_UART011_CR		0x34
+#define ZX_UART011_IFLS		0x38
+#define ZX_UART011_IMSC		0x40
+#define ZX_UART011_RIS		0x44
+#define ZX_UART011_MIS		0x48
+#define ZX_UART011_ICR		0x4c
+#define ZX_UART011_DMACR	0x50
+
 #define UART011_DR_OE		(1 << 11)
 #define UART011_DR_BE		(1 << 10)
 #define UART011_DR_PE		(1 << 9)
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 11/11] tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)
@ 2015-11-03 14:51     ` Russell King
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King @ 2015-11-03 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add (incomplete) support for the ZTE UART to the AMBA PL011 driver.
This is similar to the ARM and ST variants, except it has a different
register address layout, and requires 32-bit accesses to the registers.
Use the newly introduced register tables and access size support to
cope with these differences.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/tty/serial/amba-pl011.c | 23 +++++++++++++++++++++++
 include/linux/amba/serial.h     | 18 ++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 8f5f82039346..373b1520083f 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -171,6 +171,29 @@ static struct vendor_data vendor_st = {
 	.get_fifosize		= get_fifosize_st,
 };
 
+static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = {
+	[REG_DR] = ZX_UART011_DR,
+	[REG_FR] = ZX_UART011_FR,
+	[REG_LCRH_RX] = ZX_UART011_LCRH,
+	[REG_LCRH_TX] = ZX_UART011_LCRH,
+	[REG_IBRD] = ZX_UART011_IBRD,
+	[REG_FBRD] = ZX_UART011_FBRD,
+	[REG_CR] = ZX_UART011_CR,
+	[REG_IFLS] = ZX_UART011_IFLS,
+	[REG_IMSC] = ZX_UART011_IMSC,
+	[REG_RIS] = ZX_UART011_RIS,
+	[REG_MIS] = ZX_UART011_MIS,
+	[REG_ICR] = ZX_UART011_ICR,
+	[REG_DMACR] = ZX_UART011_DMACR,
+};
+
+static struct vendor_data vendor_zte = {
+	.reg_offset		= pl011_zte_offsets,
+	.access_32b		= true,
+	.ifls			= UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
+	.get_fifosize		= get_fifosize_arm,
+};
+
 /* Deals with DMA transactions */
 
 struct pl011_sgbuf {
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
index 0ddb5c02ad8b..d76a19ba2cff 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -65,6 +65,24 @@
 #define ST_UART011_ABCR		0x100	/* Autobaud control register. */
 #define ST_UART011_ABIMSC	0x15C	/* Autobaud interrupt mask/clear register. */
 
+/*
+ * ZTE UART register offsets.  This UART has a radically different address
+ * allocation from the ARM and ST variants, so we list all registers here.
+ * We assume unlisted registers do not exist.
+ */
+#define ZX_UART011_DR		0x04
+#define ZX_UART011_FR		0x14
+#define ZX_UART011_IBRD		0x24
+#define ZX_UART011_FBRD		0x28
+#define ZX_UART011_LCRH		0x30
+#define ZX_UART011_CR		0x34
+#define ZX_UART011_IFLS		0x38
+#define ZX_UART011_IMSC		0x40
+#define ZX_UART011_RIS		0x44
+#define ZX_UART011_MIS		0x48
+#define ZX_UART011_ICR		0x4c
+#define ZX_UART011_DMACR	0x50
+
 #define UART011_DR_OE		(1 << 11)
 #define UART011_DR_BE		(1 << 10)
 #define UART011_DR_PE		(1 << 9)
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* Re: [PATCH 01/11] tty: amba-pl011: add register accessor functions
  2015-11-03 14:50     ` Russell King
@ 2015-11-03 14:53       ` Timur Tabi
  -1 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-03 14:53 UTC (permalink / raw)
  To: Russell King, linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Russell King wrote:
> +static unsigned int pl011_read(void __iomem *base, unsigned int reg)
> +{
> +	return readw(base + reg);
> +}
> +
> +static void pl011_write(unsigned int val, void __iomem *base, unsigned int reg)
> +{
> +	writew(val, base + reg);
> +}

This has the same problem as the original, in that it doesn't support 
the SBSA subtype 13.

I'll post my version soon that addresses this.  Maybe you can consider 
it as a replacement for your patch 1/11.


-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 01/11] tty: amba-pl011: add register accessor functions
@ 2015-11-03 14:53       ` Timur Tabi
  0 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-03 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King wrote:
> +static unsigned int pl011_read(void __iomem *base, unsigned int reg)
> +{
> +	return readw(base + reg);
> +}
> +
> +static void pl011_write(unsigned int val, void __iomem *base, unsigned int reg)
> +{
> +	writew(val, base + reg);
> +}

This has the same problem as the original, in that it doesn't support 
the SBSA subtype 13.

I'll post my version soon that addresses this.  Maybe you can consider 
it as a replacement for your patch 1/11.


-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 10/11] tty: amba-pl011: add support for 32-bit register access
  2015-11-03 14:51     ` Russell King
@ 2015-11-03 14:57       ` Timur Tabi
  -1 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-03 14:57 UTC (permalink / raw)
  To: Russell King, linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Greg Kroah-Hartman, Jiri Slaby, Jun Nie

Russell King wrote:
> -	return readw(uap->port.membase + pl011_reg_to_offset(uap, reg));
> +	void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
> +
> +	return uap->access_32b ? readl(addr) : readw(addr);

Ok, ignore my previous email.  I just noticed this.

This version is fine, except that it now performs a runtime check for 
every I/O access.  Isn't that too much overhead?  access_32b will always 
be either True or False for the life of the entire SOC.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 10/11] tty: amba-pl011: add support for 32-bit register access
@ 2015-11-03 14:57       ` Timur Tabi
  0 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-03 14:57 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King wrote:
> -	return readw(uap->port.membase + pl011_reg_to_offset(uap, reg));
> +	void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
> +
> +	return uap->access_32b ? readl(addr) : readw(addr);

Ok, ignore my previous email.  I just noticed this.

This version is fine, except that it now performs a runtime check for 
every I/O access.  Isn't that too much overhead?  access_32b will always 
be either True or False for the life of the entire SOC.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 01/11] tty: amba-pl011: add register accessor functions
  2015-11-03 14:53       ` Timur Tabi
@ 2015-11-03 15:18         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 15:18 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	linux-serial, Greg Kroah-Hartman, Jiri Slaby, Jun Nie,
	linux-arm-kernel

On Tue, Nov 03, 2015 at 08:53:49AM -0600, Timur Tabi wrote:
> Russell King wrote:
> >+static unsigned int pl011_read(void __iomem *base, unsigned int reg)
> >+{
> >+	return readw(base + reg);
> >+}
> >+
> >+static void pl011_write(unsigned int val, void __iomem *base, unsigned int reg)
> >+{
> >+	writew(val, base + reg);
> >+}
> 
> This has the same problem as the original, in that it doesn't support the
> SBSA subtype 13.
> 
> I'll post my version soon that addresses this.  Maybe you can consider it as
> a replacement for your patch 1/11.

(I know you've already replied saying to ignore this, but I'm going to
reply to this anyway.)

This is one step in a series of single transformations to the code,
where this one merely replaces readw()/writew() with a local accessor
function.  Adding other changes into this patch would mean that it's
no longer a single transformation.

This "single transformation" theme applies across every patch in this
series, and IMHO shows how the addition of ZTE should have been done
in the first place: a series of single transformations, each one being
fairly obvious and easy to review.

Yes, it produces a bigger patch set, but it means that if there's a
problem with one of the transformations, the whole work doesn't need
to be reverted.  Eg, you'll notice that the more "dodgy" changes (such
as removing register offset entries) are done towards the end of the
series meaning that if there's a problem removing those, either a
single patch can be reverted, or the series can be reverted back to
that point and the benefit of the previous patches isn't lost.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 01/11] tty: amba-pl011: add register accessor functions
@ 2015-11-03 15:18         ` Russell King - ARM Linux
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 15:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 03, 2015 at 08:53:49AM -0600, Timur Tabi wrote:
> Russell King wrote:
> >+static unsigned int pl011_read(void __iomem *base, unsigned int reg)
> >+{
> >+	return readw(base + reg);
> >+}
> >+
> >+static void pl011_write(unsigned int val, void __iomem *base, unsigned int reg)
> >+{
> >+	writew(val, base + reg);
> >+}
> 
> This has the same problem as the original, in that it doesn't support the
> SBSA subtype 13.
> 
> I'll post my version soon that addresses this.  Maybe you can consider it as
> a replacement for your patch 1/11.

(I know you've already replied saying to ignore this, but I'm going to
reply to this anyway.)

This is one step in a series of single transformations to the code,
where this one merely replaces readw()/writew() with a local accessor
function.  Adding other changes into this patch would mean that it's
no longer a single transformation.

This "single transformation" theme applies across every patch in this
series, and IMHO shows how the addition of ZTE should have been done
in the first place: a series of single transformations, each one being
fairly obvious and easy to review.

Yes, it produces a bigger patch set, but it means that if there's a
problem with one of the transformations, the whole work doesn't need
to be reverted.  Eg, you'll notice that the more "dodgy" changes (such
as removing register offset entries) are done towards the end of the
series meaning that if there's a problem removing those, either a
single patch can be reverted, or the series can be reverted back to
that point and the benefit of the previous patches isn't lost.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 10/11] tty: amba-pl011: add support for 32-bit register access
  2015-11-03 14:57       ` Timur Tabi
@ 2015-11-03 16:19         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 16:19 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	linux-serial, Greg Kroah-Hartman, Jiri Slaby, Jun Nie,
	linux-arm-kernel

On Tue, Nov 03, 2015 at 08:57:05AM -0600, Timur Tabi wrote:
> Russell King wrote:
> >-	return readw(uap->port.membase + pl011_reg_to_offset(uap, reg));
> >+	void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
> >+
> >+	return uap->access_32b ? readl(addr) : readw(addr);
> 
> Ok, ignore my previous email.  I just noticed this.
> 
> This version is fine, except that it now performs a runtime check for every
> I/O access.  Isn't that too much overhead?  access_32b will always be either
> True or False for the life of the entire SOC.

It's a balance between a few more branches and killing six registers
(r0 - r3, ip, lr) on every register access due to a function call.
If GCC was a reasonable compiler, it could be done without incuring
any branches, merely by using conditional instructions, but GCC on
ARM really sucks - it wants to reload the base address, offset and
access_32b flag on every device access despite the struct being
marked const.  You'll get the same with your approach when adding
the register offsets, but it'll be worse - the compiler will have to
also reload the function pointer as well on every access.

So, my gut feeling is that my approach is better than the function
pointer call, especially with modern CPUs with branch prediction.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 10/11] tty: amba-pl011: add support for 32-bit register access
@ 2015-11-03 16:19         ` Russell King - ARM Linux
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-03 16:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 03, 2015 at 08:57:05AM -0600, Timur Tabi wrote:
> Russell King wrote:
> >-	return readw(uap->port.membase + pl011_reg_to_offset(uap, reg));
> >+	void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
> >+
> >+	return uap->access_32b ? readl(addr) : readw(addr);
> 
> Ok, ignore my previous email.  I just noticed this.
> 
> This version is fine, except that it now performs a runtime check for every
> I/O access.  Isn't that too much overhead?  access_32b will always be either
> True or False for the life of the entire SOC.

It's a balance between a few more branches and killing six registers
(r0 - r3, ip, lr) on every register access due to a function call.
If GCC was a reasonable compiler, it could be done without incuring
any branches, merely by using conditional instructions, but GCC on
ARM really sucks - it wants to reload the base address, offset and
access_32b flag on every device access despite the struct being
marked const.  You'll get the same with your approach when adding
the register offsets, but it'll be worse - the compiler will have to
also reload the function pointer as well on every access.

So, my gut feeling is that my approach is better than the function
pointer call, especially with modern CPUs with branch prediction.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 10/11] tty: amba-pl011: add support for 32-bit register access
  2015-11-03 16:19         ` Russell King - ARM Linux
@ 2015-11-05  4:46           ` Peter Hurley
  -1 siblings, 0 replies; 72+ messages in thread
From: Peter Hurley @ 2015-11-05  4:46 UTC (permalink / raw)
  To: Russell King - ARM Linux, Timur Tabi
  Cc: Andre Przywara, Linus Walleij, Andrew.Jackson, linux-serial,
	Greg Kroah-Hartman, Jiri Slaby, Jun Nie, linux-arm-kernel

On 11/03/2015 11:19 AM, Russell King - ARM Linux wrote:
> On Tue, Nov 03, 2015 at 08:57:05AM -0600, Timur Tabi wrote:
>> Russell King wrote:
>>> -	return readw(uap->port.membase + pl011_reg_to_offset(uap, reg));
>>> +	void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
>>> +
>>> +	return uap->access_32b ? readl(addr) : readw(addr);
>>
>> Ok, ignore my previous email.  I just noticed this.
>>
>> This version is fine, except that it now performs a runtime check for every
>> I/O access.  Isn't that too much overhead?  access_32b will always be either
>> True or False for the life of the entire SOC.
> 
> It's a balance between a few more branches and killing six registers
> (r0 - r3, ip, lr) on every register access due to a function call.
> If GCC was a reasonable compiler, it could be done without incuring
> any branches, merely by using conditional instructions, but GCC on
> ARM really sucks - it wants to reload the base address, offset and
> access_32b flag on every device access despite the struct being
> marked const.

The compiler reloads are probably due to the barriers in readw()/writew();
I think the relaxed i/o accessor variants avoid the reloads.

Regards,
Peter Hurley

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 10/11] tty: amba-pl011: add support for 32-bit register access
@ 2015-11-05  4:46           ` Peter Hurley
  0 siblings, 0 replies; 72+ messages in thread
From: Peter Hurley @ 2015-11-05  4:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 11/03/2015 11:19 AM, Russell King - ARM Linux wrote:
> On Tue, Nov 03, 2015 at 08:57:05AM -0600, Timur Tabi wrote:
>> Russell King wrote:
>>> -	return readw(uap->port.membase + pl011_reg_to_offset(uap, reg));
>>> +	void __iomem *addr = uap->port.membase + pl011_reg_to_offset(uap, reg);
>>> +
>>> +	return uap->access_32b ? readl(addr) : readw(addr);
>>
>> Ok, ignore my previous email.  I just noticed this.
>>
>> This version is fine, except that it now performs a runtime check for every
>> I/O access.  Isn't that too much overhead?  access_32b will always be either
>> True or False for the life of the entire SOC.
> 
> It's a balance between a few more branches and killing six registers
> (r0 - r3, ip, lr) on every register access due to a function call.
> If GCC was a reasonable compiler, it could be done without incuring
> any branches, merely by using conditional instructions, but GCC on
> ARM really sucks - it wants to reload the base address, offset and
> access_32b flag on every device access despite the struct being
> marked const.

The compiler reloads are probably due to the barriers in readw()/writew();
I think the relaxed i/o accessor variants avoid the reloads.

Regards,
Peter Hurley

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 11/11] tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)
  2015-11-03 14:51     ` Russell King
@ 2015-11-05  8:28       ` Linus Walleij
  -1 siblings, 0 replies; 72+ messages in thread
From: Linus Walleij @ 2015-11-05  8:28 UTC (permalink / raw)
  To: Russell King
  Cc: Peter Hurley, Andre Przywara, Andrew.Jackson, Timur Tabi,
	linux-serial, Greg Kroah-Hartman, Jiri Slaby, Jun Nie,
	linux-arm-kernel

On Tue, Nov 3, 2015 at 3:51 PM, Russell King
<rmk+kernel@arm.linux.org.uk> wrote:

> Add (incomplete) support for the ZTE UART to the AMBA PL011 driver.
> This is similar to the ARM and ST variants, except it has a different
> register address layout, and requires 32-bit accesses to the registers.
> Use the newly introduced register tables and access size support to
> cope with these differences.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

I applied the whole series, 1-11 and tested on Ux500 (ST Micro variant)
and on the ARM RealView PB11MPCore.

It works like a charm. I also like the looks of this transformation.
Tested-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 11/11] tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)
@ 2015-11-05  8:28       ` Linus Walleij
  0 siblings, 0 replies; 72+ messages in thread
From: Linus Walleij @ 2015-11-05  8:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 3, 2015 at 3:51 PM, Russell King
<rmk+kernel@arm.linux.org.uk> wrote:

> Add (incomplete) support for the ZTE UART to the AMBA PL011 driver.
> This is similar to the ARM and ST variants, except it has a different
> register address layout, and requires 32-bit accesses to the registers.
> Use the newly introduced register tables and access size support to
> cope with these differences.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

I applied the whole series, 1-11 and tested on Ux500 (ST Micro variant)
and on the ARM RealView PB11MPCore.

It works like a charm. I also like the looks of this transformation.
Tested-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 11/11] tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)
  2015-11-05  8:28       ` Linus Walleij
@ 2015-11-05  9:27         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-05  9:27 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Peter Hurley, Andre Przywara, Andrew.Jackson, Timur Tabi,
	linux-serial, Greg Kroah-Hartman, Jiri Slaby, Jun Nie,
	linux-arm-kernel

On Thu, Nov 05, 2015 at 09:28:23AM +0100, Linus Walleij wrote:
> On Tue, Nov 3, 2015 at 3:51 PM, Russell King
> <rmk+kernel@arm.linux.org.uk> wrote:
> 
> > Add (incomplete) support for the ZTE UART to the AMBA PL011 driver.
> > This is similar to the ARM and ST variants, except it has a different
> > register address layout, and requires 32-bit accesses to the registers.
> > Use the newly introduced register tables and access size support to
> > cope with these differences.
> >
> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> 
> I applied the whole series, 1-11 and tested on Ux500 (ST Micro variant)
> and on the ARM RealView PB11MPCore.
> 
> It works like a charm. I also like the looks of this transformation.
> Tested-by: Linus Walleij <linus.walleij@linaro.org>

As I mentioned, the change in pl011_putc() needs undoing (I've already
modified that in my series).  Also, I'll try switching to the relaxed
accessors and checking that.  Thanks for the tested-by though, can I
assume that you're happy I add that even with the pl011_putc() change
undone?

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 11/11] tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)
@ 2015-11-05  9:27         ` Russell King - ARM Linux
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-05  9:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Nov 05, 2015 at 09:28:23AM +0100, Linus Walleij wrote:
> On Tue, Nov 3, 2015 at 3:51 PM, Russell King
> <rmk+kernel@arm.linux.org.uk> wrote:
> 
> > Add (incomplete) support for the ZTE UART to the AMBA PL011 driver.
> > This is similar to the ARM and ST variants, except it has a different
> > register address layout, and requires 32-bit accesses to the registers.
> > Use the newly introduced register tables and access size support to
> > cope with these differences.
> >
> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> 
> I applied the whole series, 1-11 and tested on Ux500 (ST Micro variant)
> and on the ARM RealView PB11MPCore.
> 
> It works like a charm. I also like the looks of this transformation.
> Tested-by: Linus Walleij <linus.walleij@linaro.org>

As I mentioned, the change in pl011_putc() needs undoing (I've already
modified that in my series).  Also, I'll try switching to the relaxed
accessors and checking that.  Thanks for the tested-by though, can I
assume that you're happy I add that even with the pl011_putc() change
undone?

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
  2015-11-03 13:46     ` Russell King - ARM Linux
@ 2015-11-05  9:54       ` Jun Nie
  -1 siblings, 0 replies; 72+ messages in thread
From: Jun Nie @ 2015-11-05  9:54 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Peter Hurley, Andre Przywara, Andrew Jackson, Timur Tabi,
	linux-serial, linux-arm-kernel

2015-11-03 21:46 GMT+08:00 Russell King - ARM Linux <linux@arm.linux.org.uk>:
> On Mon, Nov 02, 2015 at 12:24:02PM +0000, Andre Przywara wrote:
>> +int reg_table_zte[] = {
>> +     [UART01x_DR]    = ZX_UART01x_DR,
>
> No entry for RSR, so the value will be zero.  That means when we read
> the RSR, we'll be reading the register at offset 0.  Maybe that's
> intentional, maybe it isn't, but it's totally screwy.
>
> Someone needs to document what the register layout for the ZTE UART
> is.  Better still, point to where the spec can be found.

I am checking ZTE engineer to make their UART spec public. Before
that, we can also make ZTE UART work from existing code. Just some
register offset and bit offset are different with PL011.

>
>> +     [UART011_LCRH]  = ZX_UART011_LCRH_TX,
>> +     [UART011_CR]    = ZX_UART011_CR,
>> +     [UART01x_FR]    = ZX_UART01x_FR,
>> +     [UART011_ICR]   = ZX_UART011_ICR,
>> +     [UART011_IBRD]  = UART011_IBRD,
>> +     [UART011_FBRD]  = UART011_FBRD,
>> +     [UART011_IFLS]  = ZX_UART011_IFLS,
>> +     [UART011_IMSC]  = ZX_UART011_IMSC,
>> +     [UART011_RIS]   = ZX_UART011_RIS,
>> +     [UART011_MIS]   = ZX_UART011_MIS,
>> +     [UART011_DMACR] = ZX_UART011_DMACR,
>> +};
>>  static unsigned int pl011_read(struct uart_amba_port *uap, int offset)
>>  {
>> +#ifdef CONFIG_SOC_ZX296702
>> +     if (uap->vendor->reg_table)
>> +             offset = uap->vendor->reg_table[offset];
>> +#endif
>>       return readw(uap->port.membase + offset);
>>  }
>>
>>  static void pl011_write(struct uart_amba_port *uap, int val, int offset)
>>  {
>> +#ifdef CONFIG_SOC_ZX296702
>> +     if (uap->vendor->reg_table)
>> +             offset = uap->vendor->reg_table[offset];
>> +#endif
>>       writew(val, uap->port.membase + offset);
>>  }
>>
>> diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
>> index 0ddb5c0..1c71b83 100644
>> --- a/include/linux/amba/serial.h
>> +++ b/include/linux/amba/serial.h
>> @@ -31,6 +31,7 @@
>>   *  UART Register Offsets.
>>   */
>>  #define UART01x_DR           0x00    /* Data read or written from the interface. */
>> +#define ZX_UART01x_DR                0x04    /* Different offset in the ZTE UART. */
>>  #define UART01x_RSR          0x04    /* Receive status register (Read). */
>>  #define UART01x_ECR          0x04    /* Error clear register (Write). */
>>  #define UART010_LCRH         0x08    /* Line control register, high byte. */
>> @@ -39,6 +40,7 @@
>>  #define ST_UART011_TIMEOUT   0x0C    /* Timeout period register. */
>>  #define UART010_LCRL         0x10    /* Line control register, low byte. */
>>  #define UART010_CR           0x14    /* Control register. */
>> +#define ZX_UART01x_FR                0x14    /* Different offset in the ZTE UART. */
>>  #define UART01x_FR           0x18    /* Flag register (Read only). */
>>  #define UART010_IIR          0x1C    /* Interrupt identification register (Read). */
>>  #define UART010_ICR          0x1C    /* Interrupt clear register (Write). */
>> @@ -48,14 +50,22 @@
>>  #define UART011_FBRD         0x28    /* Fractional baud rate divisor register. */
>>  #define UART011_LCRH         0x2c    /* Line control register. */
>>  #define ST_UART011_LCRH_TX   0x2c    /* Tx Line control register. */
>> +#define ZX_UART011_LCRH_TX   0x30    /* Different offset in the ZTE UART. */
>>  #define UART011_CR           0x30    /* Control register. */
>>  #define UART011_IFLS         0x34    /* Interrupt fifo level select. */
>> +#define ZX_UART011_CR                0x34    /* Different offset in the ZTE UART. */
>> +#define ZX_UART011_IFLS              0x38    /* Different offset in the ZTE UART. */
>>  #define UART011_IMSC         0x38    /* Interrupt mask. */
>>  #define UART011_RIS          0x3c    /* Raw interrupt status. */
>>  #define UART011_MIS          0x40    /* Masked interrupt status. */
>> +#define ZX_UART011_IMSC              0x40    /* Different offset in the ZTE UART. */
>>  #define UART011_ICR          0x44    /* Interrupt clear register. */
>> +#define ZX_UART011_RIS               0x44    /* Different offset in the ZTE UART. */
>>  #define UART011_DMACR                0x48    /* DMA control register. */
>> +#define ZX_UART011_MIS               0x48    /* Different offset in the ZTE UART. */
>> +#define ZX_UART011_ICR               0x4c    /* Different offset in the ZTE UART. */
>>  #define ST_UART011_XFCR              0x50    /* XON/XOFF control register. */
>> +#define ZX_UART011_DMACR     0x50    /* Different offset in the ZTE UART. */
>>  #define ST_UART011_XON1              0x54    /* XON1 register. */
>>  #define ST_UART011_XON2              0x58    /* XON2 register. */
>>  #define ST_UART011_XOFF1     0x5C    /* XON1 register. */
>> --
>> 2.5.1
>>
>
> --
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART
@ 2015-11-05  9:54       ` Jun Nie
  0 siblings, 0 replies; 72+ messages in thread
From: Jun Nie @ 2015-11-05  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

2015-11-03 21:46 GMT+08:00 Russell King - ARM Linux <linux@arm.linux.org.uk>:
> On Mon, Nov 02, 2015 at 12:24:02PM +0000, Andre Przywara wrote:
>> +int reg_table_zte[] = {
>> +     [UART01x_DR]    = ZX_UART01x_DR,
>
> No entry for RSR, so the value will be zero.  That means when we read
> the RSR, we'll be reading the register at offset 0.  Maybe that's
> intentional, maybe it isn't, but it's totally screwy.
>
> Someone needs to document what the register layout for the ZTE UART
> is.  Better still, point to where the spec can be found.

I am checking ZTE engineer to make their UART spec public. Before
that, we can also make ZTE UART work from existing code. Just some
register offset and bit offset are different with PL011.

>
>> +     [UART011_LCRH]  = ZX_UART011_LCRH_TX,
>> +     [UART011_CR]    = ZX_UART011_CR,
>> +     [UART01x_FR]    = ZX_UART01x_FR,
>> +     [UART011_ICR]   = ZX_UART011_ICR,
>> +     [UART011_IBRD]  = UART011_IBRD,
>> +     [UART011_FBRD]  = UART011_FBRD,
>> +     [UART011_IFLS]  = ZX_UART011_IFLS,
>> +     [UART011_IMSC]  = ZX_UART011_IMSC,
>> +     [UART011_RIS]   = ZX_UART011_RIS,
>> +     [UART011_MIS]   = ZX_UART011_MIS,
>> +     [UART011_DMACR] = ZX_UART011_DMACR,
>> +};
>>  static unsigned int pl011_read(struct uart_amba_port *uap, int offset)
>>  {
>> +#ifdef CONFIG_SOC_ZX296702
>> +     if (uap->vendor->reg_table)
>> +             offset = uap->vendor->reg_table[offset];
>> +#endif
>>       return readw(uap->port.membase + offset);
>>  }
>>
>>  static void pl011_write(struct uart_amba_port *uap, int val, int offset)
>>  {
>> +#ifdef CONFIG_SOC_ZX296702
>> +     if (uap->vendor->reg_table)
>> +             offset = uap->vendor->reg_table[offset];
>> +#endif
>>       writew(val, uap->port.membase + offset);
>>  }
>>
>> diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
>> index 0ddb5c0..1c71b83 100644
>> --- a/include/linux/amba/serial.h
>> +++ b/include/linux/amba/serial.h
>> @@ -31,6 +31,7 @@
>>   *  UART Register Offsets.
>>   */
>>  #define UART01x_DR           0x00    /* Data read or written from the interface. */
>> +#define ZX_UART01x_DR                0x04    /* Different offset in the ZTE UART. */
>>  #define UART01x_RSR          0x04    /* Receive status register (Read). */
>>  #define UART01x_ECR          0x04    /* Error clear register (Write). */
>>  #define UART010_LCRH         0x08    /* Line control register, high byte. */
>> @@ -39,6 +40,7 @@
>>  #define ST_UART011_TIMEOUT   0x0C    /* Timeout period register. */
>>  #define UART010_LCRL         0x10    /* Line control register, low byte. */
>>  #define UART010_CR           0x14    /* Control register. */
>> +#define ZX_UART01x_FR                0x14    /* Different offset in the ZTE UART. */
>>  #define UART01x_FR           0x18    /* Flag register (Read only). */
>>  #define UART010_IIR          0x1C    /* Interrupt identification register (Read). */
>>  #define UART010_ICR          0x1C    /* Interrupt clear register (Write). */
>> @@ -48,14 +50,22 @@
>>  #define UART011_FBRD         0x28    /* Fractional baud rate divisor register. */
>>  #define UART011_LCRH         0x2c    /* Line control register. */
>>  #define ST_UART011_LCRH_TX   0x2c    /* Tx Line control register. */
>> +#define ZX_UART011_LCRH_TX   0x30    /* Different offset in the ZTE UART. */
>>  #define UART011_CR           0x30    /* Control register. */
>>  #define UART011_IFLS         0x34    /* Interrupt fifo level select. */
>> +#define ZX_UART011_CR                0x34    /* Different offset in the ZTE UART. */
>> +#define ZX_UART011_IFLS              0x38    /* Different offset in the ZTE UART. */
>>  #define UART011_IMSC         0x38    /* Interrupt mask. */
>>  #define UART011_RIS          0x3c    /* Raw interrupt status. */
>>  #define UART011_MIS          0x40    /* Masked interrupt status. */
>> +#define ZX_UART011_IMSC              0x40    /* Different offset in the ZTE UART. */
>>  #define UART011_ICR          0x44    /* Interrupt clear register. */
>> +#define ZX_UART011_RIS               0x44    /* Different offset in the ZTE UART. */
>>  #define UART011_DMACR                0x48    /* DMA control register. */
>> +#define ZX_UART011_MIS               0x48    /* Different offset in the ZTE UART. */
>> +#define ZX_UART011_ICR               0x4c    /* Different offset in the ZTE UART. */
>>  #define ST_UART011_XFCR              0x50    /* XON/XOFF control register. */
>> +#define ZX_UART011_DMACR     0x50    /* Different offset in the ZTE UART. */
>>  #define ST_UART011_XON1              0x54    /* XON1 register. */
>>  #define ST_UART011_XON2              0x58    /* XON2 register. */
>>  #define ST_UART011_XOFF1     0x5C    /* XON1 register. */
>> --
>> 2.5.1
>>
>
> --
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 11/11] tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)
  2015-11-05  9:27         ` Russell King - ARM Linux
@ 2015-11-05  9:54           ` Linus Walleij
  -1 siblings, 0 replies; 72+ messages in thread
From: Linus Walleij @ 2015-11-05  9:54 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Peter Hurley, Andre Przywara, Andrew.Jackson, Timur Tabi,
	linux-serial, Greg Kroah-Hartman, Jiri Slaby, Jun Nie,
	linux-arm-kernel

On Thu, Nov 5, 2015 at 10:27 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Nov 05, 2015 at 09:28:23AM +0100, Linus Walleij wrote:
>> On Tue, Nov 3, 2015 at 3:51 PM, Russell King
>> <rmk+kernel@arm.linux.org.uk> wrote:
>>
>> > Add (incomplete) support for the ZTE UART to the AMBA PL011 driver.
>> > This is similar to the ARM and ST variants, except it has a different
>> > register address layout, and requires 32-bit accesses to the registers.
>> > Use the newly introduced register tables and access size support to
>> > cope with these differences.
>> >
>> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
>>
>> I applied the whole series, 1-11 and tested on Ux500 (ST Micro variant)
>> and on the ARM RealView PB11MPCore.
>>
>> It works like a charm. I also like the looks of this transformation.
>> Tested-by: Linus Walleij <linus.walleij@linaro.org>
>
> As I mentioned, the change in pl011_putc() needs undoing (I've already
> modified that in my series).  Also, I'll try switching to the relaxed
> accessors and checking that.  Thanks for the tested-by though, can I
> assume that you're happy I add that even with the pl011_putc() change
> undone?

Sure. I'm pretty sure that doesn't change much.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 11/11] tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)
@ 2015-11-05  9:54           ` Linus Walleij
  0 siblings, 0 replies; 72+ messages in thread
From: Linus Walleij @ 2015-11-05  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Nov 5, 2015 at 10:27 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Nov 05, 2015 at 09:28:23AM +0100, Linus Walleij wrote:
>> On Tue, Nov 3, 2015 at 3:51 PM, Russell King
>> <rmk+kernel@arm.linux.org.uk> wrote:
>>
>> > Add (incomplete) support for the ZTE UART to the AMBA PL011 driver.
>> > This is similar to the ARM and ST variants, except it has a different
>> > register address layout, and requires 32-bit accesses to the registers.
>> > Use the newly introduced register tables and access size support to
>> > cope with these differences.
>> >
>> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
>>
>> I applied the whole series, 1-11 and tested on Ux500 (ST Micro variant)
>> and on the ARM RealView PB11MPCore.
>>
>> It works like a charm. I also like the looks of this transformation.
>> Tested-by: Linus Walleij <linus.walleij@linaro.org>
>
> As I mentioned, the change in pl011_putc() needs undoing (I've already
> modified that in my series).  Also, I'll try switching to the relaxed
> accessors and checking that.  Thanks for the tested-by though, can I
> assume that you're happy I add that even with the pl011_putc() change
> undone?

Sure. I'm pretty sure that doesn't change much.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 05/11] tty: amba-pl011: add register lookup table
  2015-11-03 14:51     ` Russell King
@ 2015-11-06  0:00       ` Timur Tabi
  -1 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-06  0:00 UTC (permalink / raw)
  To: Russell King, linux-serial, linux-arm-kernel
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, Greg Kroah-Hartman, Jiri Slaby, Jun Nie

On 11/03/2015 08:51 AM, Russell King wrote:
>   enum {
> -	REG_DR = UART01x_DR,
> -	REG_ST_DMAWM = ST_UART011_DMAWM,
> -	REG_ST_TIMEOUT = ST_UART011_TIMEOUT,
> -	REG_FR = UART01x_FR,
> -	REG_ST_LCRH_RX = ST_UART011_LCRH_RX,
> -	REG_IBRD = UART011_IBRD,
> -	REG_FBRD = UART011_FBRD,
> -	REG_LCRH = UART011_LCRH,
> -	REG_ST_LCRH_TX = ST_UART011_LCRH_TX,
> -	REG_CR = UART011_CR,
> -	REG_IFLS = UART011_IFLS,
> -	REG_IMSC = UART011_IMSC,
> -	REG_RIS = UART011_RIS,
> -	REG_MIS = UART011_MIS,
> -	REG_ICR = UART011_ICR,
> -	REG_DMACR = UART011_DMACR,
> -	REG_ST_XFCR = ST_UART011_XFCR,
> -	REG_ST_XON1 = ST_UART011_XON1,
> -	REG_ST_XON2 = ST_UART011_XON2,
> -	REG_ST_XOFF1 = ST_UART011_XOFF1,
> -	REG_ST_XOFF2 = ST_UART011_XOFF2,
> -	REG_ST_ITCR = ST_UART011_ITCR,
> -	REG_ST_ITIP = ST_UART011_ITIP,
> -	REG_ST_ABCR = ST_UART011_ABCR,
> -	REG_ST_ABIMSC = ST_UART011_ABIMSC,
> +	REG_DR,
> +	REG_ST_DMAWM,
> +	REG_ST_TIMEOUT,
> +	REG_FR,
> +	REG_ST_LCRH_RX,
> +	REG_IBRD,
> +	REG_FBRD,
> +	REG_LCRH,
> +	REG_ST_LCRH_TX,
> +	REG_CR,
> +	REG_IFLS,
> +	REG_IMSC,
> +	REG_RIS,
> +	REG_MIS,
> +	REG_ICR,
> +	REG_DMACR,
> +	REG_ST_XFCR,
> +	REG_ST_XON1,
> +	REG_ST_XON2,
> +	REG_ST_XOFF1,
> +	REG_ST_XOFF2,
> +	REG_ST_ITCR,
> +	REG_ST_ITIP,
> +	REG_ST_ABCR,
> +	REG_ST_ABIMSC,
> +
> +	/* The size of the array - must be last */
> +	REG_ARRAY_SIZE,
>   };

This breaks early console because REG_DR and REG_FR are now enums 
instead of an actual register offset, and so

static void pl011_putc(struct uart_port *port, int c)
{
	while (readl(port->membase + REG_FR) & UART01x_FR_TXFF)
		;
	writeb(c, port->membase + REG_DR);
	while (readl(port->membase + REG_FR) & UART01x_FR_BUSY)
		;
}

is wrong.  I get alignment violations because REG_FR is equal to 3 
instead of 0x18.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 05/11] tty: amba-pl011: add register lookup table
@ 2015-11-06  0:00       ` Timur Tabi
  0 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-06  0:00 UTC (permalink / raw)
  To: linux-arm-kernel

On 11/03/2015 08:51 AM, Russell King wrote:
>   enum {
> -	REG_DR = UART01x_DR,
> -	REG_ST_DMAWM = ST_UART011_DMAWM,
> -	REG_ST_TIMEOUT = ST_UART011_TIMEOUT,
> -	REG_FR = UART01x_FR,
> -	REG_ST_LCRH_RX = ST_UART011_LCRH_RX,
> -	REG_IBRD = UART011_IBRD,
> -	REG_FBRD = UART011_FBRD,
> -	REG_LCRH = UART011_LCRH,
> -	REG_ST_LCRH_TX = ST_UART011_LCRH_TX,
> -	REG_CR = UART011_CR,
> -	REG_IFLS = UART011_IFLS,
> -	REG_IMSC = UART011_IMSC,
> -	REG_RIS = UART011_RIS,
> -	REG_MIS = UART011_MIS,
> -	REG_ICR = UART011_ICR,
> -	REG_DMACR = UART011_DMACR,
> -	REG_ST_XFCR = ST_UART011_XFCR,
> -	REG_ST_XON1 = ST_UART011_XON1,
> -	REG_ST_XON2 = ST_UART011_XON2,
> -	REG_ST_XOFF1 = ST_UART011_XOFF1,
> -	REG_ST_XOFF2 = ST_UART011_XOFF2,
> -	REG_ST_ITCR = ST_UART011_ITCR,
> -	REG_ST_ITIP = ST_UART011_ITIP,
> -	REG_ST_ABCR = ST_UART011_ABCR,
> -	REG_ST_ABIMSC = ST_UART011_ABIMSC,
> +	REG_DR,
> +	REG_ST_DMAWM,
> +	REG_ST_TIMEOUT,
> +	REG_FR,
> +	REG_ST_LCRH_RX,
> +	REG_IBRD,
> +	REG_FBRD,
> +	REG_LCRH,
> +	REG_ST_LCRH_TX,
> +	REG_CR,
> +	REG_IFLS,
> +	REG_IMSC,
> +	REG_RIS,
> +	REG_MIS,
> +	REG_ICR,
> +	REG_DMACR,
> +	REG_ST_XFCR,
> +	REG_ST_XON1,
> +	REG_ST_XON2,
> +	REG_ST_XOFF1,
> +	REG_ST_XOFF2,
> +	REG_ST_ITCR,
> +	REG_ST_ITIP,
> +	REG_ST_ABCR,
> +	REG_ST_ABIMSC,
> +
> +	/* The size of the array - must be last */
> +	REG_ARRAY_SIZE,
>   };

This breaks early console because REG_DR and REG_FR are now enums 
instead of an actual register offset, and so

static void pl011_putc(struct uart_port *port, int c)
{
	while (readl(port->membase + REG_FR) & UART01x_FR_TXFF)
		;
	writeb(c, port->membase + REG_DR);
	while (readl(port->membase + REG_FR) & UART01x_FR_BUSY)
		;
}

is wrong.  I get alignment violations because REG_FR is equal to 3 
instead of 0x18.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 05/11] tty: amba-pl011: add register lookup table
  2015-11-06  0:00       ` Timur Tabi
@ 2015-11-06  0:24         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-06  0:24 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, linux-serial, Greg Kroah-Hartman, Jiri Slaby,
	Jun Nie, linux-arm-kernel

On Thu, Nov 05, 2015 at 06:00:08PM -0600, Timur Tabi wrote:
> On 11/03/2015 08:51 AM, Russell King wrote:
> >  enum {
> >-	REG_DR = UART01x_DR,
> >-	REG_ST_DMAWM = ST_UART011_DMAWM,
> >-	REG_ST_TIMEOUT = ST_UART011_TIMEOUT,
> >-	REG_FR = UART01x_FR,
> >-	REG_ST_LCRH_RX = ST_UART011_LCRH_RX,
> >-	REG_IBRD = UART011_IBRD,
> >-	REG_FBRD = UART011_FBRD,
> >-	REG_LCRH = UART011_LCRH,
> >-	REG_ST_LCRH_TX = ST_UART011_LCRH_TX,
> >-	REG_CR = UART011_CR,
> >-	REG_IFLS = UART011_IFLS,
> >-	REG_IMSC = UART011_IMSC,
> >-	REG_RIS = UART011_RIS,
> >-	REG_MIS = UART011_MIS,
> >-	REG_ICR = UART011_ICR,
> >-	REG_DMACR = UART011_DMACR,
> >-	REG_ST_XFCR = ST_UART011_XFCR,
> >-	REG_ST_XON1 = ST_UART011_XON1,
> >-	REG_ST_XON2 = ST_UART011_XON2,
> >-	REG_ST_XOFF1 = ST_UART011_XOFF1,
> >-	REG_ST_XOFF2 = ST_UART011_XOFF2,
> >-	REG_ST_ITCR = ST_UART011_ITCR,
> >-	REG_ST_ITIP = ST_UART011_ITIP,
> >-	REG_ST_ABCR = ST_UART011_ABCR,
> >-	REG_ST_ABIMSC = ST_UART011_ABIMSC,
> >+	REG_DR,
> >+	REG_ST_DMAWM,
> >+	REG_ST_TIMEOUT,
> >+	REG_FR,
> >+	REG_ST_LCRH_RX,
> >+	REG_IBRD,
> >+	REG_FBRD,
> >+	REG_LCRH,
> >+	REG_ST_LCRH_TX,
> >+	REG_CR,
> >+	REG_IFLS,
> >+	REG_IMSC,
> >+	REG_RIS,
> >+	REG_MIS,
> >+	REG_ICR,
> >+	REG_DMACR,
> >+	REG_ST_XFCR,
> >+	REG_ST_XON1,
> >+	REG_ST_XON2,
> >+	REG_ST_XOFF1,
> >+	REG_ST_XOFF2,
> >+	REG_ST_ITCR,
> >+	REG_ST_ITIP,
> >+	REG_ST_ABCR,
> >+	REG_ST_ABIMSC,
> >+
> >+	/* The size of the array - must be last */
> >+	REG_ARRAY_SIZE,
> >  };
> 
> This breaks early console because REG_DR and REG_FR are now enums instead of
> an actual register offset, and so
> 
> static void pl011_putc(struct uart_port *port, int c)
> {
> 	while (readl(port->membase + REG_FR) & UART01x_FR_TXFF)
> 		;
> 	writeb(c, port->membase + REG_DR);
> 	while (readl(port->membase + REG_FR) & UART01x_FR_BUSY)
> 		;
> }
> 
> is wrong.  I get alignment violations because REG_FR is equal to 3 instead
> of 0x18.

I know, and I said as much on the 3rd November in my reply to you that
this change should be undone, and again earlier today in reply to Linus.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 05/11] tty: amba-pl011: add register lookup table
@ 2015-11-06  0:24         ` Russell King - ARM Linux
  0 siblings, 0 replies; 72+ messages in thread
From: Russell King - ARM Linux @ 2015-11-06  0:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Nov 05, 2015 at 06:00:08PM -0600, Timur Tabi wrote:
> On 11/03/2015 08:51 AM, Russell King wrote:
> >  enum {
> >-	REG_DR = UART01x_DR,
> >-	REG_ST_DMAWM = ST_UART011_DMAWM,
> >-	REG_ST_TIMEOUT = ST_UART011_TIMEOUT,
> >-	REG_FR = UART01x_FR,
> >-	REG_ST_LCRH_RX = ST_UART011_LCRH_RX,
> >-	REG_IBRD = UART011_IBRD,
> >-	REG_FBRD = UART011_FBRD,
> >-	REG_LCRH = UART011_LCRH,
> >-	REG_ST_LCRH_TX = ST_UART011_LCRH_TX,
> >-	REG_CR = UART011_CR,
> >-	REG_IFLS = UART011_IFLS,
> >-	REG_IMSC = UART011_IMSC,
> >-	REG_RIS = UART011_RIS,
> >-	REG_MIS = UART011_MIS,
> >-	REG_ICR = UART011_ICR,
> >-	REG_DMACR = UART011_DMACR,
> >-	REG_ST_XFCR = ST_UART011_XFCR,
> >-	REG_ST_XON1 = ST_UART011_XON1,
> >-	REG_ST_XON2 = ST_UART011_XON2,
> >-	REG_ST_XOFF1 = ST_UART011_XOFF1,
> >-	REG_ST_XOFF2 = ST_UART011_XOFF2,
> >-	REG_ST_ITCR = ST_UART011_ITCR,
> >-	REG_ST_ITIP = ST_UART011_ITIP,
> >-	REG_ST_ABCR = ST_UART011_ABCR,
> >-	REG_ST_ABIMSC = ST_UART011_ABIMSC,
> >+	REG_DR,
> >+	REG_ST_DMAWM,
> >+	REG_ST_TIMEOUT,
> >+	REG_FR,
> >+	REG_ST_LCRH_RX,
> >+	REG_IBRD,
> >+	REG_FBRD,
> >+	REG_LCRH,
> >+	REG_ST_LCRH_TX,
> >+	REG_CR,
> >+	REG_IFLS,
> >+	REG_IMSC,
> >+	REG_RIS,
> >+	REG_MIS,
> >+	REG_ICR,
> >+	REG_DMACR,
> >+	REG_ST_XFCR,
> >+	REG_ST_XON1,
> >+	REG_ST_XON2,
> >+	REG_ST_XOFF1,
> >+	REG_ST_XOFF2,
> >+	REG_ST_ITCR,
> >+	REG_ST_ITIP,
> >+	REG_ST_ABCR,
> >+	REG_ST_ABIMSC,
> >+
> >+	/* The size of the array - must be last */
> >+	REG_ARRAY_SIZE,
> >  };
> 
> This breaks early console because REG_DR and REG_FR are now enums instead of
> an actual register offset, and so
> 
> static void pl011_putc(struct uart_port *port, int c)
> {
> 	while (readl(port->membase + REG_FR) & UART01x_FR_TXFF)
> 		;
> 	writeb(c, port->membase + REG_DR);
> 	while (readl(port->membase + REG_FR) & UART01x_FR_BUSY)
> 		;
> }
> 
> is wrong.  I get alignment violations because REG_FR is equal to 3 instead
> of 0x18.

I know, and I said as much on the 3rd November in my reply to you that
this change should be undone, and again earlier today in reply to Linus.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 05/11] tty: amba-pl011: add register lookup table
  2015-11-06  0:24         ` Russell King - ARM Linux
@ 2015-11-06  0:27           ` Timur Tabi
  -1 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-06  0:27 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	linux-serial, Greg Kroah-Hartman, Jiri Slaby, Jun Nie,
	linux-arm-kernel

On 11/05/2015 06:24 PM, Russell King - ARM Linux wrote:
> I know, and I said as much on the 3rd November in my reply to you that
> this change should be undone, and again earlier today in reply to Linus.

Sorry, with so much pl011 stuff flying around, I can't keep track of 
much anymore.

Anyway, I do have a fix, but it's kinda ugly.  I'll post it soon.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 05/11] tty: amba-pl011: add register lookup table
@ 2015-11-06  0:27           ` Timur Tabi
  0 siblings, 0 replies; 72+ messages in thread
From: Timur Tabi @ 2015-11-06  0:27 UTC (permalink / raw)
  To: linux-arm-kernel

On 11/05/2015 06:24 PM, Russell King - ARM Linux wrote:
> I know, and I said as much on the 3rd November in my reply to you that
> this change should be undone, and again earlier today in reply to Linus.

Sorry, with so much pl011 stuff flying around, I can't keep track of 
much anymore.

Anyway, I do have a fix, but it's kinda ugly.  I'll post it soon.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 05/11] tty: amba-pl011: add register lookup table
  2015-11-03 14:51     ` Russell King
@ 2015-12-13  6:03       ` Greg Kroah-Hartman
  -1 siblings, 0 replies; 72+ messages in thread
From: Greg Kroah-Hartman @ 2015-12-13  6:03 UTC (permalink / raw)
  To: Russell King
  Cc: Peter Hurley, Andre Przywara, Linus Walleij, Andrew.Jackson,
	Timur Tabi, linux-serial, Jiri Slaby, Jun Nie, linux-arm-kernel

On Tue, Nov 03, 2015 at 02:51:18PM +0000, Russell King wrote:
> Add a register lookup table, which allows the register offsets to be
> adjusted on a per-port basis.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  drivers/tty/serial/amba-pl011.c | 33 ++++++++++++++++++++++++-
>  drivers/tty/serial/amba-pl011.h | 53 ++++++++++++++++++++++-------------------
>  2 files changed, 60 insertions(+), 26 deletions(-)

I'm guessing I should stop here in the series, so I haven't applied
this, or any patch after this to my tree.  Please resend what you have
left over as I think you have updates.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 05/11] tty: amba-pl011: add register lookup table
@ 2015-12-13  6:03       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 72+ messages in thread
From: Greg Kroah-Hartman @ 2015-12-13  6:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 03, 2015 at 02:51:18PM +0000, Russell King wrote:
> Add a register lookup table, which allows the register offsets to be
> adjusted on a per-port basis.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  drivers/tty/serial/amba-pl011.c | 33 ++++++++++++++++++++++++-
>  drivers/tty/serial/amba-pl011.h | 53 ++++++++++++++++++++++-------------------
>  2 files changed, 60 insertions(+), 26 deletions(-)

I'm guessing I should stop here in the series, so I haven't applied
this, or any patch after this to my tree.  Please resend what you have
left over as I think you have updates.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 72+ messages in thread

end of thread, other threads:[~2015-12-13  6:03 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-02 12:24 [PATCH DRAFT 0/2] Sketch for ZTE ZX296702 UART integration Andre Przywara
2015-11-02 12:24 ` Andre Przywara
2015-11-02 12:24 ` [PATCH DRAFT 1/2] drivers: serial: PL011: refactor register access Andre Przywara
2015-11-02 12:24   ` Andre Przywara
2015-11-02 13:27   ` Timur Tabi
2015-11-02 13:27     ` Timur Tabi
2015-11-02 13:40     ` Andre Przywara
2015-11-02 13:40       ` Andre Przywara
2015-11-02 13:44       ` Timur Tabi
2015-11-02 13:44         ` Timur Tabi
2015-11-02 12:24 ` [PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART Andre Przywara
2015-11-02 12:24   ` Andre Przywara
2015-11-03 13:46   ` Russell King - ARM Linux
2015-11-03 13:46     ` Russell King - ARM Linux
2015-11-03 13:57     ` Andre Przywara
2015-11-03 13:57       ` Andre Przywara
2015-11-05  9:54     ` Jun Nie
2015-11-05  9:54       ` Jun Nie
2015-11-03 14:23   ` Russell King - ARM Linux
2015-11-03 14:23     ` Russell King - ARM Linux
2015-11-03 14:30     ` Andre Przywara
2015-11-03 14:30       ` Andre Przywara
2015-11-03 13:43 ` [PATCH DRAFT 0/2] Sketch for ZTE ZX296702 UART integration Russell King - ARM Linux
2015-11-03 13:43   ` Russell King - ARM Linux
2015-11-03 14:48   ` Russell King - ARM Linux
2015-11-03 14:48     ` Russell King - ARM Linux
2015-11-03 14:50   ` [PATCH 01/11] tty: amba-pl011: add register accessor functions Russell King
2015-11-03 14:50     ` Russell King
2015-11-03 14:53     ` Timur Tabi
2015-11-03 14:53       ` Timur Tabi
2015-11-03 15:18       ` Russell King - ARM Linux
2015-11-03 15:18         ` Russell King - ARM Linux
2015-11-03 14:51   ` [PATCH 02/11] tty: amba-pl011: convert accessor functions to take uart_amba_port Russell King
2015-11-03 14:51     ` Russell King
2015-11-03 14:51   ` [PATCH 03/11] tty: amba-pl011: add helper to detect split LCRH register Russell King
2015-11-03 14:51     ` Russell King
2015-11-03 14:51   ` [PATCH 04/11] tty: amba-pl011: prepare REG_* register indexes Russell King
2015-11-03 14:51     ` Russell King
2015-11-03 14:51   ` [PATCH 05/11] tty: amba-pl011: add register lookup table Russell King
2015-11-03 14:51     ` Russell King
2015-11-06  0:00     ` Timur Tabi
2015-11-06  0:00       ` Timur Tabi
2015-11-06  0:24       ` Russell King - ARM Linux
2015-11-06  0:24         ` Russell King - ARM Linux
2015-11-06  0:27         ` Timur Tabi
2015-11-06  0:27           ` Timur Tabi
2015-12-13  6:03     ` Greg Kroah-Hartman
2015-12-13  6:03       ` Greg Kroah-Hartman
2015-11-03 14:51   ` [PATCH 06/11] tty: amba-pl011: add register offset table to vendor data Russell King
2015-11-03 14:51     ` Russell King
2015-11-03 14:51   ` [PATCH 07/11] tty: amba-pl011: add ST register offset table Russell King
2015-11-03 14:51     ` Russell King
2015-11-03 14:51   ` [PATCH 08/11] tty: amba-pl011: clean up LCR register offsets Russell King
2015-11-03 14:51     ` Russell King
2015-11-03 14:51   ` [PATCH 09/11] tty: amba-pl011: remove ST micro registers from standard table Russell King
2015-11-03 14:51     ` Russell King
2015-11-03 14:51   ` [PATCH 10/11] tty: amba-pl011: add support for 32-bit register access Russell King
2015-11-03 14:51     ` Russell King
2015-11-03 14:57     ` Timur Tabi
2015-11-03 14:57       ` Timur Tabi
2015-11-03 16:19       ` Russell King - ARM Linux
2015-11-03 16:19         ` Russell King - ARM Linux
2015-11-05  4:46         ` Peter Hurley
2015-11-05  4:46           ` Peter Hurley
2015-11-03 14:51   ` [PATCH 11/11] tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL) Russell King
2015-11-03 14:51     ` Russell King
2015-11-05  8:28     ` Linus Walleij
2015-11-05  8:28       ` Linus Walleij
2015-11-05  9:27       ` Russell King - ARM Linux
2015-11-05  9:27         ` Russell King - ARM Linux
2015-11-05  9:54         ` Linus Walleij
2015-11-05  9:54           ` Linus Walleij

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.