All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/5] tty/serial: at91: add support to FIFOs
@ 2015-07-02 13:18 ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt,
	Cyrille Pitchen

ChangeLog

v4:
- insert a new patch in the series to remove UART_PUT_* and UART_GET_*
  macros. replace them by atmel_uart_writel() and atmel_uart_readl().

v3:
- add "Acked-by" tags on patches 1, 2 and 4.
- define macros check the FIFO size and to configure the high and low RTS
  thresholds in patch 3.
- fix a spelling mistake in patch 3: s/raisonable/reasonably/

v2:
- remove "atmel,rts-high-threshold" and "atmel,rts-low-threshold" from new
  DT properties. For now these two thresholds are set once for all during the
  probe but a later patch might allow to configure them at run time.
- reword the commit message of the DT property patch to better explain why we
  have chosen to introduce the new property "atmel,fifo-size".
- add a missing chunk in the FIFO patch: as the commit message explains, we
  need to use 8bit accesses when dealing with the Transmit/Receive Holding
  Registers.

v1:
This series of patches add support to FIFOs which will be introduced with Atmel
sama5d2x SoC.

FIFOs allow to reduce the number of I/O access. Indeed depending on the data
size and the USART mode, FIFOs work in either single or multiple data. For
multiple data, up to 4 data can be written into the Transmit Holding Register
or read from the Receive Holding Register in a single word access.

Also the RX FIFO allows to reduce the risk of receive overrun and data loss,
especially when the DMA controller is not used.

Finally, when the hardware handshake mode is selected, the RTS line can now be
controlled by two thresholds on the RX FIFO. When FIFO level (the number of
data available to be read) crosses the high threshold, the RTS line is set to
high level telling the peer that it should stop sending new data. Data are read
from the RX FIFO and when the FIFO level crosses the low threshold, the RTS
is set back to low level telling the remote peer that it can send data again.

This new feature resolves a long time hardware limitation where the RTS line
was directly controlled by a PDC signal. There is no equivalent of that signal
for the DMA controller so for all SoCs without PDC for USART there was no mean
to control the RTS line properly: once the hardware handshake mode selected,
the RTS line remains high level. Next SoCs with FIFOs will be able to use the
hardware handshake mode thanks to the RX FIFO.

Cyrille Pitchen (5):
  ARM: at91/dt: add a new DT property to support FIFOs on Atmel USARTs
  tty/serial: at91: fix some macro definitions to fit coding style
  tty/serial: at91: remove bunch of macros to access UART registers
  tty/serial: at91: add support to FIFOs
  tty/serial: at91: use 32bit writes into TX FIFO when DMA is enabled

 .../devicetree/bindings/serial/atmel-usart.txt     |   3 +
 drivers/tty/serial/atmel_serial.c                  | 467 +++++++++++++--------
 include/linux/atmel_serial.h                       | 240 ++++++-----
 3 files changed, 439 insertions(+), 271 deletions(-)

-- 
1.8.2.2


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

* [PATCH v4 0/5] tty/serial: at91: add support to FIFOs
@ 2015-07-02 13:18 ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	wenyou.yang-AIFe0yeh4nAAvxtiuMwx3w,
	ludovic.desroches-AIFe0yeh4nAAvxtiuMwx3w,
	leilei.zhao-AIFe0yeh4nAAvxtiuMwx3w,
	josh.wu-AIFe0yeh4nAAvxtiuMwx3w,
	alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	linux-serial-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, galak-sgV2jX0FEOL9JmXXK+q4OQ,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg, mark.rutland-5wv7dgnIgG8,
	pawel.moll-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	Cyrille Pitchen

ChangeLog

v4:
- insert a new patch in the series to remove UART_PUT_* and UART_GET_*
  macros. replace them by atmel_uart_writel() and atmel_uart_readl().

v3:
- add "Acked-by" tags on patches 1, 2 and 4.
- define macros check the FIFO size and to configure the high and low RTS
  thresholds in patch 3.
- fix a spelling mistake in patch 3: s/raisonable/reasonably/

v2:
- remove "atmel,rts-high-threshold" and "atmel,rts-low-threshold" from new
  DT properties. For now these two thresholds are set once for all during the
  probe but a later patch might allow to configure them at run time.
- reword the commit message of the DT property patch to better explain why we
  have chosen to introduce the new property "atmel,fifo-size".
- add a missing chunk in the FIFO patch: as the commit message explains, we
  need to use 8bit accesses when dealing with the Transmit/Receive Holding
  Registers.

v1:
This series of patches add support to FIFOs which will be introduced with Atmel
sama5d2x SoC.

FIFOs allow to reduce the number of I/O access. Indeed depending on the data
size and the USART mode, FIFOs work in either single or multiple data. For
multiple data, up to 4 data can be written into the Transmit Holding Register
or read from the Receive Holding Register in a single word access.

Also the RX FIFO allows to reduce the risk of receive overrun and data loss,
especially when the DMA controller is not used.

Finally, when the hardware handshake mode is selected, the RTS line can now be
controlled by two thresholds on the RX FIFO. When FIFO level (the number of
data available to be read) crosses the high threshold, the RTS line is set to
high level telling the peer that it should stop sending new data. Data are read
from the RX FIFO and when the FIFO level crosses the low threshold, the RTS
is set back to low level telling the remote peer that it can send data again.

This new feature resolves a long time hardware limitation where the RTS line
was directly controlled by a PDC signal. There is no equivalent of that signal
for the DMA controller so for all SoCs without PDC for USART there was no mean
to control the RTS line properly: once the hardware handshake mode selected,
the RTS line remains high level. Next SoCs with FIFOs will be able to use the
hardware handshake mode thanks to the RX FIFO.

Cyrille Pitchen (5):
  ARM: at91/dt: add a new DT property to support FIFOs on Atmel USARTs
  tty/serial: at91: fix some macro definitions to fit coding style
  tty/serial: at91: remove bunch of macros to access UART registers
  tty/serial: at91: add support to FIFOs
  tty/serial: at91: use 32bit writes into TX FIFO when DMA is enabled

 .../devicetree/bindings/serial/atmel-usart.txt     |   3 +
 drivers/tty/serial/atmel_serial.c                  | 467 +++++++++++++--------
 include/linux/atmel_serial.h                       | 240 ++++++-----
 3 files changed, 439 insertions(+), 271 deletions(-)

-- 
1.8.2.2

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

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

* [PATCH v4 0/5] tty/serial: at91: add support to FIFOs
@ 2015-07-02 13:18 ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: linux-arm-kernel

ChangeLog

v4:
- insert a new patch in the series to remove UART_PUT_* and UART_GET_*
  macros. replace them by atmel_uart_writel() and atmel_uart_readl().

v3:
- add "Acked-by" tags on patches 1, 2 and 4.
- define macros check the FIFO size and to configure the high and low RTS
  thresholds in patch 3.
- fix a spelling mistake in patch 3: s/raisonable/reasonably/

v2:
- remove "atmel,rts-high-threshold" and "atmel,rts-low-threshold" from new
  DT properties. For now these two thresholds are set once for all during the
  probe but a later patch might allow to configure them at run time.
- reword the commit message of the DT property patch to better explain why we
  have chosen to introduce the new property "atmel,fifo-size".
- add a missing chunk in the FIFO patch: as the commit message explains, we
  need to use 8bit accesses when dealing with the Transmit/Receive Holding
  Registers.

v1:
This series of patches add support to FIFOs which will be introduced with Atmel
sama5d2x SoC.

FIFOs allow to reduce the number of I/O access. Indeed depending on the data
size and the USART mode, FIFOs work in either single or multiple data. For
multiple data, up to 4 data can be written into the Transmit Holding Register
or read from the Receive Holding Register in a single word access.

Also the RX FIFO allows to reduce the risk of receive overrun and data loss,
especially when the DMA controller is not used.

Finally, when the hardware handshake mode is selected, the RTS line can now be
controlled by two thresholds on the RX FIFO. When FIFO level (the number of
data available to be read) crosses the high threshold, the RTS line is set to
high level telling the peer that it should stop sending new data. Data are read
from the RX FIFO and when the FIFO level crosses the low threshold, the RTS
is set back to low level telling the remote peer that it can send data again.

This new feature resolves a long time hardware limitation where the RTS line
was directly controlled by a PDC signal. There is no equivalent of that signal
for the DMA controller so for all SoCs without PDC for USART there was no mean
to control the RTS line properly: once the hardware handshake mode selected,
the RTS line remains high level. Next SoCs with FIFOs will be able to use the
hardware handshake mode thanks to the RX FIFO.

Cyrille Pitchen (5):
  ARM: at91/dt: add a new DT property to support FIFOs on Atmel USARTs
  tty/serial: at91: fix some macro definitions to fit coding style
  tty/serial: at91: remove bunch of macros to access UART registers
  tty/serial: at91: add support to FIFOs
  tty/serial: at91: use 32bit writes into TX FIFO when DMA is enabled

 .../devicetree/bindings/serial/atmel-usart.txt     |   3 +
 drivers/tty/serial/atmel_serial.c                  | 467 +++++++++++++--------
 include/linux/atmel_serial.h                       | 240 ++++++-----
 3 files changed, 439 insertions(+), 271 deletions(-)

-- 
1.8.2.2

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

* [PATCH v4 1/5] ARM: at91/dt: add a new DT property to support FIFOs on Atmel USARTs
  2015-07-02 13:18 ` Cyrille Pitchen
  (?)
@ 2015-07-02 13:18   ` Cyrille Pitchen
  -1 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt,
	Cyrille Pitchen

This patch adds a new DT property, "atmel,fifo-size", to enable and set
the maximum number of data the RX and TX FIFOs can store on FIFO capable
USARTs.

Please be aware that the VERSION register can not be used to guess the
size of FIFOs. Indeed, for a given hardware version, the USARTs can be
integrated on Atmel SoCs with different FIFO sizes. Also the
"atmel,fifo-size" property is optional as older USARTs don't embed FIFO at
all.

Besides, the FIFO size can not be read or guessed from other registers:
When designing the FIFO feature, no dedicated registers were added to
store this size. Unsed spaces in the I/O register range are limited and
better reserved for future usages. Instead, the FIFO size of each
peripheral is documented in the programmer datasheet.

Finally, on a given SoC, there can be several instances of USART with
different FIFO sizes. This explain why we'd rather use a dedicated DT
property than use the "compatible" property.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 Documentation/devicetree/bindings/serial/atmel-usart.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/serial/atmel-usart.txt
index 90787aa2e648..e6e6142e33ac 100644
--- a/Documentation/devicetree/bindings/serial/atmel-usart.txt
+++ b/Documentation/devicetree/bindings/serial/atmel-usart.txt
@@ -22,6 +22,8 @@ Optional properties:
 		memory peripheral interface and USART DMA channel ID, FIFO configuration.
 		Refer to dma.txt and atmel-dma.txt for details.
 	- dma-names: "rx" for RX channel, "tx" for TX channel.
+- atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO
+  capable USARTs.
 
 <chip> compatible description:
 - at91rm9200:  legacy USART support
@@ -57,4 +59,5 @@ Example:
 		dmas = <&dma0 2 0x3>,
 		       <&dma0 2 0x204>;
 		dma-names = "tx", "rx";
+		atmel,fifo-size = <32>;
 	};
-- 
1.8.2.2


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

* [PATCH v4 1/5] ARM: at91/dt: add a new DT property to support FIFOs on Atmel USARTs
@ 2015-07-02 13:18   ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: mark.rutland, devicetree, pawel.moll, ijc+devicetree,
	linux-kernel, robh+dt, galak, Cyrille Pitchen, linux-arm-kernel

This patch adds a new DT property, "atmel,fifo-size", to enable and set
the maximum number of data the RX and TX FIFOs can store on FIFO capable
USARTs.

Please be aware that the VERSION register can not be used to guess the
size of FIFOs. Indeed, for a given hardware version, the USARTs can be
integrated on Atmel SoCs with different FIFO sizes. Also the
"atmel,fifo-size" property is optional as older USARTs don't embed FIFO at
all.

Besides, the FIFO size can not be read or guessed from other registers:
When designing the FIFO feature, no dedicated registers were added to
store this size. Unsed spaces in the I/O register range are limited and
better reserved for future usages. Instead, the FIFO size of each
peripheral is documented in the programmer datasheet.

Finally, on a given SoC, there can be several instances of USART with
different FIFO sizes. This explain why we'd rather use a dedicated DT
property than use the "compatible" property.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 Documentation/devicetree/bindings/serial/atmel-usart.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/serial/atmel-usart.txt
index 90787aa2e648..e6e6142e33ac 100644
--- a/Documentation/devicetree/bindings/serial/atmel-usart.txt
+++ b/Documentation/devicetree/bindings/serial/atmel-usart.txt
@@ -22,6 +22,8 @@ Optional properties:
 		memory peripheral interface and USART DMA channel ID, FIFO configuration.
 		Refer to dma.txt and atmel-dma.txt for details.
 	- dma-names: "rx" for RX channel, "tx" for TX channel.
+- atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO
+  capable USARTs.
 
 <chip> compatible description:
 - at91rm9200:  legacy USART support
@@ -57,4 +59,5 @@ Example:
 		dmas = <&dma0 2 0x3>,
 		       <&dma0 2 0x204>;
 		dma-names = "tx", "rx";
+		atmel,fifo-size = <32>;
 	};
-- 
1.8.2.2

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

* [PATCH v4 1/5] ARM: at91/dt: add a new DT property to support FIFOs on Atmel USARTs
@ 2015-07-02 13:18   ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds a new DT property, "atmel,fifo-size", to enable and set
the maximum number of data the RX and TX FIFOs can store on FIFO capable
USARTs.

Please be aware that the VERSION register can not be used to guess the
size of FIFOs. Indeed, for a given hardware version, the USARTs can be
integrated on Atmel SoCs with different FIFO sizes. Also the
"atmel,fifo-size" property is optional as older USARTs don't embed FIFO at
all.

Besides, the FIFO size can not be read or guessed from other registers:
When designing the FIFO feature, no dedicated registers were added to
store this size. Unsed spaces in the I/O register range are limited and
better reserved for future usages. Instead, the FIFO size of each
peripheral is documented in the programmer datasheet.

Finally, on a given SoC, there can be several instances of USART with
different FIFO sizes. This explain why we'd rather use a dedicated DT
property than use the "compatible" property.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 Documentation/devicetree/bindings/serial/atmel-usart.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/serial/atmel-usart.txt
index 90787aa2e648..e6e6142e33ac 100644
--- a/Documentation/devicetree/bindings/serial/atmel-usart.txt
+++ b/Documentation/devicetree/bindings/serial/atmel-usart.txt
@@ -22,6 +22,8 @@ Optional properties:
 		memory peripheral interface and USART DMA channel ID, FIFO configuration.
 		Refer to dma.txt and atmel-dma.txt for details.
 	- dma-names: "rx" for RX channel, "tx" for TX channel.
+- atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO
+  capable USARTs.
 
 <chip> compatible description:
 - at91rm9200:  legacy USART support
@@ -57,4 +59,5 @@ Example:
 		dmas = <&dma0 2 0x3>,
 		       <&dma0 2 0x204>;
 		dma-names = "tx", "rx";
+		atmel,fifo-size = <32>;
 	};
-- 
1.8.2.2

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

* [PATCH v4 2/5] tty/serial: at91: fix some macro definitions to fit coding style
  2015-07-02 13:18 ` Cyrille Pitchen
  (?)
@ 2015-07-02 13:18   ` Cyrille Pitchen
  -1 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt,
	Cyrille Pitchen

This patch updates macro definitions in atmel_serial.h to fit the
80 column rule.

Please note that some deprecated comments such as "[AT91SAM9261 only]"
are removed as the corresponding bits also exist in some later chips.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 include/linux/atmel_serial.h | 204 +++++++++++++++++++++----------------------
 1 file changed, 102 insertions(+), 102 deletions(-)

diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
index 00beddf6be20..c384c21d65f0 100644
--- a/include/linux/atmel_serial.h
+++ b/include/linux/atmel_serial.h
@@ -16,115 +16,115 @@
 #ifndef ATMEL_SERIAL_H
 #define ATMEL_SERIAL_H
 
-#define ATMEL_US_CR		0x00			/* Control Register */
-#define		ATMEL_US_RSTRX		(1 <<  2)		/* Reset Receiver */
-#define		ATMEL_US_RSTTX		(1 <<  3)		/* Reset Transmitter */
-#define		ATMEL_US_RXEN		(1 <<  4)		/* Receiver Enable */
-#define		ATMEL_US_RXDIS		(1 <<  5)		/* Receiver Disable */
-#define		ATMEL_US_TXEN		(1 <<  6)		/* Transmitter Enable */
-#define		ATMEL_US_TXDIS		(1 <<  7)		/* Transmitter Disable */
-#define		ATMEL_US_RSTSTA		(1 <<  8)		/* Reset Status Bits */
-#define		ATMEL_US_STTBRK		(1 <<  9)		/* Start Break */
-#define		ATMEL_US_STPBRK		(1 << 10)		/* Stop Break */
-#define		ATMEL_US_STTTO		(1 << 11)		/* Start Time-out */
-#define		ATMEL_US_SENDA		(1 << 12)		/* Send Address */
-#define		ATMEL_US_RSTIT		(1 << 13)		/* Reset Iterations */
-#define		ATMEL_US_RSTNACK	(1 << 14)		/* Reset Non Acknowledge */
-#define		ATMEL_US_RETTO		(1 << 15)		/* Rearm Time-out */
-#define		ATMEL_US_DTREN		(1 << 16)		/* Data Terminal Ready Enable [AT91RM9200 only] */
-#define		ATMEL_US_DTRDIS		(1 << 17)		/* Data Terminal Ready Disable [AT91RM9200 only] */
-#define		ATMEL_US_RTSEN		(1 << 18)		/* Request To Send Enable */
-#define		ATMEL_US_RTSDIS		(1 << 19)		/* Request To Send Disable */
+#define ATMEL_US_CR		0x00	/* Control Register */
+#define	ATMEL_US_RSTRX		BIT(2)	/* Reset Receiver */
+#define	ATMEL_US_RSTTX		BIT(3)	/* Reset Transmitter */
+#define	ATMEL_US_RXEN		BIT(4)	/* Receiver Enable */
+#define	ATMEL_US_RXDIS		BIT(5)	/* Receiver Disable */
+#define	ATMEL_US_TXEN		BIT(6)	/* Transmitter Enable */
+#define	ATMEL_US_TXDIS		BIT(7)	/* Transmitter Disable */
+#define	ATMEL_US_RSTSTA		BIT(8)	/* Reset Status Bits */
+#define	ATMEL_US_STTBRK		BIT(9)	/* Start Break */
+#define	ATMEL_US_STPBRK		BIT(10)	/* Stop Break */
+#define	ATMEL_US_STTTO		BIT(11)	/* Start Time-out */
+#define	ATMEL_US_SENDA		BIT(12)	/* Send Address */
+#define	ATMEL_US_RSTIT		BIT(13)	/* Reset Iterations */
+#define	ATMEL_US_RSTNACK	BIT(14)	/* Reset Non Acknowledge */
+#define	ATMEL_US_RETTO		BIT(15)	/* Rearm Time-out */
+#define	ATMEL_US_DTREN		BIT(16)	/* Data Terminal Ready Enable */
+#define	ATMEL_US_DTRDIS		BIT(17)	/* Data Terminal Ready Disable */
+#define	ATMEL_US_RTSEN		BIT(18)	/* Request To Send Enable */
+#define	ATMEL_US_RTSDIS		BIT(19)	/* Request To Send Disable */
 
-#define ATMEL_US_MR		0x04			/* Mode Register */
-#define		ATMEL_US_USMODE		(0xf <<  0)		/* Mode of the USART */
-#define			ATMEL_US_USMODE_NORMAL		0
-#define			ATMEL_US_USMODE_RS485		1
-#define			ATMEL_US_USMODE_HWHS		2
-#define			ATMEL_US_USMODE_MODEM		3
-#define			ATMEL_US_USMODE_ISO7816_T0	4
-#define			ATMEL_US_USMODE_ISO7816_T1	6
-#define			ATMEL_US_USMODE_IRDA		8
-#define		ATMEL_US_USCLKS		(3   <<  4)		/* Clock Selection */
-#define			ATMEL_US_USCLKS_MCK		(0 <<  4)
-#define			ATMEL_US_USCLKS_MCK_DIV8	(1 <<  4)
-#define			ATMEL_US_USCLKS_SCK		(3 <<  4)
-#define		ATMEL_US_CHRL		(3   <<  6)		/* Character Length */
-#define			ATMEL_US_CHRL_5			(0 <<  6)
-#define			ATMEL_US_CHRL_6			(1 <<  6)
-#define			ATMEL_US_CHRL_7			(2 <<  6)
-#define			ATMEL_US_CHRL_8			(3 <<  6)
-#define		ATMEL_US_SYNC		(1 <<  8)		/* Synchronous Mode Select */
-#define		ATMEL_US_PAR		(7 <<  9)		/* Parity Type */
-#define			ATMEL_US_PAR_EVEN		(0 <<  9)
-#define			ATMEL_US_PAR_ODD		(1 <<  9)
-#define			ATMEL_US_PAR_SPACE		(2 <<  9)
-#define			ATMEL_US_PAR_MARK		(3 <<  9)
-#define			ATMEL_US_PAR_NONE		(4 <<  9)
-#define			ATMEL_US_PAR_MULTI_DROP		(6 <<  9)
-#define		ATMEL_US_NBSTOP		(3 << 12)		/* Number of Stop Bits */
-#define			ATMEL_US_NBSTOP_1		(0 << 12)
-#define			ATMEL_US_NBSTOP_1_5		(1 << 12)
-#define			ATMEL_US_NBSTOP_2		(2 << 12)
-#define		ATMEL_US_CHMODE		(3 << 14)		/* Channel Mode */
-#define			ATMEL_US_CHMODE_NORMAL		(0 << 14)
-#define			ATMEL_US_CHMODE_ECHO		(1 << 14)
-#define			ATMEL_US_CHMODE_LOC_LOOP	(2 << 14)
-#define			ATMEL_US_CHMODE_REM_LOOP	(3 << 14)
-#define		ATMEL_US_MSBF		(1 << 16)		/* Bit Order */
-#define		ATMEL_US_MODE9		(1 << 17)		/* 9-bit Character Length */
-#define		ATMEL_US_CLKO		(1 << 18)		/* Clock Output Select */
-#define		ATMEL_US_OVER		(1 << 19)		/* Oversampling Mode */
-#define		ATMEL_US_INACK		(1 << 20)		/* Inhibit Non Acknowledge */
-#define		ATMEL_US_DSNACK		(1 << 21)		/* Disable Successive NACK */
-#define		ATMEL_US_MAX_ITER	(7 << 24)		/* Max Iterations */
-#define		ATMEL_US_FILTER		(1 << 28)		/* Infrared Receive Line Filter */
+#define ATMEL_US_MR		0x04	/* Mode Register */
+#define	ATMEL_US_USMODE		GENMASK(3, 0)	/* Mode of the USART */
+#define		ATMEL_US_USMODE_NORMAL		0
+#define		ATMEL_US_USMODE_RS485		1
+#define		ATMEL_US_USMODE_HWHS		2
+#define		ATMEL_US_USMODE_MODEM		3
+#define		ATMEL_US_USMODE_ISO7816_T0	4
+#define		ATMEL_US_USMODE_ISO7816_T1	6
+#define		ATMEL_US_USMODE_IRDA		8
+#define	ATMEL_US_USCLKS		GENMASK(5, 4)	/* Clock Selection */
+#define		ATMEL_US_USCLKS_MCK		(0 <<  4)
+#define		ATMEL_US_USCLKS_MCK_DIV8	(1 <<  4)
+#define		ATMEL_US_USCLKS_SCK		(3 <<  4)
+#define	ATMEL_US_CHRL		GENMASK(7, 6)	/* Character Length */
+#define		ATMEL_US_CHRL_5			(0 <<  6)
+#define		ATMEL_US_CHRL_6			(1 <<  6)
+#define		ATMEL_US_CHRL_7			(2 <<  6)
+#define		ATMEL_US_CHRL_8			(3 <<  6)
+#define	ATMEL_US_SYNC		BIT(8)		/* Synchronous Mode Select */
+#define	ATMEL_US_PAR		GENMASK(11, 9)	/* Parity Type */
+#define		ATMEL_US_PAR_EVEN		(0 <<  9)
+#define		ATMEL_US_PAR_ODD		(1 <<  9)
+#define		ATMEL_US_PAR_SPACE		(2 <<  9)
+#define		ATMEL_US_PAR_MARK		(3 <<  9)
+#define		ATMEL_US_PAR_NONE		(4 <<  9)
+#define		ATMEL_US_PAR_MULTI_DROP		(6 <<  9)
+#define	ATMEL_US_NBSTOP		GENMASK(13, 12)	/* Number of Stop Bits */
+#define		ATMEL_US_NBSTOP_1		(0 << 12)
+#define		ATMEL_US_NBSTOP_1_5		(1 << 12)
+#define		ATMEL_US_NBSTOP_2		(2 << 12)
+#define	ATMEL_US_CHMODE		GENMASK(15, 14)	/* Channel Mode */
+#define		ATMEL_US_CHMODE_NORMAL		(0 << 14)
+#define		ATMEL_US_CHMODE_ECHO		(1 << 14)
+#define		ATMEL_US_CHMODE_LOC_LOOP	(2 << 14)
+#define		ATMEL_US_CHMODE_REM_LOOP	(3 << 14)
+#define	ATMEL_US_MSBF		BIT(16)	/* Bit Order */
+#define	ATMEL_US_MODE9		BIT(17)	/* 9-bit Character Length */
+#define	ATMEL_US_CLKO		BIT(18)	/* Clock Output Select */
+#define	ATMEL_US_OVER		BIT(19)	/* Oversampling Mode */
+#define	ATMEL_US_INACK		BIT(20)	/* Inhibit Non Acknowledge */
+#define	ATMEL_US_DSNACK		BIT(21)	/* Disable Successive NACK */
+#define	ATMEL_US_MAX_ITER	GENMASK(26, 24)	/* Max Iterations */
+#define	ATMEL_US_FILTER		BIT(28)	/* Infrared Receive Line Filter */
 
-#define ATMEL_US_IER		0x08			/* Interrupt Enable Register */
-#define		ATMEL_US_RXRDY		(1 <<  0)		/* Receiver Ready */
-#define		ATMEL_US_TXRDY		(1 <<  1)		/* Transmitter Ready */
-#define		ATMEL_US_RXBRK		(1 <<  2)		/* Break Received / End of Break */
-#define		ATMEL_US_ENDRX		(1 <<  3)		/* End of Receiver Transfer */
-#define		ATMEL_US_ENDTX		(1 <<  4)		/* End of Transmitter Transfer */
-#define		ATMEL_US_OVRE		(1 <<  5)		/* Overrun Error */
-#define		ATMEL_US_FRAME		(1 <<  6)		/* Framing Error */
-#define		ATMEL_US_PARE		(1 <<  7)		/* Parity Error */
-#define		ATMEL_US_TIMEOUT	(1 <<  8)		/* Receiver Time-out */
-#define		ATMEL_US_TXEMPTY	(1 <<  9)		/* Transmitter Empty */
-#define		ATMEL_US_ITERATION	(1 << 10)		/* Max number of Repetitions Reached */
-#define		ATMEL_US_TXBUFE		(1 << 11)		/* Transmission Buffer Empty */
-#define		ATMEL_US_RXBUFF		(1 << 12)		/* Reception Buffer Full */
-#define		ATMEL_US_NACK		(1 << 13)		/* Non Acknowledge */
-#define		ATMEL_US_RIIC		(1 << 16)		/* Ring Indicator Input Change [AT91RM9200 only] */
-#define		ATMEL_US_DSRIC		(1 << 17)		/* Data Set Ready Input Change [AT91RM9200 only] */
-#define		ATMEL_US_DCDIC		(1 << 18)		/* Data Carrier Detect Input Change [AT91RM9200 only] */
-#define		ATMEL_US_CTSIC		(1 << 19)		/* Clear to Send Input Change */
-#define		ATMEL_US_RI		(1 << 20)		/* RI */
-#define		ATMEL_US_DSR		(1 << 21)		/* DSR */
-#define		ATMEL_US_DCD		(1 << 22)		/* DCD */
-#define		ATMEL_US_CTS		(1 << 23)		/* CTS */
+#define ATMEL_US_IER		0x08	/* Interrupt Enable Register */
+#define	ATMEL_US_RXRDY		BIT(0)	/* Receiver Ready */
+#define	ATMEL_US_TXRDY		BIT(1)	/* Transmitter Ready */
+#define	ATMEL_US_RXBRK		BIT(2)	/* Break Received / End of Break */
+#define	ATMEL_US_ENDRX		BIT(3)	/* End of Receiver Transfer */
+#define	ATMEL_US_ENDTX		BIT(4)	/* End of Transmitter Transfer */
+#define	ATMEL_US_OVRE		BIT(5)	/* Overrun Error */
+#define	ATMEL_US_FRAME		BIT(6)	/* Framing Error */
+#define	ATMEL_US_PARE		BIT(7)	/* Parity Error */
+#define	ATMEL_US_TIMEOUT	BIT(8)	/* Receiver Time-out */
+#define	ATMEL_US_TXEMPTY	BIT(9)	/* Transmitter Empty */
+#define	ATMEL_US_ITERATION	BIT(10)	/* Max number of Repetitions Reached */
+#define	ATMEL_US_TXBUFE		BIT(11)	/* Transmission Buffer Empty */
+#define	ATMEL_US_RXBUFF		BIT(12)	/* Reception Buffer Full */
+#define	ATMEL_US_NACK		BIT(13)	/* Non Acknowledge */
+#define	ATMEL_US_RIIC		BIT(16)	/* Ring Indicator Input Change */
+#define	ATMEL_US_DSRIC		BIT(17)	/* Data Set Ready Input Change */
+#define	ATMEL_US_DCDIC		BIT(18)	/* Data Carrier Detect Input Change */
+#define	ATMEL_US_CTSIC		BIT(19)	/* Clear to Send Input Change */
+#define	ATMEL_US_RI		BIT(20)	/* RI */
+#define	ATMEL_US_DSR		BIT(21)	/* DSR */
+#define	ATMEL_US_DCD		BIT(22)	/* DCD */
+#define	ATMEL_US_CTS		BIT(23)	/* CTS */
 
-#define ATMEL_US_IDR		0x0c			/* Interrupt Disable Register */
-#define ATMEL_US_IMR		0x10			/* Interrupt Mask Register */
-#define ATMEL_US_CSR		0x14			/* Channel Status Register */
-#define ATMEL_US_RHR		0x18			/* Receiver Holding Register */
-#define ATMEL_US_THR		0x1c			/* Transmitter Holding Register */
-#define		ATMEL_US_SYNH		(1 << 15)		/* Transmit/Receive Sync [AT91SAM9261 only] */
+#define ATMEL_US_IDR		0x0c	/* Interrupt Disable Register */
+#define ATMEL_US_IMR		0x10	/* Interrupt Mask Register */
+#define ATMEL_US_CSR		0x14	/* Channel Status Register */
+#define ATMEL_US_RHR		0x18	/* Receiver Holding Register */
+#define ATMEL_US_THR		0x1c	/* Transmitter Holding Register */
+#define	ATMEL_US_SYNH		BIT(15)	/* Transmit/Receive Sync */
 
-#define ATMEL_US_BRGR		0x20			/* Baud Rate Generator Register */
-#define		ATMEL_US_CD		(0xffff << 0)		/* Clock Divider */
+#define ATMEL_US_BRGR		0x20	/* Baud Rate Generator Register */
+#define	ATMEL_US_CD		GENMASK(15, 0)	/* Clock Divider */
 
-#define ATMEL_US_RTOR		0x24			/* Receiver Time-out Register */
-#define		ATMEL_US_TO		(0xffff << 0)		/* Time-out Value */
+#define ATMEL_US_RTOR		0x24	/* Receiver Time-out Register */
+#define	ATMEL_US_TO		GENMASK(15, 0)	/* Time-out Value */
 
-#define ATMEL_US_TTGR		0x28			/* Transmitter Timeguard Register */
-#define		ATMEL_US_TG		(0xff << 0)		/* Timeguard Value */
+#define ATMEL_US_TTGR		0x28	/* Transmitter Timeguard Register */
+#define	ATMEL_US_TG		GENMASK(7, 0)	/* Timeguard Value */
 
-#define ATMEL_US_FIDI		0x40			/* FI DI Ratio Register */
-#define ATMEL_US_NER		0x44			/* Number of Errors Register */
-#define ATMEL_US_IF		0x4c			/* IrDA Filter Register */
+#define ATMEL_US_FIDI		0x40	/* FI DI Ratio Register */
+#define ATMEL_US_NER		0x44	/* Number of Errors Register */
+#define ATMEL_US_IF		0x4c	/* IrDA Filter Register */
 
-#define ATMEL_US_NAME		0xf0			/* Ip Name */
-#define ATMEL_US_VERSION	0xfc			/* Ip Version */
+#define ATMEL_US_NAME		0xf0	/* Ip Name */
+#define ATMEL_US_VERSION	0xfc	/* Ip Version */
 
 #endif
-- 
1.8.2.2


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

* [PATCH v4 2/5] tty/serial: at91: fix some macro definitions to fit coding style
@ 2015-07-02 13:18   ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt,
	Cyrille Pitchen

This patch updates macro definitions in atmel_serial.h to fit the
80 column rule.

Please note that some deprecated comments such as "[AT91SAM9261 only]"
are removed as the corresponding bits also exist in some later chips.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 include/linux/atmel_serial.h | 204 +++++++++++++++++++++----------------------
 1 file changed, 102 insertions(+), 102 deletions(-)

diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
index 00beddf6be20..c384c21d65f0 100644
--- a/include/linux/atmel_serial.h
+++ b/include/linux/atmel_serial.h
@@ -16,115 +16,115 @@
 #ifndef ATMEL_SERIAL_H
 #define ATMEL_SERIAL_H
 
-#define ATMEL_US_CR		0x00			/* Control Register */
-#define		ATMEL_US_RSTRX		(1 <<  2)		/* Reset Receiver */
-#define		ATMEL_US_RSTTX		(1 <<  3)		/* Reset Transmitter */
-#define		ATMEL_US_RXEN		(1 <<  4)		/* Receiver Enable */
-#define		ATMEL_US_RXDIS		(1 <<  5)		/* Receiver Disable */
-#define		ATMEL_US_TXEN		(1 <<  6)		/* Transmitter Enable */
-#define		ATMEL_US_TXDIS		(1 <<  7)		/* Transmitter Disable */
-#define		ATMEL_US_RSTSTA		(1 <<  8)		/* Reset Status Bits */
-#define		ATMEL_US_STTBRK		(1 <<  9)		/* Start Break */
-#define		ATMEL_US_STPBRK		(1 << 10)		/* Stop Break */
-#define		ATMEL_US_STTTO		(1 << 11)		/* Start Time-out */
-#define		ATMEL_US_SENDA		(1 << 12)		/* Send Address */
-#define		ATMEL_US_RSTIT		(1 << 13)		/* Reset Iterations */
-#define		ATMEL_US_RSTNACK	(1 << 14)		/* Reset Non Acknowledge */
-#define		ATMEL_US_RETTO		(1 << 15)		/* Rearm Time-out */
-#define		ATMEL_US_DTREN		(1 << 16)		/* Data Terminal Ready Enable [AT91RM9200 only] */
-#define		ATMEL_US_DTRDIS		(1 << 17)		/* Data Terminal Ready Disable [AT91RM9200 only] */
-#define		ATMEL_US_RTSEN		(1 << 18)		/* Request To Send Enable */
-#define		ATMEL_US_RTSDIS		(1 << 19)		/* Request To Send Disable */
+#define ATMEL_US_CR		0x00	/* Control Register */
+#define	ATMEL_US_RSTRX		BIT(2)	/* Reset Receiver */
+#define	ATMEL_US_RSTTX		BIT(3)	/* Reset Transmitter */
+#define	ATMEL_US_RXEN		BIT(4)	/* Receiver Enable */
+#define	ATMEL_US_RXDIS		BIT(5)	/* Receiver Disable */
+#define	ATMEL_US_TXEN		BIT(6)	/* Transmitter Enable */
+#define	ATMEL_US_TXDIS		BIT(7)	/* Transmitter Disable */
+#define	ATMEL_US_RSTSTA		BIT(8)	/* Reset Status Bits */
+#define	ATMEL_US_STTBRK		BIT(9)	/* Start Break */
+#define	ATMEL_US_STPBRK		BIT(10)	/* Stop Break */
+#define	ATMEL_US_STTTO		BIT(11)	/* Start Time-out */
+#define	ATMEL_US_SENDA		BIT(12)	/* Send Address */
+#define	ATMEL_US_RSTIT		BIT(13)	/* Reset Iterations */
+#define	ATMEL_US_RSTNACK	BIT(14)	/* Reset Non Acknowledge */
+#define	ATMEL_US_RETTO		BIT(15)	/* Rearm Time-out */
+#define	ATMEL_US_DTREN		BIT(16)	/* Data Terminal Ready Enable */
+#define	ATMEL_US_DTRDIS		BIT(17)	/* Data Terminal Ready Disable */
+#define	ATMEL_US_RTSEN		BIT(18)	/* Request To Send Enable */
+#define	ATMEL_US_RTSDIS		BIT(19)	/* Request To Send Disable */
 
-#define ATMEL_US_MR		0x04			/* Mode Register */
-#define		ATMEL_US_USMODE		(0xf <<  0)		/* Mode of the USART */
-#define			ATMEL_US_USMODE_NORMAL		0
-#define			ATMEL_US_USMODE_RS485		1
-#define			ATMEL_US_USMODE_HWHS		2
-#define			ATMEL_US_USMODE_MODEM		3
-#define			ATMEL_US_USMODE_ISO7816_T0	4
-#define			ATMEL_US_USMODE_ISO7816_T1	6
-#define			ATMEL_US_USMODE_IRDA		8
-#define		ATMEL_US_USCLKS		(3   <<  4)		/* Clock Selection */
-#define			ATMEL_US_USCLKS_MCK		(0 <<  4)
-#define			ATMEL_US_USCLKS_MCK_DIV8	(1 <<  4)
-#define			ATMEL_US_USCLKS_SCK		(3 <<  4)
-#define		ATMEL_US_CHRL		(3   <<  6)		/* Character Length */
-#define			ATMEL_US_CHRL_5			(0 <<  6)
-#define			ATMEL_US_CHRL_6			(1 <<  6)
-#define			ATMEL_US_CHRL_7			(2 <<  6)
-#define			ATMEL_US_CHRL_8			(3 <<  6)
-#define		ATMEL_US_SYNC		(1 <<  8)		/* Synchronous Mode Select */
-#define		ATMEL_US_PAR		(7 <<  9)		/* Parity Type */
-#define			ATMEL_US_PAR_EVEN		(0 <<  9)
-#define			ATMEL_US_PAR_ODD		(1 <<  9)
-#define			ATMEL_US_PAR_SPACE		(2 <<  9)
-#define			ATMEL_US_PAR_MARK		(3 <<  9)
-#define			ATMEL_US_PAR_NONE		(4 <<  9)
-#define			ATMEL_US_PAR_MULTI_DROP		(6 <<  9)
-#define		ATMEL_US_NBSTOP		(3 << 12)		/* Number of Stop Bits */
-#define			ATMEL_US_NBSTOP_1		(0 << 12)
-#define			ATMEL_US_NBSTOP_1_5		(1 << 12)
-#define			ATMEL_US_NBSTOP_2		(2 << 12)
-#define		ATMEL_US_CHMODE		(3 << 14)		/* Channel Mode */
-#define			ATMEL_US_CHMODE_NORMAL		(0 << 14)
-#define			ATMEL_US_CHMODE_ECHO		(1 << 14)
-#define			ATMEL_US_CHMODE_LOC_LOOP	(2 << 14)
-#define			ATMEL_US_CHMODE_REM_LOOP	(3 << 14)
-#define		ATMEL_US_MSBF		(1 << 16)		/* Bit Order */
-#define		ATMEL_US_MODE9		(1 << 17)		/* 9-bit Character Length */
-#define		ATMEL_US_CLKO		(1 << 18)		/* Clock Output Select */
-#define		ATMEL_US_OVER		(1 << 19)		/* Oversampling Mode */
-#define		ATMEL_US_INACK		(1 << 20)		/* Inhibit Non Acknowledge */
-#define		ATMEL_US_DSNACK		(1 << 21)		/* Disable Successive NACK */
-#define		ATMEL_US_MAX_ITER	(7 << 24)		/* Max Iterations */
-#define		ATMEL_US_FILTER		(1 << 28)		/* Infrared Receive Line Filter */
+#define ATMEL_US_MR		0x04	/* Mode Register */
+#define	ATMEL_US_USMODE		GENMASK(3, 0)	/* Mode of the USART */
+#define		ATMEL_US_USMODE_NORMAL		0
+#define		ATMEL_US_USMODE_RS485		1
+#define		ATMEL_US_USMODE_HWHS		2
+#define		ATMEL_US_USMODE_MODEM		3
+#define		ATMEL_US_USMODE_ISO7816_T0	4
+#define		ATMEL_US_USMODE_ISO7816_T1	6
+#define		ATMEL_US_USMODE_IRDA		8
+#define	ATMEL_US_USCLKS		GENMASK(5, 4)	/* Clock Selection */
+#define		ATMEL_US_USCLKS_MCK		(0 <<  4)
+#define		ATMEL_US_USCLKS_MCK_DIV8	(1 <<  4)
+#define		ATMEL_US_USCLKS_SCK		(3 <<  4)
+#define	ATMEL_US_CHRL		GENMASK(7, 6)	/* Character Length */
+#define		ATMEL_US_CHRL_5			(0 <<  6)
+#define		ATMEL_US_CHRL_6			(1 <<  6)
+#define		ATMEL_US_CHRL_7			(2 <<  6)
+#define		ATMEL_US_CHRL_8			(3 <<  6)
+#define	ATMEL_US_SYNC		BIT(8)		/* Synchronous Mode Select */
+#define	ATMEL_US_PAR		GENMASK(11, 9)	/* Parity Type */
+#define		ATMEL_US_PAR_EVEN		(0 <<  9)
+#define		ATMEL_US_PAR_ODD		(1 <<  9)
+#define		ATMEL_US_PAR_SPACE		(2 <<  9)
+#define		ATMEL_US_PAR_MARK		(3 <<  9)
+#define		ATMEL_US_PAR_NONE		(4 <<  9)
+#define		ATMEL_US_PAR_MULTI_DROP		(6 <<  9)
+#define	ATMEL_US_NBSTOP		GENMASK(13, 12)	/* Number of Stop Bits */
+#define		ATMEL_US_NBSTOP_1		(0 << 12)
+#define		ATMEL_US_NBSTOP_1_5		(1 << 12)
+#define		ATMEL_US_NBSTOP_2		(2 << 12)
+#define	ATMEL_US_CHMODE		GENMASK(15, 14)	/* Channel Mode */
+#define		ATMEL_US_CHMODE_NORMAL		(0 << 14)
+#define		ATMEL_US_CHMODE_ECHO		(1 << 14)
+#define		ATMEL_US_CHMODE_LOC_LOOP	(2 << 14)
+#define		ATMEL_US_CHMODE_REM_LOOP	(3 << 14)
+#define	ATMEL_US_MSBF		BIT(16)	/* Bit Order */
+#define	ATMEL_US_MODE9		BIT(17)	/* 9-bit Character Length */
+#define	ATMEL_US_CLKO		BIT(18)	/* Clock Output Select */
+#define	ATMEL_US_OVER		BIT(19)	/* Oversampling Mode */
+#define	ATMEL_US_INACK		BIT(20)	/* Inhibit Non Acknowledge */
+#define	ATMEL_US_DSNACK		BIT(21)	/* Disable Successive NACK */
+#define	ATMEL_US_MAX_ITER	GENMASK(26, 24)	/* Max Iterations */
+#define	ATMEL_US_FILTER		BIT(28)	/* Infrared Receive Line Filter */
 
-#define ATMEL_US_IER		0x08			/* Interrupt Enable Register */
-#define		ATMEL_US_RXRDY		(1 <<  0)		/* Receiver Ready */
-#define		ATMEL_US_TXRDY		(1 <<  1)		/* Transmitter Ready */
-#define		ATMEL_US_RXBRK		(1 <<  2)		/* Break Received / End of Break */
-#define		ATMEL_US_ENDRX		(1 <<  3)		/* End of Receiver Transfer */
-#define		ATMEL_US_ENDTX		(1 <<  4)		/* End of Transmitter Transfer */
-#define		ATMEL_US_OVRE		(1 <<  5)		/* Overrun Error */
-#define		ATMEL_US_FRAME		(1 <<  6)		/* Framing Error */
-#define		ATMEL_US_PARE		(1 <<  7)		/* Parity Error */
-#define		ATMEL_US_TIMEOUT	(1 <<  8)		/* Receiver Time-out */
-#define		ATMEL_US_TXEMPTY	(1 <<  9)		/* Transmitter Empty */
-#define		ATMEL_US_ITERATION	(1 << 10)		/* Max number of Repetitions Reached */
-#define		ATMEL_US_TXBUFE		(1 << 11)		/* Transmission Buffer Empty */
-#define		ATMEL_US_RXBUFF		(1 << 12)		/* Reception Buffer Full */
-#define		ATMEL_US_NACK		(1 << 13)		/* Non Acknowledge */
-#define		ATMEL_US_RIIC		(1 << 16)		/* Ring Indicator Input Change [AT91RM9200 only] */
-#define		ATMEL_US_DSRIC		(1 << 17)		/* Data Set Ready Input Change [AT91RM9200 only] */
-#define		ATMEL_US_DCDIC		(1 << 18)		/* Data Carrier Detect Input Change [AT91RM9200 only] */
-#define		ATMEL_US_CTSIC		(1 << 19)		/* Clear to Send Input Change */
-#define		ATMEL_US_RI		(1 << 20)		/* RI */
-#define		ATMEL_US_DSR		(1 << 21)		/* DSR */
-#define		ATMEL_US_DCD		(1 << 22)		/* DCD */
-#define		ATMEL_US_CTS		(1 << 23)		/* CTS */
+#define ATMEL_US_IER		0x08	/* Interrupt Enable Register */
+#define	ATMEL_US_RXRDY		BIT(0)	/* Receiver Ready */
+#define	ATMEL_US_TXRDY		BIT(1)	/* Transmitter Ready */
+#define	ATMEL_US_RXBRK		BIT(2)	/* Break Received / End of Break */
+#define	ATMEL_US_ENDRX		BIT(3)	/* End of Receiver Transfer */
+#define	ATMEL_US_ENDTX		BIT(4)	/* End of Transmitter Transfer */
+#define	ATMEL_US_OVRE		BIT(5)	/* Overrun Error */
+#define	ATMEL_US_FRAME		BIT(6)	/* Framing Error */
+#define	ATMEL_US_PARE		BIT(7)	/* Parity Error */
+#define	ATMEL_US_TIMEOUT	BIT(8)	/* Receiver Time-out */
+#define	ATMEL_US_TXEMPTY	BIT(9)	/* Transmitter Empty */
+#define	ATMEL_US_ITERATION	BIT(10)	/* Max number of Repetitions Reached */
+#define	ATMEL_US_TXBUFE		BIT(11)	/* Transmission Buffer Empty */
+#define	ATMEL_US_RXBUFF		BIT(12)	/* Reception Buffer Full */
+#define	ATMEL_US_NACK		BIT(13)	/* Non Acknowledge */
+#define	ATMEL_US_RIIC		BIT(16)	/* Ring Indicator Input Change */
+#define	ATMEL_US_DSRIC		BIT(17)	/* Data Set Ready Input Change */
+#define	ATMEL_US_DCDIC		BIT(18)	/* Data Carrier Detect Input Change */
+#define	ATMEL_US_CTSIC		BIT(19)	/* Clear to Send Input Change */
+#define	ATMEL_US_RI		BIT(20)	/* RI */
+#define	ATMEL_US_DSR		BIT(21)	/* DSR */
+#define	ATMEL_US_DCD		BIT(22)	/* DCD */
+#define	ATMEL_US_CTS		BIT(23)	/* CTS */
 
-#define ATMEL_US_IDR		0x0c			/* Interrupt Disable Register */
-#define ATMEL_US_IMR		0x10			/* Interrupt Mask Register */
-#define ATMEL_US_CSR		0x14			/* Channel Status Register */
-#define ATMEL_US_RHR		0x18			/* Receiver Holding Register */
-#define ATMEL_US_THR		0x1c			/* Transmitter Holding Register */
-#define		ATMEL_US_SYNH		(1 << 15)		/* Transmit/Receive Sync [AT91SAM9261 only] */
+#define ATMEL_US_IDR		0x0c	/* Interrupt Disable Register */
+#define ATMEL_US_IMR		0x10	/* Interrupt Mask Register */
+#define ATMEL_US_CSR		0x14	/* Channel Status Register */
+#define ATMEL_US_RHR		0x18	/* Receiver Holding Register */
+#define ATMEL_US_THR		0x1c	/* Transmitter Holding Register */
+#define	ATMEL_US_SYNH		BIT(15)	/* Transmit/Receive Sync */
 
-#define ATMEL_US_BRGR		0x20			/* Baud Rate Generator Register */
-#define		ATMEL_US_CD		(0xffff << 0)		/* Clock Divider */
+#define ATMEL_US_BRGR		0x20	/* Baud Rate Generator Register */
+#define	ATMEL_US_CD		GENMASK(15, 0)	/* Clock Divider */
 
-#define ATMEL_US_RTOR		0x24			/* Receiver Time-out Register */
-#define		ATMEL_US_TO		(0xffff << 0)		/* Time-out Value */
+#define ATMEL_US_RTOR		0x24	/* Receiver Time-out Register */
+#define	ATMEL_US_TO		GENMASK(15, 0)	/* Time-out Value */
 
-#define ATMEL_US_TTGR		0x28			/* Transmitter Timeguard Register */
-#define		ATMEL_US_TG		(0xff << 0)		/* Timeguard Value */
+#define ATMEL_US_TTGR		0x28	/* Transmitter Timeguard Register */
+#define	ATMEL_US_TG		GENMASK(7, 0)	/* Timeguard Value */
 
-#define ATMEL_US_FIDI		0x40			/* FI DI Ratio Register */
-#define ATMEL_US_NER		0x44			/* Number of Errors Register */
-#define ATMEL_US_IF		0x4c			/* IrDA Filter Register */
+#define ATMEL_US_FIDI		0x40	/* FI DI Ratio Register */
+#define ATMEL_US_NER		0x44	/* Number of Errors Register */
+#define ATMEL_US_IF		0x4c	/* IrDA Filter Register */
 
-#define ATMEL_US_NAME		0xf0			/* Ip Name */
-#define ATMEL_US_VERSION	0xfc			/* Ip Version */
+#define ATMEL_US_NAME		0xf0	/* Ip Name */
+#define ATMEL_US_VERSION	0xfc	/* Ip Version */
 
 #endif
-- 
1.8.2.2

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

* [PATCH v4 2/5] tty/serial: at91: fix some macro definitions to fit coding style
@ 2015-07-02 13:18   ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: linux-arm-kernel

This patch updates macro definitions in atmel_serial.h to fit the
80 column rule.

Please note that some deprecated comments such as "[AT91SAM9261 only]"
are removed as the corresponding bits also exist in some later chips.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 include/linux/atmel_serial.h | 204 +++++++++++++++++++++----------------------
 1 file changed, 102 insertions(+), 102 deletions(-)

diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
index 00beddf6be20..c384c21d65f0 100644
--- a/include/linux/atmel_serial.h
+++ b/include/linux/atmel_serial.h
@@ -16,115 +16,115 @@
 #ifndef ATMEL_SERIAL_H
 #define ATMEL_SERIAL_H
 
-#define ATMEL_US_CR		0x00			/* Control Register */
-#define		ATMEL_US_RSTRX		(1 <<  2)		/* Reset Receiver */
-#define		ATMEL_US_RSTTX		(1 <<  3)		/* Reset Transmitter */
-#define		ATMEL_US_RXEN		(1 <<  4)		/* Receiver Enable */
-#define		ATMEL_US_RXDIS		(1 <<  5)		/* Receiver Disable */
-#define		ATMEL_US_TXEN		(1 <<  6)		/* Transmitter Enable */
-#define		ATMEL_US_TXDIS		(1 <<  7)		/* Transmitter Disable */
-#define		ATMEL_US_RSTSTA		(1 <<  8)		/* Reset Status Bits */
-#define		ATMEL_US_STTBRK		(1 <<  9)		/* Start Break */
-#define		ATMEL_US_STPBRK		(1 << 10)		/* Stop Break */
-#define		ATMEL_US_STTTO		(1 << 11)		/* Start Time-out */
-#define		ATMEL_US_SENDA		(1 << 12)		/* Send Address */
-#define		ATMEL_US_RSTIT		(1 << 13)		/* Reset Iterations */
-#define		ATMEL_US_RSTNACK	(1 << 14)		/* Reset Non Acknowledge */
-#define		ATMEL_US_RETTO		(1 << 15)		/* Rearm Time-out */
-#define		ATMEL_US_DTREN		(1 << 16)		/* Data Terminal Ready Enable [AT91RM9200 only] */
-#define		ATMEL_US_DTRDIS		(1 << 17)		/* Data Terminal Ready Disable [AT91RM9200 only] */
-#define		ATMEL_US_RTSEN		(1 << 18)		/* Request To Send Enable */
-#define		ATMEL_US_RTSDIS		(1 << 19)		/* Request To Send Disable */
+#define ATMEL_US_CR		0x00	/* Control Register */
+#define	ATMEL_US_RSTRX		BIT(2)	/* Reset Receiver */
+#define	ATMEL_US_RSTTX		BIT(3)	/* Reset Transmitter */
+#define	ATMEL_US_RXEN		BIT(4)	/* Receiver Enable */
+#define	ATMEL_US_RXDIS		BIT(5)	/* Receiver Disable */
+#define	ATMEL_US_TXEN		BIT(6)	/* Transmitter Enable */
+#define	ATMEL_US_TXDIS		BIT(7)	/* Transmitter Disable */
+#define	ATMEL_US_RSTSTA		BIT(8)	/* Reset Status Bits */
+#define	ATMEL_US_STTBRK		BIT(9)	/* Start Break */
+#define	ATMEL_US_STPBRK		BIT(10)	/* Stop Break */
+#define	ATMEL_US_STTTO		BIT(11)	/* Start Time-out */
+#define	ATMEL_US_SENDA		BIT(12)	/* Send Address */
+#define	ATMEL_US_RSTIT		BIT(13)	/* Reset Iterations */
+#define	ATMEL_US_RSTNACK	BIT(14)	/* Reset Non Acknowledge */
+#define	ATMEL_US_RETTO		BIT(15)	/* Rearm Time-out */
+#define	ATMEL_US_DTREN		BIT(16)	/* Data Terminal Ready Enable */
+#define	ATMEL_US_DTRDIS		BIT(17)	/* Data Terminal Ready Disable */
+#define	ATMEL_US_RTSEN		BIT(18)	/* Request To Send Enable */
+#define	ATMEL_US_RTSDIS		BIT(19)	/* Request To Send Disable */
 
-#define ATMEL_US_MR		0x04			/* Mode Register */
-#define		ATMEL_US_USMODE		(0xf <<  0)		/* Mode of the USART */
-#define			ATMEL_US_USMODE_NORMAL		0
-#define			ATMEL_US_USMODE_RS485		1
-#define			ATMEL_US_USMODE_HWHS		2
-#define			ATMEL_US_USMODE_MODEM		3
-#define			ATMEL_US_USMODE_ISO7816_T0	4
-#define			ATMEL_US_USMODE_ISO7816_T1	6
-#define			ATMEL_US_USMODE_IRDA		8
-#define		ATMEL_US_USCLKS		(3   <<  4)		/* Clock Selection */
-#define			ATMEL_US_USCLKS_MCK		(0 <<  4)
-#define			ATMEL_US_USCLKS_MCK_DIV8	(1 <<  4)
-#define			ATMEL_US_USCLKS_SCK		(3 <<  4)
-#define		ATMEL_US_CHRL		(3   <<  6)		/* Character Length */
-#define			ATMEL_US_CHRL_5			(0 <<  6)
-#define			ATMEL_US_CHRL_6			(1 <<  6)
-#define			ATMEL_US_CHRL_7			(2 <<  6)
-#define			ATMEL_US_CHRL_8			(3 <<  6)
-#define		ATMEL_US_SYNC		(1 <<  8)		/* Synchronous Mode Select */
-#define		ATMEL_US_PAR		(7 <<  9)		/* Parity Type */
-#define			ATMEL_US_PAR_EVEN		(0 <<  9)
-#define			ATMEL_US_PAR_ODD		(1 <<  9)
-#define			ATMEL_US_PAR_SPACE		(2 <<  9)
-#define			ATMEL_US_PAR_MARK		(3 <<  9)
-#define			ATMEL_US_PAR_NONE		(4 <<  9)
-#define			ATMEL_US_PAR_MULTI_DROP		(6 <<  9)
-#define		ATMEL_US_NBSTOP		(3 << 12)		/* Number of Stop Bits */
-#define			ATMEL_US_NBSTOP_1		(0 << 12)
-#define			ATMEL_US_NBSTOP_1_5		(1 << 12)
-#define			ATMEL_US_NBSTOP_2		(2 << 12)
-#define		ATMEL_US_CHMODE		(3 << 14)		/* Channel Mode */
-#define			ATMEL_US_CHMODE_NORMAL		(0 << 14)
-#define			ATMEL_US_CHMODE_ECHO		(1 << 14)
-#define			ATMEL_US_CHMODE_LOC_LOOP	(2 << 14)
-#define			ATMEL_US_CHMODE_REM_LOOP	(3 << 14)
-#define		ATMEL_US_MSBF		(1 << 16)		/* Bit Order */
-#define		ATMEL_US_MODE9		(1 << 17)		/* 9-bit Character Length */
-#define		ATMEL_US_CLKO		(1 << 18)		/* Clock Output Select */
-#define		ATMEL_US_OVER		(1 << 19)		/* Oversampling Mode */
-#define		ATMEL_US_INACK		(1 << 20)		/* Inhibit Non Acknowledge */
-#define		ATMEL_US_DSNACK		(1 << 21)		/* Disable Successive NACK */
-#define		ATMEL_US_MAX_ITER	(7 << 24)		/* Max Iterations */
-#define		ATMEL_US_FILTER		(1 << 28)		/* Infrared Receive Line Filter */
+#define ATMEL_US_MR		0x04	/* Mode Register */
+#define	ATMEL_US_USMODE		GENMASK(3, 0)	/* Mode of the USART */
+#define		ATMEL_US_USMODE_NORMAL		0
+#define		ATMEL_US_USMODE_RS485		1
+#define		ATMEL_US_USMODE_HWHS		2
+#define		ATMEL_US_USMODE_MODEM		3
+#define		ATMEL_US_USMODE_ISO7816_T0	4
+#define		ATMEL_US_USMODE_ISO7816_T1	6
+#define		ATMEL_US_USMODE_IRDA		8
+#define	ATMEL_US_USCLKS		GENMASK(5, 4)	/* Clock Selection */
+#define		ATMEL_US_USCLKS_MCK		(0 <<  4)
+#define		ATMEL_US_USCLKS_MCK_DIV8	(1 <<  4)
+#define		ATMEL_US_USCLKS_SCK		(3 <<  4)
+#define	ATMEL_US_CHRL		GENMASK(7, 6)	/* Character Length */
+#define		ATMEL_US_CHRL_5			(0 <<  6)
+#define		ATMEL_US_CHRL_6			(1 <<  6)
+#define		ATMEL_US_CHRL_7			(2 <<  6)
+#define		ATMEL_US_CHRL_8			(3 <<  6)
+#define	ATMEL_US_SYNC		BIT(8)		/* Synchronous Mode Select */
+#define	ATMEL_US_PAR		GENMASK(11, 9)	/* Parity Type */
+#define		ATMEL_US_PAR_EVEN		(0 <<  9)
+#define		ATMEL_US_PAR_ODD		(1 <<  9)
+#define		ATMEL_US_PAR_SPACE		(2 <<  9)
+#define		ATMEL_US_PAR_MARK		(3 <<  9)
+#define		ATMEL_US_PAR_NONE		(4 <<  9)
+#define		ATMEL_US_PAR_MULTI_DROP		(6 <<  9)
+#define	ATMEL_US_NBSTOP		GENMASK(13, 12)	/* Number of Stop Bits */
+#define		ATMEL_US_NBSTOP_1		(0 << 12)
+#define		ATMEL_US_NBSTOP_1_5		(1 << 12)
+#define		ATMEL_US_NBSTOP_2		(2 << 12)
+#define	ATMEL_US_CHMODE		GENMASK(15, 14)	/* Channel Mode */
+#define		ATMEL_US_CHMODE_NORMAL		(0 << 14)
+#define		ATMEL_US_CHMODE_ECHO		(1 << 14)
+#define		ATMEL_US_CHMODE_LOC_LOOP	(2 << 14)
+#define		ATMEL_US_CHMODE_REM_LOOP	(3 << 14)
+#define	ATMEL_US_MSBF		BIT(16)	/* Bit Order */
+#define	ATMEL_US_MODE9		BIT(17)	/* 9-bit Character Length */
+#define	ATMEL_US_CLKO		BIT(18)	/* Clock Output Select */
+#define	ATMEL_US_OVER		BIT(19)	/* Oversampling Mode */
+#define	ATMEL_US_INACK		BIT(20)	/* Inhibit Non Acknowledge */
+#define	ATMEL_US_DSNACK		BIT(21)	/* Disable Successive NACK */
+#define	ATMEL_US_MAX_ITER	GENMASK(26, 24)	/* Max Iterations */
+#define	ATMEL_US_FILTER		BIT(28)	/* Infrared Receive Line Filter */
 
-#define ATMEL_US_IER		0x08			/* Interrupt Enable Register */
-#define		ATMEL_US_RXRDY		(1 <<  0)		/* Receiver Ready */
-#define		ATMEL_US_TXRDY		(1 <<  1)		/* Transmitter Ready */
-#define		ATMEL_US_RXBRK		(1 <<  2)		/* Break Received / End of Break */
-#define		ATMEL_US_ENDRX		(1 <<  3)		/* End of Receiver Transfer */
-#define		ATMEL_US_ENDTX		(1 <<  4)		/* End of Transmitter Transfer */
-#define		ATMEL_US_OVRE		(1 <<  5)		/* Overrun Error */
-#define		ATMEL_US_FRAME		(1 <<  6)		/* Framing Error */
-#define		ATMEL_US_PARE		(1 <<  7)		/* Parity Error */
-#define		ATMEL_US_TIMEOUT	(1 <<  8)		/* Receiver Time-out */
-#define		ATMEL_US_TXEMPTY	(1 <<  9)		/* Transmitter Empty */
-#define		ATMEL_US_ITERATION	(1 << 10)		/* Max number of Repetitions Reached */
-#define		ATMEL_US_TXBUFE		(1 << 11)		/* Transmission Buffer Empty */
-#define		ATMEL_US_RXBUFF		(1 << 12)		/* Reception Buffer Full */
-#define		ATMEL_US_NACK		(1 << 13)		/* Non Acknowledge */
-#define		ATMEL_US_RIIC		(1 << 16)		/* Ring Indicator Input Change [AT91RM9200 only] */
-#define		ATMEL_US_DSRIC		(1 << 17)		/* Data Set Ready Input Change [AT91RM9200 only] */
-#define		ATMEL_US_DCDIC		(1 << 18)		/* Data Carrier Detect Input Change [AT91RM9200 only] */
-#define		ATMEL_US_CTSIC		(1 << 19)		/* Clear to Send Input Change */
-#define		ATMEL_US_RI		(1 << 20)		/* RI */
-#define		ATMEL_US_DSR		(1 << 21)		/* DSR */
-#define		ATMEL_US_DCD		(1 << 22)		/* DCD */
-#define		ATMEL_US_CTS		(1 << 23)		/* CTS */
+#define ATMEL_US_IER		0x08	/* Interrupt Enable Register */
+#define	ATMEL_US_RXRDY		BIT(0)	/* Receiver Ready */
+#define	ATMEL_US_TXRDY		BIT(1)	/* Transmitter Ready */
+#define	ATMEL_US_RXBRK		BIT(2)	/* Break Received / End of Break */
+#define	ATMEL_US_ENDRX		BIT(3)	/* End of Receiver Transfer */
+#define	ATMEL_US_ENDTX		BIT(4)	/* End of Transmitter Transfer */
+#define	ATMEL_US_OVRE		BIT(5)	/* Overrun Error */
+#define	ATMEL_US_FRAME		BIT(6)	/* Framing Error */
+#define	ATMEL_US_PARE		BIT(7)	/* Parity Error */
+#define	ATMEL_US_TIMEOUT	BIT(8)	/* Receiver Time-out */
+#define	ATMEL_US_TXEMPTY	BIT(9)	/* Transmitter Empty */
+#define	ATMEL_US_ITERATION	BIT(10)	/* Max number of Repetitions Reached */
+#define	ATMEL_US_TXBUFE		BIT(11)	/* Transmission Buffer Empty */
+#define	ATMEL_US_RXBUFF		BIT(12)	/* Reception Buffer Full */
+#define	ATMEL_US_NACK		BIT(13)	/* Non Acknowledge */
+#define	ATMEL_US_RIIC		BIT(16)	/* Ring Indicator Input Change */
+#define	ATMEL_US_DSRIC		BIT(17)	/* Data Set Ready Input Change */
+#define	ATMEL_US_DCDIC		BIT(18)	/* Data Carrier Detect Input Change */
+#define	ATMEL_US_CTSIC		BIT(19)	/* Clear to Send Input Change */
+#define	ATMEL_US_RI		BIT(20)	/* RI */
+#define	ATMEL_US_DSR		BIT(21)	/* DSR */
+#define	ATMEL_US_DCD		BIT(22)	/* DCD */
+#define	ATMEL_US_CTS		BIT(23)	/* CTS */
 
-#define ATMEL_US_IDR		0x0c			/* Interrupt Disable Register */
-#define ATMEL_US_IMR		0x10			/* Interrupt Mask Register */
-#define ATMEL_US_CSR		0x14			/* Channel Status Register */
-#define ATMEL_US_RHR		0x18			/* Receiver Holding Register */
-#define ATMEL_US_THR		0x1c			/* Transmitter Holding Register */
-#define		ATMEL_US_SYNH		(1 << 15)		/* Transmit/Receive Sync [AT91SAM9261 only] */
+#define ATMEL_US_IDR		0x0c	/* Interrupt Disable Register */
+#define ATMEL_US_IMR		0x10	/* Interrupt Mask Register */
+#define ATMEL_US_CSR		0x14	/* Channel Status Register */
+#define ATMEL_US_RHR		0x18	/* Receiver Holding Register */
+#define ATMEL_US_THR		0x1c	/* Transmitter Holding Register */
+#define	ATMEL_US_SYNH		BIT(15)	/* Transmit/Receive Sync */
 
-#define ATMEL_US_BRGR		0x20			/* Baud Rate Generator Register */
-#define		ATMEL_US_CD		(0xffff << 0)		/* Clock Divider */
+#define ATMEL_US_BRGR		0x20	/* Baud Rate Generator Register */
+#define	ATMEL_US_CD		GENMASK(15, 0)	/* Clock Divider */
 
-#define ATMEL_US_RTOR		0x24			/* Receiver Time-out Register */
-#define		ATMEL_US_TO		(0xffff << 0)		/* Time-out Value */
+#define ATMEL_US_RTOR		0x24	/* Receiver Time-out Register */
+#define	ATMEL_US_TO		GENMASK(15, 0)	/* Time-out Value */
 
-#define ATMEL_US_TTGR		0x28			/* Transmitter Timeguard Register */
-#define		ATMEL_US_TG		(0xff << 0)		/* Timeguard Value */
+#define ATMEL_US_TTGR		0x28	/* Transmitter Timeguard Register */
+#define	ATMEL_US_TG		GENMASK(7, 0)	/* Timeguard Value */
 
-#define ATMEL_US_FIDI		0x40			/* FI DI Ratio Register */
-#define ATMEL_US_NER		0x44			/* Number of Errors Register */
-#define ATMEL_US_IF		0x4c			/* IrDA Filter Register */
+#define ATMEL_US_FIDI		0x40	/* FI DI Ratio Register */
+#define ATMEL_US_NER		0x44	/* Number of Errors Register */
+#define ATMEL_US_IF		0x4c	/* IrDA Filter Register */
 
-#define ATMEL_US_NAME		0xf0			/* Ip Name */
-#define ATMEL_US_VERSION	0xfc			/* Ip Version */
+#define ATMEL_US_NAME		0xf0	/* Ip Name */
+#define ATMEL_US_VERSION	0xfc	/* Ip Version */
 
 #endif
-- 
1.8.2.2

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

* [PATCH v4 3/5] tty/serial: at91: remove bunch of macros to access UART registers
  2015-07-02 13:18 ` Cyrille Pitchen
  (?)
@ 2015-07-02 13:18   ` Cyrille Pitchen
  -1 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt,
	Cyrille Pitchen

This patch replaces the UART_PUT_*, resp. UART_GET_*, macros by
atmel_uart_writel(), resp. atmel_uart_readl(), inline function calls.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
---
 drivers/tty/serial/atmel_serial.c | 313 +++++++++++++++++++-------------------
 1 file changed, 159 insertions(+), 154 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 2a8f528153e7..e7c337de31d1 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -88,37 +88,6 @@ static void atmel_stop_rx(struct uart_port *port);
 
 #define ATMEL_ISR_PASS_LIMIT	256
 
-/* UART registers. CR is write-only, hence no GET macro */
-#define UART_PUT_CR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_CR)
-#define UART_GET_MR(port)	__raw_readl((port)->membase + ATMEL_US_MR)
-#define UART_PUT_MR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_MR)
-#define UART_PUT_IER(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IER)
-#define UART_PUT_IDR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IDR)
-#define UART_GET_IMR(port)	__raw_readl((port)->membase + ATMEL_US_IMR)
-#define UART_GET_CSR(port)	__raw_readl((port)->membase + ATMEL_US_CSR)
-#define UART_GET_CHAR(port)	__raw_readl((port)->membase + ATMEL_US_RHR)
-#define UART_PUT_CHAR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_THR)
-#define UART_GET_BRGR(port)	__raw_readl((port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_BRGR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
-#define UART_PUT_TTGR(port, v)	__raw_writel(v, (port)->membase + ATMEL_US_TTGR)
-#define UART_GET_IP_NAME(port)	__raw_readl((port)->membase + ATMEL_US_NAME)
-#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
-
- /* PDC registers */
-#define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
-#define UART_GET_PTSR(port)	__raw_readl((port)->membase + ATMEL_PDC_PTSR)
-
-#define UART_PUT_RPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
-#define UART_GET_RPR(port)	__raw_readl((port)->membase + ATMEL_PDC_RPR)
-#define UART_PUT_RCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
-#define UART_PUT_RNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
-#define UART_PUT_RNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
-
-#define UART_PUT_TPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
-#define UART_PUT_TCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
-#define UART_GET_TCR(port)	__raw_readl((port)->membase + ATMEL_PDC_TCR)
-
 struct atmel_dma_buffer {
 	unsigned char	*buf;
 	dma_addr_t	dma_addr;
@@ -212,6 +181,16 @@ to_atmel_uart_port(struct uart_port *uart)
 	return container_of(uart, struct atmel_uart_port, uart);
 }
 
+static inline u32 atmel_uart_readl(struct uart_port *port, u32 reg)
+{
+	return __raw_readl(port->membase + reg);
+}
+
+static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
+{
+	__raw_writel(value, port->membase + reg);
+}
+
 #ifdef CONFIG_SERIAL_ATMEL_PDC
 static bool atmel_use_pdc_rx(struct uart_port *port)
 {
@@ -257,7 +236,7 @@ static unsigned int atmel_get_lines_status(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned int status, ret = 0;
 
-	status = UART_GET_CSR(port);
+	status = atmel_uart_readl(port, ATMEL_US_CSR);
 
 	mctrl_gpio_get(atmel_port->gpios, &ret);
 
@@ -304,9 +283,9 @@ static int atmel_config_rs485(struct uart_port *port,
 	unsigned int mode;
 
 	/* Disable interrupts */
-	UART_PUT_IDR(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
-	mode = UART_GET_MR(port);
+	mode = atmel_uart_readl(port, ATMEL_US_MR);
 
 	/* Resetting serial mode to RS232 (0x0) */
 	mode &= ~ATMEL_US_USMODE;
@@ -316,7 +295,8 @@ static int atmel_config_rs485(struct uart_port *port,
 	if (rs485conf->flags & SER_RS485_ENABLED) {
 		dev_dbg(port->dev, "Setting UART to RS485\n");
 		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
-		UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
+		atmel_uart_writel(port, ATMEL_US_TTGR,
+				  rs485conf->delay_rts_after_send);
 		mode |= ATMEL_US_USMODE_RS485;
 	} else {
 		dev_dbg(port->dev, "Setting UART to RS232\n");
@@ -326,10 +306,10 @@ static int atmel_config_rs485(struct uart_port *port,
 		else
 			atmel_port->tx_done_mask = ATMEL_US_TXRDY;
 	}
-	UART_PUT_MR(port, mode);
+	atmel_uart_writel(port, ATMEL_US_MR, mode);
 
 	/* Enable interrupts */
-	UART_PUT_IER(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
 
 	return 0;
 }
@@ -339,7 +319,9 @@ static int atmel_config_rs485(struct uart_port *port,
  */
 static u_int atmel_tx_empty(struct uart_port *port)
 {
-	return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
+	return (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY) ?
+		TIOCSER_TEMT :
+		0;
 }
 
 /*
@@ -348,13 +330,14 @@ static u_int atmel_tx_empty(struct uart_port *port)
 static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 {
 	unsigned int control = 0;
-	unsigned int mode = UART_GET_MR(port);
+	unsigned int mode = atmel_uart_readl(port, ATMEL_US_MR);
 	unsigned int rts_paused, rts_ready;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
 	/* override mode to RS485 if needed, otherwise keep the current mode */
 	if (port->rs485.flags & SER_RS485_ENABLED) {
-		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+		atmel_uart_writel(port, ATMEL_US_TTGR,
+				  port->rs485.delay_rts_after_send);
 		mode &= ~ATMEL_US_USMODE;
 		mode |= ATMEL_US_USMODE_RS485;
 	}
@@ -384,7 +367,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 	else
 		control |= ATMEL_US_DTRDIS;
 
-	UART_PUT_CR(port, control);
+	atmel_uart_writel(port, ATMEL_US_CR, control);
 
 	mctrl_gpio_set(atmel_port->gpios, mctrl);
 
@@ -395,7 +378,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 	else
 		mode |= ATMEL_US_CHMODE_NORMAL;
 
-	UART_PUT_MR(port, mode);
+	atmel_uart_writel(port, ATMEL_US_MR, mode);
 }
 
 /*
@@ -406,7 +389,7 @@ static u_int atmel_get_mctrl(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned int ret = 0, status;
 
-	status = UART_GET_CSR(port);
+	status = atmel_uart_readl(port, ATMEL_US_CSR);
 
 	/*
 	 * The control signals are active low.
@@ -432,10 +415,10 @@ static void atmel_stop_tx(struct uart_port *port)
 
 	if (atmel_use_pdc_tx(port)) {
 		/* disable PDC transmit */
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 	}
 	/* Disable interrupts */
-	UART_PUT_IDR(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
 	if ((port->rs485.flags & SER_RS485_ENABLED) &&
 	    !(port->rs485.flags & SER_RS485_RX_DURING_TX))
@@ -450,7 +433,7 @@ static void atmel_start_tx(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
 	if (atmel_use_pdc_tx(port)) {
-		if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
+		if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
 			/* The transmitter is already running.  Yes, we
 			   really need this.*/
 			return;
@@ -460,10 +443,10 @@ static void atmel_start_tx(struct uart_port *port)
 			atmel_stop_rx(port);
 
 		/* re-enable PDC transmit */
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 	}
 	/* Enable interrupts */
-	UART_PUT_IER(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
 }
 
 /*
@@ -471,17 +454,19 @@ static void atmel_start_tx(struct uart_port *port)
  */
 static void atmel_start_rx(struct uart_port *port)
 {
-	UART_PUT_CR(port, ATMEL_US_RSTSTA);  /* reset status and receiver */
+	/* reset status and receiver */
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
-	UART_PUT_CR(port, ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXEN);
 
 	if (atmel_use_pdc_rx(port)) {
 		/* enable PDC controller */
-		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
-			port->read_status_mask);
-		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
+		atmel_uart_writel(port, ATMEL_US_IER,
+				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
+				  port->read_status_mask);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
 	} else {
-		UART_PUT_IER(port, ATMEL_US_RXRDY);
+		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
 	}
 }
 
@@ -490,15 +475,16 @@ static void atmel_start_rx(struct uart_port *port)
  */
 static void atmel_stop_rx(struct uart_port *port)
 {
-	UART_PUT_CR(port, ATMEL_US_RXDIS);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXDIS);
 
 	if (atmel_use_pdc_rx(port)) {
 		/* disable PDC receive */
-		UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
-		UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
-			port->read_status_mask);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS);
+		atmel_uart_writel(port, ATMEL_US_IDR,
+				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
+				  port->read_status_mask);
 	} else {
-		UART_PUT_IDR(port, ATMEL_US_RXRDY);
+		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXRDY);
 	}
 }
 
@@ -538,7 +524,7 @@ static void atmel_enable_ms(struct uart_port *port)
 	else
 		ier |= ATMEL_US_DCDIC;
 
-	UART_PUT_IER(port, ier);
+	atmel_uart_writel(port, ATMEL_US_IER, ier);
 }
 
 /*
@@ -577,7 +563,7 @@ static void atmel_disable_ms(struct uart_port *port)
 	else
 		idr |= ATMEL_US_DCDIC;
 
-	UART_PUT_IDR(port, idr);
+	atmel_uart_writel(port, ATMEL_US_IDR, idr);
 }
 
 /*
@@ -586,9 +572,11 @@ static void atmel_disable_ms(struct uart_port *port)
 static void atmel_break_ctl(struct uart_port *port, int break_state)
 {
 	if (break_state != 0)
-		UART_PUT_CR(port, ATMEL_US_STTBRK);	/* start break */
+		/* start break */
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTBRK);
 	else
-		UART_PUT_CR(port, ATMEL_US_STPBRK);	/* stop break */
+		/* stop break */
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STPBRK);
 }
 
 /*
@@ -622,7 +610,7 @@ atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
 static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
 {
 	/* clear error */
-	UART_PUT_CR(port, ATMEL_US_RSTSTA);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
 	if (status & ATMEL_US_RXBRK) {
 		/* ignore side-effect */
@@ -645,9 +633,9 @@ static void atmel_rx_chars(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned int status, ch;
 
-	status = UART_GET_CSR(port);
+	status = atmel_uart_readl(port, ATMEL_US_CSR);
 	while (status & ATMEL_US_RXRDY) {
-		ch = UART_GET_CHAR(port);
+		ch = atmel_uart_readl(port, ATMEL_US_RHR);
 
 		/*
 		 * note that the error handling code is
@@ -658,12 +646,13 @@ static void atmel_rx_chars(struct uart_port *port)
 			     || atmel_port->break_active)) {
 
 			/* clear error */
-			UART_PUT_CR(port, ATMEL_US_RSTSTA);
+			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
 			if (status & ATMEL_US_RXBRK
 			    && !atmel_port->break_active) {
 				atmel_port->break_active = 1;
-				UART_PUT_IER(port, ATMEL_US_RXBRK);
+				atmel_uart_writel(port, ATMEL_US_IER,
+						  ATMEL_US_RXBRK);
 			} else {
 				/*
 				 * This is either the end-of-break
@@ -672,14 +661,15 @@ static void atmel_rx_chars(struct uart_port *port)
 				 * being set. In both cases, the next
 				 * RXBRK will indicate start-of-break.
 				 */
-				UART_PUT_IDR(port, ATMEL_US_RXBRK);
+				atmel_uart_writel(port, ATMEL_US_IDR,
+						  ATMEL_US_RXBRK);
 				status &= ~ATMEL_US_RXBRK;
 				atmel_port->break_active = 0;
 			}
 		}
 
 		atmel_buffer_rx_char(port, status, ch);
-		status = UART_GET_CSR(port);
+		status = atmel_uart_readl(port, ATMEL_US_CSR);
 	}
 
 	tasklet_schedule(&atmel_port->tasklet);
@@ -694,16 +684,18 @@ static void atmel_tx_chars(struct uart_port *port)
 	struct circ_buf *xmit = &port->state->xmit;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
-		UART_PUT_CHAR(port, port->x_char);
+	if (port->x_char &&
+	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
+		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
 		port->icount.tx++;
 		port->x_char = 0;
 	}
 	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
 		return;
 
-	while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
-		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+	while (atmel_uart_readl(port, ATMEL_US_CSR) &
+	       atmel_port->tx_done_mask) {
+		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		port->icount.tx++;
 		if (uart_circ_empty(xmit))
@@ -715,7 +707,8 @@ static void atmel_tx_chars(struct uart_port *port)
 
 	if (!uart_circ_empty(xmit))
 		/* Enable interrupts */
-		UART_PUT_IER(port, atmel_port->tx_done_mask);
+		atmel_uart_writel(port, ATMEL_US_IER,
+				  atmel_port->tx_done_mask);
 }
 
 static void atmel_complete_tx_dma(void *arg)
@@ -935,14 +928,14 @@ static void atmel_rx_from_dma(struct uart_port *port)
 
 
 	/* Reset the UART timeout early so that we don't miss one */
-	UART_PUT_CR(port, ATMEL_US_STTTO);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 	dmastat = dmaengine_tx_status(chan,
 				atmel_port->cookie_rx,
 				&state);
 	/* Restart a new tasklet if DMA status is error */
 	if (dmastat == DMA_ERROR) {
 		dev_dbg(port->dev, "Get residue error, restart tasklet\n");
-		UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
 		tasklet_schedule(&atmel_port->tasklet);
 		return;
 	}
@@ -1008,7 +1001,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
 	tty_flip_buffer_push(tport);
 	spin_lock(&port->lock);
 
-	UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+	atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
 }
 
 static int atmel_prepare_rx_dma(struct uart_port *port)
@@ -1118,8 +1111,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 		 * the moment.
 		 */
 		if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
-			UART_PUT_IDR(port, (ATMEL_US_ENDRX
-						| ATMEL_US_TIMEOUT));
+			atmel_uart_writel(port, ATMEL_US_IDR,
+					  (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
 			tasklet_schedule(&atmel_port->tasklet);
 		}
 
@@ -1130,7 +1123,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 
 	if (atmel_use_dma_rx(port)) {
 		if (pending & ATMEL_US_TIMEOUT) {
-			UART_PUT_IDR(port, ATMEL_US_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_IDR,
+					  ATMEL_US_TIMEOUT);
 			tasklet_schedule(&atmel_port->tasklet);
 		}
 	}
@@ -1143,8 +1137,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 		 * End of break detected. If it came along with a
 		 * character, atmel_rx_chars will handle it.
 		 */
-		UART_PUT_CR(port, ATMEL_US_RSTSTA);
-		UART_PUT_IDR(port, ATMEL_US_RXBRK);
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
+		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXBRK);
 		atmel_port->break_active = 0;
 	}
 }
@@ -1159,7 +1153,8 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
 
 	if (pending & atmel_port->tx_done_mask) {
 		/* Either PDC or interrupt transmission */
-		UART_PUT_IDR(port, atmel_port->tx_done_mask);
+		atmel_uart_writel(port, ATMEL_US_IDR,
+				  atmel_port->tx_done_mask);
 		tasklet_schedule(&atmel_port->tasklet);
 	}
 }
@@ -1197,7 +1192,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 
 	do {
 		status = atmel_get_lines_status(port);
-		mask = UART_GET_IMR(port);
+		mask = atmel_uart_readl(port, ATMEL_US_IMR);
 		pending = status & mask;
 		if (!gpio_handled) {
 			/*
@@ -1223,7 +1218,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 		if (atmel_port->suspended) {
 			atmel_port->pending |= pending;
 			atmel_port->pending_status = status;
-			UART_PUT_IDR(port, mask);
+			atmel_uart_writel(port, ATMEL_US_IDR, mask);
 			pm_system_wakeup();
 			break;
 		}
@@ -1260,7 +1255,7 @@ static void atmel_tx_pdc(struct uart_port *port)
 	int count;
 
 	/* nothing left to transmit? */
-	if (UART_GET_TCR(port))
+	if (atmel_uart_readl(port, ATMEL_PDC_TCR))
 		return;
 
 	xmit->tail += pdc->ofs;
@@ -1272,7 +1267,7 @@ static void atmel_tx_pdc(struct uart_port *port)
 	/* more to transmit - setup next transfer */
 
 	/* disable PDC transmit */
-	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 
 	if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
 		dma_sync_single_for_device(port->dev,
@@ -1283,12 +1278,14 @@ static void atmel_tx_pdc(struct uart_port *port)
 		count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
 		pdc->ofs = count;
 
-		UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
-		UART_PUT_TCR(port, count);
+		atmel_uart_writel(port, ATMEL_PDC_TPR,
+				  pdc->dma_addr + xmit->tail);
+		atmel_uart_writel(port, ATMEL_PDC_TCR, count);
 		/* re-enable PDC transmit */
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 		/* Enable interrupts */
-		UART_PUT_IER(port, atmel_port->tx_done_mask);
+		atmel_uart_writel(port, ATMEL_US_IER,
+				  atmel_port->tx_done_mask);
 	} else {
 		if ((port->rs485.flags & SER_RS485_ENABLED) &&
 		    !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
@@ -1414,10 +1411,10 @@ static void atmel_rx_from_pdc(struct uart_port *port)
 
 	do {
 		/* Reset the UART timeout early so that we don't miss one */
-		UART_PUT_CR(port, ATMEL_US_STTTO);
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
 		pdc = &atmel_port->pdc_rx[rx_idx];
-		head = UART_GET_RPR(port) - pdc->dma_addr;
+		head = atmel_uart_readl(port, ATMEL_PDC_RPR) - pdc->dma_addr;
 		tail = pdc->ofs;
 
 		/* If the PDC has switched buffers, RPR won't contain
@@ -1460,8 +1457,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
 		 */
 		if (head >= pdc->dma_size) {
 			pdc->ofs = 0;
-			UART_PUT_RNPR(port, pdc->dma_addr);
-			UART_PUT_RNCR(port, pdc->dma_size);
+			atmel_uart_writel(port, ATMEL_PDC_RNPR, pdc->dma_addr);
+			atmel_uart_writel(port, ATMEL_PDC_RNCR, pdc->dma_size);
 
 			rx_idx = !rx_idx;
 			atmel_port->pdc_rx_idx = rx_idx;
@@ -1476,7 +1473,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
 	tty_flip_buffer_push(tport);
 	spin_lock(&port->lock);
 
-	UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+	atmel_uart_writel(port, ATMEL_US_IER,
+			  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
 }
 
 static int atmel_prepare_rx_pdc(struct uart_port *port)
@@ -1509,11 +1507,12 @@ static int atmel_prepare_rx_pdc(struct uart_port *port)
 
 	atmel_port->pdc_rx_idx = 0;
 
-	UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
-	UART_PUT_RCR(port, PDC_BUFFER_SIZE);
+	atmel_uart_writel(port, ATMEL_PDC_RPR, atmel_port->pdc_rx[0].dma_addr);
+	atmel_uart_writel(port, ATMEL_PDC_RCR, PDC_BUFFER_SIZE);
 
-	UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
-	UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
+	atmel_uart_writel(port, ATMEL_PDC_RNPR,
+			  atmel_port->pdc_rx[1].dma_addr);
+	atmel_uart_writel(port, ATMEL_PDC_RNCR, PDC_BUFFER_SIZE);
 
 	return 0;
 }
@@ -1667,7 +1666,7 @@ static void atmel_set_ops(struct uart_port *port)
 static void atmel_get_ip_name(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-	int name = UART_GET_IP_NAME(port);
+	int name = atmel_uart_readl(port, ATMEL_US_NAME);
 	u32 version;
 	int usart, uart;
 	/* usart and uart ascii */
@@ -1684,7 +1683,7 @@ static void atmel_get_ip_name(struct uart_port *port)
 		atmel_port->is_usart = false;
 	} else {
 		/* fallback for older SoCs: use version field */
-		version = UART_GET_IP_VERSION(port);
+		version = atmel_uart_readl(port, ATMEL_US_VERSION);
 		switch (version) {
 		case 0x302:
 		case 0x10213:
@@ -1756,7 +1755,7 @@ static int atmel_startup(struct uart_port *port)
 	 * request_irq() is called we could get stuck trying to
 	 * handle an unexpected interrupt
 	 */
-	UART_PUT_IDR(port, -1);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
 	atmel_port->ms_irq_enabled = false;
 
 	/*
@@ -1804,9 +1803,9 @@ static int atmel_startup(struct uart_port *port)
 	/*
 	 * Finally, enable the serial port
 	 */
-	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
 	/* enable xmit & rcvr */
-	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
 	setup_timer(&atmel_port->uart_timer,
 			atmel_uart_timer_callback,
@@ -1819,13 +1818,14 @@ static int atmel_startup(struct uart_port *port)
 					jiffies + uart_poll_timeout(port));
 		/* set USART timeout */
 		} else {
-			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
-			UART_PUT_CR(port, ATMEL_US_STTTO);
+			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
-			UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_IER,
+					  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
 		}
 		/* enable PDC controller */
-		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
 	} else if (atmel_use_dma_rx(port)) {
 		/* set UART timeout */
 		if (!atmel_port->is_usart) {
@@ -1833,14 +1833,15 @@ static int atmel_startup(struct uart_port *port)
 					jiffies + uart_poll_timeout(port));
 		/* set USART timeout */
 		} else {
-			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
-			UART_PUT_CR(port, ATMEL_US_STTTO);
+			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
-			UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_IER,
+					  ATMEL_US_TIMEOUT);
 		}
 	} else {
 		/* enable receive only */
-		UART_PUT_IER(port, ATMEL_US_RXRDY);
+		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
 	}
 
 	return 0;
@@ -1860,7 +1861,7 @@ static void atmel_flush_buffer(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
 	if (atmel_use_pdc_tx(port)) {
-		UART_PUT_TCR(port, 0);
+		atmel_uart_writel(port, ATMEL_PDC_TCR, 0);
 		atmel_port->pdc_tx.ofs = 0;
 	}
 }
@@ -1892,8 +1893,8 @@ static void atmel_shutdown(struct uart_port *port)
 	atmel_stop_rx(port);
 	atmel_stop_tx(port);
 
-	UART_PUT_CR(port, ATMEL_US_RSTSTA);
-	UART_PUT_IDR(port, -1);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
 
 	/*
@@ -1938,12 +1939,12 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
 		clk_prepare_enable(atmel_port->clk);
 
 		/* re-enable interrupts if we disabled some on suspend */
-		UART_PUT_IER(port, atmel_port->backup_imr);
+		atmel_uart_writel(port, ATMEL_US_IER, atmel_port->backup_imr);
 		break;
 	case 3:
 		/* Back up the interrupt mask and disable all interrupts */
-		atmel_port->backup_imr = UART_GET_IMR(port);
-		UART_PUT_IDR(port, -1);
+		atmel_port->backup_imr = atmel_uart_readl(port, ATMEL_US_IMR);
+		atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
 		/*
 		 * Disable the peripheral clock for this serial port.
@@ -1966,7 +1967,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	unsigned int old_mode, mode, imr, quot, baud;
 
 	/* save the current mode register */
-	mode = old_mode = UART_GET_MR(port);
+	mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR);
 
 	/* reset the mode, clock divisor, parity, stop bits and data size */
 	mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP |
@@ -2025,7 +2026,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	if (atmel_use_pdc_rx(port))
 		/* need to enable error interrupts */
-		UART_PUT_IER(port, port->read_status_mask);
+		atmel_uart_writel(port, ATMEL_US_IER, port->read_status_mask);
 
 	/*
 	 * Characters to ignore
@@ -2052,15 +2053,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	 * transmitter is empty if requested by the caller, so there's
 	 * no need to wait for it here.
 	 */
-	imr = UART_GET_IMR(port);
-	UART_PUT_IDR(port, -1);
+	imr = atmel_uart_readl(port, ATMEL_US_IMR);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
 	/* disable receiver and transmitter */
-	UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
 
 	/* mode */
 	if (port->rs485.flags & SER_RS485_ENABLED) {
-		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+		atmel_uart_writel(port, ATMEL_US_TTGR,
+				  port->rs485.delay_rts_after_send);
 		mode |= ATMEL_US_USMODE_RS485;
 	} else if (termios->c_cflag & CRTSCTS) {
 		/* RS232 with hardware handshake (RTS/CTS) */
@@ -2071,7 +2073,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	}
 
 	/* set the mode, clock divisor, parity, stop bits and data size */
-	UART_PUT_MR(port, mode);
+	atmel_uart_writel(port, ATMEL_US_MR, mode);
 
 	/*
 	 * when switching the mode, set the RTS line state according to the
@@ -2088,16 +2090,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 			rts_state = ATMEL_US_RTSEN;
 		}
 
-		UART_PUT_CR(port, rts_state);
+		atmel_uart_writel(port, ATMEL_US_CR, rts_state);
 	}
 
 	/* set the baud rate */
-	UART_PUT_BRGR(port, quot);
-	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
-	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_BRGR, quot);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
 	/* restore interrupts */
-	UART_PUT_IER(port, imr);
+	atmel_uart_writel(port, ATMEL_US_IER, imr);
 
 	/* CTS flow-control and modem-status interrupts */
 	if (UART_ENABLE_MS(port, termios->c_cflag))
@@ -2208,18 +2210,18 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
 #ifdef CONFIG_CONSOLE_POLL
 static int atmel_poll_get_char(struct uart_port *port)
 {
-	while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
+	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
 		cpu_relax();
 
-	return UART_GET_CHAR(port);
+	return atmel_uart_readl(port, ATMEL_US_RHR);
 }
 
 static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
 {
-	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
 
-	UART_PUT_CHAR(port, ch);
+	atmel_uart_writel(port, ATMEL_US_THR, ch);
 }
 #endif
 
@@ -2324,9 +2326,9 @@ struct platform_device *atmel_default_console_device;	/* the serial console devi
 #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
 static void atmel_console_putchar(struct uart_port *port, int ch)
 {
-	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
-	UART_PUT_CHAR(port, ch);
+	atmel_uart_writel(port, ATMEL_US_THR, ch);
 }
 
 /*
@@ -2342,12 +2344,13 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
 	/*
 	 * First, save IMR and then disable interrupts
 	 */
-	imr = UART_GET_IMR(port);
-	UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
+	imr = atmel_uart_readl(port, ATMEL_US_IMR);
+	atmel_uart_writel(port, ATMEL_US_IDR,
+			  ATMEL_US_RXRDY | atmel_port->tx_done_mask);
 
 	/* Store PDC transmit status and disable it */
-	pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
-	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+	pdc_tx = atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN;
+	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 
 	uart_console_write(port, s, count, atmel_console_putchar);
 
@@ -2356,15 +2359,15 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
 	 * and restore IMR
 	 */
 	do {
-		status = UART_GET_CSR(port);
+		status = atmel_uart_readl(port, ATMEL_US_CSR);
 	} while (!(status & ATMEL_US_TXRDY));
 
 	/* Restore PDC transmit status */
 	if (pdc_tx)
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 
 	/* set interrupts back the way they were */
-	UART_PUT_IER(port, imr);
+	atmel_uart_writel(port, ATMEL_US_IER, imr);
 }
 
 /*
@@ -2380,17 +2383,17 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
 	 * If the baud rate generator isn't running, the port wasn't
 	 * initialized by the boot loader.
 	 */
-	quot = UART_GET_BRGR(port) & ATMEL_US_CD;
+	quot = atmel_uart_readl(port, ATMEL_US_BRGR) & ATMEL_US_CD;
 	if (!quot)
 		return;
 
-	mr = UART_GET_MR(port) & ATMEL_US_CHRL;
+	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_CHRL;
 	if (mr == ATMEL_US_CHRL_8)
 		*bits = 8;
 	else
 		*bits = 7;
 
-	mr = UART_GET_MR(port) & ATMEL_US_PAR;
+	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_PAR;
 	if (mr == ATMEL_US_PAR_EVEN)
 		*parity = 'e';
 	else if (mr == ATMEL_US_PAR_ODD)
@@ -2423,9 +2426,9 @@ static int __init atmel_console_setup(struct console *co, char *options)
 	if (ret)
 		return ret;
 
-	UART_PUT_IDR(port, -1);
-	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
-	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -2532,7 +2535,8 @@ static int atmel_serial_suspend(struct platform_device *pdev,
 
 	if (atmel_is_console_port(port) && console_suspend_enabled) {
 		/* Drain the TX shifter */
-		while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
+		while (!(atmel_uart_readl(port, ATMEL_US_CSR) &
+			 ATMEL_US_TXEMPTY))
 			cpu_relax();
 	}
 
@@ -2684,8 +2688,9 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	clk_prepare_enable(port->clk);
 
 	if (rs485_enabled) {
-		UART_PUT_MR(&port->uart, ATMEL_US_USMODE_NORMAL);
-		UART_PUT_CR(&port->uart, ATMEL_US_RTSEN);
+		atmel_uart_writel(&port->uart, ATMEL_US_MR,
+				  ATMEL_US_USMODE_NORMAL);
+		atmel_uart_writel(&port->uart, ATMEL_US_CR, ATMEL_US_RTSEN);
 	}
 
 	/*
-- 
1.8.2.2


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

* [PATCH v4 3/5] tty/serial: at91: remove bunch of macros to access UART registers
@ 2015-07-02 13:18   ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt,
	Cyrille Pitchen

This patch replaces the UART_PUT_*, resp. UART_GET_*, macros by
atmel_uart_writel(), resp. atmel_uart_readl(), inline function calls.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
---
 drivers/tty/serial/atmel_serial.c | 313 +++++++++++++++++++-------------------
 1 file changed, 159 insertions(+), 154 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 2a8f528153e7..e7c337de31d1 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -88,37 +88,6 @@ static void atmel_stop_rx(struct uart_port *port);
 
 #define ATMEL_ISR_PASS_LIMIT	256
 
-/* UART registers. CR is write-only, hence no GET macro */
-#define UART_PUT_CR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_CR)
-#define UART_GET_MR(port)	__raw_readl((port)->membase + ATMEL_US_MR)
-#define UART_PUT_MR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_MR)
-#define UART_PUT_IER(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IER)
-#define UART_PUT_IDR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IDR)
-#define UART_GET_IMR(port)	__raw_readl((port)->membase + ATMEL_US_IMR)
-#define UART_GET_CSR(port)	__raw_readl((port)->membase + ATMEL_US_CSR)
-#define UART_GET_CHAR(port)	__raw_readl((port)->membase + ATMEL_US_RHR)
-#define UART_PUT_CHAR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_THR)
-#define UART_GET_BRGR(port)	__raw_readl((port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_BRGR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
-#define UART_PUT_TTGR(port, v)	__raw_writel(v, (port)->membase + ATMEL_US_TTGR)
-#define UART_GET_IP_NAME(port)	__raw_readl((port)->membase + ATMEL_US_NAME)
-#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
-
- /* PDC registers */
-#define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
-#define UART_GET_PTSR(port)	__raw_readl((port)->membase + ATMEL_PDC_PTSR)
-
-#define UART_PUT_RPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
-#define UART_GET_RPR(port)	__raw_readl((port)->membase + ATMEL_PDC_RPR)
-#define UART_PUT_RCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
-#define UART_PUT_RNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
-#define UART_PUT_RNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
-
-#define UART_PUT_TPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
-#define UART_PUT_TCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
-#define UART_GET_TCR(port)	__raw_readl((port)->membase + ATMEL_PDC_TCR)
-
 struct atmel_dma_buffer {
 	unsigned char	*buf;
 	dma_addr_t	dma_addr;
@@ -212,6 +181,16 @@ to_atmel_uart_port(struct uart_port *uart)
 	return container_of(uart, struct atmel_uart_port, uart);
 }
 
+static inline u32 atmel_uart_readl(struct uart_port *port, u32 reg)
+{
+	return __raw_readl(port->membase + reg);
+}
+
+static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
+{
+	__raw_writel(value, port->membase + reg);
+}
+
 #ifdef CONFIG_SERIAL_ATMEL_PDC
 static bool atmel_use_pdc_rx(struct uart_port *port)
 {
@@ -257,7 +236,7 @@ static unsigned int atmel_get_lines_status(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned int status, ret = 0;
 
-	status = UART_GET_CSR(port);
+	status = atmel_uart_readl(port, ATMEL_US_CSR);
 
 	mctrl_gpio_get(atmel_port->gpios, &ret);
 
@@ -304,9 +283,9 @@ static int atmel_config_rs485(struct uart_port *port,
 	unsigned int mode;
 
 	/* Disable interrupts */
-	UART_PUT_IDR(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
-	mode = UART_GET_MR(port);
+	mode = atmel_uart_readl(port, ATMEL_US_MR);
 
 	/* Resetting serial mode to RS232 (0x0) */
 	mode &= ~ATMEL_US_USMODE;
@@ -316,7 +295,8 @@ static int atmel_config_rs485(struct uart_port *port,
 	if (rs485conf->flags & SER_RS485_ENABLED) {
 		dev_dbg(port->dev, "Setting UART to RS485\n");
 		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
-		UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
+		atmel_uart_writel(port, ATMEL_US_TTGR,
+				  rs485conf->delay_rts_after_send);
 		mode |= ATMEL_US_USMODE_RS485;
 	} else {
 		dev_dbg(port->dev, "Setting UART to RS232\n");
@@ -326,10 +306,10 @@ static int atmel_config_rs485(struct uart_port *port,
 		else
 			atmel_port->tx_done_mask = ATMEL_US_TXRDY;
 	}
-	UART_PUT_MR(port, mode);
+	atmel_uart_writel(port, ATMEL_US_MR, mode);
 
 	/* Enable interrupts */
-	UART_PUT_IER(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
 
 	return 0;
 }
@@ -339,7 +319,9 @@ static int atmel_config_rs485(struct uart_port *port,
  */
 static u_int atmel_tx_empty(struct uart_port *port)
 {
-	return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
+	return (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY) ?
+		TIOCSER_TEMT :
+		0;
 }
 
 /*
@@ -348,13 +330,14 @@ static u_int atmel_tx_empty(struct uart_port *port)
 static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 {
 	unsigned int control = 0;
-	unsigned int mode = UART_GET_MR(port);
+	unsigned int mode = atmel_uart_readl(port, ATMEL_US_MR);
 	unsigned int rts_paused, rts_ready;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
 	/* override mode to RS485 if needed, otherwise keep the current mode */
 	if (port->rs485.flags & SER_RS485_ENABLED) {
-		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+		atmel_uart_writel(port, ATMEL_US_TTGR,
+				  port->rs485.delay_rts_after_send);
 		mode &= ~ATMEL_US_USMODE;
 		mode |= ATMEL_US_USMODE_RS485;
 	}
@@ -384,7 +367,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 	else
 		control |= ATMEL_US_DTRDIS;
 
-	UART_PUT_CR(port, control);
+	atmel_uart_writel(port, ATMEL_US_CR, control);
 
 	mctrl_gpio_set(atmel_port->gpios, mctrl);
 
@@ -395,7 +378,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 	else
 		mode |= ATMEL_US_CHMODE_NORMAL;
 
-	UART_PUT_MR(port, mode);
+	atmel_uart_writel(port, ATMEL_US_MR, mode);
 }
 
 /*
@@ -406,7 +389,7 @@ static u_int atmel_get_mctrl(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned int ret = 0, status;
 
-	status = UART_GET_CSR(port);
+	status = atmel_uart_readl(port, ATMEL_US_CSR);
 
 	/*
 	 * The control signals are active low.
@@ -432,10 +415,10 @@ static void atmel_stop_tx(struct uart_port *port)
 
 	if (atmel_use_pdc_tx(port)) {
 		/* disable PDC transmit */
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 	}
 	/* Disable interrupts */
-	UART_PUT_IDR(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
 	if ((port->rs485.flags & SER_RS485_ENABLED) &&
 	    !(port->rs485.flags & SER_RS485_RX_DURING_TX))
@@ -450,7 +433,7 @@ static void atmel_start_tx(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
 	if (atmel_use_pdc_tx(port)) {
-		if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
+		if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
 			/* The transmitter is already running.  Yes, we
 			   really need this.*/
 			return;
@@ -460,10 +443,10 @@ static void atmel_start_tx(struct uart_port *port)
 			atmel_stop_rx(port);
 
 		/* re-enable PDC transmit */
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 	}
 	/* Enable interrupts */
-	UART_PUT_IER(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
 }
 
 /*
@@ -471,17 +454,19 @@ static void atmel_start_tx(struct uart_port *port)
  */
 static void atmel_start_rx(struct uart_port *port)
 {
-	UART_PUT_CR(port, ATMEL_US_RSTSTA);  /* reset status and receiver */
+	/* reset status and receiver */
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
-	UART_PUT_CR(port, ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXEN);
 
 	if (atmel_use_pdc_rx(port)) {
 		/* enable PDC controller */
-		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
-			port->read_status_mask);
-		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
+		atmel_uart_writel(port, ATMEL_US_IER,
+				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
+				  port->read_status_mask);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
 	} else {
-		UART_PUT_IER(port, ATMEL_US_RXRDY);
+		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
 	}
 }
 
@@ -490,15 +475,16 @@ static void atmel_start_rx(struct uart_port *port)
  */
 static void atmel_stop_rx(struct uart_port *port)
 {
-	UART_PUT_CR(port, ATMEL_US_RXDIS);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXDIS);
 
 	if (atmel_use_pdc_rx(port)) {
 		/* disable PDC receive */
-		UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
-		UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
-			port->read_status_mask);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS);
+		atmel_uart_writel(port, ATMEL_US_IDR,
+				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
+				  port->read_status_mask);
 	} else {
-		UART_PUT_IDR(port, ATMEL_US_RXRDY);
+		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXRDY);
 	}
 }
 
@@ -538,7 +524,7 @@ static void atmel_enable_ms(struct uart_port *port)
 	else
 		ier |= ATMEL_US_DCDIC;
 
-	UART_PUT_IER(port, ier);
+	atmel_uart_writel(port, ATMEL_US_IER, ier);
 }
 
 /*
@@ -577,7 +563,7 @@ static void atmel_disable_ms(struct uart_port *port)
 	else
 		idr |= ATMEL_US_DCDIC;
 
-	UART_PUT_IDR(port, idr);
+	atmel_uart_writel(port, ATMEL_US_IDR, idr);
 }
 
 /*
@@ -586,9 +572,11 @@ static void atmel_disable_ms(struct uart_port *port)
 static void atmel_break_ctl(struct uart_port *port, int break_state)
 {
 	if (break_state != 0)
-		UART_PUT_CR(port, ATMEL_US_STTBRK);	/* start break */
+		/* start break */
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTBRK);
 	else
-		UART_PUT_CR(port, ATMEL_US_STPBRK);	/* stop break */
+		/* stop break */
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STPBRK);
 }
 
 /*
@@ -622,7 +610,7 @@ atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
 static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
 {
 	/* clear error */
-	UART_PUT_CR(port, ATMEL_US_RSTSTA);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
 	if (status & ATMEL_US_RXBRK) {
 		/* ignore side-effect */
@@ -645,9 +633,9 @@ static void atmel_rx_chars(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned int status, ch;
 
-	status = UART_GET_CSR(port);
+	status = atmel_uart_readl(port, ATMEL_US_CSR);
 	while (status & ATMEL_US_RXRDY) {
-		ch = UART_GET_CHAR(port);
+		ch = atmel_uart_readl(port, ATMEL_US_RHR);
 
 		/*
 		 * note that the error handling code is
@@ -658,12 +646,13 @@ static void atmel_rx_chars(struct uart_port *port)
 			     || atmel_port->break_active)) {
 
 			/* clear error */
-			UART_PUT_CR(port, ATMEL_US_RSTSTA);
+			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
 			if (status & ATMEL_US_RXBRK
 			    && !atmel_port->break_active) {
 				atmel_port->break_active = 1;
-				UART_PUT_IER(port, ATMEL_US_RXBRK);
+				atmel_uart_writel(port, ATMEL_US_IER,
+						  ATMEL_US_RXBRK);
 			} else {
 				/*
 				 * This is either the end-of-break
@@ -672,14 +661,15 @@ static void atmel_rx_chars(struct uart_port *port)
 				 * being set. In both cases, the next
 				 * RXBRK will indicate start-of-break.
 				 */
-				UART_PUT_IDR(port, ATMEL_US_RXBRK);
+				atmel_uart_writel(port, ATMEL_US_IDR,
+						  ATMEL_US_RXBRK);
 				status &= ~ATMEL_US_RXBRK;
 				atmel_port->break_active = 0;
 			}
 		}
 
 		atmel_buffer_rx_char(port, status, ch);
-		status = UART_GET_CSR(port);
+		status = atmel_uart_readl(port, ATMEL_US_CSR);
 	}
 
 	tasklet_schedule(&atmel_port->tasklet);
@@ -694,16 +684,18 @@ static void atmel_tx_chars(struct uart_port *port)
 	struct circ_buf *xmit = &port->state->xmit;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
-		UART_PUT_CHAR(port, port->x_char);
+	if (port->x_char &&
+	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
+		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
 		port->icount.tx++;
 		port->x_char = 0;
 	}
 	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
 		return;
 
-	while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
-		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+	while (atmel_uart_readl(port, ATMEL_US_CSR) &
+	       atmel_port->tx_done_mask) {
+		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		port->icount.tx++;
 		if (uart_circ_empty(xmit))
@@ -715,7 +707,8 @@ static void atmel_tx_chars(struct uart_port *port)
 
 	if (!uart_circ_empty(xmit))
 		/* Enable interrupts */
-		UART_PUT_IER(port, atmel_port->tx_done_mask);
+		atmel_uart_writel(port, ATMEL_US_IER,
+				  atmel_port->tx_done_mask);
 }
 
 static void atmel_complete_tx_dma(void *arg)
@@ -935,14 +928,14 @@ static void atmel_rx_from_dma(struct uart_port *port)
 
 
 	/* Reset the UART timeout early so that we don't miss one */
-	UART_PUT_CR(port, ATMEL_US_STTTO);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 	dmastat = dmaengine_tx_status(chan,
 				atmel_port->cookie_rx,
 				&state);
 	/* Restart a new tasklet if DMA status is error */
 	if (dmastat == DMA_ERROR) {
 		dev_dbg(port->dev, "Get residue error, restart tasklet\n");
-		UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
 		tasklet_schedule(&atmel_port->tasklet);
 		return;
 	}
@@ -1008,7 +1001,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
 	tty_flip_buffer_push(tport);
 	spin_lock(&port->lock);
 
-	UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+	atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
 }
 
 static int atmel_prepare_rx_dma(struct uart_port *port)
@@ -1118,8 +1111,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 		 * the moment.
 		 */
 		if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
-			UART_PUT_IDR(port, (ATMEL_US_ENDRX
-						| ATMEL_US_TIMEOUT));
+			atmel_uart_writel(port, ATMEL_US_IDR,
+					  (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
 			tasklet_schedule(&atmel_port->tasklet);
 		}
 
@@ -1130,7 +1123,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 
 	if (atmel_use_dma_rx(port)) {
 		if (pending & ATMEL_US_TIMEOUT) {
-			UART_PUT_IDR(port, ATMEL_US_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_IDR,
+					  ATMEL_US_TIMEOUT);
 			tasklet_schedule(&atmel_port->tasklet);
 		}
 	}
@@ -1143,8 +1137,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 		 * End of break detected. If it came along with a
 		 * character, atmel_rx_chars will handle it.
 		 */
-		UART_PUT_CR(port, ATMEL_US_RSTSTA);
-		UART_PUT_IDR(port, ATMEL_US_RXBRK);
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
+		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXBRK);
 		atmel_port->break_active = 0;
 	}
 }
@@ -1159,7 +1153,8 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
 
 	if (pending & atmel_port->tx_done_mask) {
 		/* Either PDC or interrupt transmission */
-		UART_PUT_IDR(port, atmel_port->tx_done_mask);
+		atmel_uart_writel(port, ATMEL_US_IDR,
+				  atmel_port->tx_done_mask);
 		tasklet_schedule(&atmel_port->tasklet);
 	}
 }
@@ -1197,7 +1192,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 
 	do {
 		status = atmel_get_lines_status(port);
-		mask = UART_GET_IMR(port);
+		mask = atmel_uart_readl(port, ATMEL_US_IMR);
 		pending = status & mask;
 		if (!gpio_handled) {
 			/*
@@ -1223,7 +1218,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 		if (atmel_port->suspended) {
 			atmel_port->pending |= pending;
 			atmel_port->pending_status = status;
-			UART_PUT_IDR(port, mask);
+			atmel_uart_writel(port, ATMEL_US_IDR, mask);
 			pm_system_wakeup();
 			break;
 		}
@@ -1260,7 +1255,7 @@ static void atmel_tx_pdc(struct uart_port *port)
 	int count;
 
 	/* nothing left to transmit? */
-	if (UART_GET_TCR(port))
+	if (atmel_uart_readl(port, ATMEL_PDC_TCR))
 		return;
 
 	xmit->tail += pdc->ofs;
@@ -1272,7 +1267,7 @@ static void atmel_tx_pdc(struct uart_port *port)
 	/* more to transmit - setup next transfer */
 
 	/* disable PDC transmit */
-	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 
 	if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
 		dma_sync_single_for_device(port->dev,
@@ -1283,12 +1278,14 @@ static void atmel_tx_pdc(struct uart_port *port)
 		count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
 		pdc->ofs = count;
 
-		UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
-		UART_PUT_TCR(port, count);
+		atmel_uart_writel(port, ATMEL_PDC_TPR,
+				  pdc->dma_addr + xmit->tail);
+		atmel_uart_writel(port, ATMEL_PDC_TCR, count);
 		/* re-enable PDC transmit */
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 		/* Enable interrupts */
-		UART_PUT_IER(port, atmel_port->tx_done_mask);
+		atmel_uart_writel(port, ATMEL_US_IER,
+				  atmel_port->tx_done_mask);
 	} else {
 		if ((port->rs485.flags & SER_RS485_ENABLED) &&
 		    !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
@@ -1414,10 +1411,10 @@ static void atmel_rx_from_pdc(struct uart_port *port)
 
 	do {
 		/* Reset the UART timeout early so that we don't miss one */
-		UART_PUT_CR(port, ATMEL_US_STTTO);
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
 		pdc = &atmel_port->pdc_rx[rx_idx];
-		head = UART_GET_RPR(port) - pdc->dma_addr;
+		head = atmel_uart_readl(port, ATMEL_PDC_RPR) - pdc->dma_addr;
 		tail = pdc->ofs;
 
 		/* If the PDC has switched buffers, RPR won't contain
@@ -1460,8 +1457,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
 		 */
 		if (head >= pdc->dma_size) {
 			pdc->ofs = 0;
-			UART_PUT_RNPR(port, pdc->dma_addr);
-			UART_PUT_RNCR(port, pdc->dma_size);
+			atmel_uart_writel(port, ATMEL_PDC_RNPR, pdc->dma_addr);
+			atmel_uart_writel(port, ATMEL_PDC_RNCR, pdc->dma_size);
 
 			rx_idx = !rx_idx;
 			atmel_port->pdc_rx_idx = rx_idx;
@@ -1476,7 +1473,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
 	tty_flip_buffer_push(tport);
 	spin_lock(&port->lock);
 
-	UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+	atmel_uart_writel(port, ATMEL_US_IER,
+			  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
 }
 
 static int atmel_prepare_rx_pdc(struct uart_port *port)
@@ -1509,11 +1507,12 @@ static int atmel_prepare_rx_pdc(struct uart_port *port)
 
 	atmel_port->pdc_rx_idx = 0;
 
-	UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
-	UART_PUT_RCR(port, PDC_BUFFER_SIZE);
+	atmel_uart_writel(port, ATMEL_PDC_RPR, atmel_port->pdc_rx[0].dma_addr);
+	atmel_uart_writel(port, ATMEL_PDC_RCR, PDC_BUFFER_SIZE);
 
-	UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
-	UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
+	atmel_uart_writel(port, ATMEL_PDC_RNPR,
+			  atmel_port->pdc_rx[1].dma_addr);
+	atmel_uart_writel(port, ATMEL_PDC_RNCR, PDC_BUFFER_SIZE);
 
 	return 0;
 }
@@ -1667,7 +1666,7 @@ static void atmel_set_ops(struct uart_port *port)
 static void atmel_get_ip_name(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-	int name = UART_GET_IP_NAME(port);
+	int name = atmel_uart_readl(port, ATMEL_US_NAME);
 	u32 version;
 	int usart, uart;
 	/* usart and uart ascii */
@@ -1684,7 +1683,7 @@ static void atmel_get_ip_name(struct uart_port *port)
 		atmel_port->is_usart = false;
 	} else {
 		/* fallback for older SoCs: use version field */
-		version = UART_GET_IP_VERSION(port);
+		version = atmel_uart_readl(port, ATMEL_US_VERSION);
 		switch (version) {
 		case 0x302:
 		case 0x10213:
@@ -1756,7 +1755,7 @@ static int atmel_startup(struct uart_port *port)
 	 * request_irq() is called we could get stuck trying to
 	 * handle an unexpected interrupt
 	 */
-	UART_PUT_IDR(port, -1);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
 	atmel_port->ms_irq_enabled = false;
 
 	/*
@@ -1804,9 +1803,9 @@ static int atmel_startup(struct uart_port *port)
 	/*
 	 * Finally, enable the serial port
 	 */
-	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
 	/* enable xmit & rcvr */
-	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
 	setup_timer(&atmel_port->uart_timer,
 			atmel_uart_timer_callback,
@@ -1819,13 +1818,14 @@ static int atmel_startup(struct uart_port *port)
 					jiffies + uart_poll_timeout(port));
 		/* set USART timeout */
 		} else {
-			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
-			UART_PUT_CR(port, ATMEL_US_STTTO);
+			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
-			UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_IER,
+					  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
 		}
 		/* enable PDC controller */
-		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
 	} else if (atmel_use_dma_rx(port)) {
 		/* set UART timeout */
 		if (!atmel_port->is_usart) {
@@ -1833,14 +1833,15 @@ static int atmel_startup(struct uart_port *port)
 					jiffies + uart_poll_timeout(port));
 		/* set USART timeout */
 		} else {
-			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
-			UART_PUT_CR(port, ATMEL_US_STTTO);
+			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
-			UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_IER,
+					  ATMEL_US_TIMEOUT);
 		}
 	} else {
 		/* enable receive only */
-		UART_PUT_IER(port, ATMEL_US_RXRDY);
+		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
 	}
 
 	return 0;
@@ -1860,7 +1861,7 @@ static void atmel_flush_buffer(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
 	if (atmel_use_pdc_tx(port)) {
-		UART_PUT_TCR(port, 0);
+		atmel_uart_writel(port, ATMEL_PDC_TCR, 0);
 		atmel_port->pdc_tx.ofs = 0;
 	}
 }
@@ -1892,8 +1893,8 @@ static void atmel_shutdown(struct uart_port *port)
 	atmel_stop_rx(port);
 	atmel_stop_tx(port);
 
-	UART_PUT_CR(port, ATMEL_US_RSTSTA);
-	UART_PUT_IDR(port, -1);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
 
 	/*
@@ -1938,12 +1939,12 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
 		clk_prepare_enable(atmel_port->clk);
 
 		/* re-enable interrupts if we disabled some on suspend */
-		UART_PUT_IER(port, atmel_port->backup_imr);
+		atmel_uart_writel(port, ATMEL_US_IER, atmel_port->backup_imr);
 		break;
 	case 3:
 		/* Back up the interrupt mask and disable all interrupts */
-		atmel_port->backup_imr = UART_GET_IMR(port);
-		UART_PUT_IDR(port, -1);
+		atmel_port->backup_imr = atmel_uart_readl(port, ATMEL_US_IMR);
+		atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
 		/*
 		 * Disable the peripheral clock for this serial port.
@@ -1966,7 +1967,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	unsigned int old_mode, mode, imr, quot, baud;
 
 	/* save the current mode register */
-	mode = old_mode = UART_GET_MR(port);
+	mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR);
 
 	/* reset the mode, clock divisor, parity, stop bits and data size */
 	mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP |
@@ -2025,7 +2026,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	if (atmel_use_pdc_rx(port))
 		/* need to enable error interrupts */
-		UART_PUT_IER(port, port->read_status_mask);
+		atmel_uart_writel(port, ATMEL_US_IER, port->read_status_mask);
 
 	/*
 	 * Characters to ignore
@@ -2052,15 +2053,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	 * transmitter is empty if requested by the caller, so there's
 	 * no need to wait for it here.
 	 */
-	imr = UART_GET_IMR(port);
-	UART_PUT_IDR(port, -1);
+	imr = atmel_uart_readl(port, ATMEL_US_IMR);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
 	/* disable receiver and transmitter */
-	UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
 
 	/* mode */
 	if (port->rs485.flags & SER_RS485_ENABLED) {
-		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+		atmel_uart_writel(port, ATMEL_US_TTGR,
+				  port->rs485.delay_rts_after_send);
 		mode |= ATMEL_US_USMODE_RS485;
 	} else if (termios->c_cflag & CRTSCTS) {
 		/* RS232 with hardware handshake (RTS/CTS) */
@@ -2071,7 +2073,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	}
 
 	/* set the mode, clock divisor, parity, stop bits and data size */
-	UART_PUT_MR(port, mode);
+	atmel_uart_writel(port, ATMEL_US_MR, mode);
 
 	/*
 	 * when switching the mode, set the RTS line state according to the
@@ -2088,16 +2090,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 			rts_state = ATMEL_US_RTSEN;
 		}
 
-		UART_PUT_CR(port, rts_state);
+		atmel_uart_writel(port, ATMEL_US_CR, rts_state);
 	}
 
 	/* set the baud rate */
-	UART_PUT_BRGR(port, quot);
-	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
-	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_BRGR, quot);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
 	/* restore interrupts */
-	UART_PUT_IER(port, imr);
+	atmel_uart_writel(port, ATMEL_US_IER, imr);
 
 	/* CTS flow-control and modem-status interrupts */
 	if (UART_ENABLE_MS(port, termios->c_cflag))
@@ -2208,18 +2210,18 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
 #ifdef CONFIG_CONSOLE_POLL
 static int atmel_poll_get_char(struct uart_port *port)
 {
-	while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
+	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
 		cpu_relax();
 
-	return UART_GET_CHAR(port);
+	return atmel_uart_readl(port, ATMEL_US_RHR);
 }
 
 static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
 {
-	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
 
-	UART_PUT_CHAR(port, ch);
+	atmel_uart_writel(port, ATMEL_US_THR, ch);
 }
 #endif
 
@@ -2324,9 +2326,9 @@ struct platform_device *atmel_default_console_device;	/* the serial console devi
 #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
 static void atmel_console_putchar(struct uart_port *port, int ch)
 {
-	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
-	UART_PUT_CHAR(port, ch);
+	atmel_uart_writel(port, ATMEL_US_THR, ch);
 }
 
 /*
@@ -2342,12 +2344,13 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
 	/*
 	 * First, save IMR and then disable interrupts
 	 */
-	imr = UART_GET_IMR(port);
-	UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
+	imr = atmel_uart_readl(port, ATMEL_US_IMR);
+	atmel_uart_writel(port, ATMEL_US_IDR,
+			  ATMEL_US_RXRDY | atmel_port->tx_done_mask);
 
 	/* Store PDC transmit status and disable it */
-	pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
-	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+	pdc_tx = atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN;
+	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 
 	uart_console_write(port, s, count, atmel_console_putchar);
 
@@ -2356,15 +2359,15 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
 	 * and restore IMR
 	 */
 	do {
-		status = UART_GET_CSR(port);
+		status = atmel_uart_readl(port, ATMEL_US_CSR);
 	} while (!(status & ATMEL_US_TXRDY));
 
 	/* Restore PDC transmit status */
 	if (pdc_tx)
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 
 	/* set interrupts back the way they were */
-	UART_PUT_IER(port, imr);
+	atmel_uart_writel(port, ATMEL_US_IER, imr);
 }
 
 /*
@@ -2380,17 +2383,17 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
 	 * If the baud rate generator isn't running, the port wasn't
 	 * initialized by the boot loader.
 	 */
-	quot = UART_GET_BRGR(port) & ATMEL_US_CD;
+	quot = atmel_uart_readl(port, ATMEL_US_BRGR) & ATMEL_US_CD;
 	if (!quot)
 		return;
 
-	mr = UART_GET_MR(port) & ATMEL_US_CHRL;
+	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_CHRL;
 	if (mr == ATMEL_US_CHRL_8)
 		*bits = 8;
 	else
 		*bits = 7;
 
-	mr = UART_GET_MR(port) & ATMEL_US_PAR;
+	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_PAR;
 	if (mr == ATMEL_US_PAR_EVEN)
 		*parity = 'e';
 	else if (mr == ATMEL_US_PAR_ODD)
@@ -2423,9 +2426,9 @@ static int __init atmel_console_setup(struct console *co, char *options)
 	if (ret)
 		return ret;
 
-	UART_PUT_IDR(port, -1);
-	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
-	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -2532,7 +2535,8 @@ static int atmel_serial_suspend(struct platform_device *pdev,
 
 	if (atmel_is_console_port(port) && console_suspend_enabled) {
 		/* Drain the TX shifter */
-		while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
+		while (!(atmel_uart_readl(port, ATMEL_US_CSR) &
+			 ATMEL_US_TXEMPTY))
 			cpu_relax();
 	}
 
@@ -2684,8 +2688,9 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	clk_prepare_enable(port->clk);
 
 	if (rs485_enabled) {
-		UART_PUT_MR(&port->uart, ATMEL_US_USMODE_NORMAL);
-		UART_PUT_CR(&port->uart, ATMEL_US_RTSEN);
+		atmel_uart_writel(&port->uart, ATMEL_US_MR,
+				  ATMEL_US_USMODE_NORMAL);
+		atmel_uart_writel(&port->uart, ATMEL_US_CR, ATMEL_US_RTSEN);
 	}
 
 	/*
-- 
1.8.2.2

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

* [PATCH v4 3/5] tty/serial: at91: remove bunch of macros to access UART registers
@ 2015-07-02 13:18   ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: linux-arm-kernel

This patch replaces the UART_PUT_*, resp. UART_GET_*, macros by
atmel_uart_writel(), resp. atmel_uart_readl(), inline function calls.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
---
 drivers/tty/serial/atmel_serial.c | 313 +++++++++++++++++++-------------------
 1 file changed, 159 insertions(+), 154 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 2a8f528153e7..e7c337de31d1 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -88,37 +88,6 @@ static void atmel_stop_rx(struct uart_port *port);
 
 #define ATMEL_ISR_PASS_LIMIT	256
 
-/* UART registers. CR is write-only, hence no GET macro */
-#define UART_PUT_CR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_CR)
-#define UART_GET_MR(port)	__raw_readl((port)->membase + ATMEL_US_MR)
-#define UART_PUT_MR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_MR)
-#define UART_PUT_IER(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IER)
-#define UART_PUT_IDR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IDR)
-#define UART_GET_IMR(port)	__raw_readl((port)->membase + ATMEL_US_IMR)
-#define UART_GET_CSR(port)	__raw_readl((port)->membase + ATMEL_US_CSR)
-#define UART_GET_CHAR(port)	__raw_readl((port)->membase + ATMEL_US_RHR)
-#define UART_PUT_CHAR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_THR)
-#define UART_GET_BRGR(port)	__raw_readl((port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_BRGR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
-#define UART_PUT_TTGR(port, v)	__raw_writel(v, (port)->membase + ATMEL_US_TTGR)
-#define UART_GET_IP_NAME(port)	__raw_readl((port)->membase + ATMEL_US_NAME)
-#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
-
- /* PDC registers */
-#define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
-#define UART_GET_PTSR(port)	__raw_readl((port)->membase + ATMEL_PDC_PTSR)
-
-#define UART_PUT_RPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
-#define UART_GET_RPR(port)	__raw_readl((port)->membase + ATMEL_PDC_RPR)
-#define UART_PUT_RCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
-#define UART_PUT_RNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
-#define UART_PUT_RNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
-
-#define UART_PUT_TPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
-#define UART_PUT_TCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
-#define UART_GET_TCR(port)	__raw_readl((port)->membase + ATMEL_PDC_TCR)
-
 struct atmel_dma_buffer {
 	unsigned char	*buf;
 	dma_addr_t	dma_addr;
@@ -212,6 +181,16 @@ to_atmel_uart_port(struct uart_port *uart)
 	return container_of(uart, struct atmel_uart_port, uart);
 }
 
+static inline u32 atmel_uart_readl(struct uart_port *port, u32 reg)
+{
+	return __raw_readl(port->membase + reg);
+}
+
+static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
+{
+	__raw_writel(value, port->membase + reg);
+}
+
 #ifdef CONFIG_SERIAL_ATMEL_PDC
 static bool atmel_use_pdc_rx(struct uart_port *port)
 {
@@ -257,7 +236,7 @@ static unsigned int atmel_get_lines_status(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned int status, ret = 0;
 
-	status = UART_GET_CSR(port);
+	status = atmel_uart_readl(port, ATMEL_US_CSR);
 
 	mctrl_gpio_get(atmel_port->gpios, &ret);
 
@@ -304,9 +283,9 @@ static int atmel_config_rs485(struct uart_port *port,
 	unsigned int mode;
 
 	/* Disable interrupts */
-	UART_PUT_IDR(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
-	mode = UART_GET_MR(port);
+	mode = atmel_uart_readl(port, ATMEL_US_MR);
 
 	/* Resetting serial mode to RS232 (0x0) */
 	mode &= ~ATMEL_US_USMODE;
@@ -316,7 +295,8 @@ static int atmel_config_rs485(struct uart_port *port,
 	if (rs485conf->flags & SER_RS485_ENABLED) {
 		dev_dbg(port->dev, "Setting UART to RS485\n");
 		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
-		UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
+		atmel_uart_writel(port, ATMEL_US_TTGR,
+				  rs485conf->delay_rts_after_send);
 		mode |= ATMEL_US_USMODE_RS485;
 	} else {
 		dev_dbg(port->dev, "Setting UART to RS232\n");
@@ -326,10 +306,10 @@ static int atmel_config_rs485(struct uart_port *port,
 		else
 			atmel_port->tx_done_mask = ATMEL_US_TXRDY;
 	}
-	UART_PUT_MR(port, mode);
+	atmel_uart_writel(port, ATMEL_US_MR, mode);
 
 	/* Enable interrupts */
-	UART_PUT_IER(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
 
 	return 0;
 }
@@ -339,7 +319,9 @@ static int atmel_config_rs485(struct uart_port *port,
  */
 static u_int atmel_tx_empty(struct uart_port *port)
 {
-	return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
+	return (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY) ?
+		TIOCSER_TEMT :
+		0;
 }
 
 /*
@@ -348,13 +330,14 @@ static u_int atmel_tx_empty(struct uart_port *port)
 static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 {
 	unsigned int control = 0;
-	unsigned int mode = UART_GET_MR(port);
+	unsigned int mode = atmel_uart_readl(port, ATMEL_US_MR);
 	unsigned int rts_paused, rts_ready;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
 	/* override mode to RS485 if needed, otherwise keep the current mode */
 	if (port->rs485.flags & SER_RS485_ENABLED) {
-		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+		atmel_uart_writel(port, ATMEL_US_TTGR,
+				  port->rs485.delay_rts_after_send);
 		mode &= ~ATMEL_US_USMODE;
 		mode |= ATMEL_US_USMODE_RS485;
 	}
@@ -384,7 +367,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 	else
 		control |= ATMEL_US_DTRDIS;
 
-	UART_PUT_CR(port, control);
+	atmel_uart_writel(port, ATMEL_US_CR, control);
 
 	mctrl_gpio_set(atmel_port->gpios, mctrl);
 
@@ -395,7 +378,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 	else
 		mode |= ATMEL_US_CHMODE_NORMAL;
 
-	UART_PUT_MR(port, mode);
+	atmel_uart_writel(port, ATMEL_US_MR, mode);
 }
 
 /*
@@ -406,7 +389,7 @@ static u_int atmel_get_mctrl(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned int ret = 0, status;
 
-	status = UART_GET_CSR(port);
+	status = atmel_uart_readl(port, ATMEL_US_CSR);
 
 	/*
 	 * The control signals are active low.
@@ -432,10 +415,10 @@ static void atmel_stop_tx(struct uart_port *port)
 
 	if (atmel_use_pdc_tx(port)) {
 		/* disable PDC transmit */
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 	}
 	/* Disable interrupts */
-	UART_PUT_IDR(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
 	if ((port->rs485.flags & SER_RS485_ENABLED) &&
 	    !(port->rs485.flags & SER_RS485_RX_DURING_TX))
@@ -450,7 +433,7 @@ static void atmel_start_tx(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
 	if (atmel_use_pdc_tx(port)) {
-		if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
+		if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
 			/* The transmitter is already running.  Yes, we
 			   really need this.*/
 			return;
@@ -460,10 +443,10 @@ static void atmel_start_tx(struct uart_port *port)
 			atmel_stop_rx(port);
 
 		/* re-enable PDC transmit */
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 	}
 	/* Enable interrupts */
-	UART_PUT_IER(port, atmel_port->tx_done_mask);
+	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
 }
 
 /*
@@ -471,17 +454,19 @@ static void atmel_start_tx(struct uart_port *port)
  */
 static void atmel_start_rx(struct uart_port *port)
 {
-	UART_PUT_CR(port, ATMEL_US_RSTSTA);  /* reset status and receiver */
+	/* reset status and receiver */
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
-	UART_PUT_CR(port, ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXEN);
 
 	if (atmel_use_pdc_rx(port)) {
 		/* enable PDC controller */
-		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
-			port->read_status_mask);
-		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
+		atmel_uart_writel(port, ATMEL_US_IER,
+				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
+				  port->read_status_mask);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
 	} else {
-		UART_PUT_IER(port, ATMEL_US_RXRDY);
+		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
 	}
 }
 
@@ -490,15 +475,16 @@ static void atmel_start_rx(struct uart_port *port)
  */
 static void atmel_stop_rx(struct uart_port *port)
 {
-	UART_PUT_CR(port, ATMEL_US_RXDIS);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXDIS);
 
 	if (atmel_use_pdc_rx(port)) {
 		/* disable PDC receive */
-		UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
-		UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
-			port->read_status_mask);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS);
+		atmel_uart_writel(port, ATMEL_US_IDR,
+				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
+				  port->read_status_mask);
 	} else {
-		UART_PUT_IDR(port, ATMEL_US_RXRDY);
+		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXRDY);
 	}
 }
 
@@ -538,7 +524,7 @@ static void atmel_enable_ms(struct uart_port *port)
 	else
 		ier |= ATMEL_US_DCDIC;
 
-	UART_PUT_IER(port, ier);
+	atmel_uart_writel(port, ATMEL_US_IER, ier);
 }
 
 /*
@@ -577,7 +563,7 @@ static void atmel_disable_ms(struct uart_port *port)
 	else
 		idr |= ATMEL_US_DCDIC;
 
-	UART_PUT_IDR(port, idr);
+	atmel_uart_writel(port, ATMEL_US_IDR, idr);
 }
 
 /*
@@ -586,9 +572,11 @@ static void atmel_disable_ms(struct uart_port *port)
 static void atmel_break_ctl(struct uart_port *port, int break_state)
 {
 	if (break_state != 0)
-		UART_PUT_CR(port, ATMEL_US_STTBRK);	/* start break */
+		/* start break */
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTBRK);
 	else
-		UART_PUT_CR(port, ATMEL_US_STPBRK);	/* stop break */
+		/* stop break */
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STPBRK);
 }
 
 /*
@@ -622,7 +610,7 @@ atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
 static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
 {
 	/* clear error */
-	UART_PUT_CR(port, ATMEL_US_RSTSTA);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
 	if (status & ATMEL_US_RXBRK) {
 		/* ignore side-effect */
@@ -645,9 +633,9 @@ static void atmel_rx_chars(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned int status, ch;
 
-	status = UART_GET_CSR(port);
+	status = atmel_uart_readl(port, ATMEL_US_CSR);
 	while (status & ATMEL_US_RXRDY) {
-		ch = UART_GET_CHAR(port);
+		ch = atmel_uart_readl(port, ATMEL_US_RHR);
 
 		/*
 		 * note that the error handling code is
@@ -658,12 +646,13 @@ static void atmel_rx_chars(struct uart_port *port)
 			     || atmel_port->break_active)) {
 
 			/* clear error */
-			UART_PUT_CR(port, ATMEL_US_RSTSTA);
+			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
 			if (status & ATMEL_US_RXBRK
 			    && !atmel_port->break_active) {
 				atmel_port->break_active = 1;
-				UART_PUT_IER(port, ATMEL_US_RXBRK);
+				atmel_uart_writel(port, ATMEL_US_IER,
+						  ATMEL_US_RXBRK);
 			} else {
 				/*
 				 * This is either the end-of-break
@@ -672,14 +661,15 @@ static void atmel_rx_chars(struct uart_port *port)
 				 * being set. In both cases, the next
 				 * RXBRK will indicate start-of-break.
 				 */
-				UART_PUT_IDR(port, ATMEL_US_RXBRK);
+				atmel_uart_writel(port, ATMEL_US_IDR,
+						  ATMEL_US_RXBRK);
 				status &= ~ATMEL_US_RXBRK;
 				atmel_port->break_active = 0;
 			}
 		}
 
 		atmel_buffer_rx_char(port, status, ch);
-		status = UART_GET_CSR(port);
+		status = atmel_uart_readl(port, ATMEL_US_CSR);
 	}
 
 	tasklet_schedule(&atmel_port->tasklet);
@@ -694,16 +684,18 @@ static void atmel_tx_chars(struct uart_port *port)
 	struct circ_buf *xmit = &port->state->xmit;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
-		UART_PUT_CHAR(port, port->x_char);
+	if (port->x_char &&
+	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
+		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
 		port->icount.tx++;
 		port->x_char = 0;
 	}
 	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
 		return;
 
-	while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
-		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+	while (atmel_uart_readl(port, ATMEL_US_CSR) &
+	       atmel_port->tx_done_mask) {
+		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		port->icount.tx++;
 		if (uart_circ_empty(xmit))
@@ -715,7 +707,8 @@ static void atmel_tx_chars(struct uart_port *port)
 
 	if (!uart_circ_empty(xmit))
 		/* Enable interrupts */
-		UART_PUT_IER(port, atmel_port->tx_done_mask);
+		atmel_uart_writel(port, ATMEL_US_IER,
+				  atmel_port->tx_done_mask);
 }
 
 static void atmel_complete_tx_dma(void *arg)
@@ -935,14 +928,14 @@ static void atmel_rx_from_dma(struct uart_port *port)
 
 
 	/* Reset the UART timeout early so that we don't miss one */
-	UART_PUT_CR(port, ATMEL_US_STTTO);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 	dmastat = dmaengine_tx_status(chan,
 				atmel_port->cookie_rx,
 				&state);
 	/* Restart a new tasklet if DMA status is error */
 	if (dmastat == DMA_ERROR) {
 		dev_dbg(port->dev, "Get residue error, restart tasklet\n");
-		UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
 		tasklet_schedule(&atmel_port->tasklet);
 		return;
 	}
@@ -1008,7 +1001,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
 	tty_flip_buffer_push(tport);
 	spin_lock(&port->lock);
 
-	UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+	atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
 }
 
 static int atmel_prepare_rx_dma(struct uart_port *port)
@@ -1118,8 +1111,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 		 * the moment.
 		 */
 		if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
-			UART_PUT_IDR(port, (ATMEL_US_ENDRX
-						| ATMEL_US_TIMEOUT));
+			atmel_uart_writel(port, ATMEL_US_IDR,
+					  (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
 			tasklet_schedule(&atmel_port->tasklet);
 		}
 
@@ -1130,7 +1123,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 
 	if (atmel_use_dma_rx(port)) {
 		if (pending & ATMEL_US_TIMEOUT) {
-			UART_PUT_IDR(port, ATMEL_US_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_IDR,
+					  ATMEL_US_TIMEOUT);
 			tasklet_schedule(&atmel_port->tasklet);
 		}
 	}
@@ -1143,8 +1137,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 		 * End of break detected. If it came along with a
 		 * character, atmel_rx_chars will handle it.
 		 */
-		UART_PUT_CR(port, ATMEL_US_RSTSTA);
-		UART_PUT_IDR(port, ATMEL_US_RXBRK);
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
+		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXBRK);
 		atmel_port->break_active = 0;
 	}
 }
@@ -1159,7 +1153,8 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
 
 	if (pending & atmel_port->tx_done_mask) {
 		/* Either PDC or interrupt transmission */
-		UART_PUT_IDR(port, atmel_port->tx_done_mask);
+		atmel_uart_writel(port, ATMEL_US_IDR,
+				  atmel_port->tx_done_mask);
 		tasklet_schedule(&atmel_port->tasklet);
 	}
 }
@@ -1197,7 +1192,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 
 	do {
 		status = atmel_get_lines_status(port);
-		mask = UART_GET_IMR(port);
+		mask = atmel_uart_readl(port, ATMEL_US_IMR);
 		pending = status & mask;
 		if (!gpio_handled) {
 			/*
@@ -1223,7 +1218,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 		if (atmel_port->suspended) {
 			atmel_port->pending |= pending;
 			atmel_port->pending_status = status;
-			UART_PUT_IDR(port, mask);
+			atmel_uart_writel(port, ATMEL_US_IDR, mask);
 			pm_system_wakeup();
 			break;
 		}
@@ -1260,7 +1255,7 @@ static void atmel_tx_pdc(struct uart_port *port)
 	int count;
 
 	/* nothing left to transmit? */
-	if (UART_GET_TCR(port))
+	if (atmel_uart_readl(port, ATMEL_PDC_TCR))
 		return;
 
 	xmit->tail += pdc->ofs;
@@ -1272,7 +1267,7 @@ static void atmel_tx_pdc(struct uart_port *port)
 	/* more to transmit - setup next transfer */
 
 	/* disable PDC transmit */
-	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 
 	if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
 		dma_sync_single_for_device(port->dev,
@@ -1283,12 +1278,14 @@ static void atmel_tx_pdc(struct uart_port *port)
 		count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
 		pdc->ofs = count;
 
-		UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
-		UART_PUT_TCR(port, count);
+		atmel_uart_writel(port, ATMEL_PDC_TPR,
+				  pdc->dma_addr + xmit->tail);
+		atmel_uart_writel(port, ATMEL_PDC_TCR, count);
 		/* re-enable PDC transmit */
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 		/* Enable interrupts */
-		UART_PUT_IER(port, atmel_port->tx_done_mask);
+		atmel_uart_writel(port, ATMEL_US_IER,
+				  atmel_port->tx_done_mask);
 	} else {
 		if ((port->rs485.flags & SER_RS485_ENABLED) &&
 		    !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
@@ -1414,10 +1411,10 @@ static void atmel_rx_from_pdc(struct uart_port *port)
 
 	do {
 		/* Reset the UART timeout early so that we don't miss one */
-		UART_PUT_CR(port, ATMEL_US_STTTO);
+		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
 		pdc = &atmel_port->pdc_rx[rx_idx];
-		head = UART_GET_RPR(port) - pdc->dma_addr;
+		head = atmel_uart_readl(port, ATMEL_PDC_RPR) - pdc->dma_addr;
 		tail = pdc->ofs;
 
 		/* If the PDC has switched buffers, RPR won't contain
@@ -1460,8 +1457,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
 		 */
 		if (head >= pdc->dma_size) {
 			pdc->ofs = 0;
-			UART_PUT_RNPR(port, pdc->dma_addr);
-			UART_PUT_RNCR(port, pdc->dma_size);
+			atmel_uart_writel(port, ATMEL_PDC_RNPR, pdc->dma_addr);
+			atmel_uart_writel(port, ATMEL_PDC_RNCR, pdc->dma_size);
 
 			rx_idx = !rx_idx;
 			atmel_port->pdc_rx_idx = rx_idx;
@@ -1476,7 +1473,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
 	tty_flip_buffer_push(tport);
 	spin_lock(&port->lock);
 
-	UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+	atmel_uart_writel(port, ATMEL_US_IER,
+			  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
 }
 
 static int atmel_prepare_rx_pdc(struct uart_port *port)
@@ -1509,11 +1507,12 @@ static int atmel_prepare_rx_pdc(struct uart_port *port)
 
 	atmel_port->pdc_rx_idx = 0;
 
-	UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
-	UART_PUT_RCR(port, PDC_BUFFER_SIZE);
+	atmel_uart_writel(port, ATMEL_PDC_RPR, atmel_port->pdc_rx[0].dma_addr);
+	atmel_uart_writel(port, ATMEL_PDC_RCR, PDC_BUFFER_SIZE);
 
-	UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
-	UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
+	atmel_uart_writel(port, ATMEL_PDC_RNPR,
+			  atmel_port->pdc_rx[1].dma_addr);
+	atmel_uart_writel(port, ATMEL_PDC_RNCR, PDC_BUFFER_SIZE);
 
 	return 0;
 }
@@ -1667,7 +1666,7 @@ static void atmel_set_ops(struct uart_port *port)
 static void atmel_get_ip_name(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-	int name = UART_GET_IP_NAME(port);
+	int name = atmel_uart_readl(port, ATMEL_US_NAME);
 	u32 version;
 	int usart, uart;
 	/* usart and uart ascii */
@@ -1684,7 +1683,7 @@ static void atmel_get_ip_name(struct uart_port *port)
 		atmel_port->is_usart = false;
 	} else {
 		/* fallback for older SoCs: use version field */
-		version = UART_GET_IP_VERSION(port);
+		version = atmel_uart_readl(port, ATMEL_US_VERSION);
 		switch (version) {
 		case 0x302:
 		case 0x10213:
@@ -1756,7 +1755,7 @@ static int atmel_startup(struct uart_port *port)
 	 * request_irq() is called we could get stuck trying to
 	 * handle an unexpected interrupt
 	 */
-	UART_PUT_IDR(port, -1);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
 	atmel_port->ms_irq_enabled = false;
 
 	/*
@@ -1804,9 +1803,9 @@ static int atmel_startup(struct uart_port *port)
 	/*
 	 * Finally, enable the serial port
 	 */
-	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
 	/* enable xmit & rcvr */
-	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
 	setup_timer(&atmel_port->uart_timer,
 			atmel_uart_timer_callback,
@@ -1819,13 +1818,14 @@ static int atmel_startup(struct uart_port *port)
 					jiffies + uart_poll_timeout(port));
 		/* set USART timeout */
 		} else {
-			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
-			UART_PUT_CR(port, ATMEL_US_STTTO);
+			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
-			UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_IER,
+					  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
 		}
 		/* enable PDC controller */
-		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
 	} else if (atmel_use_dma_rx(port)) {
 		/* set UART timeout */
 		if (!atmel_port->is_usart) {
@@ -1833,14 +1833,15 @@ static int atmel_startup(struct uart_port *port)
 					jiffies + uart_poll_timeout(port));
 		/* set USART timeout */
 		} else {
-			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
-			UART_PUT_CR(port, ATMEL_US_STTTO);
+			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
-			UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+			atmel_uart_writel(port, ATMEL_US_IER,
+					  ATMEL_US_TIMEOUT);
 		}
 	} else {
 		/* enable receive only */
-		UART_PUT_IER(port, ATMEL_US_RXRDY);
+		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
 	}
 
 	return 0;
@@ -1860,7 +1861,7 @@ static void atmel_flush_buffer(struct uart_port *port)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
 	if (atmel_use_pdc_tx(port)) {
-		UART_PUT_TCR(port, 0);
+		atmel_uart_writel(port, ATMEL_PDC_TCR, 0);
 		atmel_port->pdc_tx.ofs = 0;
 	}
 }
@@ -1892,8 +1893,8 @@ static void atmel_shutdown(struct uart_port *port)
 	atmel_stop_rx(port);
 	atmel_stop_tx(port);
 
-	UART_PUT_CR(port, ATMEL_US_RSTSTA);
-	UART_PUT_IDR(port, -1);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
 
 	/*
@@ -1938,12 +1939,12 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
 		clk_prepare_enable(atmel_port->clk);
 
 		/* re-enable interrupts if we disabled some on suspend */
-		UART_PUT_IER(port, atmel_port->backup_imr);
+		atmel_uart_writel(port, ATMEL_US_IER, atmel_port->backup_imr);
 		break;
 	case 3:
 		/* Back up the interrupt mask and disable all interrupts */
-		atmel_port->backup_imr = UART_GET_IMR(port);
-		UART_PUT_IDR(port, -1);
+		atmel_port->backup_imr = atmel_uart_readl(port, ATMEL_US_IMR);
+		atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
 		/*
 		 * Disable the peripheral clock for this serial port.
@@ -1966,7 +1967,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	unsigned int old_mode, mode, imr, quot, baud;
 
 	/* save the current mode register */
-	mode = old_mode = UART_GET_MR(port);
+	mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR);
 
 	/* reset the mode, clock divisor, parity, stop bits and data size */
 	mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP |
@@ -2025,7 +2026,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	if (atmel_use_pdc_rx(port))
 		/* need to enable error interrupts */
-		UART_PUT_IER(port, port->read_status_mask);
+		atmel_uart_writel(port, ATMEL_US_IER, port->read_status_mask);
 
 	/*
 	 * Characters to ignore
@@ -2052,15 +2053,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	 * transmitter is empty if requested by the caller, so there's
 	 * no need to wait for it here.
 	 */
-	imr = UART_GET_IMR(port);
-	UART_PUT_IDR(port, -1);
+	imr = atmel_uart_readl(port, ATMEL_US_IMR);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
 	/* disable receiver and transmitter */
-	UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
 
 	/* mode */
 	if (port->rs485.flags & SER_RS485_ENABLED) {
-		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+		atmel_uart_writel(port, ATMEL_US_TTGR,
+				  port->rs485.delay_rts_after_send);
 		mode |= ATMEL_US_USMODE_RS485;
 	} else if (termios->c_cflag & CRTSCTS) {
 		/* RS232 with hardware handshake (RTS/CTS) */
@@ -2071,7 +2073,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	}
 
 	/* set the mode, clock divisor, parity, stop bits and data size */
-	UART_PUT_MR(port, mode);
+	atmel_uart_writel(port, ATMEL_US_MR, mode);
 
 	/*
 	 * when switching the mode, set the RTS line state according to the
@@ -2088,16 +2090,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 			rts_state = ATMEL_US_RTSEN;
 		}
 
-		UART_PUT_CR(port, rts_state);
+		atmel_uart_writel(port, ATMEL_US_CR, rts_state);
 	}
 
 	/* set the baud rate */
-	UART_PUT_BRGR(port, quot);
-	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
-	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_BRGR, quot);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
 	/* restore interrupts */
-	UART_PUT_IER(port, imr);
+	atmel_uart_writel(port, ATMEL_US_IER, imr);
 
 	/* CTS flow-control and modem-status interrupts */
 	if (UART_ENABLE_MS(port, termios->c_cflag))
@@ -2208,18 +2210,18 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
 #ifdef CONFIG_CONSOLE_POLL
 static int atmel_poll_get_char(struct uart_port *port)
 {
-	while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
+	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
 		cpu_relax();
 
-	return UART_GET_CHAR(port);
+	return atmel_uart_readl(port, ATMEL_US_RHR);
 }
 
 static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
 {
-	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
 
-	UART_PUT_CHAR(port, ch);
+	atmel_uart_writel(port, ATMEL_US_THR, ch);
 }
 #endif
 
@@ -2324,9 +2326,9 @@ struct platform_device *atmel_default_console_device;	/* the serial console devi
 #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
 static void atmel_console_putchar(struct uart_port *port, int ch)
 {
-	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
-	UART_PUT_CHAR(port, ch);
+	atmel_uart_writel(port, ATMEL_US_THR, ch);
 }
 
 /*
@@ -2342,12 +2344,13 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
 	/*
 	 * First, save IMR and then disable interrupts
 	 */
-	imr = UART_GET_IMR(port);
-	UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
+	imr = atmel_uart_readl(port, ATMEL_US_IMR);
+	atmel_uart_writel(port, ATMEL_US_IDR,
+			  ATMEL_US_RXRDY | atmel_port->tx_done_mask);
 
 	/* Store PDC transmit status and disable it */
-	pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
-	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+	pdc_tx = atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN;
+	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 
 	uart_console_write(port, s, count, atmel_console_putchar);
 
@@ -2356,15 +2359,15 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
 	 * and restore IMR
 	 */
 	do {
-		status = UART_GET_CSR(port);
+		status = atmel_uart_readl(port, ATMEL_US_CSR);
 	} while (!(status & ATMEL_US_TXRDY));
 
 	/* Restore PDC transmit status */
 	if (pdc_tx)
-		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 
 	/* set interrupts back the way they were */
-	UART_PUT_IER(port, imr);
+	atmel_uart_writel(port, ATMEL_US_IER, imr);
 }
 
 /*
@@ -2380,17 +2383,17 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
 	 * If the baud rate generator isn't running, the port wasn't
 	 * initialized by the boot loader.
 	 */
-	quot = UART_GET_BRGR(port) & ATMEL_US_CD;
+	quot = atmel_uart_readl(port, ATMEL_US_BRGR) & ATMEL_US_CD;
 	if (!quot)
 		return;
 
-	mr = UART_GET_MR(port) & ATMEL_US_CHRL;
+	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_CHRL;
 	if (mr == ATMEL_US_CHRL_8)
 		*bits = 8;
 	else
 		*bits = 7;
 
-	mr = UART_GET_MR(port) & ATMEL_US_PAR;
+	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_PAR;
 	if (mr == ATMEL_US_PAR_EVEN)
 		*parity = 'e';
 	else if (mr == ATMEL_US_PAR_ODD)
@@ -2423,9 +2426,9 @@ static int __init atmel_console_setup(struct console *co, char *options)
 	if (ret)
 		return ret;
 
-	UART_PUT_IDR(port, -1);
-	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
-	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_uart_writel(port, ATMEL_US_IDR, -1);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -2532,7 +2535,8 @@ static int atmel_serial_suspend(struct platform_device *pdev,
 
 	if (atmel_is_console_port(port) && console_suspend_enabled) {
 		/* Drain the TX shifter */
-		while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
+		while (!(atmel_uart_readl(port, ATMEL_US_CSR) &
+			 ATMEL_US_TXEMPTY))
 			cpu_relax();
 	}
 
@@ -2684,8 +2688,9 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	clk_prepare_enable(port->clk);
 
 	if (rs485_enabled) {
-		UART_PUT_MR(&port->uart, ATMEL_US_USMODE_NORMAL);
-		UART_PUT_CR(&port->uart, ATMEL_US_RTSEN);
+		atmel_uart_writel(&port->uart, ATMEL_US_MR,
+				  ATMEL_US_USMODE_NORMAL);
+		atmel_uart_writel(&port->uart, ATMEL_US_CR, ATMEL_US_RTSEN);
 	}
 
 	/*
-- 
1.8.2.2

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

* [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-02 13:18   ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt,
	Cyrille Pitchen

Depending on the hardware, TX and RX FIFOs may be available. The RX
FIFO can avoid receive overruns, especially when DMA transfers are
not used to read data from the Receive Holding Register. For heavy
system load, The CPU is likely not be able to fetch data fast enough
from the RHR.

In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
line when the Hardware Handshaking mode is enabled. Two thresholds
are to be set for that purpose:
- When the number of data in the RX FIFO crosses and becomes lower
  than or equal to the low threshold, the RTS line is set to low
  level: the remote peer is requested to send data.
- When the number of data in the RX FIFO crosses and becomes greater
  than or equal to the high threshold, the RTS line is set to high
  level: the remote peer should stop sending new data.
- low threshold <= high threshold
Once these two thresholds are set properly, this new feature is
enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.

FIFOs also introduce a new multiple data mode: the USART works either
in multiple data mode or in single data (legacy) mode.

If MODE9 bit is set into the Mode Register or if USMODE is set to
either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
data mode. Otherwise, they operate in multiple data mode.

In this new multiple data mode, accesses to the Receive Holding
Register or Transmit Holding Register slightly change.

Since this driver implements neither the 9bit data feature (MODE9 bit
set into the Mode Register) nor LIN modes, the USART works in
multiple data mode whenever FIFOs are available and enabled. We also
assume that data are 8bit wide.

In single data mode, 32bit access CAN be used to read a single data
from RHR or write a single data into THR.
However in multiple data mode, a 32bit access to RHR now allows us to
read four consecutive data from RX FIFO. Also a 32bit access to THR
now allows to write four consecutive data into TX FIFO. So we MUST
use 8bit access whenever only one data have to be read/written at a
time.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
---
 drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
 include/linux/atmel_serial.h      |  36 ++++++++++++++
 2 files changed, 130 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index e7c337de31d1..87de21f0c7a3 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -56,6 +56,15 @@
 /* Revisit: We should calculate this based on the actual port settings */
 #define PDC_RX_TIMEOUT		(3 * 10)		/* 3 bytes */
 
+/* The minium number of data FIFOs should be able to contain */
+#define ATMEL_MIN_FIFO_SIZE	8
+/*
+ * These two offsets are substracted from the RX FIFO size to define the RTS
+ * high and low thresholds
+ */
+#define ATMEL_RTS_HIGH_OFFSET	16
+#define ATMEL_RTS_LOW_OFFSET	20
+
 #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
@@ -141,6 +150,9 @@ struct atmel_uart_port {
 	struct mctrl_gpios	*gpios;
 	int			gpio_irq[UART_GPIO_MAX];
 	unsigned int		tx_done_mask;
+	u32			fifo_size;
+	u32			rts_high;
+	u32			rts_low;
 	bool			ms_irq_enabled;
 	bool			is_usart;	/* usart or uart */
 	struct timer_list	uart_timer;	/* uart timer */
@@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
 	__raw_writel(value, port->membase + reg);
 }
 
+static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
+{
+	return __raw_readb(port->membase + reg);
+}
+
+static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
+{
+	__raw_writeb(value, port->membase + reg);
+}
+
 #ifdef CONFIG_SERIAL_ATMEL_PDC
 static bool atmel_use_pdc_rx(struct uart_port *port)
 {
@@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
 
 	status = atmel_uart_readl(port, ATMEL_US_CSR);
 	while (status & ATMEL_US_RXRDY) {
-		ch = atmel_uart_readl(port, ATMEL_US_RHR);
+		ch = atmel_uart_readb(port, ATMEL_US_RHR);
 
 		/*
 		 * note that the error handling code is
@@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
 
 	if (port->x_char &&
 	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
-		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
+		atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
 		port->icount.tx++;
 		port->x_char = 0;
 	}
@@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
 
 	while (atmel_uart_readl(port, ATMEL_US_CSR) &
 	       atmel_port->tx_done_mask) {
-		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
+		atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		port->icount.tx++;
 		if (uart_circ_empty(xmit))
@@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
 			atmel_set_ops(port);
 	}
 
+	/*
+	 * Enable FIFO when available
+	 */
+	if (atmel_port->fifo_size) {
+		unsigned int txrdym = ATMEL_US_ONE_DATA;
+		unsigned int rxrdym = ATMEL_US_ONE_DATA;
+		unsigned int fmr;
+
+		atmel_uart_writel(port, ATMEL_US_CR,
+				  ATMEL_US_FIFOEN |
+				  ATMEL_US_RXFCLR |
+				  ATMEL_US_TXFLCLR);
+
+		fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
+		if (atmel_port->rts_high &&
+		    atmel_port->rts_low)
+			fmr |=	ATMEL_US_FRTSC |
+				ATMEL_US_RXFTHRES(atmel_port->rts_high) |
+				ATMEL_US_RXFTHRES2(atmel_port->rts_low);
+
+		atmel_uart_writel(port, ATMEL_US_FMR, fmr);
+	}
+
 	/* Save current CSR for comparison in atmel_tasklet_func() */
 	atmel_port->irq_status_prev = atmel_get_lines_status(port);
 	atmel_port->irq_status = atmel_port->irq_status_prev;
@@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
 	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
 		cpu_relax();
 
-	return atmel_uart_readl(port, ATMEL_US_RHR);
+	return atmel_uart_readb(port, ATMEL_US_RHR);
 }
 
 static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
@@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
 	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
 
-	atmel_uart_writel(port, ATMEL_US_THR, ch);
+	atmel_uart_writeb(port, ATMEL_US_THR, ch);
 }
 #endif
 
@@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
 {
 	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
-	atmel_uart_writel(port, ATMEL_US_THR, ch);
+	atmel_uart_writeb(port, ATMEL_US_THR, ch);
 }
 
 /*
@@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
 	return 0;
 }
 
+static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
+				     struct platform_device *pdev)
+{
+	port->fifo_size = 0;
+	port->rts_low = 0;
+	port->rts_high = 0;
+
+	if (of_property_read_u32(pdev->dev.of_node,
+				 "atmel,fifo-size",
+				 &port->fifo_size))
+		return;
+
+	if (!port->fifo_size)
+		return;
+
+	if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
+		port->fifo_size = 0;
+		dev_err(&pdev->dev, "Invalid FIFO size\n");
+		return;
+	}
+
+	/*
+	 * 0 <= rts_low <= rts_high <= fifo_size
+	 * Once their CTS line asserted by the remote peer, some x86 UARTs tend
+	 * to flush their internal TX FIFO, commonly up to 16 data, before
+	 * actually stopping to send new data. So we try to set the RTS High
+	 * Threshold to a reasonably high value respecting this 16 data
+	 * empirical rule when possible.
+	 */
+	port->rts_high = max_t(int, port->fifo_size >> 1,
+			       port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
+	port->rts_low  = max_t(int, port->fifo_size >> 2,
+			       port->fifo_size - ATMEL_RTS_LOW_OFFSET);
+
+	dev_info(&pdev->dev, "Using FIFO (%u data)\n",
+		 port->fifo_size);
+	dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
+		port->rts_high);
+	dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
+		port->rts_low);
+}
+
 static int atmel_serial_probe(struct platform_device *pdev)
 {
 	struct atmel_uart_port *port;
@@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	port = &atmel_ports[ret];
 	port->backup_imr = 0;
 	port->uart.line = ret;
+	atmel_serial_probe_fifos(port, pdev);
 
 	spin_lock_init(&port->lock_suspended);
 
diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
index c384c21d65f0..ee696d7e8a43 100644
--- a/include/linux/atmel_serial.h
+++ b/include/linux/atmel_serial.h
@@ -35,6 +35,11 @@
 #define	ATMEL_US_DTRDIS		BIT(17)	/* Data Terminal Ready Disable */
 #define	ATMEL_US_RTSEN		BIT(18)	/* Request To Send Enable */
 #define	ATMEL_US_RTSDIS		BIT(19)	/* Request To Send Disable */
+#define	ATMEL_US_TXFCLR		BIT(24)	/* Transmit FIFO Clear */
+#define	ATMEL_US_RXFCLR		BIT(25)	/* Receive FIFO Clear */
+#define	ATMEL_US_TXFLCLR	BIT(26)	/* Transmit FIFO Lock Clear */
+#define	ATMEL_US_FIFOEN		BIT(30)	/* FIFO enable */
+#define	ATMEL_US_FIFODIS	BIT(31)	/* FIFO disable */
 
 #define ATMEL_US_MR		0x04	/* Mode Register */
 #define	ATMEL_US_USMODE		GENMASK(3, 0)	/* Mode of the USART */
@@ -124,6 +129,37 @@
 #define ATMEL_US_NER		0x44	/* Number of Errors Register */
 #define ATMEL_US_IF		0x4c	/* IrDA Filter Register */
 
+#define ATMEL_US_CMPR		0x90	/* Comparaison Register */
+#define ATMEL_US_FMR		0xa0	/* FIFO Mode Register */
+#define	ATMEL_US_TXRDYM(data)	(((data) & 0x3) << 0)	/* TX Ready Mode */
+#define	ATMEL_US_RXRDYM(data)	(((data) & 0x3) << 4)	/* RX Ready Mode */
+#define		ATMEL_US_ONE_DATA	0x0
+#define		ATMEL_US_TWO_DATA	0x1
+#define		ATMEL_US_FOUR_DATA	0x2
+#define	ATMEL_US_FRTSC		BIT(7)	/* FIFO RTS pin Control */
+#define	ATMEL_US_TXFTHRES(thr)	(((thr) & 0x3f) << 8)	/* TX FIFO Threshold */
+#define	ATMEL_US_RXFTHRES(thr)	(((thr) & 0x3f) << 16)	/* RX FIFO Threshold */
+#define	ATMEL_US_RXFTHRES2(thr)	(((thr) & 0x3f) << 24)	/* RX FIFO Threshold2 */
+
+#define ATMEL_US_FLR		0xa4	/* FIFO Level Register */
+#define	ATMEL_US_TXFL(reg)	(((reg) >> 0) & 0x3f)	/* TX FIFO Level */
+#define	ATMEL_US_RXFL(reg)	(((reg) >> 16) & 0x3f)	/* RX FIFO Level */
+
+#define ATMEL_US_FIER		0xa8	/* FIFO Interrupt Enable Register */
+#define ATMEL_US_FIDR		0xac	/* FIFO Interrupt Disable Register */
+#define ATMEL_US_FIMR		0xb0	/* FIFO Interrupt Mask Register */
+#define ATMEL_US_FESR		0xb4	/* FIFO Event Status Register */
+#define	ATMEL_US_TXFEF		BIT(0)	/* Transmit FIFO Empty Flag */
+#define	ATMEL_US_TXFFF		BIT(1)	/* Transmit FIFO Full Flag */
+#define	ATMEL_US_TXFTHF		BIT(2)	/* Transmit FIFO Threshold Flag */
+#define	ATMEL_US_RXFEF		BIT(3)	/* Receive FIFO Empty Flag */
+#define	ATMEL_US_RXFFF		BIT(4)	/* Receive FIFO Full Flag */
+#define	ATMEL_US_RXFTHF		BIT(5)	/* Receive FIFO Threshold Flag */
+#define	ATMEL_US_TXFPTEF	BIT(6)	/* Transmit FIFO Pointer Error Flag */
+#define	ATMEL_US_RXFPTEF	BIT(7)	/* Receive FIFO Pointer Error Flag */
+#define	ATMEL_US_TXFLOCK	BIT(8)	/* Transmit FIFO Lock (FESR only) */
+#define	ATMEL_US_RXFTHF2	BIT(9)	/* Receive FIFO Threshold Flag 2 */
+
 #define ATMEL_US_NAME		0xf0	/* Ip Name */
 #define ATMEL_US_VERSION	0xfc	/* Ip Version */
 
-- 
1.8.2.2


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

* [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-02 13:18   ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	wenyou.yang-AIFe0yeh4nAAvxtiuMwx3w,
	ludovic.desroches-AIFe0yeh4nAAvxtiuMwx3w,
	leilei.zhao-AIFe0yeh4nAAvxtiuMwx3w,
	josh.wu-AIFe0yeh4nAAvxtiuMwx3w,
	alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	linux-serial-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, galak-sgV2jX0FEOL9JmXXK+q4OQ,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg, mark.rutland-5wv7dgnIgG8,
	pawel.moll-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	Cyrille Pitchen

Depending on the hardware, TX and RX FIFOs may be available. The RX
FIFO can avoid receive overruns, especially when DMA transfers are
not used to read data from the Receive Holding Register. For heavy
system load, The CPU is likely not be able to fetch data fast enough
from the RHR.

In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
line when the Hardware Handshaking mode is enabled. Two thresholds
are to be set for that purpose:
- When the number of data in the RX FIFO crosses and becomes lower
  than or equal to the low threshold, the RTS line is set to low
  level: the remote peer is requested to send data.
- When the number of data in the RX FIFO crosses and becomes greater
  than or equal to the high threshold, the RTS line is set to high
  level: the remote peer should stop sending new data.
- low threshold <= high threshold
Once these two thresholds are set properly, this new feature is
enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.

FIFOs also introduce a new multiple data mode: the USART works either
in multiple data mode or in single data (legacy) mode.

If MODE9 bit is set into the Mode Register or if USMODE is set to
either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
data mode. Otherwise, they operate in multiple data mode.

In this new multiple data mode, accesses to the Receive Holding
Register or Transmit Holding Register slightly change.

Since this driver implements neither the 9bit data feature (MODE9 bit
set into the Mode Register) nor LIN modes, the USART works in
multiple data mode whenever FIFOs are available and enabled. We also
assume that data are 8bit wide.

In single data mode, 32bit access CAN be used to read a single data
from RHR or write a single data into THR.
However in multiple data mode, a 32bit access to RHR now allows us to
read four consecutive data from RX FIFO. Also a 32bit access to THR
now allows to write four consecutive data into TX FIFO. So we MUST
use 8bit access whenever only one data have to be read/written at a
time.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org>
---
 drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
 include/linux/atmel_serial.h      |  36 ++++++++++++++
 2 files changed, 130 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index e7c337de31d1..87de21f0c7a3 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -56,6 +56,15 @@
 /* Revisit: We should calculate this based on the actual port settings */
 #define PDC_RX_TIMEOUT		(3 * 10)		/* 3 bytes */
 
+/* The minium number of data FIFOs should be able to contain */
+#define ATMEL_MIN_FIFO_SIZE	8
+/*
+ * These two offsets are substracted from the RX FIFO size to define the RTS
+ * high and low thresholds
+ */
+#define ATMEL_RTS_HIGH_OFFSET	16
+#define ATMEL_RTS_LOW_OFFSET	20
+
 #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
@@ -141,6 +150,9 @@ struct atmel_uart_port {
 	struct mctrl_gpios	*gpios;
 	int			gpio_irq[UART_GPIO_MAX];
 	unsigned int		tx_done_mask;
+	u32			fifo_size;
+	u32			rts_high;
+	u32			rts_low;
 	bool			ms_irq_enabled;
 	bool			is_usart;	/* usart or uart */
 	struct timer_list	uart_timer;	/* uart timer */
@@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
 	__raw_writel(value, port->membase + reg);
 }
 
+static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
+{
+	return __raw_readb(port->membase + reg);
+}
+
+static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
+{
+	__raw_writeb(value, port->membase + reg);
+}
+
 #ifdef CONFIG_SERIAL_ATMEL_PDC
 static bool atmel_use_pdc_rx(struct uart_port *port)
 {
@@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
 
 	status = atmel_uart_readl(port, ATMEL_US_CSR);
 	while (status & ATMEL_US_RXRDY) {
-		ch = atmel_uart_readl(port, ATMEL_US_RHR);
+		ch = atmel_uart_readb(port, ATMEL_US_RHR);
 
 		/*
 		 * note that the error handling code is
@@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
 
 	if (port->x_char &&
 	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
-		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
+		atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
 		port->icount.tx++;
 		port->x_char = 0;
 	}
@@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
 
 	while (atmel_uart_readl(port, ATMEL_US_CSR) &
 	       atmel_port->tx_done_mask) {
-		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
+		atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		port->icount.tx++;
 		if (uart_circ_empty(xmit))
@@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
 			atmel_set_ops(port);
 	}
 
+	/*
+	 * Enable FIFO when available
+	 */
+	if (atmel_port->fifo_size) {
+		unsigned int txrdym = ATMEL_US_ONE_DATA;
+		unsigned int rxrdym = ATMEL_US_ONE_DATA;
+		unsigned int fmr;
+
+		atmel_uart_writel(port, ATMEL_US_CR,
+				  ATMEL_US_FIFOEN |
+				  ATMEL_US_RXFCLR |
+				  ATMEL_US_TXFLCLR);
+
+		fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
+		if (atmel_port->rts_high &&
+		    atmel_port->rts_low)
+			fmr |=	ATMEL_US_FRTSC |
+				ATMEL_US_RXFTHRES(atmel_port->rts_high) |
+				ATMEL_US_RXFTHRES2(atmel_port->rts_low);
+
+		atmel_uart_writel(port, ATMEL_US_FMR, fmr);
+	}
+
 	/* Save current CSR for comparison in atmel_tasklet_func() */
 	atmel_port->irq_status_prev = atmel_get_lines_status(port);
 	atmel_port->irq_status = atmel_port->irq_status_prev;
@@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
 	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
 		cpu_relax();
 
-	return atmel_uart_readl(port, ATMEL_US_RHR);
+	return atmel_uart_readb(port, ATMEL_US_RHR);
 }
 
 static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
@@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
 	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
 
-	atmel_uart_writel(port, ATMEL_US_THR, ch);
+	atmel_uart_writeb(port, ATMEL_US_THR, ch);
 }
 #endif
 
@@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
 {
 	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
-	atmel_uart_writel(port, ATMEL_US_THR, ch);
+	atmel_uart_writeb(port, ATMEL_US_THR, ch);
 }
 
 /*
@@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
 	return 0;
 }
 
+static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
+				     struct platform_device *pdev)
+{
+	port->fifo_size = 0;
+	port->rts_low = 0;
+	port->rts_high = 0;
+
+	if (of_property_read_u32(pdev->dev.of_node,
+				 "atmel,fifo-size",
+				 &port->fifo_size))
+		return;
+
+	if (!port->fifo_size)
+		return;
+
+	if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
+		port->fifo_size = 0;
+		dev_err(&pdev->dev, "Invalid FIFO size\n");
+		return;
+	}
+
+	/*
+	 * 0 <= rts_low <= rts_high <= fifo_size
+	 * Once their CTS line asserted by the remote peer, some x86 UARTs tend
+	 * to flush their internal TX FIFO, commonly up to 16 data, before
+	 * actually stopping to send new data. So we try to set the RTS High
+	 * Threshold to a reasonably high value respecting this 16 data
+	 * empirical rule when possible.
+	 */
+	port->rts_high = max_t(int, port->fifo_size >> 1,
+			       port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
+	port->rts_low  = max_t(int, port->fifo_size >> 2,
+			       port->fifo_size - ATMEL_RTS_LOW_OFFSET);
+
+	dev_info(&pdev->dev, "Using FIFO (%u data)\n",
+		 port->fifo_size);
+	dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
+		port->rts_high);
+	dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
+		port->rts_low);
+}
+
 static int atmel_serial_probe(struct platform_device *pdev)
 {
 	struct atmel_uart_port *port;
@@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	port = &atmel_ports[ret];
 	port->backup_imr = 0;
 	port->uart.line = ret;
+	atmel_serial_probe_fifos(port, pdev);
 
 	spin_lock_init(&port->lock_suspended);
 
diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
index c384c21d65f0..ee696d7e8a43 100644
--- a/include/linux/atmel_serial.h
+++ b/include/linux/atmel_serial.h
@@ -35,6 +35,11 @@
 #define	ATMEL_US_DTRDIS		BIT(17)	/* Data Terminal Ready Disable */
 #define	ATMEL_US_RTSEN		BIT(18)	/* Request To Send Enable */
 #define	ATMEL_US_RTSDIS		BIT(19)	/* Request To Send Disable */
+#define	ATMEL_US_TXFCLR		BIT(24)	/* Transmit FIFO Clear */
+#define	ATMEL_US_RXFCLR		BIT(25)	/* Receive FIFO Clear */
+#define	ATMEL_US_TXFLCLR	BIT(26)	/* Transmit FIFO Lock Clear */
+#define	ATMEL_US_FIFOEN		BIT(30)	/* FIFO enable */
+#define	ATMEL_US_FIFODIS	BIT(31)	/* FIFO disable */
 
 #define ATMEL_US_MR		0x04	/* Mode Register */
 #define	ATMEL_US_USMODE		GENMASK(3, 0)	/* Mode of the USART */
@@ -124,6 +129,37 @@
 #define ATMEL_US_NER		0x44	/* Number of Errors Register */
 #define ATMEL_US_IF		0x4c	/* IrDA Filter Register */
 
+#define ATMEL_US_CMPR		0x90	/* Comparaison Register */
+#define ATMEL_US_FMR		0xa0	/* FIFO Mode Register */
+#define	ATMEL_US_TXRDYM(data)	(((data) & 0x3) << 0)	/* TX Ready Mode */
+#define	ATMEL_US_RXRDYM(data)	(((data) & 0x3) << 4)	/* RX Ready Mode */
+#define		ATMEL_US_ONE_DATA	0x0
+#define		ATMEL_US_TWO_DATA	0x1
+#define		ATMEL_US_FOUR_DATA	0x2
+#define	ATMEL_US_FRTSC		BIT(7)	/* FIFO RTS pin Control */
+#define	ATMEL_US_TXFTHRES(thr)	(((thr) & 0x3f) << 8)	/* TX FIFO Threshold */
+#define	ATMEL_US_RXFTHRES(thr)	(((thr) & 0x3f) << 16)	/* RX FIFO Threshold */
+#define	ATMEL_US_RXFTHRES2(thr)	(((thr) & 0x3f) << 24)	/* RX FIFO Threshold2 */
+
+#define ATMEL_US_FLR		0xa4	/* FIFO Level Register */
+#define	ATMEL_US_TXFL(reg)	(((reg) >> 0) & 0x3f)	/* TX FIFO Level */
+#define	ATMEL_US_RXFL(reg)	(((reg) >> 16) & 0x3f)	/* RX FIFO Level */
+
+#define ATMEL_US_FIER		0xa8	/* FIFO Interrupt Enable Register */
+#define ATMEL_US_FIDR		0xac	/* FIFO Interrupt Disable Register */
+#define ATMEL_US_FIMR		0xb0	/* FIFO Interrupt Mask Register */
+#define ATMEL_US_FESR		0xb4	/* FIFO Event Status Register */
+#define	ATMEL_US_TXFEF		BIT(0)	/* Transmit FIFO Empty Flag */
+#define	ATMEL_US_TXFFF		BIT(1)	/* Transmit FIFO Full Flag */
+#define	ATMEL_US_TXFTHF		BIT(2)	/* Transmit FIFO Threshold Flag */
+#define	ATMEL_US_RXFEF		BIT(3)	/* Receive FIFO Empty Flag */
+#define	ATMEL_US_RXFFF		BIT(4)	/* Receive FIFO Full Flag */
+#define	ATMEL_US_RXFTHF		BIT(5)	/* Receive FIFO Threshold Flag */
+#define	ATMEL_US_TXFPTEF	BIT(6)	/* Transmit FIFO Pointer Error Flag */
+#define	ATMEL_US_RXFPTEF	BIT(7)	/* Receive FIFO Pointer Error Flag */
+#define	ATMEL_US_TXFLOCK	BIT(8)	/* Transmit FIFO Lock (FESR only) */
+#define	ATMEL_US_RXFTHF2	BIT(9)	/* Receive FIFO Threshold Flag 2 */
+
 #define ATMEL_US_NAME		0xf0	/* Ip Name */
 #define ATMEL_US_VERSION	0xfc	/* Ip Version */
 
-- 
1.8.2.2

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

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

* [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-02 13:18   ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: linux-arm-kernel

Depending on the hardware, TX and RX FIFOs may be available. The RX
FIFO can avoid receive overruns, especially when DMA transfers are
not used to read data from the Receive Holding Register. For heavy
system load, The CPU is likely not be able to fetch data fast enough
from the RHR.

In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
line when the Hardware Handshaking mode is enabled. Two thresholds
are to be set for that purpose:
- When the number of data in the RX FIFO crosses and becomes lower
  than or equal to the low threshold, the RTS line is set to low
  level: the remote peer is requested to send data.
- When the number of data in the RX FIFO crosses and becomes greater
  than or equal to the high threshold, the RTS line is set to high
  level: the remote peer should stop sending new data.
- low threshold <= high threshold
Once these two thresholds are set properly, this new feature is
enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.

FIFOs also introduce a new multiple data mode: the USART works either
in multiple data mode or in single data (legacy) mode.

If MODE9 bit is set into the Mode Register or if USMODE is set to
either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
data mode. Otherwise, they operate in multiple data mode.

In this new multiple data mode, accesses to the Receive Holding
Register or Transmit Holding Register slightly change.

Since this driver implements neither the 9bit data feature (MODE9 bit
set into the Mode Register) nor LIN modes, the USART works in
multiple data mode whenever FIFOs are available and enabled. We also
assume that data are 8bit wide.

In single data mode, 32bit access CAN be used to read a single data
from RHR or write a single data into THR.
However in multiple data mode, a 32bit access to RHR now allows us to
read four consecutive data from RX FIFO. Also a 32bit access to THR
now allows to write four consecutive data into TX FIFO. So we MUST
use 8bit access whenever only one data have to be read/written at a
time.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
---
 drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
 include/linux/atmel_serial.h      |  36 ++++++++++++++
 2 files changed, 130 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index e7c337de31d1..87de21f0c7a3 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -56,6 +56,15 @@
 /* Revisit: We should calculate this based on the actual port settings */
 #define PDC_RX_TIMEOUT		(3 * 10)		/* 3 bytes */
 
+/* The minium number of data FIFOs should be able to contain */
+#define ATMEL_MIN_FIFO_SIZE	8
+/*
+ * These two offsets are substracted from the RX FIFO size to define the RTS
+ * high and low thresholds
+ */
+#define ATMEL_RTS_HIGH_OFFSET	16
+#define ATMEL_RTS_LOW_OFFSET	20
+
 #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
@@ -141,6 +150,9 @@ struct atmel_uart_port {
 	struct mctrl_gpios	*gpios;
 	int			gpio_irq[UART_GPIO_MAX];
 	unsigned int		tx_done_mask;
+	u32			fifo_size;
+	u32			rts_high;
+	u32			rts_low;
 	bool			ms_irq_enabled;
 	bool			is_usart;	/* usart or uart */
 	struct timer_list	uart_timer;	/* uart timer */
@@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
 	__raw_writel(value, port->membase + reg);
 }
 
+static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
+{
+	return __raw_readb(port->membase + reg);
+}
+
+static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
+{
+	__raw_writeb(value, port->membase + reg);
+}
+
 #ifdef CONFIG_SERIAL_ATMEL_PDC
 static bool atmel_use_pdc_rx(struct uart_port *port)
 {
@@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
 
 	status = atmel_uart_readl(port, ATMEL_US_CSR);
 	while (status & ATMEL_US_RXRDY) {
-		ch = atmel_uart_readl(port, ATMEL_US_RHR);
+		ch = atmel_uart_readb(port, ATMEL_US_RHR);
 
 		/*
 		 * note that the error handling code is
@@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
 
 	if (port->x_char &&
 	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
-		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
+		atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
 		port->icount.tx++;
 		port->x_char = 0;
 	}
@@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
 
 	while (atmel_uart_readl(port, ATMEL_US_CSR) &
 	       atmel_port->tx_done_mask) {
-		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
+		atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		port->icount.tx++;
 		if (uart_circ_empty(xmit))
@@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
 			atmel_set_ops(port);
 	}
 
+	/*
+	 * Enable FIFO when available
+	 */
+	if (atmel_port->fifo_size) {
+		unsigned int txrdym = ATMEL_US_ONE_DATA;
+		unsigned int rxrdym = ATMEL_US_ONE_DATA;
+		unsigned int fmr;
+
+		atmel_uart_writel(port, ATMEL_US_CR,
+				  ATMEL_US_FIFOEN |
+				  ATMEL_US_RXFCLR |
+				  ATMEL_US_TXFLCLR);
+
+		fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
+		if (atmel_port->rts_high &&
+		    atmel_port->rts_low)
+			fmr |=	ATMEL_US_FRTSC |
+				ATMEL_US_RXFTHRES(atmel_port->rts_high) |
+				ATMEL_US_RXFTHRES2(atmel_port->rts_low);
+
+		atmel_uart_writel(port, ATMEL_US_FMR, fmr);
+	}
+
 	/* Save current CSR for comparison in atmel_tasklet_func() */
 	atmel_port->irq_status_prev = atmel_get_lines_status(port);
 	atmel_port->irq_status = atmel_port->irq_status_prev;
@@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
 	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
 		cpu_relax();
 
-	return atmel_uart_readl(port, ATMEL_US_RHR);
+	return atmel_uart_readb(port, ATMEL_US_RHR);
 }
 
 static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
@@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
 	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
 
-	atmel_uart_writel(port, ATMEL_US_THR, ch);
+	atmel_uart_writeb(port, ATMEL_US_THR, ch);
 }
 #endif
 
@@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
 {
 	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
 		cpu_relax();
-	atmel_uart_writel(port, ATMEL_US_THR, ch);
+	atmel_uart_writeb(port, ATMEL_US_THR, ch);
 }
 
 /*
@@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
 	return 0;
 }
 
+static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
+				     struct platform_device *pdev)
+{
+	port->fifo_size = 0;
+	port->rts_low = 0;
+	port->rts_high = 0;
+
+	if (of_property_read_u32(pdev->dev.of_node,
+				 "atmel,fifo-size",
+				 &port->fifo_size))
+		return;
+
+	if (!port->fifo_size)
+		return;
+
+	if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
+		port->fifo_size = 0;
+		dev_err(&pdev->dev, "Invalid FIFO size\n");
+		return;
+	}
+
+	/*
+	 * 0 <= rts_low <= rts_high <= fifo_size
+	 * Once their CTS line asserted by the remote peer, some x86 UARTs tend
+	 * to flush their internal TX FIFO, commonly up to 16 data, before
+	 * actually stopping to send new data. So we try to set the RTS High
+	 * Threshold to a reasonably high value respecting this 16 data
+	 * empirical rule when possible.
+	 */
+	port->rts_high = max_t(int, port->fifo_size >> 1,
+			       port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
+	port->rts_low  = max_t(int, port->fifo_size >> 2,
+			       port->fifo_size - ATMEL_RTS_LOW_OFFSET);
+
+	dev_info(&pdev->dev, "Using FIFO (%u data)\n",
+		 port->fifo_size);
+	dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
+		port->rts_high);
+	dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
+		port->rts_low);
+}
+
 static int atmel_serial_probe(struct platform_device *pdev)
 {
 	struct atmel_uart_port *port;
@@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
 	port = &atmel_ports[ret];
 	port->backup_imr = 0;
 	port->uart.line = ret;
+	atmel_serial_probe_fifos(port, pdev);
 
 	spin_lock_init(&port->lock_suspended);
 
diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
index c384c21d65f0..ee696d7e8a43 100644
--- a/include/linux/atmel_serial.h
+++ b/include/linux/atmel_serial.h
@@ -35,6 +35,11 @@
 #define	ATMEL_US_DTRDIS		BIT(17)	/* Data Terminal Ready Disable */
 #define	ATMEL_US_RTSEN		BIT(18)	/* Request To Send Enable */
 #define	ATMEL_US_RTSDIS		BIT(19)	/* Request To Send Disable */
+#define	ATMEL_US_TXFCLR		BIT(24)	/* Transmit FIFO Clear */
+#define	ATMEL_US_RXFCLR		BIT(25)	/* Receive FIFO Clear */
+#define	ATMEL_US_TXFLCLR	BIT(26)	/* Transmit FIFO Lock Clear */
+#define	ATMEL_US_FIFOEN		BIT(30)	/* FIFO enable */
+#define	ATMEL_US_FIFODIS	BIT(31)	/* FIFO disable */
 
 #define ATMEL_US_MR		0x04	/* Mode Register */
 #define	ATMEL_US_USMODE		GENMASK(3, 0)	/* Mode of the USART */
@@ -124,6 +129,37 @@
 #define ATMEL_US_NER		0x44	/* Number of Errors Register */
 #define ATMEL_US_IF		0x4c	/* IrDA Filter Register */
 
+#define ATMEL_US_CMPR		0x90	/* Comparaison Register */
+#define ATMEL_US_FMR		0xa0	/* FIFO Mode Register */
+#define	ATMEL_US_TXRDYM(data)	(((data) & 0x3) << 0)	/* TX Ready Mode */
+#define	ATMEL_US_RXRDYM(data)	(((data) & 0x3) << 4)	/* RX Ready Mode */
+#define		ATMEL_US_ONE_DATA	0x0
+#define		ATMEL_US_TWO_DATA	0x1
+#define		ATMEL_US_FOUR_DATA	0x2
+#define	ATMEL_US_FRTSC		BIT(7)	/* FIFO RTS pin Control */
+#define	ATMEL_US_TXFTHRES(thr)	(((thr) & 0x3f) << 8)	/* TX FIFO Threshold */
+#define	ATMEL_US_RXFTHRES(thr)	(((thr) & 0x3f) << 16)	/* RX FIFO Threshold */
+#define	ATMEL_US_RXFTHRES2(thr)	(((thr) & 0x3f) << 24)	/* RX FIFO Threshold2 */
+
+#define ATMEL_US_FLR		0xa4	/* FIFO Level Register */
+#define	ATMEL_US_TXFL(reg)	(((reg) >> 0) & 0x3f)	/* TX FIFO Level */
+#define	ATMEL_US_RXFL(reg)	(((reg) >> 16) & 0x3f)	/* RX FIFO Level */
+
+#define ATMEL_US_FIER		0xa8	/* FIFO Interrupt Enable Register */
+#define ATMEL_US_FIDR		0xac	/* FIFO Interrupt Disable Register */
+#define ATMEL_US_FIMR		0xb0	/* FIFO Interrupt Mask Register */
+#define ATMEL_US_FESR		0xb4	/* FIFO Event Status Register */
+#define	ATMEL_US_TXFEF		BIT(0)	/* Transmit FIFO Empty Flag */
+#define	ATMEL_US_TXFFF		BIT(1)	/* Transmit FIFO Full Flag */
+#define	ATMEL_US_TXFTHF		BIT(2)	/* Transmit FIFO Threshold Flag */
+#define	ATMEL_US_RXFEF		BIT(3)	/* Receive FIFO Empty Flag */
+#define	ATMEL_US_RXFFF		BIT(4)	/* Receive FIFO Full Flag */
+#define	ATMEL_US_RXFTHF		BIT(5)	/* Receive FIFO Threshold Flag */
+#define	ATMEL_US_TXFPTEF	BIT(6)	/* Transmit FIFO Pointer Error Flag */
+#define	ATMEL_US_RXFPTEF	BIT(7)	/* Receive FIFO Pointer Error Flag */
+#define	ATMEL_US_TXFLOCK	BIT(8)	/* Transmit FIFO Lock (FESR only) */
+#define	ATMEL_US_RXFTHF2	BIT(9)	/* Receive FIFO Threshold Flag 2 */
+
 #define ATMEL_US_NAME		0xf0	/* Ip Name */
 #define ATMEL_US_VERSION	0xfc	/* Ip Version */
 
-- 
1.8.2.2

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

* [PATCH v4 5/5] tty/serial: at91: use 32bit writes into TX FIFO when DMA is enabled
  2015-07-02 13:18 ` Cyrille Pitchen
  (?)
@ 2015-07-02 13:18   ` Cyrille Pitchen
  -1 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt,
	Cyrille Pitchen

For now this improvement is only used with TX DMA transfers. The data
width must be set properly when configuring the DMA controller. Also
the FIFO configuration must be set to match the DMA transfer data
width:
TXRDYM (Transmitter Ready Mode) and RXRDYM (Receiver Ready Mode) must
be set into the FIFO Mode Register. These values are used by the
USART to trigger the DMA controller. In single data mode they are not
used and should be reset to 0.
So the TXRDYM bits are changed to FOUR_DATA; then USART triggers the
DMA controller when at least 4 data can be written into the TX FIFO
througth the THR. On the other hand the RXRDYM bits are left unchanged
to ONE_DATA.

Atmel eXtended DMA controller allows us to set a different data width
for each part of a scatter-gather transfer. So when calling
dmaengine_slave_config() to configure the TX path, we just need to set
dst_addr_width to the maximum data width. Then DMA writes into THR are
split into up to two parts. The first part carries the first data to
be sent and has a length equal to the greatest multiple of 4 (bytes)
lower than or equal to the total length of the TX DMA transfer. The
second part carries the trailing data (up to 3 bytes). The first part
is written by the DMA into THR using 32 bit accesses, whereas 8bit
accesses are used for the second part.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/tty/serial/atmel_serial.c | 66 ++++++++++++++++++++++++++++++---------
 1 file changed, 51 insertions(+), 15 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 87de21f0c7a3..e91b3b2f0590 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -144,6 +144,7 @@ struct atmel_uart_port {
 	unsigned int		irq_status;
 	unsigned int		irq_status_prev;
 	unsigned int		status_change;
+	unsigned int		tx_len;
 
 	struct circ_buf		rx_ring;
 
@@ -745,10 +746,10 @@ static void atmel_complete_tx_dma(void *arg)
 
 	if (chan)
 		dmaengine_terminate_all(chan);
-	xmit->tail += sg_dma_len(&atmel_port->sg_tx);
+	xmit->tail += atmel_port->tx_len;
 	xmit->tail &= UART_XMIT_SIZE - 1;
 
-	port->icount.tx += sg_dma_len(&atmel_port->sg_tx);
+	port->icount.tx += atmel_port->tx_len;
 
 	spin_lock_irq(&atmel_port->lock_tx);
 	async_tx_ack(atmel_port->desc_tx);
@@ -796,7 +797,9 @@ static void atmel_tx_dma(struct uart_port *port)
 	struct circ_buf *xmit = &port->state->xmit;
 	struct dma_chan *chan = atmel_port->chan_tx;
 	struct dma_async_tx_descriptor *desc;
-	struct scatterlist *sg = &atmel_port->sg_tx;
+	struct scatterlist sgl[2], *sg, *sg_tx = &atmel_port->sg_tx;
+	unsigned int tx_len, part1_len, part2_len, sg_len;
+	dma_addr_t phys_addr;
 
 	/* Make sure we have an idle channel */
 	if (atmel_port->desc_tx != NULL)
@@ -812,18 +815,46 @@ static void atmel_tx_dma(struct uart_port *port)
 		 * Take the port lock to get a
 		 * consistent xmit buffer state.
 		 */
-		sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
-		sg_dma_address(sg) = (sg_dma_address(sg) &
-					~(UART_XMIT_SIZE - 1))
-					+ sg->offset;
-		sg_dma_len(sg) = CIRC_CNT_TO_END(xmit->head,
-						xmit->tail,
-						UART_XMIT_SIZE);
-		BUG_ON(!sg_dma_len(sg));
+		tx_len = CIRC_CNT_TO_END(xmit->head,
+					 xmit->tail,
+					 UART_XMIT_SIZE);
+
+		if (atmel_port->fifo_size) {
+			/* multi data mode */
+			part1_len = (tx_len & ~0x3); /* DWORD access */
+			part2_len = (tx_len & 0x3); /* BYTE access */
+		} else {
+			/* single data (legacy) mode */
+			part1_len = 0;
+			part2_len = tx_len; /* BYTE access only */
+		}
+
+		sg_init_table(sgl, 2);
+		sg_len = 0;
+		phys_addr = sg_dma_address(sg_tx) + xmit->tail;
+		if (part1_len) {
+			sg = &sgl[sg_len++];
+			sg_dma_address(sg) = phys_addr;
+			sg_dma_len(sg) = part1_len;
+
+			phys_addr += part1_len;
+		}
+
+		if (part2_len) {
+			sg = &sgl[sg_len++];
+			sg_dma_address(sg) = phys_addr;
+			sg_dma_len(sg) = part2_len;
+		}
+
+		/*
+		 * save tx_len so atmel_complete_tx_dma() will increase
+		 * xmit->tail correctly
+		 */
+		atmel_port->tx_len = tx_len;
 
 		desc = dmaengine_prep_slave_sg(chan,
-					       sg,
-					       1,
+					       sgl,
+					       sg_len,
 					       DMA_MEM_TO_DEV,
 					       DMA_PREP_INTERRUPT |
 					       DMA_CTRL_ACK);
@@ -832,7 +863,7 @@ static void atmel_tx_dma(struct uart_port *port)
 			return;
 		}
 
-		dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
+		dma_sync_sg_for_device(port->dev, sg_tx, 1, DMA_TO_DEVICE);
 
 		atmel_port->desc_tx = desc;
 		desc->callback = atmel_complete_tx_dma;
@@ -892,7 +923,9 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
 	/* Configure the slave DMA */
 	memset(&config, 0, sizeof(config));
 	config.direction = DMA_MEM_TO_DEV;
-	config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	config.dst_addr_width = (atmel_port->fifo_size) ?
+				DMA_SLAVE_BUSWIDTH_4_BYTES :
+				DMA_SLAVE_BUSWIDTH_1_BYTE;
 	config.dst_addr = port->mapbase + ATMEL_US_THR;
 	config.dst_maxburst = 1;
 
@@ -1831,6 +1864,9 @@ static int atmel_startup(struct uart_port *port)
 				  ATMEL_US_RXFCLR |
 				  ATMEL_US_TXFLCLR);
 
+		if (atmel_use_dma_tx(port))
+			txrdym = ATMEL_US_FOUR_DATA;
+
 		fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
 		if (atmel_port->rts_high &&
 		    atmel_port->rts_low)
-- 
1.8.2.2


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

* [PATCH v4 5/5] tty/serial: at91: use 32bit writes into TX FIFO when DMA is enabled
@ 2015-07-02 13:18   ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: nicolas.ferre, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt,
	Cyrille Pitchen

For now this improvement is only used with TX DMA transfers. The data
width must be set properly when configuring the DMA controller. Also
the FIFO configuration must be set to match the DMA transfer data
width:
TXRDYM (Transmitter Ready Mode) and RXRDYM (Receiver Ready Mode) must
be set into the FIFO Mode Register. These values are used by the
USART to trigger the DMA controller. In single data mode they are not
used and should be reset to 0.
So the TXRDYM bits are changed to FOUR_DATA; then USART triggers the
DMA controller when at least 4 data can be written into the TX FIFO
througth the THR. On the other hand the RXRDYM bits are left unchanged
to ONE_DATA.

Atmel eXtended DMA controller allows us to set a different data width
for each part of a scatter-gather transfer. So when calling
dmaengine_slave_config() to configure the TX path, we just need to set
dst_addr_width to the maximum data width. Then DMA writes into THR are
split into up to two parts. The first part carries the first data to
be sent and has a length equal to the greatest multiple of 4 (bytes)
lower than or equal to the total length of the TX DMA transfer. The
second part carries the trailing data (up to 3 bytes). The first part
is written by the DMA into THR using 32 bit accesses, whereas 8bit
accesses are used for the second part.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/tty/serial/atmel_serial.c | 66 ++++++++++++++++++++++++++++++---------
 1 file changed, 51 insertions(+), 15 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 87de21f0c7a3..e91b3b2f0590 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -144,6 +144,7 @@ struct atmel_uart_port {
 	unsigned int		irq_status;
 	unsigned int		irq_status_prev;
 	unsigned int		status_change;
+	unsigned int		tx_len;
 
 	struct circ_buf		rx_ring;
 
@@ -745,10 +746,10 @@ static void atmel_complete_tx_dma(void *arg)
 
 	if (chan)
 		dmaengine_terminate_all(chan);
-	xmit->tail += sg_dma_len(&atmel_port->sg_tx);
+	xmit->tail += atmel_port->tx_len;
 	xmit->tail &= UART_XMIT_SIZE - 1;
 
-	port->icount.tx += sg_dma_len(&atmel_port->sg_tx);
+	port->icount.tx += atmel_port->tx_len;
 
 	spin_lock_irq(&atmel_port->lock_tx);
 	async_tx_ack(atmel_port->desc_tx);
@@ -796,7 +797,9 @@ static void atmel_tx_dma(struct uart_port *port)
 	struct circ_buf *xmit = &port->state->xmit;
 	struct dma_chan *chan = atmel_port->chan_tx;
 	struct dma_async_tx_descriptor *desc;
-	struct scatterlist *sg = &atmel_port->sg_tx;
+	struct scatterlist sgl[2], *sg, *sg_tx = &atmel_port->sg_tx;
+	unsigned int tx_len, part1_len, part2_len, sg_len;
+	dma_addr_t phys_addr;
 
 	/* Make sure we have an idle channel */
 	if (atmel_port->desc_tx != NULL)
@@ -812,18 +815,46 @@ static void atmel_tx_dma(struct uart_port *port)
 		 * Take the port lock to get a
 		 * consistent xmit buffer state.
 		 */
-		sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
-		sg_dma_address(sg) = (sg_dma_address(sg) &
-					~(UART_XMIT_SIZE - 1))
-					+ sg->offset;
-		sg_dma_len(sg) = CIRC_CNT_TO_END(xmit->head,
-						xmit->tail,
-						UART_XMIT_SIZE);
-		BUG_ON(!sg_dma_len(sg));
+		tx_len = CIRC_CNT_TO_END(xmit->head,
+					 xmit->tail,
+					 UART_XMIT_SIZE);
+
+		if (atmel_port->fifo_size) {
+			/* multi data mode */
+			part1_len = (tx_len & ~0x3); /* DWORD access */
+			part2_len = (tx_len & 0x3); /* BYTE access */
+		} else {
+			/* single data (legacy) mode */
+			part1_len = 0;
+			part2_len = tx_len; /* BYTE access only */
+		}
+
+		sg_init_table(sgl, 2);
+		sg_len = 0;
+		phys_addr = sg_dma_address(sg_tx) + xmit->tail;
+		if (part1_len) {
+			sg = &sgl[sg_len++];
+			sg_dma_address(sg) = phys_addr;
+			sg_dma_len(sg) = part1_len;
+
+			phys_addr += part1_len;
+		}
+
+		if (part2_len) {
+			sg = &sgl[sg_len++];
+			sg_dma_address(sg) = phys_addr;
+			sg_dma_len(sg) = part2_len;
+		}
+
+		/*
+		 * save tx_len so atmel_complete_tx_dma() will increase
+		 * xmit->tail correctly
+		 */
+		atmel_port->tx_len = tx_len;
 
 		desc = dmaengine_prep_slave_sg(chan,
-					       sg,
-					       1,
+					       sgl,
+					       sg_len,
 					       DMA_MEM_TO_DEV,
 					       DMA_PREP_INTERRUPT |
 					       DMA_CTRL_ACK);
@@ -832,7 +863,7 @@ static void atmel_tx_dma(struct uart_port *port)
 			return;
 		}
 
-		dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
+		dma_sync_sg_for_device(port->dev, sg_tx, 1, DMA_TO_DEVICE);
 
 		atmel_port->desc_tx = desc;
 		desc->callback = atmel_complete_tx_dma;
@@ -892,7 +923,9 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
 	/* Configure the slave DMA */
 	memset(&config, 0, sizeof(config));
 	config.direction = DMA_MEM_TO_DEV;
-	config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	config.dst_addr_width = (atmel_port->fifo_size) ?
+				DMA_SLAVE_BUSWIDTH_4_BYTES :
+				DMA_SLAVE_BUSWIDTH_1_BYTE;
 	config.dst_addr = port->mapbase + ATMEL_US_THR;
 	config.dst_maxburst = 1;
 
@@ -1831,6 +1864,9 @@ static int atmel_startup(struct uart_port *port)
 				  ATMEL_US_RXFCLR |
 				  ATMEL_US_TXFLCLR);
 
+		if (atmel_use_dma_tx(port))
+			txrdym = ATMEL_US_FOUR_DATA;
+
 		fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
 		if (atmel_port->rts_high &&
 		    atmel_port->rts_low)
-- 
1.8.2.2

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

* [PATCH v4 5/5] tty/serial: at91: use 32bit writes into TX FIFO when DMA is enabled
@ 2015-07-02 13:18   ` Cyrille Pitchen
  0 siblings, 0 replies; 35+ messages in thread
From: Cyrille Pitchen @ 2015-07-02 13:18 UTC (permalink / raw)
  To: linux-arm-kernel

For now this improvement is only used with TX DMA transfers. The data
width must be set properly when configuring the DMA controller. Also
the FIFO configuration must be set to match the DMA transfer data
width:
TXRDYM (Transmitter Ready Mode) and RXRDYM (Receiver Ready Mode) must
be set into the FIFO Mode Register. These values are used by the
USART to trigger the DMA controller. In single data mode they are not
used and should be reset to 0.
So the TXRDYM bits are changed to FOUR_DATA; then USART triggers the
DMA controller when at least 4 data can be written into the TX FIFO
througth the THR. On the other hand the RXRDYM bits are left unchanged
to ONE_DATA.

Atmel eXtended DMA controller allows us to set a different data width
for each part of a scatter-gather transfer. So when calling
dmaengine_slave_config() to configure the TX path, we just need to set
dst_addr_width to the maximum data width. Then DMA writes into THR are
split into up to two parts. The first part carries the first data to
be sent and has a length equal to the greatest multiple of 4 (bytes)
lower than or equal to the total length of the TX DMA transfer. The
second part carries the trailing data (up to 3 bytes). The first part
is written by the DMA into THR using 32 bit accesses, whereas 8bit
accesses are used for the second part.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/tty/serial/atmel_serial.c | 66 ++++++++++++++++++++++++++++++---------
 1 file changed, 51 insertions(+), 15 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 87de21f0c7a3..e91b3b2f0590 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -144,6 +144,7 @@ struct atmel_uart_port {
 	unsigned int		irq_status;
 	unsigned int		irq_status_prev;
 	unsigned int		status_change;
+	unsigned int		tx_len;
 
 	struct circ_buf		rx_ring;
 
@@ -745,10 +746,10 @@ static void atmel_complete_tx_dma(void *arg)
 
 	if (chan)
 		dmaengine_terminate_all(chan);
-	xmit->tail += sg_dma_len(&atmel_port->sg_tx);
+	xmit->tail += atmel_port->tx_len;
 	xmit->tail &= UART_XMIT_SIZE - 1;
 
-	port->icount.tx += sg_dma_len(&atmel_port->sg_tx);
+	port->icount.tx += atmel_port->tx_len;
 
 	spin_lock_irq(&atmel_port->lock_tx);
 	async_tx_ack(atmel_port->desc_tx);
@@ -796,7 +797,9 @@ static void atmel_tx_dma(struct uart_port *port)
 	struct circ_buf *xmit = &port->state->xmit;
 	struct dma_chan *chan = atmel_port->chan_tx;
 	struct dma_async_tx_descriptor *desc;
-	struct scatterlist *sg = &atmel_port->sg_tx;
+	struct scatterlist sgl[2], *sg, *sg_tx = &atmel_port->sg_tx;
+	unsigned int tx_len, part1_len, part2_len, sg_len;
+	dma_addr_t phys_addr;
 
 	/* Make sure we have an idle channel */
 	if (atmel_port->desc_tx != NULL)
@@ -812,18 +815,46 @@ static void atmel_tx_dma(struct uart_port *port)
 		 * Take the port lock to get a
 		 * consistent xmit buffer state.
 		 */
-		sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
-		sg_dma_address(sg) = (sg_dma_address(sg) &
-					~(UART_XMIT_SIZE - 1))
-					+ sg->offset;
-		sg_dma_len(sg) = CIRC_CNT_TO_END(xmit->head,
-						xmit->tail,
-						UART_XMIT_SIZE);
-		BUG_ON(!sg_dma_len(sg));
+		tx_len = CIRC_CNT_TO_END(xmit->head,
+					 xmit->tail,
+					 UART_XMIT_SIZE);
+
+		if (atmel_port->fifo_size) {
+			/* multi data mode */
+			part1_len = (tx_len & ~0x3); /* DWORD access */
+			part2_len = (tx_len & 0x3); /* BYTE access */
+		} else {
+			/* single data (legacy) mode */
+			part1_len = 0;
+			part2_len = tx_len; /* BYTE access only */
+		}
+
+		sg_init_table(sgl, 2);
+		sg_len = 0;
+		phys_addr = sg_dma_address(sg_tx) + xmit->tail;
+		if (part1_len) {
+			sg = &sgl[sg_len++];
+			sg_dma_address(sg) = phys_addr;
+			sg_dma_len(sg) = part1_len;
+
+			phys_addr += part1_len;
+		}
+
+		if (part2_len) {
+			sg = &sgl[sg_len++];
+			sg_dma_address(sg) = phys_addr;
+			sg_dma_len(sg) = part2_len;
+		}
+
+		/*
+		 * save tx_len so atmel_complete_tx_dma() will increase
+		 * xmit->tail correctly
+		 */
+		atmel_port->tx_len = tx_len;
 
 		desc = dmaengine_prep_slave_sg(chan,
-					       sg,
-					       1,
+					       sgl,
+					       sg_len,
 					       DMA_MEM_TO_DEV,
 					       DMA_PREP_INTERRUPT |
 					       DMA_CTRL_ACK);
@@ -832,7 +863,7 @@ static void atmel_tx_dma(struct uart_port *port)
 			return;
 		}
 
-		dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
+		dma_sync_sg_for_device(port->dev, sg_tx, 1, DMA_TO_DEVICE);
 
 		atmel_port->desc_tx = desc;
 		desc->callback = atmel_complete_tx_dma;
@@ -892,7 +923,9 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
 	/* Configure the slave DMA */
 	memset(&config, 0, sizeof(config));
 	config.direction = DMA_MEM_TO_DEV;
-	config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	config.dst_addr_width = (atmel_port->fifo_size) ?
+				DMA_SLAVE_BUSWIDTH_4_BYTES :
+				DMA_SLAVE_BUSWIDTH_1_BYTE;
 	config.dst_addr = port->mapbase + ATMEL_US_THR;
 	config.dst_maxburst = 1;
 
@@ -1831,6 +1864,9 @@ static int atmel_startup(struct uart_port *port)
 				  ATMEL_US_RXFCLR |
 				  ATMEL_US_TXFLCLR);
 
+		if (atmel_use_dma_tx(port))
+			txrdym = ATMEL_US_FOUR_DATA;
+
 		fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
 		if (atmel_port->rts_high &&
 		    atmel_port->rts_low)
-- 
1.8.2.2

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

* Re: [PATCH v4 3/5] tty/serial: at91: remove bunch of macros to access UART registers
  2015-07-02 13:18   ` Cyrille Pitchen
  (?)
@ 2015-07-20 12:24     ` Nicolas Ferre
  -1 siblings, 0 replies; 35+ messages in thread
From: Nicolas Ferre @ 2015-07-20 12:24 UTC (permalink / raw)
  To: Cyrille Pitchen, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt

Le 02/07/2015 15:18, Cyrille Pitchen a écrit :
> This patch replaces the UART_PUT_*, resp. UART_GET_*, macros by
> atmel_uart_writel(), resp. atmel_uart_readl(), inline function calls.
> 
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>

Ok with this move:
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>


> ---
>  drivers/tty/serial/atmel_serial.c | 313 +++++++++++++++++++-------------------
>  1 file changed, 159 insertions(+), 154 deletions(-)
> 
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index 2a8f528153e7..e7c337de31d1 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -88,37 +88,6 @@ static void atmel_stop_rx(struct uart_port *port);
>  
>  #define ATMEL_ISR_PASS_LIMIT	256
>  
> -/* UART registers. CR is write-only, hence no GET macro */
> -#define UART_PUT_CR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_CR)
> -#define UART_GET_MR(port)	__raw_readl((port)->membase + ATMEL_US_MR)
> -#define UART_PUT_MR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_MR)
> -#define UART_PUT_IER(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IER)
> -#define UART_PUT_IDR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IDR)
> -#define UART_GET_IMR(port)	__raw_readl((port)->membase + ATMEL_US_IMR)
> -#define UART_GET_CSR(port)	__raw_readl((port)->membase + ATMEL_US_CSR)
> -#define UART_GET_CHAR(port)	__raw_readl((port)->membase + ATMEL_US_RHR)
> -#define UART_PUT_CHAR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_THR)
> -#define UART_GET_BRGR(port)	__raw_readl((port)->membase + ATMEL_US_BRGR)
> -#define UART_PUT_BRGR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_BRGR)
> -#define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
> -#define UART_PUT_TTGR(port, v)	__raw_writel(v, (port)->membase + ATMEL_US_TTGR)
> -#define UART_GET_IP_NAME(port)	__raw_readl((port)->membase + ATMEL_US_NAME)
> -#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
> -
> - /* PDC registers */
> -#define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
> -#define UART_GET_PTSR(port)	__raw_readl((port)->membase + ATMEL_PDC_PTSR)
> -
> -#define UART_PUT_RPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
> -#define UART_GET_RPR(port)	__raw_readl((port)->membase + ATMEL_PDC_RPR)
> -#define UART_PUT_RCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
> -#define UART_PUT_RNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
> -#define UART_PUT_RNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
> -
> -#define UART_PUT_TPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
> -#define UART_PUT_TCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
> -#define UART_GET_TCR(port)	__raw_readl((port)->membase + ATMEL_PDC_TCR)
> -
>  struct atmel_dma_buffer {
>  	unsigned char	*buf;
>  	dma_addr_t	dma_addr;
> @@ -212,6 +181,16 @@ to_atmel_uart_port(struct uart_port *uart)
>  	return container_of(uart, struct atmel_uart_port, uart);
>  }
>  
> +static inline u32 atmel_uart_readl(struct uart_port *port, u32 reg)
> +{
> +	return __raw_readl(port->membase + reg);
> +}
> +
> +static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
> +{
> +	__raw_writel(value, port->membase + reg);
> +}
> +
>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>  static bool atmel_use_pdc_rx(struct uart_port *port)
>  {
> @@ -257,7 +236,7 @@ static unsigned int atmel_get_lines_status(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  	unsigned int status, ret = 0;
>  
> -	status = UART_GET_CSR(port);
> +	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  
>  	mctrl_gpio_get(atmel_port->gpios, &ret);
>  
> @@ -304,9 +283,9 @@ static int atmel_config_rs485(struct uart_port *port,
>  	unsigned int mode;
>  
>  	/* Disable interrupts */
> -	UART_PUT_IDR(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
>  
> -	mode = UART_GET_MR(port);
> +	mode = atmel_uart_readl(port, ATMEL_US_MR);
>  
>  	/* Resetting serial mode to RS232 (0x0) */
>  	mode &= ~ATMEL_US_USMODE;
> @@ -316,7 +295,8 @@ static int atmel_config_rs485(struct uart_port *port,
>  	if (rs485conf->flags & SER_RS485_ENABLED) {
>  		dev_dbg(port->dev, "Setting UART to RS485\n");
>  		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
> -		UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
> +		atmel_uart_writel(port, ATMEL_US_TTGR,
> +				  rs485conf->delay_rts_after_send);
>  		mode |= ATMEL_US_USMODE_RS485;
>  	} else {
>  		dev_dbg(port->dev, "Setting UART to RS232\n");
> @@ -326,10 +306,10 @@ static int atmel_config_rs485(struct uart_port *port,
>  		else
>  			atmel_port->tx_done_mask = ATMEL_US_TXRDY;
>  	}
> -	UART_PUT_MR(port, mode);
> +	atmel_uart_writel(port, ATMEL_US_MR, mode);
>  
>  	/* Enable interrupts */
> -	UART_PUT_IER(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
>  
>  	return 0;
>  }
> @@ -339,7 +319,9 @@ static int atmel_config_rs485(struct uart_port *port,
>   */
>  static u_int atmel_tx_empty(struct uart_port *port)
>  {
> -	return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
> +	return (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY) ?
> +		TIOCSER_TEMT :
> +		0;
>  }
>  
>  /*
> @@ -348,13 +330,14 @@ static u_int atmel_tx_empty(struct uart_port *port)
>  static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
>  {
>  	unsigned int control = 0;
> -	unsigned int mode = UART_GET_MR(port);
> +	unsigned int mode = atmel_uart_readl(port, ATMEL_US_MR);
>  	unsigned int rts_paused, rts_ready;
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
>  	/* override mode to RS485 if needed, otherwise keep the current mode */
>  	if (port->rs485.flags & SER_RS485_ENABLED) {
> -		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
> +		atmel_uart_writel(port, ATMEL_US_TTGR,
> +				  port->rs485.delay_rts_after_send);
>  		mode &= ~ATMEL_US_USMODE;
>  		mode |= ATMEL_US_USMODE_RS485;
>  	}
> @@ -384,7 +367,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
>  	else
>  		control |= ATMEL_US_DTRDIS;
>  
> -	UART_PUT_CR(port, control);
> +	atmel_uart_writel(port, ATMEL_US_CR, control);
>  
>  	mctrl_gpio_set(atmel_port->gpios, mctrl);
>  
> @@ -395,7 +378,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
>  	else
>  		mode |= ATMEL_US_CHMODE_NORMAL;
>  
> -	UART_PUT_MR(port, mode);
> +	atmel_uart_writel(port, ATMEL_US_MR, mode);
>  }
>  
>  /*
> @@ -406,7 +389,7 @@ static u_int atmel_get_mctrl(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  	unsigned int ret = 0, status;
>  
> -	status = UART_GET_CSR(port);
> +	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  
>  	/*
>  	 * The control signals are active low.
> @@ -432,10 +415,10 @@ static void atmel_stop_tx(struct uart_port *port)
>  
>  	if (atmel_use_pdc_tx(port)) {
>  		/* disable PDC transmit */
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
>  	}
>  	/* Disable interrupts */
> -	UART_PUT_IDR(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
>  
>  	if ((port->rs485.flags & SER_RS485_ENABLED) &&
>  	    !(port->rs485.flags & SER_RS485_RX_DURING_TX))
> @@ -450,7 +433,7 @@ static void atmel_start_tx(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
>  	if (atmel_use_pdc_tx(port)) {
> -		if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
> +		if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
>  			/* The transmitter is already running.  Yes, we
>  			   really need this.*/
>  			return;
> @@ -460,10 +443,10 @@ static void atmel_start_tx(struct uart_port *port)
>  			atmel_stop_rx(port);
>  
>  		/* re-enable PDC transmit */
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
>  	}
>  	/* Enable interrupts */
> -	UART_PUT_IER(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
>  }
>  
>  /*
> @@ -471,17 +454,19 @@ static void atmel_start_tx(struct uart_port *port)
>   */
>  static void atmel_start_rx(struct uart_port *port)
>  {
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA);  /* reset status and receiver */
> +	/* reset status and receiver */
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
>  
> -	UART_PUT_CR(port, ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXEN);
>  
>  	if (atmel_use_pdc_rx(port)) {
>  		/* enable PDC controller */
> -		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> -			port->read_status_mask);
> -		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
> +		atmel_uart_writel(port, ATMEL_US_IER,
> +				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> +				  port->read_status_mask);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
>  	} else {
> -		UART_PUT_IER(port, ATMEL_US_RXRDY);
> +		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
>  	}
>  }
>  
> @@ -490,15 +475,16 @@ static void atmel_start_rx(struct uart_port *port)
>   */
>  static void atmel_stop_rx(struct uart_port *port)
>  {
> -	UART_PUT_CR(port, ATMEL_US_RXDIS);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXDIS);
>  
>  	if (atmel_use_pdc_rx(port)) {
>  		/* disable PDC receive */
> -		UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
> -		UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> -			port->read_status_mask);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS);
> +		atmel_uart_writel(port, ATMEL_US_IDR,
> +				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> +				  port->read_status_mask);
>  	} else {
> -		UART_PUT_IDR(port, ATMEL_US_RXRDY);
> +		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXRDY);
>  	}
>  }
>  
> @@ -538,7 +524,7 @@ static void atmel_enable_ms(struct uart_port *port)
>  	else
>  		ier |= ATMEL_US_DCDIC;
>  
> -	UART_PUT_IER(port, ier);
> +	atmel_uart_writel(port, ATMEL_US_IER, ier);
>  }
>  
>  /*
> @@ -577,7 +563,7 @@ static void atmel_disable_ms(struct uart_port *port)
>  	else
>  		idr |= ATMEL_US_DCDIC;
>  
> -	UART_PUT_IDR(port, idr);
> +	atmel_uart_writel(port, ATMEL_US_IDR, idr);
>  }
>  
>  /*
> @@ -586,9 +572,11 @@ static void atmel_disable_ms(struct uart_port *port)
>  static void atmel_break_ctl(struct uart_port *port, int break_state)
>  {
>  	if (break_state != 0)
> -		UART_PUT_CR(port, ATMEL_US_STTBRK);	/* start break */
> +		/* start break */
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTBRK);
>  	else
> -		UART_PUT_CR(port, ATMEL_US_STPBRK);	/* stop break */
> +		/* stop break */
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STPBRK);
>  }
>  
>  /*
> @@ -622,7 +610,7 @@ atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
>  static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
>  {
>  	/* clear error */
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
>  
>  	if (status & ATMEL_US_RXBRK) {
>  		/* ignore side-effect */
> @@ -645,9 +633,9 @@ static void atmel_rx_chars(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  	unsigned int status, ch;
>  
> -	status = UART_GET_CSR(port);
> +	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	while (status & ATMEL_US_RXRDY) {
> -		ch = UART_GET_CHAR(port);
> +		ch = atmel_uart_readl(port, ATMEL_US_RHR);
>  
>  		/*
>  		 * note that the error handling code is
> @@ -658,12 +646,13 @@ static void atmel_rx_chars(struct uart_port *port)
>  			     || atmel_port->break_active)) {
>  
>  			/* clear error */
> -			UART_PUT_CR(port, ATMEL_US_RSTSTA);
> +			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
>  
>  			if (status & ATMEL_US_RXBRK
>  			    && !atmel_port->break_active) {
>  				atmel_port->break_active = 1;
> -				UART_PUT_IER(port, ATMEL_US_RXBRK);
> +				atmel_uart_writel(port, ATMEL_US_IER,
> +						  ATMEL_US_RXBRK);
>  			} else {
>  				/*
>  				 * This is either the end-of-break
> @@ -672,14 +661,15 @@ static void atmel_rx_chars(struct uart_port *port)
>  				 * being set. In both cases, the next
>  				 * RXBRK will indicate start-of-break.
>  				 */
> -				UART_PUT_IDR(port, ATMEL_US_RXBRK);
> +				atmel_uart_writel(port, ATMEL_US_IDR,
> +						  ATMEL_US_RXBRK);
>  				status &= ~ATMEL_US_RXBRK;
>  				atmel_port->break_active = 0;
>  			}
>  		}
>  
>  		atmel_buffer_rx_char(port, status, ch);
> -		status = UART_GET_CSR(port);
> +		status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	}
>  
>  	tasklet_schedule(&atmel_port->tasklet);
> @@ -694,16 +684,18 @@ static void atmel_tx_chars(struct uart_port *port)
>  	struct circ_buf *xmit = &port->state->xmit;
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
> -	if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
> -		UART_PUT_CHAR(port, port->x_char);
> +	if (port->x_char &&
> +	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
> +		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
>  		port->icount.tx++;
>  		port->x_char = 0;
>  	}
>  	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
>  		return;
>  
> -	while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
> -		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
> +	while (atmel_uart_readl(port, ATMEL_US_CSR) &
> +	       atmel_port->tx_done_mask) {
> +		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>  		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>  		port->icount.tx++;
>  		if (uart_circ_empty(xmit))
> @@ -715,7 +707,8 @@ static void atmel_tx_chars(struct uart_port *port)
>  
>  	if (!uart_circ_empty(xmit))
>  		/* Enable interrupts */
> -		UART_PUT_IER(port, atmel_port->tx_done_mask);
> +		atmel_uart_writel(port, ATMEL_US_IER,
> +				  atmel_port->tx_done_mask);
>  }
>  
>  static void atmel_complete_tx_dma(void *arg)
> @@ -935,14 +928,14 @@ static void atmel_rx_from_dma(struct uart_port *port)
>  
>  
>  	/* Reset the UART timeout early so that we don't miss one */
> -	UART_PUT_CR(port, ATMEL_US_STTTO);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  	dmastat = dmaengine_tx_status(chan,
>  				atmel_port->cookie_rx,
>  				&state);
>  	/* Restart a new tasklet if DMA status is error */
>  	if (dmastat == DMA_ERROR) {
>  		dev_dbg(port->dev, "Get residue error, restart tasklet\n");
> -		UART_PUT_IER(port, ATMEL_US_TIMEOUT);
> +		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
>  		tasklet_schedule(&atmel_port->tasklet);
>  		return;
>  	}
> @@ -1008,7 +1001,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
>  	tty_flip_buffer_push(tport);
>  	spin_lock(&port->lock);
>  
> -	UART_PUT_IER(port, ATMEL_US_TIMEOUT);
> +	atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
>  }
>  
>  static int atmel_prepare_rx_dma(struct uart_port *port)
> @@ -1118,8 +1111,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
>  		 * the moment.
>  		 */
>  		if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
> -			UART_PUT_IDR(port, (ATMEL_US_ENDRX
> -						| ATMEL_US_TIMEOUT));
> +			atmel_uart_writel(port, ATMEL_US_IDR,
> +					  (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
>  			tasklet_schedule(&atmel_port->tasklet);
>  		}
>  
> @@ -1130,7 +1123,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
>  
>  	if (atmel_use_dma_rx(port)) {
>  		if (pending & ATMEL_US_TIMEOUT) {
> -			UART_PUT_IDR(port, ATMEL_US_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_IDR,
> +					  ATMEL_US_TIMEOUT);
>  			tasklet_schedule(&atmel_port->tasklet);
>  		}
>  	}
> @@ -1143,8 +1137,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
>  		 * End of break detected. If it came along with a
>  		 * character, atmel_rx_chars will handle it.
>  		 */
> -		UART_PUT_CR(port, ATMEL_US_RSTSTA);
> -		UART_PUT_IDR(port, ATMEL_US_RXBRK);
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
> +		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXBRK);
>  		atmel_port->break_active = 0;
>  	}
>  }
> @@ -1159,7 +1153,8 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
>  
>  	if (pending & atmel_port->tx_done_mask) {
>  		/* Either PDC or interrupt transmission */
> -		UART_PUT_IDR(port, atmel_port->tx_done_mask);
> +		atmel_uart_writel(port, ATMEL_US_IDR,
> +				  atmel_port->tx_done_mask);
>  		tasklet_schedule(&atmel_port->tasklet);
>  	}
>  }
> @@ -1197,7 +1192,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
>  
>  	do {
>  		status = atmel_get_lines_status(port);
> -		mask = UART_GET_IMR(port);
> +		mask = atmel_uart_readl(port, ATMEL_US_IMR);
>  		pending = status & mask;
>  		if (!gpio_handled) {
>  			/*
> @@ -1223,7 +1218,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
>  		if (atmel_port->suspended) {
>  			atmel_port->pending |= pending;
>  			atmel_port->pending_status = status;
> -			UART_PUT_IDR(port, mask);
> +			atmel_uart_writel(port, ATMEL_US_IDR, mask);
>  			pm_system_wakeup();
>  			break;
>  		}
> @@ -1260,7 +1255,7 @@ static void atmel_tx_pdc(struct uart_port *port)
>  	int count;
>  
>  	/* nothing left to transmit? */
> -	if (UART_GET_TCR(port))
> +	if (atmel_uart_readl(port, ATMEL_PDC_TCR))
>  		return;
>  
>  	xmit->tail += pdc->ofs;
> @@ -1272,7 +1267,7 @@ static void atmel_tx_pdc(struct uart_port *port)
>  	/* more to transmit - setup next transfer */
>  
>  	/* disable PDC transmit */
> -	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
> +	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
>  
>  	if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
>  		dma_sync_single_for_device(port->dev,
> @@ -1283,12 +1278,14 @@ static void atmel_tx_pdc(struct uart_port *port)
>  		count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
>  		pdc->ofs = count;
>  
> -		UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
> -		UART_PUT_TCR(port, count);
> +		atmel_uart_writel(port, ATMEL_PDC_TPR,
> +				  pdc->dma_addr + xmit->tail);
> +		atmel_uart_writel(port, ATMEL_PDC_TCR, count);
>  		/* re-enable PDC transmit */
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
>  		/* Enable interrupts */
> -		UART_PUT_IER(port, atmel_port->tx_done_mask);
> +		atmel_uart_writel(port, ATMEL_US_IER,
> +				  atmel_port->tx_done_mask);
>  	} else {
>  		if ((port->rs485.flags & SER_RS485_ENABLED) &&
>  		    !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
> @@ -1414,10 +1411,10 @@ static void atmel_rx_from_pdc(struct uart_port *port)
>  
>  	do {
>  		/* Reset the UART timeout early so that we don't miss one */
> -		UART_PUT_CR(port, ATMEL_US_STTTO);
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  
>  		pdc = &atmel_port->pdc_rx[rx_idx];
> -		head = UART_GET_RPR(port) - pdc->dma_addr;
> +		head = atmel_uart_readl(port, ATMEL_PDC_RPR) - pdc->dma_addr;
>  		tail = pdc->ofs;
>  
>  		/* If the PDC has switched buffers, RPR won't contain
> @@ -1460,8 +1457,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
>  		 */
>  		if (head >= pdc->dma_size) {
>  			pdc->ofs = 0;
> -			UART_PUT_RNPR(port, pdc->dma_addr);
> -			UART_PUT_RNCR(port, pdc->dma_size);
> +			atmel_uart_writel(port, ATMEL_PDC_RNPR, pdc->dma_addr);
> +			atmel_uart_writel(port, ATMEL_PDC_RNCR, pdc->dma_size);
>  
>  			rx_idx = !rx_idx;
>  			atmel_port->pdc_rx_idx = rx_idx;
> @@ -1476,7 +1473,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
>  	tty_flip_buffer_push(tport);
>  	spin_lock(&port->lock);
>  
> -	UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
> +	atmel_uart_writel(port, ATMEL_US_IER,
> +			  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
>  }
>  
>  static int atmel_prepare_rx_pdc(struct uart_port *port)
> @@ -1509,11 +1507,12 @@ static int atmel_prepare_rx_pdc(struct uart_port *port)
>  
>  	atmel_port->pdc_rx_idx = 0;
>  
> -	UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
> -	UART_PUT_RCR(port, PDC_BUFFER_SIZE);
> +	atmel_uart_writel(port, ATMEL_PDC_RPR, atmel_port->pdc_rx[0].dma_addr);
> +	atmel_uart_writel(port, ATMEL_PDC_RCR, PDC_BUFFER_SIZE);
>  
> -	UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
> -	UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
> +	atmel_uart_writel(port, ATMEL_PDC_RNPR,
> +			  atmel_port->pdc_rx[1].dma_addr);
> +	atmel_uart_writel(port, ATMEL_PDC_RNCR, PDC_BUFFER_SIZE);
>  
>  	return 0;
>  }
> @@ -1667,7 +1666,7 @@ static void atmel_set_ops(struct uart_port *port)
>  static void atmel_get_ip_name(struct uart_port *port)
>  {
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
> -	int name = UART_GET_IP_NAME(port);
> +	int name = atmel_uart_readl(port, ATMEL_US_NAME);
>  	u32 version;
>  	int usart, uart;
>  	/* usart and uart ascii */
> @@ -1684,7 +1683,7 @@ static void atmel_get_ip_name(struct uart_port *port)
>  		atmel_port->is_usart = false;
>  	} else {
>  		/* fallback for older SoCs: use version field */
> -		version = UART_GET_IP_VERSION(port);
> +		version = atmel_uart_readl(port, ATMEL_US_VERSION);
>  		switch (version) {
>  		case 0x302:
>  		case 0x10213:
> @@ -1756,7 +1755,7 @@ static int atmel_startup(struct uart_port *port)
>  	 * request_irq() is called we could get stuck trying to
>  	 * handle an unexpected interrupt
>  	 */
> -	UART_PUT_IDR(port, -1);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  	atmel_port->ms_irq_enabled = false;
>  
>  	/*
> @@ -1804,9 +1803,9 @@ static int atmel_startup(struct uart_port *port)
>  	/*
>  	 * Finally, enable the serial port
>  	 */
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
>  	/* enable xmit & rcvr */
> -	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
>  
>  	setup_timer(&atmel_port->uart_timer,
>  			atmel_uart_timer_callback,
> @@ -1819,13 +1818,14 @@ static int atmel_startup(struct uart_port *port)
>  					jiffies + uart_poll_timeout(port));
>  		/* set USART timeout */
>  		} else {
> -			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
> -			UART_PUT_CR(port, ATMEL_US_STTTO);
> +			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  
> -			UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_IER,
> +					  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
>  		}
>  		/* enable PDC controller */
> -		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
>  	} else if (atmel_use_dma_rx(port)) {
>  		/* set UART timeout */
>  		if (!atmel_port->is_usart) {
> @@ -1833,14 +1833,15 @@ static int atmel_startup(struct uart_port *port)
>  					jiffies + uart_poll_timeout(port));
>  		/* set USART timeout */
>  		} else {
> -			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
> -			UART_PUT_CR(port, ATMEL_US_STTTO);
> +			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  
> -			UART_PUT_IER(port, ATMEL_US_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_IER,
> +					  ATMEL_US_TIMEOUT);
>  		}
>  	} else {
>  		/* enable receive only */
> -		UART_PUT_IER(port, ATMEL_US_RXRDY);
> +		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
>  	}
>  
>  	return 0;
> @@ -1860,7 +1861,7 @@ static void atmel_flush_buffer(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
>  	if (atmel_use_pdc_tx(port)) {
> -		UART_PUT_TCR(port, 0);
> +		atmel_uart_writel(port, ATMEL_PDC_TCR, 0);
>  		atmel_port->pdc_tx.ofs = 0;
>  	}
>  }
> @@ -1892,8 +1893,8 @@ static void atmel_shutdown(struct uart_port *port)
>  	atmel_stop_rx(port);
>  	atmel_stop_tx(port);
>  
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA);
> -	UART_PUT_IDR(port, -1);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  
>  
>  	/*
> @@ -1938,12 +1939,12 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
>  		clk_prepare_enable(atmel_port->clk);
>  
>  		/* re-enable interrupts if we disabled some on suspend */
> -		UART_PUT_IER(port, atmel_port->backup_imr);
> +		atmel_uart_writel(port, ATMEL_US_IER, atmel_port->backup_imr);
>  		break;
>  	case 3:
>  		/* Back up the interrupt mask and disable all interrupts */
> -		atmel_port->backup_imr = UART_GET_IMR(port);
> -		UART_PUT_IDR(port, -1);
> +		atmel_port->backup_imr = atmel_uart_readl(port, ATMEL_US_IMR);
> +		atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  
>  		/*
>  		 * Disable the peripheral clock for this serial port.
> @@ -1966,7 +1967,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  	unsigned int old_mode, mode, imr, quot, baud;
>  
>  	/* save the current mode register */
> -	mode = old_mode = UART_GET_MR(port);
> +	mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR);
>  
>  	/* reset the mode, clock divisor, parity, stop bits and data size */
>  	mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP |
> @@ -2025,7 +2026,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  
>  	if (atmel_use_pdc_rx(port))
>  		/* need to enable error interrupts */
> -		UART_PUT_IER(port, port->read_status_mask);
> +		atmel_uart_writel(port, ATMEL_US_IER, port->read_status_mask);
>  
>  	/*
>  	 * Characters to ignore
> @@ -2052,15 +2053,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  	 * transmitter is empty if requested by the caller, so there's
>  	 * no need to wait for it here.
>  	 */
> -	imr = UART_GET_IMR(port);
> -	UART_PUT_IDR(port, -1);
> +	imr = atmel_uart_readl(port, ATMEL_US_IMR);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  
>  	/* disable receiver and transmitter */
> -	UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
>  
>  	/* mode */
>  	if (port->rs485.flags & SER_RS485_ENABLED) {
> -		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
> +		atmel_uart_writel(port, ATMEL_US_TTGR,
> +				  port->rs485.delay_rts_after_send);
>  		mode |= ATMEL_US_USMODE_RS485;
>  	} else if (termios->c_cflag & CRTSCTS) {
>  		/* RS232 with hardware handshake (RTS/CTS) */
> @@ -2071,7 +2073,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  	}
>  
>  	/* set the mode, clock divisor, parity, stop bits and data size */
> -	UART_PUT_MR(port, mode);
> +	atmel_uart_writel(port, ATMEL_US_MR, mode);
>  
>  	/*
>  	 * when switching the mode, set the RTS line state according to the
> @@ -2088,16 +2090,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  			rts_state = ATMEL_US_RTSEN;
>  		}
>  
> -		UART_PUT_CR(port, rts_state);
> +		atmel_uart_writel(port, ATMEL_US_CR, rts_state);
>  	}
>  
>  	/* set the baud rate */
> -	UART_PUT_BRGR(port, quot);
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> -	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_BRGR, quot);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
>  
>  	/* restore interrupts */
> -	UART_PUT_IER(port, imr);
> +	atmel_uart_writel(port, ATMEL_US_IER, imr);
>  
>  	/* CTS flow-control and modem-status interrupts */
>  	if (UART_ENABLE_MS(port, termios->c_cflag))
> @@ -2208,18 +2210,18 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
>  #ifdef CONFIG_CONSOLE_POLL
>  static int atmel_poll_get_char(struct uart_port *port)
>  {
> -	while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
> +	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>  		cpu_relax();
>  
> -	return UART_GET_CHAR(port);
> +	return atmel_uart_readl(port, ATMEL_US_RHR);
>  }
>  
>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>  {
> -	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
> +	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
>  
> -	UART_PUT_CHAR(port, ch);
> +	atmel_uart_writel(port, ATMEL_US_THR, ch);
>  }
>  #endif
>  
> @@ -2324,9 +2326,9 @@ struct platform_device *atmel_default_console_device;	/* the serial console devi
>  #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
>  static void atmel_console_putchar(struct uart_port *port, int ch)
>  {
> -	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
> +	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
> -	UART_PUT_CHAR(port, ch);
> +	atmel_uart_writel(port, ATMEL_US_THR, ch);
>  }
>  
>  /*
> @@ -2342,12 +2344,13 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
>  	/*
>  	 * First, save IMR and then disable interrupts
>  	 */
> -	imr = UART_GET_IMR(port);
> -	UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
> +	imr = atmel_uart_readl(port, ATMEL_US_IMR);
> +	atmel_uart_writel(port, ATMEL_US_IDR,
> +			  ATMEL_US_RXRDY | atmel_port->tx_done_mask);
>  
>  	/* Store PDC transmit status and disable it */
> -	pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
> -	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
> +	pdc_tx = atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN;
> +	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
>  
>  	uart_console_write(port, s, count, atmel_console_putchar);
>  
> @@ -2356,15 +2359,15 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
>  	 * and restore IMR
>  	 */
>  	do {
> -		status = UART_GET_CSR(port);
> +		status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	} while (!(status & ATMEL_US_TXRDY));
>  
>  	/* Restore PDC transmit status */
>  	if (pdc_tx)
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
>  
>  	/* set interrupts back the way they were */
> -	UART_PUT_IER(port, imr);
> +	atmel_uart_writel(port, ATMEL_US_IER, imr);
>  }
>  
>  /*
> @@ -2380,17 +2383,17 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
>  	 * If the baud rate generator isn't running, the port wasn't
>  	 * initialized by the boot loader.
>  	 */
> -	quot = UART_GET_BRGR(port) & ATMEL_US_CD;
> +	quot = atmel_uart_readl(port, ATMEL_US_BRGR) & ATMEL_US_CD;
>  	if (!quot)
>  		return;
>  
> -	mr = UART_GET_MR(port) & ATMEL_US_CHRL;
> +	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_CHRL;
>  	if (mr == ATMEL_US_CHRL_8)
>  		*bits = 8;
>  	else
>  		*bits = 7;
>  
> -	mr = UART_GET_MR(port) & ATMEL_US_PAR;
> +	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_PAR;
>  	if (mr == ATMEL_US_PAR_EVEN)
>  		*parity = 'e';
>  	else if (mr == ATMEL_US_PAR_ODD)
> @@ -2423,9 +2426,9 @@ static int __init atmel_console_setup(struct console *co, char *options)
>  	if (ret)
>  		return ret;
>  
> -	UART_PUT_IDR(port, -1);
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> -	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
>  
>  	if (options)
>  		uart_parse_options(options, &baud, &parity, &bits, &flow);
> @@ -2532,7 +2535,8 @@ static int atmel_serial_suspend(struct platform_device *pdev,
>  
>  	if (atmel_is_console_port(port) && console_suspend_enabled) {
>  		/* Drain the TX shifter */
> -		while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
> +		while (!(atmel_uart_readl(port, ATMEL_US_CSR) &
> +			 ATMEL_US_TXEMPTY))
>  			cpu_relax();
>  	}
>  
> @@ -2684,8 +2688,9 @@ static int atmel_serial_probe(struct platform_device *pdev)
>  	clk_prepare_enable(port->clk);
>  
>  	if (rs485_enabled) {
> -		UART_PUT_MR(&port->uart, ATMEL_US_USMODE_NORMAL);
> -		UART_PUT_CR(&port->uart, ATMEL_US_RTSEN);
> +		atmel_uart_writel(&port->uart, ATMEL_US_MR,
> +				  ATMEL_US_USMODE_NORMAL);
> +		atmel_uart_writel(&port->uart, ATMEL_US_CR, ATMEL_US_RTSEN);
>  	}
>  
>  	/*
> 


-- 
Nicolas Ferre

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

* Re: [PATCH v4 3/5] tty/serial: at91: remove bunch of macros to access UART registers
@ 2015-07-20 12:24     ` Nicolas Ferre
  0 siblings, 0 replies; 35+ messages in thread
From: Nicolas Ferre @ 2015-07-20 12:24 UTC (permalink / raw)
  To: Cyrille Pitchen, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt

Le 02/07/2015 15:18, Cyrille Pitchen a écrit :
> This patch replaces the UART_PUT_*, resp. UART_GET_*, macros by
> atmel_uart_writel(), resp. atmel_uart_readl(), inline function calls.
> 
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>

Ok with this move:
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>


> ---
>  drivers/tty/serial/atmel_serial.c | 313 +++++++++++++++++++-------------------
>  1 file changed, 159 insertions(+), 154 deletions(-)
> 
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index 2a8f528153e7..e7c337de31d1 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -88,37 +88,6 @@ static void atmel_stop_rx(struct uart_port *port);
>  
>  #define ATMEL_ISR_PASS_LIMIT	256
>  
> -/* UART registers. CR is write-only, hence no GET macro */
> -#define UART_PUT_CR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_CR)
> -#define UART_GET_MR(port)	__raw_readl((port)->membase + ATMEL_US_MR)
> -#define UART_PUT_MR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_MR)
> -#define UART_PUT_IER(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IER)
> -#define UART_PUT_IDR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IDR)
> -#define UART_GET_IMR(port)	__raw_readl((port)->membase + ATMEL_US_IMR)
> -#define UART_GET_CSR(port)	__raw_readl((port)->membase + ATMEL_US_CSR)
> -#define UART_GET_CHAR(port)	__raw_readl((port)->membase + ATMEL_US_RHR)
> -#define UART_PUT_CHAR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_THR)
> -#define UART_GET_BRGR(port)	__raw_readl((port)->membase + ATMEL_US_BRGR)
> -#define UART_PUT_BRGR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_BRGR)
> -#define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
> -#define UART_PUT_TTGR(port, v)	__raw_writel(v, (port)->membase + ATMEL_US_TTGR)
> -#define UART_GET_IP_NAME(port)	__raw_readl((port)->membase + ATMEL_US_NAME)
> -#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
> -
> - /* PDC registers */
> -#define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
> -#define UART_GET_PTSR(port)	__raw_readl((port)->membase + ATMEL_PDC_PTSR)
> -
> -#define UART_PUT_RPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
> -#define UART_GET_RPR(port)	__raw_readl((port)->membase + ATMEL_PDC_RPR)
> -#define UART_PUT_RCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
> -#define UART_PUT_RNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
> -#define UART_PUT_RNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
> -
> -#define UART_PUT_TPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
> -#define UART_PUT_TCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
> -#define UART_GET_TCR(port)	__raw_readl((port)->membase + ATMEL_PDC_TCR)
> -
>  struct atmel_dma_buffer {
>  	unsigned char	*buf;
>  	dma_addr_t	dma_addr;
> @@ -212,6 +181,16 @@ to_atmel_uart_port(struct uart_port *uart)
>  	return container_of(uart, struct atmel_uart_port, uart);
>  }
>  
> +static inline u32 atmel_uart_readl(struct uart_port *port, u32 reg)
> +{
> +	return __raw_readl(port->membase + reg);
> +}
> +
> +static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
> +{
> +	__raw_writel(value, port->membase + reg);
> +}
> +
>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>  static bool atmel_use_pdc_rx(struct uart_port *port)
>  {
> @@ -257,7 +236,7 @@ static unsigned int atmel_get_lines_status(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  	unsigned int status, ret = 0;
>  
> -	status = UART_GET_CSR(port);
> +	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  
>  	mctrl_gpio_get(atmel_port->gpios, &ret);
>  
> @@ -304,9 +283,9 @@ static int atmel_config_rs485(struct uart_port *port,
>  	unsigned int mode;
>  
>  	/* Disable interrupts */
> -	UART_PUT_IDR(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
>  
> -	mode = UART_GET_MR(port);
> +	mode = atmel_uart_readl(port, ATMEL_US_MR);
>  
>  	/* Resetting serial mode to RS232 (0x0) */
>  	mode &= ~ATMEL_US_USMODE;
> @@ -316,7 +295,8 @@ static int atmel_config_rs485(struct uart_port *port,
>  	if (rs485conf->flags & SER_RS485_ENABLED) {
>  		dev_dbg(port->dev, "Setting UART to RS485\n");
>  		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
> -		UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
> +		atmel_uart_writel(port, ATMEL_US_TTGR,
> +				  rs485conf->delay_rts_after_send);
>  		mode |= ATMEL_US_USMODE_RS485;
>  	} else {
>  		dev_dbg(port->dev, "Setting UART to RS232\n");
> @@ -326,10 +306,10 @@ static int atmel_config_rs485(struct uart_port *port,
>  		else
>  			atmel_port->tx_done_mask = ATMEL_US_TXRDY;
>  	}
> -	UART_PUT_MR(port, mode);
> +	atmel_uart_writel(port, ATMEL_US_MR, mode);
>  
>  	/* Enable interrupts */
> -	UART_PUT_IER(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
>  
>  	return 0;
>  }
> @@ -339,7 +319,9 @@ static int atmel_config_rs485(struct uart_port *port,
>   */
>  static u_int atmel_tx_empty(struct uart_port *port)
>  {
> -	return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
> +	return (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY) ?
> +		TIOCSER_TEMT :
> +		0;
>  }
>  
>  /*
> @@ -348,13 +330,14 @@ static u_int atmel_tx_empty(struct uart_port *port)
>  static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
>  {
>  	unsigned int control = 0;
> -	unsigned int mode = UART_GET_MR(port);
> +	unsigned int mode = atmel_uart_readl(port, ATMEL_US_MR);
>  	unsigned int rts_paused, rts_ready;
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
>  	/* override mode to RS485 if needed, otherwise keep the current mode */
>  	if (port->rs485.flags & SER_RS485_ENABLED) {
> -		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
> +		atmel_uart_writel(port, ATMEL_US_TTGR,
> +				  port->rs485.delay_rts_after_send);
>  		mode &= ~ATMEL_US_USMODE;
>  		mode |= ATMEL_US_USMODE_RS485;
>  	}
> @@ -384,7 +367,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
>  	else
>  		control |= ATMEL_US_DTRDIS;
>  
> -	UART_PUT_CR(port, control);
> +	atmel_uart_writel(port, ATMEL_US_CR, control);
>  
>  	mctrl_gpio_set(atmel_port->gpios, mctrl);
>  
> @@ -395,7 +378,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
>  	else
>  		mode |= ATMEL_US_CHMODE_NORMAL;
>  
> -	UART_PUT_MR(port, mode);
> +	atmel_uart_writel(port, ATMEL_US_MR, mode);
>  }
>  
>  /*
> @@ -406,7 +389,7 @@ static u_int atmel_get_mctrl(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  	unsigned int ret = 0, status;
>  
> -	status = UART_GET_CSR(port);
> +	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  
>  	/*
>  	 * The control signals are active low.
> @@ -432,10 +415,10 @@ static void atmel_stop_tx(struct uart_port *port)
>  
>  	if (atmel_use_pdc_tx(port)) {
>  		/* disable PDC transmit */
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
>  	}
>  	/* Disable interrupts */
> -	UART_PUT_IDR(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
>  
>  	if ((port->rs485.flags & SER_RS485_ENABLED) &&
>  	    !(port->rs485.flags & SER_RS485_RX_DURING_TX))
> @@ -450,7 +433,7 @@ static void atmel_start_tx(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
>  	if (atmel_use_pdc_tx(port)) {
> -		if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
> +		if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
>  			/* The transmitter is already running.  Yes, we
>  			   really need this.*/
>  			return;
> @@ -460,10 +443,10 @@ static void atmel_start_tx(struct uart_port *port)
>  			atmel_stop_rx(port);
>  
>  		/* re-enable PDC transmit */
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
>  	}
>  	/* Enable interrupts */
> -	UART_PUT_IER(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
>  }
>  
>  /*
> @@ -471,17 +454,19 @@ static void atmel_start_tx(struct uart_port *port)
>   */
>  static void atmel_start_rx(struct uart_port *port)
>  {
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA);  /* reset status and receiver */
> +	/* reset status and receiver */
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
>  
> -	UART_PUT_CR(port, ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXEN);
>  
>  	if (atmel_use_pdc_rx(port)) {
>  		/* enable PDC controller */
> -		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> -			port->read_status_mask);
> -		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
> +		atmel_uart_writel(port, ATMEL_US_IER,
> +				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> +				  port->read_status_mask);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
>  	} else {
> -		UART_PUT_IER(port, ATMEL_US_RXRDY);
> +		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
>  	}
>  }
>  
> @@ -490,15 +475,16 @@ static void atmel_start_rx(struct uart_port *port)
>   */
>  static void atmel_stop_rx(struct uart_port *port)
>  {
> -	UART_PUT_CR(port, ATMEL_US_RXDIS);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXDIS);
>  
>  	if (atmel_use_pdc_rx(port)) {
>  		/* disable PDC receive */
> -		UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
> -		UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> -			port->read_status_mask);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS);
> +		atmel_uart_writel(port, ATMEL_US_IDR,
> +				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> +				  port->read_status_mask);
>  	} else {
> -		UART_PUT_IDR(port, ATMEL_US_RXRDY);
> +		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXRDY);
>  	}
>  }
>  
> @@ -538,7 +524,7 @@ static void atmel_enable_ms(struct uart_port *port)
>  	else
>  		ier |= ATMEL_US_DCDIC;
>  
> -	UART_PUT_IER(port, ier);
> +	atmel_uart_writel(port, ATMEL_US_IER, ier);
>  }
>  
>  /*
> @@ -577,7 +563,7 @@ static void atmel_disable_ms(struct uart_port *port)
>  	else
>  		idr |= ATMEL_US_DCDIC;
>  
> -	UART_PUT_IDR(port, idr);
> +	atmel_uart_writel(port, ATMEL_US_IDR, idr);
>  }
>  
>  /*
> @@ -586,9 +572,11 @@ static void atmel_disable_ms(struct uart_port *port)
>  static void atmel_break_ctl(struct uart_port *port, int break_state)
>  {
>  	if (break_state != 0)
> -		UART_PUT_CR(port, ATMEL_US_STTBRK);	/* start break */
> +		/* start break */
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTBRK);
>  	else
> -		UART_PUT_CR(port, ATMEL_US_STPBRK);	/* stop break */
> +		/* stop break */
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STPBRK);
>  }
>  
>  /*
> @@ -622,7 +610,7 @@ atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
>  static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
>  {
>  	/* clear error */
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
>  
>  	if (status & ATMEL_US_RXBRK) {
>  		/* ignore side-effect */
> @@ -645,9 +633,9 @@ static void atmel_rx_chars(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  	unsigned int status, ch;
>  
> -	status = UART_GET_CSR(port);
> +	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	while (status & ATMEL_US_RXRDY) {
> -		ch = UART_GET_CHAR(port);
> +		ch = atmel_uart_readl(port, ATMEL_US_RHR);
>  
>  		/*
>  		 * note that the error handling code is
> @@ -658,12 +646,13 @@ static void atmel_rx_chars(struct uart_port *port)
>  			     || atmel_port->break_active)) {
>  
>  			/* clear error */
> -			UART_PUT_CR(port, ATMEL_US_RSTSTA);
> +			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
>  
>  			if (status & ATMEL_US_RXBRK
>  			    && !atmel_port->break_active) {
>  				atmel_port->break_active = 1;
> -				UART_PUT_IER(port, ATMEL_US_RXBRK);
> +				atmel_uart_writel(port, ATMEL_US_IER,
> +						  ATMEL_US_RXBRK);
>  			} else {
>  				/*
>  				 * This is either the end-of-break
> @@ -672,14 +661,15 @@ static void atmel_rx_chars(struct uart_port *port)
>  				 * being set. In both cases, the next
>  				 * RXBRK will indicate start-of-break.
>  				 */
> -				UART_PUT_IDR(port, ATMEL_US_RXBRK);
> +				atmel_uart_writel(port, ATMEL_US_IDR,
> +						  ATMEL_US_RXBRK);
>  				status &= ~ATMEL_US_RXBRK;
>  				atmel_port->break_active = 0;
>  			}
>  		}
>  
>  		atmel_buffer_rx_char(port, status, ch);
> -		status = UART_GET_CSR(port);
> +		status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	}
>  
>  	tasklet_schedule(&atmel_port->tasklet);
> @@ -694,16 +684,18 @@ static void atmel_tx_chars(struct uart_port *port)
>  	struct circ_buf *xmit = &port->state->xmit;
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
> -	if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
> -		UART_PUT_CHAR(port, port->x_char);
> +	if (port->x_char &&
> +	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
> +		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
>  		port->icount.tx++;
>  		port->x_char = 0;
>  	}
>  	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
>  		return;
>  
> -	while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
> -		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
> +	while (atmel_uart_readl(port, ATMEL_US_CSR) &
> +	       atmel_port->tx_done_mask) {
> +		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>  		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>  		port->icount.tx++;
>  		if (uart_circ_empty(xmit))
> @@ -715,7 +707,8 @@ static void atmel_tx_chars(struct uart_port *port)
>  
>  	if (!uart_circ_empty(xmit))
>  		/* Enable interrupts */
> -		UART_PUT_IER(port, atmel_port->tx_done_mask);
> +		atmel_uart_writel(port, ATMEL_US_IER,
> +				  atmel_port->tx_done_mask);
>  }
>  
>  static void atmel_complete_tx_dma(void *arg)
> @@ -935,14 +928,14 @@ static void atmel_rx_from_dma(struct uart_port *port)
>  
>  
>  	/* Reset the UART timeout early so that we don't miss one */
> -	UART_PUT_CR(port, ATMEL_US_STTTO);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  	dmastat = dmaengine_tx_status(chan,
>  				atmel_port->cookie_rx,
>  				&state);
>  	/* Restart a new tasklet if DMA status is error */
>  	if (dmastat == DMA_ERROR) {
>  		dev_dbg(port->dev, "Get residue error, restart tasklet\n");
> -		UART_PUT_IER(port, ATMEL_US_TIMEOUT);
> +		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
>  		tasklet_schedule(&atmel_port->tasklet);
>  		return;
>  	}
> @@ -1008,7 +1001,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
>  	tty_flip_buffer_push(tport);
>  	spin_lock(&port->lock);
>  
> -	UART_PUT_IER(port, ATMEL_US_TIMEOUT);
> +	atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
>  }
>  
>  static int atmel_prepare_rx_dma(struct uart_port *port)
> @@ -1118,8 +1111,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
>  		 * the moment.
>  		 */
>  		if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
> -			UART_PUT_IDR(port, (ATMEL_US_ENDRX
> -						| ATMEL_US_TIMEOUT));
> +			atmel_uart_writel(port, ATMEL_US_IDR,
> +					  (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
>  			tasklet_schedule(&atmel_port->tasklet);
>  		}
>  
> @@ -1130,7 +1123,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
>  
>  	if (atmel_use_dma_rx(port)) {
>  		if (pending & ATMEL_US_TIMEOUT) {
> -			UART_PUT_IDR(port, ATMEL_US_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_IDR,
> +					  ATMEL_US_TIMEOUT);
>  			tasklet_schedule(&atmel_port->tasklet);
>  		}
>  	}
> @@ -1143,8 +1137,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
>  		 * End of break detected. If it came along with a
>  		 * character, atmel_rx_chars will handle it.
>  		 */
> -		UART_PUT_CR(port, ATMEL_US_RSTSTA);
> -		UART_PUT_IDR(port, ATMEL_US_RXBRK);
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
> +		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXBRK);
>  		atmel_port->break_active = 0;
>  	}
>  }
> @@ -1159,7 +1153,8 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
>  
>  	if (pending & atmel_port->tx_done_mask) {
>  		/* Either PDC or interrupt transmission */
> -		UART_PUT_IDR(port, atmel_port->tx_done_mask);
> +		atmel_uart_writel(port, ATMEL_US_IDR,
> +				  atmel_port->tx_done_mask);
>  		tasklet_schedule(&atmel_port->tasklet);
>  	}
>  }
> @@ -1197,7 +1192,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
>  
>  	do {
>  		status = atmel_get_lines_status(port);
> -		mask = UART_GET_IMR(port);
> +		mask = atmel_uart_readl(port, ATMEL_US_IMR);
>  		pending = status & mask;
>  		if (!gpio_handled) {
>  			/*
> @@ -1223,7 +1218,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
>  		if (atmel_port->suspended) {
>  			atmel_port->pending |= pending;
>  			atmel_port->pending_status = status;
> -			UART_PUT_IDR(port, mask);
> +			atmel_uart_writel(port, ATMEL_US_IDR, mask);
>  			pm_system_wakeup();
>  			break;
>  		}
> @@ -1260,7 +1255,7 @@ static void atmel_tx_pdc(struct uart_port *port)
>  	int count;
>  
>  	/* nothing left to transmit? */
> -	if (UART_GET_TCR(port))
> +	if (atmel_uart_readl(port, ATMEL_PDC_TCR))
>  		return;
>  
>  	xmit->tail += pdc->ofs;
> @@ -1272,7 +1267,7 @@ static void atmel_tx_pdc(struct uart_port *port)
>  	/* more to transmit - setup next transfer */
>  
>  	/* disable PDC transmit */
> -	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
> +	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
>  
>  	if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
>  		dma_sync_single_for_device(port->dev,
> @@ -1283,12 +1278,14 @@ static void atmel_tx_pdc(struct uart_port *port)
>  		count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
>  		pdc->ofs = count;
>  
> -		UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
> -		UART_PUT_TCR(port, count);
> +		atmel_uart_writel(port, ATMEL_PDC_TPR,
> +				  pdc->dma_addr + xmit->tail);
> +		atmel_uart_writel(port, ATMEL_PDC_TCR, count);
>  		/* re-enable PDC transmit */
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
>  		/* Enable interrupts */
> -		UART_PUT_IER(port, atmel_port->tx_done_mask);
> +		atmel_uart_writel(port, ATMEL_US_IER,
> +				  atmel_port->tx_done_mask);
>  	} else {
>  		if ((port->rs485.flags & SER_RS485_ENABLED) &&
>  		    !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
> @@ -1414,10 +1411,10 @@ static void atmel_rx_from_pdc(struct uart_port *port)
>  
>  	do {
>  		/* Reset the UART timeout early so that we don't miss one */
> -		UART_PUT_CR(port, ATMEL_US_STTTO);
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  
>  		pdc = &atmel_port->pdc_rx[rx_idx];
> -		head = UART_GET_RPR(port) - pdc->dma_addr;
> +		head = atmel_uart_readl(port, ATMEL_PDC_RPR) - pdc->dma_addr;
>  		tail = pdc->ofs;
>  
>  		/* If the PDC has switched buffers, RPR won't contain
> @@ -1460,8 +1457,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
>  		 */
>  		if (head >= pdc->dma_size) {
>  			pdc->ofs = 0;
> -			UART_PUT_RNPR(port, pdc->dma_addr);
> -			UART_PUT_RNCR(port, pdc->dma_size);
> +			atmel_uart_writel(port, ATMEL_PDC_RNPR, pdc->dma_addr);
> +			atmel_uart_writel(port, ATMEL_PDC_RNCR, pdc->dma_size);
>  
>  			rx_idx = !rx_idx;
>  			atmel_port->pdc_rx_idx = rx_idx;
> @@ -1476,7 +1473,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
>  	tty_flip_buffer_push(tport);
>  	spin_lock(&port->lock);
>  
> -	UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
> +	atmel_uart_writel(port, ATMEL_US_IER,
> +			  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
>  }
>  
>  static int atmel_prepare_rx_pdc(struct uart_port *port)
> @@ -1509,11 +1507,12 @@ static int atmel_prepare_rx_pdc(struct uart_port *port)
>  
>  	atmel_port->pdc_rx_idx = 0;
>  
> -	UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
> -	UART_PUT_RCR(port, PDC_BUFFER_SIZE);
> +	atmel_uart_writel(port, ATMEL_PDC_RPR, atmel_port->pdc_rx[0].dma_addr);
> +	atmel_uart_writel(port, ATMEL_PDC_RCR, PDC_BUFFER_SIZE);
>  
> -	UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
> -	UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
> +	atmel_uart_writel(port, ATMEL_PDC_RNPR,
> +			  atmel_port->pdc_rx[1].dma_addr);
> +	atmel_uart_writel(port, ATMEL_PDC_RNCR, PDC_BUFFER_SIZE);
>  
>  	return 0;
>  }
> @@ -1667,7 +1666,7 @@ static void atmel_set_ops(struct uart_port *port)
>  static void atmel_get_ip_name(struct uart_port *port)
>  {
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
> -	int name = UART_GET_IP_NAME(port);
> +	int name = atmel_uart_readl(port, ATMEL_US_NAME);
>  	u32 version;
>  	int usart, uart;
>  	/* usart and uart ascii */
> @@ -1684,7 +1683,7 @@ static void atmel_get_ip_name(struct uart_port *port)
>  		atmel_port->is_usart = false;
>  	} else {
>  		/* fallback for older SoCs: use version field */
> -		version = UART_GET_IP_VERSION(port);
> +		version = atmel_uart_readl(port, ATMEL_US_VERSION);
>  		switch (version) {
>  		case 0x302:
>  		case 0x10213:
> @@ -1756,7 +1755,7 @@ static int atmel_startup(struct uart_port *port)
>  	 * request_irq() is called we could get stuck trying to
>  	 * handle an unexpected interrupt
>  	 */
> -	UART_PUT_IDR(port, -1);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  	atmel_port->ms_irq_enabled = false;
>  
>  	/*
> @@ -1804,9 +1803,9 @@ static int atmel_startup(struct uart_port *port)
>  	/*
>  	 * Finally, enable the serial port
>  	 */
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
>  	/* enable xmit & rcvr */
> -	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
>  
>  	setup_timer(&atmel_port->uart_timer,
>  			atmel_uart_timer_callback,
> @@ -1819,13 +1818,14 @@ static int atmel_startup(struct uart_port *port)
>  					jiffies + uart_poll_timeout(port));
>  		/* set USART timeout */
>  		} else {
> -			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
> -			UART_PUT_CR(port, ATMEL_US_STTTO);
> +			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  
> -			UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_IER,
> +					  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
>  		}
>  		/* enable PDC controller */
> -		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
>  	} else if (atmel_use_dma_rx(port)) {
>  		/* set UART timeout */
>  		if (!atmel_port->is_usart) {
> @@ -1833,14 +1833,15 @@ static int atmel_startup(struct uart_port *port)
>  					jiffies + uart_poll_timeout(port));
>  		/* set USART timeout */
>  		} else {
> -			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
> -			UART_PUT_CR(port, ATMEL_US_STTTO);
> +			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  
> -			UART_PUT_IER(port, ATMEL_US_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_IER,
> +					  ATMEL_US_TIMEOUT);
>  		}
>  	} else {
>  		/* enable receive only */
> -		UART_PUT_IER(port, ATMEL_US_RXRDY);
> +		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
>  	}
>  
>  	return 0;
> @@ -1860,7 +1861,7 @@ static void atmel_flush_buffer(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
>  	if (atmel_use_pdc_tx(port)) {
> -		UART_PUT_TCR(port, 0);
> +		atmel_uart_writel(port, ATMEL_PDC_TCR, 0);
>  		atmel_port->pdc_tx.ofs = 0;
>  	}
>  }
> @@ -1892,8 +1893,8 @@ static void atmel_shutdown(struct uart_port *port)
>  	atmel_stop_rx(port);
>  	atmel_stop_tx(port);
>  
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA);
> -	UART_PUT_IDR(port, -1);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  
>  
>  	/*
> @@ -1938,12 +1939,12 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
>  		clk_prepare_enable(atmel_port->clk);
>  
>  		/* re-enable interrupts if we disabled some on suspend */
> -		UART_PUT_IER(port, atmel_port->backup_imr);
> +		atmel_uart_writel(port, ATMEL_US_IER, atmel_port->backup_imr);
>  		break;
>  	case 3:
>  		/* Back up the interrupt mask and disable all interrupts */
> -		atmel_port->backup_imr = UART_GET_IMR(port);
> -		UART_PUT_IDR(port, -1);
> +		atmel_port->backup_imr = atmel_uart_readl(port, ATMEL_US_IMR);
> +		atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  
>  		/*
>  		 * Disable the peripheral clock for this serial port.
> @@ -1966,7 +1967,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  	unsigned int old_mode, mode, imr, quot, baud;
>  
>  	/* save the current mode register */
> -	mode = old_mode = UART_GET_MR(port);
> +	mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR);
>  
>  	/* reset the mode, clock divisor, parity, stop bits and data size */
>  	mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP |
> @@ -2025,7 +2026,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  
>  	if (atmel_use_pdc_rx(port))
>  		/* need to enable error interrupts */
> -		UART_PUT_IER(port, port->read_status_mask);
> +		atmel_uart_writel(port, ATMEL_US_IER, port->read_status_mask);
>  
>  	/*
>  	 * Characters to ignore
> @@ -2052,15 +2053,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  	 * transmitter is empty if requested by the caller, so there's
>  	 * no need to wait for it here.
>  	 */
> -	imr = UART_GET_IMR(port);
> -	UART_PUT_IDR(port, -1);
> +	imr = atmel_uart_readl(port, ATMEL_US_IMR);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  
>  	/* disable receiver and transmitter */
> -	UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
>  
>  	/* mode */
>  	if (port->rs485.flags & SER_RS485_ENABLED) {
> -		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
> +		atmel_uart_writel(port, ATMEL_US_TTGR,
> +				  port->rs485.delay_rts_after_send);
>  		mode |= ATMEL_US_USMODE_RS485;
>  	} else if (termios->c_cflag & CRTSCTS) {
>  		/* RS232 with hardware handshake (RTS/CTS) */
> @@ -2071,7 +2073,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  	}
>  
>  	/* set the mode, clock divisor, parity, stop bits and data size */
> -	UART_PUT_MR(port, mode);
> +	atmel_uart_writel(port, ATMEL_US_MR, mode);
>  
>  	/*
>  	 * when switching the mode, set the RTS line state according to the
> @@ -2088,16 +2090,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  			rts_state = ATMEL_US_RTSEN;
>  		}
>  
> -		UART_PUT_CR(port, rts_state);
> +		atmel_uart_writel(port, ATMEL_US_CR, rts_state);
>  	}
>  
>  	/* set the baud rate */
> -	UART_PUT_BRGR(port, quot);
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> -	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_BRGR, quot);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
>  
>  	/* restore interrupts */
> -	UART_PUT_IER(port, imr);
> +	atmel_uart_writel(port, ATMEL_US_IER, imr);
>  
>  	/* CTS flow-control and modem-status interrupts */
>  	if (UART_ENABLE_MS(port, termios->c_cflag))
> @@ -2208,18 +2210,18 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
>  #ifdef CONFIG_CONSOLE_POLL
>  static int atmel_poll_get_char(struct uart_port *port)
>  {
> -	while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
> +	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>  		cpu_relax();
>  
> -	return UART_GET_CHAR(port);
> +	return atmel_uart_readl(port, ATMEL_US_RHR);
>  }
>  
>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>  {
> -	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
> +	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
>  
> -	UART_PUT_CHAR(port, ch);
> +	atmel_uart_writel(port, ATMEL_US_THR, ch);
>  }
>  #endif
>  
> @@ -2324,9 +2326,9 @@ struct platform_device *atmel_default_console_device;	/* the serial console devi
>  #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
>  static void atmel_console_putchar(struct uart_port *port, int ch)
>  {
> -	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
> +	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
> -	UART_PUT_CHAR(port, ch);
> +	atmel_uart_writel(port, ATMEL_US_THR, ch);
>  }
>  
>  /*
> @@ -2342,12 +2344,13 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
>  	/*
>  	 * First, save IMR and then disable interrupts
>  	 */
> -	imr = UART_GET_IMR(port);
> -	UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
> +	imr = atmel_uart_readl(port, ATMEL_US_IMR);
> +	atmel_uart_writel(port, ATMEL_US_IDR,
> +			  ATMEL_US_RXRDY | atmel_port->tx_done_mask);
>  
>  	/* Store PDC transmit status and disable it */
> -	pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
> -	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
> +	pdc_tx = atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN;
> +	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
>  
>  	uart_console_write(port, s, count, atmel_console_putchar);
>  
> @@ -2356,15 +2359,15 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
>  	 * and restore IMR
>  	 */
>  	do {
> -		status = UART_GET_CSR(port);
> +		status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	} while (!(status & ATMEL_US_TXRDY));
>  
>  	/* Restore PDC transmit status */
>  	if (pdc_tx)
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
>  
>  	/* set interrupts back the way they were */
> -	UART_PUT_IER(port, imr);
> +	atmel_uart_writel(port, ATMEL_US_IER, imr);
>  }
>  
>  /*
> @@ -2380,17 +2383,17 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
>  	 * If the baud rate generator isn't running, the port wasn't
>  	 * initialized by the boot loader.
>  	 */
> -	quot = UART_GET_BRGR(port) & ATMEL_US_CD;
> +	quot = atmel_uart_readl(port, ATMEL_US_BRGR) & ATMEL_US_CD;
>  	if (!quot)
>  		return;
>  
> -	mr = UART_GET_MR(port) & ATMEL_US_CHRL;
> +	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_CHRL;
>  	if (mr == ATMEL_US_CHRL_8)
>  		*bits = 8;
>  	else
>  		*bits = 7;
>  
> -	mr = UART_GET_MR(port) & ATMEL_US_PAR;
> +	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_PAR;
>  	if (mr == ATMEL_US_PAR_EVEN)
>  		*parity = 'e';
>  	else if (mr == ATMEL_US_PAR_ODD)
> @@ -2423,9 +2426,9 @@ static int __init atmel_console_setup(struct console *co, char *options)
>  	if (ret)
>  		return ret;
>  
> -	UART_PUT_IDR(port, -1);
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> -	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
>  
>  	if (options)
>  		uart_parse_options(options, &baud, &parity, &bits, &flow);
> @@ -2532,7 +2535,8 @@ static int atmel_serial_suspend(struct platform_device *pdev,
>  
>  	if (atmel_is_console_port(port) && console_suspend_enabled) {
>  		/* Drain the TX shifter */
> -		while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
> +		while (!(atmel_uart_readl(port, ATMEL_US_CSR) &
> +			 ATMEL_US_TXEMPTY))
>  			cpu_relax();
>  	}
>  
> @@ -2684,8 +2688,9 @@ static int atmel_serial_probe(struct platform_device *pdev)
>  	clk_prepare_enable(port->clk);
>  
>  	if (rs485_enabled) {
> -		UART_PUT_MR(&port->uart, ATMEL_US_USMODE_NORMAL);
> -		UART_PUT_CR(&port->uart, ATMEL_US_RTSEN);
> +		atmel_uart_writel(&port->uart, ATMEL_US_MR,
> +				  ATMEL_US_USMODE_NORMAL);
> +		atmel_uart_writel(&port->uart, ATMEL_US_CR, ATMEL_US_RTSEN);
>  	}
>  
>  	/*
> 


-- 
Nicolas Ferre

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

* [PATCH v4 3/5] tty/serial: at91: remove bunch of macros to access UART registers
@ 2015-07-20 12:24     ` Nicolas Ferre
  0 siblings, 0 replies; 35+ messages in thread
From: Nicolas Ferre @ 2015-07-20 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

Le 02/07/2015 15:18, Cyrille Pitchen a ?crit :
> This patch replaces the UART_PUT_*, resp. UART_GET_*, macros by
> atmel_uart_writel(), resp. atmel_uart_readl(), inline function calls.
> 
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>

Ok with this move:
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>


> ---
>  drivers/tty/serial/atmel_serial.c | 313 +++++++++++++++++++-------------------
>  1 file changed, 159 insertions(+), 154 deletions(-)
> 
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index 2a8f528153e7..e7c337de31d1 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -88,37 +88,6 @@ static void atmel_stop_rx(struct uart_port *port);
>  
>  #define ATMEL_ISR_PASS_LIMIT	256
>  
> -/* UART registers. CR is write-only, hence no GET macro */
> -#define UART_PUT_CR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_CR)
> -#define UART_GET_MR(port)	__raw_readl((port)->membase + ATMEL_US_MR)
> -#define UART_PUT_MR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_MR)
> -#define UART_PUT_IER(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IER)
> -#define UART_PUT_IDR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IDR)
> -#define UART_GET_IMR(port)	__raw_readl((port)->membase + ATMEL_US_IMR)
> -#define UART_GET_CSR(port)	__raw_readl((port)->membase + ATMEL_US_CSR)
> -#define UART_GET_CHAR(port)	__raw_readl((port)->membase + ATMEL_US_RHR)
> -#define UART_PUT_CHAR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_THR)
> -#define UART_GET_BRGR(port)	__raw_readl((port)->membase + ATMEL_US_BRGR)
> -#define UART_PUT_BRGR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_BRGR)
> -#define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
> -#define UART_PUT_TTGR(port, v)	__raw_writel(v, (port)->membase + ATMEL_US_TTGR)
> -#define UART_GET_IP_NAME(port)	__raw_readl((port)->membase + ATMEL_US_NAME)
> -#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
> -
> - /* PDC registers */
> -#define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
> -#define UART_GET_PTSR(port)	__raw_readl((port)->membase + ATMEL_PDC_PTSR)
> -
> -#define UART_PUT_RPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
> -#define UART_GET_RPR(port)	__raw_readl((port)->membase + ATMEL_PDC_RPR)
> -#define UART_PUT_RCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
> -#define UART_PUT_RNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
> -#define UART_PUT_RNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
> -
> -#define UART_PUT_TPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
> -#define UART_PUT_TCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
> -#define UART_GET_TCR(port)	__raw_readl((port)->membase + ATMEL_PDC_TCR)
> -
>  struct atmel_dma_buffer {
>  	unsigned char	*buf;
>  	dma_addr_t	dma_addr;
> @@ -212,6 +181,16 @@ to_atmel_uart_port(struct uart_port *uart)
>  	return container_of(uart, struct atmel_uart_port, uart);
>  }
>  
> +static inline u32 atmel_uart_readl(struct uart_port *port, u32 reg)
> +{
> +	return __raw_readl(port->membase + reg);
> +}
> +
> +static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
> +{
> +	__raw_writel(value, port->membase + reg);
> +}
> +
>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>  static bool atmel_use_pdc_rx(struct uart_port *port)
>  {
> @@ -257,7 +236,7 @@ static unsigned int atmel_get_lines_status(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  	unsigned int status, ret = 0;
>  
> -	status = UART_GET_CSR(port);
> +	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  
>  	mctrl_gpio_get(atmel_port->gpios, &ret);
>  
> @@ -304,9 +283,9 @@ static int atmel_config_rs485(struct uart_port *port,
>  	unsigned int mode;
>  
>  	/* Disable interrupts */
> -	UART_PUT_IDR(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
>  
> -	mode = UART_GET_MR(port);
> +	mode = atmel_uart_readl(port, ATMEL_US_MR);
>  
>  	/* Resetting serial mode to RS232 (0x0) */
>  	mode &= ~ATMEL_US_USMODE;
> @@ -316,7 +295,8 @@ static int atmel_config_rs485(struct uart_port *port,
>  	if (rs485conf->flags & SER_RS485_ENABLED) {
>  		dev_dbg(port->dev, "Setting UART to RS485\n");
>  		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
> -		UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
> +		atmel_uart_writel(port, ATMEL_US_TTGR,
> +				  rs485conf->delay_rts_after_send);
>  		mode |= ATMEL_US_USMODE_RS485;
>  	} else {
>  		dev_dbg(port->dev, "Setting UART to RS232\n");
> @@ -326,10 +306,10 @@ static int atmel_config_rs485(struct uart_port *port,
>  		else
>  			atmel_port->tx_done_mask = ATMEL_US_TXRDY;
>  	}
> -	UART_PUT_MR(port, mode);
> +	atmel_uart_writel(port, ATMEL_US_MR, mode);
>  
>  	/* Enable interrupts */
> -	UART_PUT_IER(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
>  
>  	return 0;
>  }
> @@ -339,7 +319,9 @@ static int atmel_config_rs485(struct uart_port *port,
>   */
>  static u_int atmel_tx_empty(struct uart_port *port)
>  {
> -	return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
> +	return (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY) ?
> +		TIOCSER_TEMT :
> +		0;
>  }
>  
>  /*
> @@ -348,13 +330,14 @@ static u_int atmel_tx_empty(struct uart_port *port)
>  static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
>  {
>  	unsigned int control = 0;
> -	unsigned int mode = UART_GET_MR(port);
> +	unsigned int mode = atmel_uart_readl(port, ATMEL_US_MR);
>  	unsigned int rts_paused, rts_ready;
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
>  	/* override mode to RS485 if needed, otherwise keep the current mode */
>  	if (port->rs485.flags & SER_RS485_ENABLED) {
> -		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
> +		atmel_uart_writel(port, ATMEL_US_TTGR,
> +				  port->rs485.delay_rts_after_send);
>  		mode &= ~ATMEL_US_USMODE;
>  		mode |= ATMEL_US_USMODE_RS485;
>  	}
> @@ -384,7 +367,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
>  	else
>  		control |= ATMEL_US_DTRDIS;
>  
> -	UART_PUT_CR(port, control);
> +	atmel_uart_writel(port, ATMEL_US_CR, control);
>  
>  	mctrl_gpio_set(atmel_port->gpios, mctrl);
>  
> @@ -395,7 +378,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
>  	else
>  		mode |= ATMEL_US_CHMODE_NORMAL;
>  
> -	UART_PUT_MR(port, mode);
> +	atmel_uart_writel(port, ATMEL_US_MR, mode);
>  }
>  
>  /*
> @@ -406,7 +389,7 @@ static u_int atmel_get_mctrl(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  	unsigned int ret = 0, status;
>  
> -	status = UART_GET_CSR(port);
> +	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  
>  	/*
>  	 * The control signals are active low.
> @@ -432,10 +415,10 @@ static void atmel_stop_tx(struct uart_port *port)
>  
>  	if (atmel_use_pdc_tx(port)) {
>  		/* disable PDC transmit */
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
>  	}
>  	/* Disable interrupts */
> -	UART_PUT_IDR(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
>  
>  	if ((port->rs485.flags & SER_RS485_ENABLED) &&
>  	    !(port->rs485.flags & SER_RS485_RX_DURING_TX))
> @@ -450,7 +433,7 @@ static void atmel_start_tx(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
>  	if (atmel_use_pdc_tx(port)) {
> -		if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
> +		if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
>  			/* The transmitter is already running.  Yes, we
>  			   really need this.*/
>  			return;
> @@ -460,10 +443,10 @@ static void atmel_start_tx(struct uart_port *port)
>  			atmel_stop_rx(port);
>  
>  		/* re-enable PDC transmit */
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
>  	}
>  	/* Enable interrupts */
> -	UART_PUT_IER(port, atmel_port->tx_done_mask);
> +	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
>  }
>  
>  /*
> @@ -471,17 +454,19 @@ static void atmel_start_tx(struct uart_port *port)
>   */
>  static void atmel_start_rx(struct uart_port *port)
>  {
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA);  /* reset status and receiver */
> +	/* reset status and receiver */
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
>  
> -	UART_PUT_CR(port, ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXEN);
>  
>  	if (atmel_use_pdc_rx(port)) {
>  		/* enable PDC controller */
> -		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> -			port->read_status_mask);
> -		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
> +		atmel_uart_writel(port, ATMEL_US_IER,
> +				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> +				  port->read_status_mask);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
>  	} else {
> -		UART_PUT_IER(port, ATMEL_US_RXRDY);
> +		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
>  	}
>  }
>  
> @@ -490,15 +475,16 @@ static void atmel_start_rx(struct uart_port *port)
>   */
>  static void atmel_stop_rx(struct uart_port *port)
>  {
> -	UART_PUT_CR(port, ATMEL_US_RXDIS);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXDIS);
>  
>  	if (atmel_use_pdc_rx(port)) {
>  		/* disable PDC receive */
> -		UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
> -		UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> -			port->read_status_mask);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS);
> +		atmel_uart_writel(port, ATMEL_US_IDR,
> +				  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
> +				  port->read_status_mask);
>  	} else {
> -		UART_PUT_IDR(port, ATMEL_US_RXRDY);
> +		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXRDY);
>  	}
>  }
>  
> @@ -538,7 +524,7 @@ static void atmel_enable_ms(struct uart_port *port)
>  	else
>  		ier |= ATMEL_US_DCDIC;
>  
> -	UART_PUT_IER(port, ier);
> +	atmel_uart_writel(port, ATMEL_US_IER, ier);
>  }
>  
>  /*
> @@ -577,7 +563,7 @@ static void atmel_disable_ms(struct uart_port *port)
>  	else
>  		idr |= ATMEL_US_DCDIC;
>  
> -	UART_PUT_IDR(port, idr);
> +	atmel_uart_writel(port, ATMEL_US_IDR, idr);
>  }
>  
>  /*
> @@ -586,9 +572,11 @@ static void atmel_disable_ms(struct uart_port *port)
>  static void atmel_break_ctl(struct uart_port *port, int break_state)
>  {
>  	if (break_state != 0)
> -		UART_PUT_CR(port, ATMEL_US_STTBRK);	/* start break */
> +		/* start break */
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTBRK);
>  	else
> -		UART_PUT_CR(port, ATMEL_US_STPBRK);	/* stop break */
> +		/* stop break */
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STPBRK);
>  }
>  
>  /*
> @@ -622,7 +610,7 @@ atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
>  static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
>  {
>  	/* clear error */
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
>  
>  	if (status & ATMEL_US_RXBRK) {
>  		/* ignore side-effect */
> @@ -645,9 +633,9 @@ static void atmel_rx_chars(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  	unsigned int status, ch;
>  
> -	status = UART_GET_CSR(port);
> +	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	while (status & ATMEL_US_RXRDY) {
> -		ch = UART_GET_CHAR(port);
> +		ch = atmel_uart_readl(port, ATMEL_US_RHR);
>  
>  		/*
>  		 * note that the error handling code is
> @@ -658,12 +646,13 @@ static void atmel_rx_chars(struct uart_port *port)
>  			     || atmel_port->break_active)) {
>  
>  			/* clear error */
> -			UART_PUT_CR(port, ATMEL_US_RSTSTA);
> +			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
>  
>  			if (status & ATMEL_US_RXBRK
>  			    && !atmel_port->break_active) {
>  				atmel_port->break_active = 1;
> -				UART_PUT_IER(port, ATMEL_US_RXBRK);
> +				atmel_uart_writel(port, ATMEL_US_IER,
> +						  ATMEL_US_RXBRK);
>  			} else {
>  				/*
>  				 * This is either the end-of-break
> @@ -672,14 +661,15 @@ static void atmel_rx_chars(struct uart_port *port)
>  				 * being set. In both cases, the next
>  				 * RXBRK will indicate start-of-break.
>  				 */
> -				UART_PUT_IDR(port, ATMEL_US_RXBRK);
> +				atmel_uart_writel(port, ATMEL_US_IDR,
> +						  ATMEL_US_RXBRK);
>  				status &= ~ATMEL_US_RXBRK;
>  				atmel_port->break_active = 0;
>  			}
>  		}
>  
>  		atmel_buffer_rx_char(port, status, ch);
> -		status = UART_GET_CSR(port);
> +		status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	}
>  
>  	tasklet_schedule(&atmel_port->tasklet);
> @@ -694,16 +684,18 @@ static void atmel_tx_chars(struct uart_port *port)
>  	struct circ_buf *xmit = &port->state->xmit;
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
> -	if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
> -		UART_PUT_CHAR(port, port->x_char);
> +	if (port->x_char &&
> +	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
> +		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
>  		port->icount.tx++;
>  		port->x_char = 0;
>  	}
>  	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
>  		return;
>  
> -	while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
> -		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
> +	while (atmel_uart_readl(port, ATMEL_US_CSR) &
> +	       atmel_port->tx_done_mask) {
> +		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>  		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>  		port->icount.tx++;
>  		if (uart_circ_empty(xmit))
> @@ -715,7 +707,8 @@ static void atmel_tx_chars(struct uart_port *port)
>  
>  	if (!uart_circ_empty(xmit))
>  		/* Enable interrupts */
> -		UART_PUT_IER(port, atmel_port->tx_done_mask);
> +		atmel_uart_writel(port, ATMEL_US_IER,
> +				  atmel_port->tx_done_mask);
>  }
>  
>  static void atmel_complete_tx_dma(void *arg)
> @@ -935,14 +928,14 @@ static void atmel_rx_from_dma(struct uart_port *port)
>  
>  
>  	/* Reset the UART timeout early so that we don't miss one */
> -	UART_PUT_CR(port, ATMEL_US_STTTO);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  	dmastat = dmaengine_tx_status(chan,
>  				atmel_port->cookie_rx,
>  				&state);
>  	/* Restart a new tasklet if DMA status is error */
>  	if (dmastat == DMA_ERROR) {
>  		dev_dbg(port->dev, "Get residue error, restart tasklet\n");
> -		UART_PUT_IER(port, ATMEL_US_TIMEOUT);
> +		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
>  		tasklet_schedule(&atmel_port->tasklet);
>  		return;
>  	}
> @@ -1008,7 +1001,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
>  	tty_flip_buffer_push(tport);
>  	spin_lock(&port->lock);
>  
> -	UART_PUT_IER(port, ATMEL_US_TIMEOUT);
> +	atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
>  }
>  
>  static int atmel_prepare_rx_dma(struct uart_port *port)
> @@ -1118,8 +1111,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
>  		 * the moment.
>  		 */
>  		if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
> -			UART_PUT_IDR(port, (ATMEL_US_ENDRX
> -						| ATMEL_US_TIMEOUT));
> +			atmel_uart_writel(port, ATMEL_US_IDR,
> +					  (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
>  			tasklet_schedule(&atmel_port->tasklet);
>  		}
>  
> @@ -1130,7 +1123,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
>  
>  	if (atmel_use_dma_rx(port)) {
>  		if (pending & ATMEL_US_TIMEOUT) {
> -			UART_PUT_IDR(port, ATMEL_US_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_IDR,
> +					  ATMEL_US_TIMEOUT);
>  			tasklet_schedule(&atmel_port->tasklet);
>  		}
>  	}
> @@ -1143,8 +1137,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
>  		 * End of break detected. If it came along with a
>  		 * character, atmel_rx_chars will handle it.
>  		 */
> -		UART_PUT_CR(port, ATMEL_US_RSTSTA);
> -		UART_PUT_IDR(port, ATMEL_US_RXBRK);
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
> +		atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXBRK);
>  		atmel_port->break_active = 0;
>  	}
>  }
> @@ -1159,7 +1153,8 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
>  
>  	if (pending & atmel_port->tx_done_mask) {
>  		/* Either PDC or interrupt transmission */
> -		UART_PUT_IDR(port, atmel_port->tx_done_mask);
> +		atmel_uart_writel(port, ATMEL_US_IDR,
> +				  atmel_port->tx_done_mask);
>  		tasklet_schedule(&atmel_port->tasklet);
>  	}
>  }
> @@ -1197,7 +1192,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
>  
>  	do {
>  		status = atmel_get_lines_status(port);
> -		mask = UART_GET_IMR(port);
> +		mask = atmel_uart_readl(port, ATMEL_US_IMR);
>  		pending = status & mask;
>  		if (!gpio_handled) {
>  			/*
> @@ -1223,7 +1218,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
>  		if (atmel_port->suspended) {
>  			atmel_port->pending |= pending;
>  			atmel_port->pending_status = status;
> -			UART_PUT_IDR(port, mask);
> +			atmel_uart_writel(port, ATMEL_US_IDR, mask);
>  			pm_system_wakeup();
>  			break;
>  		}
> @@ -1260,7 +1255,7 @@ static void atmel_tx_pdc(struct uart_port *port)
>  	int count;
>  
>  	/* nothing left to transmit? */
> -	if (UART_GET_TCR(port))
> +	if (atmel_uart_readl(port, ATMEL_PDC_TCR))
>  		return;
>  
>  	xmit->tail += pdc->ofs;
> @@ -1272,7 +1267,7 @@ static void atmel_tx_pdc(struct uart_port *port)
>  	/* more to transmit - setup next transfer */
>  
>  	/* disable PDC transmit */
> -	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
> +	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
>  
>  	if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
>  		dma_sync_single_for_device(port->dev,
> @@ -1283,12 +1278,14 @@ static void atmel_tx_pdc(struct uart_port *port)
>  		count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
>  		pdc->ofs = count;
>  
> -		UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
> -		UART_PUT_TCR(port, count);
> +		atmel_uart_writel(port, ATMEL_PDC_TPR,
> +				  pdc->dma_addr + xmit->tail);
> +		atmel_uart_writel(port, ATMEL_PDC_TCR, count);
>  		/* re-enable PDC transmit */
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
>  		/* Enable interrupts */
> -		UART_PUT_IER(port, atmel_port->tx_done_mask);
> +		atmel_uart_writel(port, ATMEL_US_IER,
> +				  atmel_port->tx_done_mask);
>  	} else {
>  		if ((port->rs485.flags & SER_RS485_ENABLED) &&
>  		    !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
> @@ -1414,10 +1411,10 @@ static void atmel_rx_from_pdc(struct uart_port *port)
>  
>  	do {
>  		/* Reset the UART timeout early so that we don't miss one */
> -		UART_PUT_CR(port, ATMEL_US_STTTO);
> +		atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  
>  		pdc = &atmel_port->pdc_rx[rx_idx];
> -		head = UART_GET_RPR(port) - pdc->dma_addr;
> +		head = atmel_uart_readl(port, ATMEL_PDC_RPR) - pdc->dma_addr;
>  		tail = pdc->ofs;
>  
>  		/* If the PDC has switched buffers, RPR won't contain
> @@ -1460,8 +1457,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
>  		 */
>  		if (head >= pdc->dma_size) {
>  			pdc->ofs = 0;
> -			UART_PUT_RNPR(port, pdc->dma_addr);
> -			UART_PUT_RNCR(port, pdc->dma_size);
> +			atmel_uart_writel(port, ATMEL_PDC_RNPR, pdc->dma_addr);
> +			atmel_uart_writel(port, ATMEL_PDC_RNCR, pdc->dma_size);
>  
>  			rx_idx = !rx_idx;
>  			atmel_port->pdc_rx_idx = rx_idx;
> @@ -1476,7 +1473,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
>  	tty_flip_buffer_push(tport);
>  	spin_lock(&port->lock);
>  
> -	UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
> +	atmel_uart_writel(port, ATMEL_US_IER,
> +			  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
>  }
>  
>  static int atmel_prepare_rx_pdc(struct uart_port *port)
> @@ -1509,11 +1507,12 @@ static int atmel_prepare_rx_pdc(struct uart_port *port)
>  
>  	atmel_port->pdc_rx_idx = 0;
>  
> -	UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
> -	UART_PUT_RCR(port, PDC_BUFFER_SIZE);
> +	atmel_uart_writel(port, ATMEL_PDC_RPR, atmel_port->pdc_rx[0].dma_addr);
> +	atmel_uart_writel(port, ATMEL_PDC_RCR, PDC_BUFFER_SIZE);
>  
> -	UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
> -	UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
> +	atmel_uart_writel(port, ATMEL_PDC_RNPR,
> +			  atmel_port->pdc_rx[1].dma_addr);
> +	atmel_uart_writel(port, ATMEL_PDC_RNCR, PDC_BUFFER_SIZE);
>  
>  	return 0;
>  }
> @@ -1667,7 +1666,7 @@ static void atmel_set_ops(struct uart_port *port)
>  static void atmel_get_ip_name(struct uart_port *port)
>  {
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
> -	int name = UART_GET_IP_NAME(port);
> +	int name = atmel_uart_readl(port, ATMEL_US_NAME);
>  	u32 version;
>  	int usart, uart;
>  	/* usart and uart ascii */
> @@ -1684,7 +1683,7 @@ static void atmel_get_ip_name(struct uart_port *port)
>  		atmel_port->is_usart = false;
>  	} else {
>  		/* fallback for older SoCs: use version field */
> -		version = UART_GET_IP_VERSION(port);
> +		version = atmel_uart_readl(port, ATMEL_US_VERSION);
>  		switch (version) {
>  		case 0x302:
>  		case 0x10213:
> @@ -1756,7 +1755,7 @@ static int atmel_startup(struct uart_port *port)
>  	 * request_irq() is called we could get stuck trying to
>  	 * handle an unexpected interrupt
>  	 */
> -	UART_PUT_IDR(port, -1);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  	atmel_port->ms_irq_enabled = false;
>  
>  	/*
> @@ -1804,9 +1803,9 @@ static int atmel_startup(struct uart_port *port)
>  	/*
>  	 * Finally, enable the serial port
>  	 */
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
>  	/* enable xmit & rcvr */
> -	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
>  
>  	setup_timer(&atmel_port->uart_timer,
>  			atmel_uart_timer_callback,
> @@ -1819,13 +1818,14 @@ static int atmel_startup(struct uart_port *port)
>  					jiffies + uart_poll_timeout(port));
>  		/* set USART timeout */
>  		} else {
> -			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
> -			UART_PUT_CR(port, ATMEL_US_STTTO);
> +			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  
> -			UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_IER,
> +					  ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
>  		}
>  		/* enable PDC controller */
> -		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
>  	} else if (atmel_use_dma_rx(port)) {
>  		/* set UART timeout */
>  		if (!atmel_port->is_usart) {
> @@ -1833,14 +1833,15 @@ static int atmel_startup(struct uart_port *port)
>  					jiffies + uart_poll_timeout(port));
>  		/* set USART timeout */
>  		} else {
> -			UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
> -			UART_PUT_CR(port, ATMEL_US_STTTO);
> +			atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
>  
> -			UART_PUT_IER(port, ATMEL_US_TIMEOUT);
> +			atmel_uart_writel(port, ATMEL_US_IER,
> +					  ATMEL_US_TIMEOUT);
>  		}
>  	} else {
>  		/* enable receive only */
> -		UART_PUT_IER(port, ATMEL_US_RXRDY);
> +		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
>  	}
>  
>  	return 0;
> @@ -1860,7 +1861,7 @@ static void atmel_flush_buffer(struct uart_port *port)
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
>  
>  	if (atmel_use_pdc_tx(port)) {
> -		UART_PUT_TCR(port, 0);
> +		atmel_uart_writel(port, ATMEL_PDC_TCR, 0);
>  		atmel_port->pdc_tx.ofs = 0;
>  	}
>  }
> @@ -1892,8 +1893,8 @@ static void atmel_shutdown(struct uart_port *port)
>  	atmel_stop_rx(port);
>  	atmel_stop_tx(port);
>  
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA);
> -	UART_PUT_IDR(port, -1);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  
>  
>  	/*
> @@ -1938,12 +1939,12 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
>  		clk_prepare_enable(atmel_port->clk);
>  
>  		/* re-enable interrupts if we disabled some on suspend */
> -		UART_PUT_IER(port, atmel_port->backup_imr);
> +		atmel_uart_writel(port, ATMEL_US_IER, atmel_port->backup_imr);
>  		break;
>  	case 3:
>  		/* Back up the interrupt mask and disable all interrupts */
> -		atmel_port->backup_imr = UART_GET_IMR(port);
> -		UART_PUT_IDR(port, -1);
> +		atmel_port->backup_imr = atmel_uart_readl(port, ATMEL_US_IMR);
> +		atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  
>  		/*
>  		 * Disable the peripheral clock for this serial port.
> @@ -1966,7 +1967,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  	unsigned int old_mode, mode, imr, quot, baud;
>  
>  	/* save the current mode register */
> -	mode = old_mode = UART_GET_MR(port);
> +	mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR);
>  
>  	/* reset the mode, clock divisor, parity, stop bits and data size */
>  	mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP |
> @@ -2025,7 +2026,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  
>  	if (atmel_use_pdc_rx(port))
>  		/* need to enable error interrupts */
> -		UART_PUT_IER(port, port->read_status_mask);
> +		atmel_uart_writel(port, ATMEL_US_IER, port->read_status_mask);
>  
>  	/*
>  	 * Characters to ignore
> @@ -2052,15 +2053,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  	 * transmitter is empty if requested by the caller, so there's
>  	 * no need to wait for it here.
>  	 */
> -	imr = UART_GET_IMR(port);
> -	UART_PUT_IDR(port, -1);
> +	imr = atmel_uart_readl(port, ATMEL_US_IMR);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
>  
>  	/* disable receiver and transmitter */
> -	UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
>  
>  	/* mode */
>  	if (port->rs485.flags & SER_RS485_ENABLED) {
> -		UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
> +		atmel_uart_writel(port, ATMEL_US_TTGR,
> +				  port->rs485.delay_rts_after_send);
>  		mode |= ATMEL_US_USMODE_RS485;
>  	} else if (termios->c_cflag & CRTSCTS) {
>  		/* RS232 with hardware handshake (RTS/CTS) */
> @@ -2071,7 +2073,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  	}
>  
>  	/* set the mode, clock divisor, parity, stop bits and data size */
> -	UART_PUT_MR(port, mode);
> +	atmel_uart_writel(port, ATMEL_US_MR, mode);
>  
>  	/*
>  	 * when switching the mode, set the RTS line state according to the
> @@ -2088,16 +2090,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
>  			rts_state = ATMEL_US_RTSEN;
>  		}
>  
> -		UART_PUT_CR(port, rts_state);
> +		atmel_uart_writel(port, ATMEL_US_CR, rts_state);
>  	}
>  
>  	/* set the baud rate */
> -	UART_PUT_BRGR(port, quot);
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> -	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_BRGR, quot);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
>  
>  	/* restore interrupts */
> -	UART_PUT_IER(port, imr);
> +	atmel_uart_writel(port, ATMEL_US_IER, imr);
>  
>  	/* CTS flow-control and modem-status interrupts */
>  	if (UART_ENABLE_MS(port, termios->c_cflag))
> @@ -2208,18 +2210,18 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
>  #ifdef CONFIG_CONSOLE_POLL
>  static int atmel_poll_get_char(struct uart_port *port)
>  {
> -	while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
> +	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>  		cpu_relax();
>  
> -	return UART_GET_CHAR(port);
> +	return atmel_uart_readl(port, ATMEL_US_RHR);
>  }
>  
>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>  {
> -	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
> +	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
>  
> -	UART_PUT_CHAR(port, ch);
> +	atmel_uart_writel(port, ATMEL_US_THR, ch);
>  }
>  #endif
>  
> @@ -2324,9 +2326,9 @@ struct platform_device *atmel_default_console_device;	/* the serial console devi
>  #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
>  static void atmel_console_putchar(struct uart_port *port, int ch)
>  {
> -	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
> +	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
> -	UART_PUT_CHAR(port, ch);
> +	atmel_uart_writel(port, ATMEL_US_THR, ch);
>  }
>  
>  /*
> @@ -2342,12 +2344,13 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
>  	/*
>  	 * First, save IMR and then disable interrupts
>  	 */
> -	imr = UART_GET_IMR(port);
> -	UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
> +	imr = atmel_uart_readl(port, ATMEL_US_IMR);
> +	atmel_uart_writel(port, ATMEL_US_IDR,
> +			  ATMEL_US_RXRDY | atmel_port->tx_done_mask);
>  
>  	/* Store PDC transmit status and disable it */
> -	pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
> -	UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
> +	pdc_tx = atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN;
> +	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
>  
>  	uart_console_write(port, s, count, atmel_console_putchar);
>  
> @@ -2356,15 +2359,15 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
>  	 * and restore IMR
>  	 */
>  	do {
> -		status = UART_GET_CSR(port);
> +		status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	} while (!(status & ATMEL_US_TXRDY));
>  
>  	/* Restore PDC transmit status */
>  	if (pdc_tx)
> -		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
> +		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
>  
>  	/* set interrupts back the way they were */
> -	UART_PUT_IER(port, imr);
> +	atmel_uart_writel(port, ATMEL_US_IER, imr);
>  }
>  
>  /*
> @@ -2380,17 +2383,17 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
>  	 * If the baud rate generator isn't running, the port wasn't
>  	 * initialized by the boot loader.
>  	 */
> -	quot = UART_GET_BRGR(port) & ATMEL_US_CD;
> +	quot = atmel_uart_readl(port, ATMEL_US_BRGR) & ATMEL_US_CD;
>  	if (!quot)
>  		return;
>  
> -	mr = UART_GET_MR(port) & ATMEL_US_CHRL;
> +	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_CHRL;
>  	if (mr == ATMEL_US_CHRL_8)
>  		*bits = 8;
>  	else
>  		*bits = 7;
>  
> -	mr = UART_GET_MR(port) & ATMEL_US_PAR;
> +	mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_PAR;
>  	if (mr == ATMEL_US_PAR_EVEN)
>  		*parity = 'e';
>  	else if (mr == ATMEL_US_PAR_ODD)
> @@ -2423,9 +2426,9 @@ static int __init atmel_console_setup(struct console *co, char *options)
>  	if (ret)
>  		return ret;
>  
> -	UART_PUT_IDR(port, -1);
> -	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> -	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
> +	atmel_uart_writel(port, ATMEL_US_IDR, -1);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
> +	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
>  
>  	if (options)
>  		uart_parse_options(options, &baud, &parity, &bits, &flow);
> @@ -2532,7 +2535,8 @@ static int atmel_serial_suspend(struct platform_device *pdev,
>  
>  	if (atmel_is_console_port(port) && console_suspend_enabled) {
>  		/* Drain the TX shifter */
> -		while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
> +		while (!(atmel_uart_readl(port, ATMEL_US_CSR) &
> +			 ATMEL_US_TXEMPTY))
>  			cpu_relax();
>  	}
>  
> @@ -2684,8 +2688,9 @@ static int atmel_serial_probe(struct platform_device *pdev)
>  	clk_prepare_enable(port->clk);
>  
>  	if (rs485_enabled) {
> -		UART_PUT_MR(&port->uart, ATMEL_US_USMODE_NORMAL);
> -		UART_PUT_CR(&port->uart, ATMEL_US_RTSEN);
> +		atmel_uart_writel(&port->uart, ATMEL_US_MR,
> +				  ATMEL_US_USMODE_NORMAL);
> +		atmel_uart_writel(&port->uart, ATMEL_US_CR, ATMEL_US_RTSEN);
>  	}
>  
>  	/*
> 


-- 
Nicolas Ferre

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

* Re: [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-20 12:25     ` Nicolas Ferre
  0 siblings, 0 replies; 35+ messages in thread
From: Nicolas Ferre @ 2015-07-20 12:25 UTC (permalink / raw)
  To: Cyrille Pitchen, gregkh, wenyou.yang, ludovic.desroches,
	leilei.zhao, josh.wu, alexandre.belloni, linux-serial
  Cc: linux-kernel, linux-arm-kernel, devicetree, galak,
	ijc+devicetree, mark.rutland, pawel.moll, robh+dt

Le 02/07/2015 15:18, Cyrille Pitchen a écrit :
> Depending on the hardware, TX and RX FIFOs may be available. The RX
> FIFO can avoid receive overruns, especially when DMA transfers are
> not used to read data from the Receive Holding Register. For heavy
> system load, The CPU is likely not be able to fetch data fast enough
> from the RHR.
> 
> In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
> line when the Hardware Handshaking mode is enabled. Two thresholds
> are to be set for that purpose:
> - When the number of data in the RX FIFO crosses and becomes lower
>   than or equal to the low threshold, the RTS line is set to low
>   level: the remote peer is requested to send data.
> - When the number of data in the RX FIFO crosses and becomes greater
>   than or equal to the high threshold, the RTS line is set to high
>   level: the remote peer should stop sending new data.
> - low threshold <= high threshold
> Once these two thresholds are set properly, this new feature is
> enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.
> 
> FIFOs also introduce a new multiple data mode: the USART works either
> in multiple data mode or in single data (legacy) mode.
> 
> If MODE9 bit is set into the Mode Register or if USMODE is set to
> either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
> data mode. Otherwise, they operate in multiple data mode.
> 
> In this new multiple data mode, accesses to the Receive Holding
> Register or Transmit Holding Register slightly change.
> 
> Since this driver implements neither the 9bit data feature (MODE9 bit
> set into the Mode Register) nor LIN modes, the USART works in
> multiple data mode whenever FIFOs are available and enabled. We also
> assume that data are 8bit wide.
> 
> In single data mode, 32bit access CAN be used to read a single data
> from RHR or write a single data into THR.
> However in multiple data mode, a 32bit access to RHR now allows us to
> read four consecutive data from RX FIFO. Also a 32bit access to THR
> now allows to write four consecutive data into TX FIFO. So we MUST
> use 8bit access whenever only one data have to be read/written at a
> time.
> 
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>

Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Thanks!

> ---
>  drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
>  include/linux/atmel_serial.h      |  36 ++++++++++++++
>  2 files changed, 130 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index e7c337de31d1..87de21f0c7a3 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -56,6 +56,15 @@
>  /* Revisit: We should calculate this based on the actual port settings */
>  #define PDC_RX_TIMEOUT		(3 * 10)		/* 3 bytes */
>  
> +/* The minium number of data FIFOs should be able to contain */
> +#define ATMEL_MIN_FIFO_SIZE	8
> +/*
> + * These two offsets are substracted from the RX FIFO size to define the RTS
> + * high and low thresholds
> + */
> +#define ATMEL_RTS_HIGH_OFFSET	16
> +#define ATMEL_RTS_LOW_OFFSET	20
> +
>  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>  #define SUPPORT_SYSRQ
>  #endif
> @@ -141,6 +150,9 @@ struct atmel_uart_port {
>  	struct mctrl_gpios	*gpios;
>  	int			gpio_irq[UART_GPIO_MAX];
>  	unsigned int		tx_done_mask;
> +	u32			fifo_size;
> +	u32			rts_high;
> +	u32			rts_low;
>  	bool			ms_irq_enabled;
>  	bool			is_usart;	/* usart or uart */
>  	struct timer_list	uart_timer;	/* uart timer */
> @@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
>  	__raw_writel(value, port->membase + reg);
>  }
>  
> +static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
> +{
> +	return __raw_readb(port->membase + reg);
> +}
> +
> +static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
> +{
> +	__raw_writeb(value, port->membase + reg);
> +}
> +
>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>  static bool atmel_use_pdc_rx(struct uart_port *port)
>  {
> @@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
>  
>  	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	while (status & ATMEL_US_RXRDY) {
> -		ch = atmel_uart_readl(port, ATMEL_US_RHR);
> +		ch = atmel_uart_readb(port, ATMEL_US_RHR);
>  
>  		/*
>  		 * note that the error handling code is
> @@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
>  
>  	if (port->x_char &&
>  	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
> -		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
> +		atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
>  		port->icount.tx++;
>  		port->x_char = 0;
>  	}
> @@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
>  
>  	while (atmel_uart_readl(port, ATMEL_US_CSR) &
>  	       atmel_port->tx_done_mask) {
> -		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
> +		atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>  		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>  		port->icount.tx++;
>  		if (uart_circ_empty(xmit))
> @@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
>  			atmel_set_ops(port);
>  	}
>  
> +	/*
> +	 * Enable FIFO when available
> +	 */
> +	if (atmel_port->fifo_size) {
> +		unsigned int txrdym = ATMEL_US_ONE_DATA;
> +		unsigned int rxrdym = ATMEL_US_ONE_DATA;
> +		unsigned int fmr;
> +
> +		atmel_uart_writel(port, ATMEL_US_CR,
> +				  ATMEL_US_FIFOEN |
> +				  ATMEL_US_RXFCLR |
> +				  ATMEL_US_TXFLCLR);
> +
> +		fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
> +		if (atmel_port->rts_high &&
> +		    atmel_port->rts_low)
> +			fmr |=	ATMEL_US_FRTSC |
> +				ATMEL_US_RXFTHRES(atmel_port->rts_high) |
> +				ATMEL_US_RXFTHRES2(atmel_port->rts_low);
> +
> +		atmel_uart_writel(port, ATMEL_US_FMR, fmr);
> +	}
> +
>  	/* Save current CSR for comparison in atmel_tasklet_func() */
>  	atmel_port->irq_status_prev = atmel_get_lines_status(port);
>  	atmel_port->irq_status = atmel_port->irq_status_prev;
> @@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
>  	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>  		cpu_relax();
>  
> -	return atmel_uart_readl(port, ATMEL_US_RHR);
> +	return atmel_uart_readb(port, ATMEL_US_RHR);
>  }
>  
>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
> @@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>  	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
>  
> -	atmel_uart_writel(port, ATMEL_US_THR, ch);
> +	atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>  #endif
>  
> @@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
>  {
>  	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
> -	atmel_uart_writel(port, ATMEL_US_THR, ch);
> +	atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>  
>  /*
> @@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
>  	return 0;
>  }
>  
> +static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
> +				     struct platform_device *pdev)
> +{
> +	port->fifo_size = 0;
> +	port->rts_low = 0;
> +	port->rts_high = 0;
> +
> +	if (of_property_read_u32(pdev->dev.of_node,
> +				 "atmel,fifo-size",
> +				 &port->fifo_size))
> +		return;
> +
> +	if (!port->fifo_size)
> +		return;
> +
> +	if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
> +		port->fifo_size = 0;
> +		dev_err(&pdev->dev, "Invalid FIFO size\n");
> +		return;
> +	}
> +
> +	/*
> +	 * 0 <= rts_low <= rts_high <= fifo_size
> +	 * Once their CTS line asserted by the remote peer, some x86 UARTs tend
> +	 * to flush their internal TX FIFO, commonly up to 16 data, before
> +	 * actually stopping to send new data. So we try to set the RTS High
> +	 * Threshold to a reasonably high value respecting this 16 data
> +	 * empirical rule when possible.
> +	 */
> +	port->rts_high = max_t(int, port->fifo_size >> 1,
> +			       port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
> +	port->rts_low  = max_t(int, port->fifo_size >> 2,
> +			       port->fifo_size - ATMEL_RTS_LOW_OFFSET);
> +
> +	dev_info(&pdev->dev, "Using FIFO (%u data)\n",
> +		 port->fifo_size);
> +	dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
> +		port->rts_high);
> +	dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
> +		port->rts_low);
> +}
> +
>  static int atmel_serial_probe(struct platform_device *pdev)
>  {
>  	struct atmel_uart_port *port;
> @@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
>  	port = &atmel_ports[ret];
>  	port->backup_imr = 0;
>  	port->uart.line = ret;
> +	atmel_serial_probe_fifos(port, pdev);
>  
>  	spin_lock_init(&port->lock_suspended);
>  
> diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
> index c384c21d65f0..ee696d7e8a43 100644
> --- a/include/linux/atmel_serial.h
> +++ b/include/linux/atmel_serial.h
> @@ -35,6 +35,11 @@
>  #define	ATMEL_US_DTRDIS		BIT(17)	/* Data Terminal Ready Disable */
>  #define	ATMEL_US_RTSEN		BIT(18)	/* Request To Send Enable */
>  #define	ATMEL_US_RTSDIS		BIT(19)	/* Request To Send Disable */
> +#define	ATMEL_US_TXFCLR		BIT(24)	/* Transmit FIFO Clear */
> +#define	ATMEL_US_RXFCLR		BIT(25)	/* Receive FIFO Clear */
> +#define	ATMEL_US_TXFLCLR	BIT(26)	/* Transmit FIFO Lock Clear */
> +#define	ATMEL_US_FIFOEN		BIT(30)	/* FIFO enable */
> +#define	ATMEL_US_FIFODIS	BIT(31)	/* FIFO disable */
>  
>  #define ATMEL_US_MR		0x04	/* Mode Register */
>  #define	ATMEL_US_USMODE		GENMASK(3, 0)	/* Mode of the USART */
> @@ -124,6 +129,37 @@
>  #define ATMEL_US_NER		0x44	/* Number of Errors Register */
>  #define ATMEL_US_IF		0x4c	/* IrDA Filter Register */
>  
> +#define ATMEL_US_CMPR		0x90	/* Comparaison Register */
> +#define ATMEL_US_FMR		0xa0	/* FIFO Mode Register */
> +#define	ATMEL_US_TXRDYM(data)	(((data) & 0x3) << 0)	/* TX Ready Mode */
> +#define	ATMEL_US_RXRDYM(data)	(((data) & 0x3) << 4)	/* RX Ready Mode */
> +#define		ATMEL_US_ONE_DATA	0x0
> +#define		ATMEL_US_TWO_DATA	0x1
> +#define		ATMEL_US_FOUR_DATA	0x2
> +#define	ATMEL_US_FRTSC		BIT(7)	/* FIFO RTS pin Control */
> +#define	ATMEL_US_TXFTHRES(thr)	(((thr) & 0x3f) << 8)	/* TX FIFO Threshold */
> +#define	ATMEL_US_RXFTHRES(thr)	(((thr) & 0x3f) << 16)	/* RX FIFO Threshold */
> +#define	ATMEL_US_RXFTHRES2(thr)	(((thr) & 0x3f) << 24)	/* RX FIFO Threshold2 */
> +
> +#define ATMEL_US_FLR		0xa4	/* FIFO Level Register */
> +#define	ATMEL_US_TXFL(reg)	(((reg) >> 0) & 0x3f)	/* TX FIFO Level */
> +#define	ATMEL_US_RXFL(reg)	(((reg) >> 16) & 0x3f)	/* RX FIFO Level */
> +
> +#define ATMEL_US_FIER		0xa8	/* FIFO Interrupt Enable Register */
> +#define ATMEL_US_FIDR		0xac	/* FIFO Interrupt Disable Register */
> +#define ATMEL_US_FIMR		0xb0	/* FIFO Interrupt Mask Register */
> +#define ATMEL_US_FESR		0xb4	/* FIFO Event Status Register */
> +#define	ATMEL_US_TXFEF		BIT(0)	/* Transmit FIFO Empty Flag */
> +#define	ATMEL_US_TXFFF		BIT(1)	/* Transmit FIFO Full Flag */
> +#define	ATMEL_US_TXFTHF		BIT(2)	/* Transmit FIFO Threshold Flag */
> +#define	ATMEL_US_RXFEF		BIT(3)	/* Receive FIFO Empty Flag */
> +#define	ATMEL_US_RXFFF		BIT(4)	/* Receive FIFO Full Flag */
> +#define	ATMEL_US_RXFTHF		BIT(5)	/* Receive FIFO Threshold Flag */
> +#define	ATMEL_US_TXFPTEF	BIT(6)	/* Transmit FIFO Pointer Error Flag */
> +#define	ATMEL_US_RXFPTEF	BIT(7)	/* Receive FIFO Pointer Error Flag */
> +#define	ATMEL_US_TXFLOCK	BIT(8)	/* Transmit FIFO Lock (FESR only) */
> +#define	ATMEL_US_RXFTHF2	BIT(9)	/* Receive FIFO Threshold Flag 2 */
> +
>  #define ATMEL_US_NAME		0xf0	/* Ip Name */
>  #define ATMEL_US_VERSION	0xfc	/* Ip Version */
>  
> 


-- 
Nicolas Ferre

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

* Re: [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-20 12:25     ` Nicolas Ferre
  0 siblings, 0 replies; 35+ messages in thread
From: Nicolas Ferre @ 2015-07-20 12:25 UTC (permalink / raw)
  To: Cyrille Pitchen, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	wenyou.yang-AIFe0yeh4nAAvxtiuMwx3w,
	ludovic.desroches-AIFe0yeh4nAAvxtiuMwx3w,
	leilei.zhao-AIFe0yeh4nAAvxtiuMwx3w,
	josh.wu-AIFe0yeh4nAAvxtiuMwx3w,
	alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	linux-serial-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, galak-sgV2jX0FEOL9JmXXK+q4OQ,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg, mark.rutland-5wv7dgnIgG8,
	pawel.moll-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A

Le 02/07/2015 15:18, Cyrille Pitchen a écrit :
> Depending on the hardware, TX and RX FIFOs may be available. The RX
> FIFO can avoid receive overruns, especially when DMA transfers are
> not used to read data from the Receive Holding Register. For heavy
> system load, The CPU is likely not be able to fetch data fast enough
> from the RHR.
> 
> In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
> line when the Hardware Handshaking mode is enabled. Two thresholds
> are to be set for that purpose:
> - When the number of data in the RX FIFO crosses and becomes lower
>   than or equal to the low threshold, the RTS line is set to low
>   level: the remote peer is requested to send data.
> - When the number of data in the RX FIFO crosses and becomes greater
>   than or equal to the high threshold, the RTS line is set to high
>   level: the remote peer should stop sending new data.
> - low threshold <= high threshold
> Once these two thresholds are set properly, this new feature is
> enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.
> 
> FIFOs also introduce a new multiple data mode: the USART works either
> in multiple data mode or in single data (legacy) mode.
> 
> If MODE9 bit is set into the Mode Register or if USMODE is set to
> either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
> data mode. Otherwise, they operate in multiple data mode.
> 
> In this new multiple data mode, accesses to the Receive Holding
> Register or Transmit Holding Register slightly change.
> 
> Since this driver implements neither the 9bit data feature (MODE9 bit
> set into the Mode Register) nor LIN modes, the USART works in
> multiple data mode whenever FIFOs are available and enabled. We also
> assume that data are 8bit wide.
> 
> In single data mode, 32bit access CAN be used to read a single data
> from RHR or write a single data into THR.
> However in multiple data mode, a 32bit access to RHR now allows us to
> read four consecutive data from RX FIFO. Also a 32bit access to THR
> now allows to write four consecutive data into TX FIFO. So we MUST
> use 8bit access whenever only one data have to be read/written at a
> time.
> 
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org>

Acked-by: Nicolas Ferre <nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org>
Thanks!

> ---
>  drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
>  include/linux/atmel_serial.h      |  36 ++++++++++++++
>  2 files changed, 130 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index e7c337de31d1..87de21f0c7a3 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -56,6 +56,15 @@
>  /* Revisit: We should calculate this based on the actual port settings */
>  #define PDC_RX_TIMEOUT		(3 * 10)		/* 3 bytes */
>  
> +/* The minium number of data FIFOs should be able to contain */
> +#define ATMEL_MIN_FIFO_SIZE	8
> +/*
> + * These two offsets are substracted from the RX FIFO size to define the RTS
> + * high and low thresholds
> + */
> +#define ATMEL_RTS_HIGH_OFFSET	16
> +#define ATMEL_RTS_LOW_OFFSET	20
> +
>  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>  #define SUPPORT_SYSRQ
>  #endif
> @@ -141,6 +150,9 @@ struct atmel_uart_port {
>  	struct mctrl_gpios	*gpios;
>  	int			gpio_irq[UART_GPIO_MAX];
>  	unsigned int		tx_done_mask;
> +	u32			fifo_size;
> +	u32			rts_high;
> +	u32			rts_low;
>  	bool			ms_irq_enabled;
>  	bool			is_usart;	/* usart or uart */
>  	struct timer_list	uart_timer;	/* uart timer */
> @@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
>  	__raw_writel(value, port->membase + reg);
>  }
>  
> +static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
> +{
> +	return __raw_readb(port->membase + reg);
> +}
> +
> +static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
> +{
> +	__raw_writeb(value, port->membase + reg);
> +}
> +
>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>  static bool atmel_use_pdc_rx(struct uart_port *port)
>  {
> @@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
>  
>  	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	while (status & ATMEL_US_RXRDY) {
> -		ch = atmel_uart_readl(port, ATMEL_US_RHR);
> +		ch = atmel_uart_readb(port, ATMEL_US_RHR);
>  
>  		/*
>  		 * note that the error handling code is
> @@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
>  
>  	if (port->x_char &&
>  	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
> -		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
> +		atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
>  		port->icount.tx++;
>  		port->x_char = 0;
>  	}
> @@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
>  
>  	while (atmel_uart_readl(port, ATMEL_US_CSR) &
>  	       atmel_port->tx_done_mask) {
> -		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
> +		atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>  		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>  		port->icount.tx++;
>  		if (uart_circ_empty(xmit))
> @@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
>  			atmel_set_ops(port);
>  	}
>  
> +	/*
> +	 * Enable FIFO when available
> +	 */
> +	if (atmel_port->fifo_size) {
> +		unsigned int txrdym = ATMEL_US_ONE_DATA;
> +		unsigned int rxrdym = ATMEL_US_ONE_DATA;
> +		unsigned int fmr;
> +
> +		atmel_uart_writel(port, ATMEL_US_CR,
> +				  ATMEL_US_FIFOEN |
> +				  ATMEL_US_RXFCLR |
> +				  ATMEL_US_TXFLCLR);
> +
> +		fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
> +		if (atmel_port->rts_high &&
> +		    atmel_port->rts_low)
> +			fmr |=	ATMEL_US_FRTSC |
> +				ATMEL_US_RXFTHRES(atmel_port->rts_high) |
> +				ATMEL_US_RXFTHRES2(atmel_port->rts_low);
> +
> +		atmel_uart_writel(port, ATMEL_US_FMR, fmr);
> +	}
> +
>  	/* Save current CSR for comparison in atmel_tasklet_func() */
>  	atmel_port->irq_status_prev = atmel_get_lines_status(port);
>  	atmel_port->irq_status = atmel_port->irq_status_prev;
> @@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
>  	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>  		cpu_relax();
>  
> -	return atmel_uart_readl(port, ATMEL_US_RHR);
> +	return atmel_uart_readb(port, ATMEL_US_RHR);
>  }
>  
>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
> @@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>  	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
>  
> -	atmel_uart_writel(port, ATMEL_US_THR, ch);
> +	atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>  #endif
>  
> @@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
>  {
>  	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
> -	atmel_uart_writel(port, ATMEL_US_THR, ch);
> +	atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>  
>  /*
> @@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
>  	return 0;
>  }
>  
> +static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
> +				     struct platform_device *pdev)
> +{
> +	port->fifo_size = 0;
> +	port->rts_low = 0;
> +	port->rts_high = 0;
> +
> +	if (of_property_read_u32(pdev->dev.of_node,
> +				 "atmel,fifo-size",
> +				 &port->fifo_size))
> +		return;
> +
> +	if (!port->fifo_size)
> +		return;
> +
> +	if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
> +		port->fifo_size = 0;
> +		dev_err(&pdev->dev, "Invalid FIFO size\n");
> +		return;
> +	}
> +
> +	/*
> +	 * 0 <= rts_low <= rts_high <= fifo_size
> +	 * Once their CTS line asserted by the remote peer, some x86 UARTs tend
> +	 * to flush their internal TX FIFO, commonly up to 16 data, before
> +	 * actually stopping to send new data. So we try to set the RTS High
> +	 * Threshold to a reasonably high value respecting this 16 data
> +	 * empirical rule when possible.
> +	 */
> +	port->rts_high = max_t(int, port->fifo_size >> 1,
> +			       port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
> +	port->rts_low  = max_t(int, port->fifo_size >> 2,
> +			       port->fifo_size - ATMEL_RTS_LOW_OFFSET);
> +
> +	dev_info(&pdev->dev, "Using FIFO (%u data)\n",
> +		 port->fifo_size);
> +	dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
> +		port->rts_high);
> +	dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
> +		port->rts_low);
> +}
> +
>  static int atmel_serial_probe(struct platform_device *pdev)
>  {
>  	struct atmel_uart_port *port;
> @@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
>  	port = &atmel_ports[ret];
>  	port->backup_imr = 0;
>  	port->uart.line = ret;
> +	atmel_serial_probe_fifos(port, pdev);
>  
>  	spin_lock_init(&port->lock_suspended);
>  
> diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
> index c384c21d65f0..ee696d7e8a43 100644
> --- a/include/linux/atmel_serial.h
> +++ b/include/linux/atmel_serial.h
> @@ -35,6 +35,11 @@
>  #define	ATMEL_US_DTRDIS		BIT(17)	/* Data Terminal Ready Disable */
>  #define	ATMEL_US_RTSEN		BIT(18)	/* Request To Send Enable */
>  #define	ATMEL_US_RTSDIS		BIT(19)	/* Request To Send Disable */
> +#define	ATMEL_US_TXFCLR		BIT(24)	/* Transmit FIFO Clear */
> +#define	ATMEL_US_RXFCLR		BIT(25)	/* Receive FIFO Clear */
> +#define	ATMEL_US_TXFLCLR	BIT(26)	/* Transmit FIFO Lock Clear */
> +#define	ATMEL_US_FIFOEN		BIT(30)	/* FIFO enable */
> +#define	ATMEL_US_FIFODIS	BIT(31)	/* FIFO disable */
>  
>  #define ATMEL_US_MR		0x04	/* Mode Register */
>  #define	ATMEL_US_USMODE		GENMASK(3, 0)	/* Mode of the USART */
> @@ -124,6 +129,37 @@
>  #define ATMEL_US_NER		0x44	/* Number of Errors Register */
>  #define ATMEL_US_IF		0x4c	/* IrDA Filter Register */
>  
> +#define ATMEL_US_CMPR		0x90	/* Comparaison Register */
> +#define ATMEL_US_FMR		0xa0	/* FIFO Mode Register */
> +#define	ATMEL_US_TXRDYM(data)	(((data) & 0x3) << 0)	/* TX Ready Mode */
> +#define	ATMEL_US_RXRDYM(data)	(((data) & 0x3) << 4)	/* RX Ready Mode */
> +#define		ATMEL_US_ONE_DATA	0x0
> +#define		ATMEL_US_TWO_DATA	0x1
> +#define		ATMEL_US_FOUR_DATA	0x2
> +#define	ATMEL_US_FRTSC		BIT(7)	/* FIFO RTS pin Control */
> +#define	ATMEL_US_TXFTHRES(thr)	(((thr) & 0x3f) << 8)	/* TX FIFO Threshold */
> +#define	ATMEL_US_RXFTHRES(thr)	(((thr) & 0x3f) << 16)	/* RX FIFO Threshold */
> +#define	ATMEL_US_RXFTHRES2(thr)	(((thr) & 0x3f) << 24)	/* RX FIFO Threshold2 */
> +
> +#define ATMEL_US_FLR		0xa4	/* FIFO Level Register */
> +#define	ATMEL_US_TXFL(reg)	(((reg) >> 0) & 0x3f)	/* TX FIFO Level */
> +#define	ATMEL_US_RXFL(reg)	(((reg) >> 16) & 0x3f)	/* RX FIFO Level */
> +
> +#define ATMEL_US_FIER		0xa8	/* FIFO Interrupt Enable Register */
> +#define ATMEL_US_FIDR		0xac	/* FIFO Interrupt Disable Register */
> +#define ATMEL_US_FIMR		0xb0	/* FIFO Interrupt Mask Register */
> +#define ATMEL_US_FESR		0xb4	/* FIFO Event Status Register */
> +#define	ATMEL_US_TXFEF		BIT(0)	/* Transmit FIFO Empty Flag */
> +#define	ATMEL_US_TXFFF		BIT(1)	/* Transmit FIFO Full Flag */
> +#define	ATMEL_US_TXFTHF		BIT(2)	/* Transmit FIFO Threshold Flag */
> +#define	ATMEL_US_RXFEF		BIT(3)	/* Receive FIFO Empty Flag */
> +#define	ATMEL_US_RXFFF		BIT(4)	/* Receive FIFO Full Flag */
> +#define	ATMEL_US_RXFTHF		BIT(5)	/* Receive FIFO Threshold Flag */
> +#define	ATMEL_US_TXFPTEF	BIT(6)	/* Transmit FIFO Pointer Error Flag */
> +#define	ATMEL_US_RXFPTEF	BIT(7)	/* Receive FIFO Pointer Error Flag */
> +#define	ATMEL_US_TXFLOCK	BIT(8)	/* Transmit FIFO Lock (FESR only) */
> +#define	ATMEL_US_RXFTHF2	BIT(9)	/* Receive FIFO Threshold Flag 2 */
> +
>  #define ATMEL_US_NAME		0xf0	/* Ip Name */
>  #define ATMEL_US_VERSION	0xfc	/* Ip Version */
>  
> 


-- 
Nicolas Ferre
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-20 12:25     ` Nicolas Ferre
  0 siblings, 0 replies; 35+ messages in thread
From: Nicolas Ferre @ 2015-07-20 12:25 UTC (permalink / raw)
  To: linux-arm-kernel

Le 02/07/2015 15:18, Cyrille Pitchen a ?crit :
> Depending on the hardware, TX and RX FIFOs may be available. The RX
> FIFO can avoid receive overruns, especially when DMA transfers are
> not used to read data from the Receive Holding Register. For heavy
> system load, The CPU is likely not be able to fetch data fast enough
> from the RHR.
> 
> In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
> line when the Hardware Handshaking mode is enabled. Two thresholds
> are to be set for that purpose:
> - When the number of data in the RX FIFO crosses and becomes lower
>   than or equal to the low threshold, the RTS line is set to low
>   level: the remote peer is requested to send data.
> - When the number of data in the RX FIFO crosses and becomes greater
>   than or equal to the high threshold, the RTS line is set to high
>   level: the remote peer should stop sending new data.
> - low threshold <= high threshold
> Once these two thresholds are set properly, this new feature is
> enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.
> 
> FIFOs also introduce a new multiple data mode: the USART works either
> in multiple data mode or in single data (legacy) mode.
> 
> If MODE9 bit is set into the Mode Register or if USMODE is set to
> either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
> data mode. Otherwise, they operate in multiple data mode.
> 
> In this new multiple data mode, accesses to the Receive Holding
> Register or Transmit Holding Register slightly change.
> 
> Since this driver implements neither the 9bit data feature (MODE9 bit
> set into the Mode Register) nor LIN modes, the USART works in
> multiple data mode whenever FIFOs are available and enabled. We also
> assume that data are 8bit wide.
> 
> In single data mode, 32bit access CAN be used to read a single data
> from RHR or write a single data into THR.
> However in multiple data mode, a 32bit access to RHR now allows us to
> read four consecutive data from RX FIFO. Also a 32bit access to THR
> now allows to write four consecutive data into TX FIFO. So we MUST
> use 8bit access whenever only one data have to be read/written at a
> time.
> 
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>

Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Thanks!

> ---
>  drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
>  include/linux/atmel_serial.h      |  36 ++++++++++++++
>  2 files changed, 130 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index e7c337de31d1..87de21f0c7a3 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -56,6 +56,15 @@
>  /* Revisit: We should calculate this based on the actual port settings */
>  #define PDC_RX_TIMEOUT		(3 * 10)		/* 3 bytes */
>  
> +/* The minium number of data FIFOs should be able to contain */
> +#define ATMEL_MIN_FIFO_SIZE	8
> +/*
> + * These two offsets are substracted from the RX FIFO size to define the RTS
> + * high and low thresholds
> + */
> +#define ATMEL_RTS_HIGH_OFFSET	16
> +#define ATMEL_RTS_LOW_OFFSET	20
> +
>  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>  #define SUPPORT_SYSRQ
>  #endif
> @@ -141,6 +150,9 @@ struct atmel_uart_port {
>  	struct mctrl_gpios	*gpios;
>  	int			gpio_irq[UART_GPIO_MAX];
>  	unsigned int		tx_done_mask;
> +	u32			fifo_size;
> +	u32			rts_high;
> +	u32			rts_low;
>  	bool			ms_irq_enabled;
>  	bool			is_usart;	/* usart or uart */
>  	struct timer_list	uart_timer;	/* uart timer */
> @@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
>  	__raw_writel(value, port->membase + reg);
>  }
>  
> +static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
> +{
> +	return __raw_readb(port->membase + reg);
> +}
> +
> +static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
> +{
> +	__raw_writeb(value, port->membase + reg);
> +}
> +
>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>  static bool atmel_use_pdc_rx(struct uart_port *port)
>  {
> @@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
>  
>  	status = atmel_uart_readl(port, ATMEL_US_CSR);
>  	while (status & ATMEL_US_RXRDY) {
> -		ch = atmel_uart_readl(port, ATMEL_US_RHR);
> +		ch = atmel_uart_readb(port, ATMEL_US_RHR);
>  
>  		/*
>  		 * note that the error handling code is
> @@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
>  
>  	if (port->x_char &&
>  	    (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
> -		atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
> +		atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
>  		port->icount.tx++;
>  		port->x_char = 0;
>  	}
> @@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
>  
>  	while (atmel_uart_readl(port, ATMEL_US_CSR) &
>  	       atmel_port->tx_done_mask) {
> -		atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
> +		atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>  		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>  		port->icount.tx++;
>  		if (uart_circ_empty(xmit))
> @@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
>  			atmel_set_ops(port);
>  	}
>  
> +	/*
> +	 * Enable FIFO when available
> +	 */
> +	if (atmel_port->fifo_size) {
> +		unsigned int txrdym = ATMEL_US_ONE_DATA;
> +		unsigned int rxrdym = ATMEL_US_ONE_DATA;
> +		unsigned int fmr;
> +
> +		atmel_uart_writel(port, ATMEL_US_CR,
> +				  ATMEL_US_FIFOEN |
> +				  ATMEL_US_RXFCLR |
> +				  ATMEL_US_TXFLCLR);
> +
> +		fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
> +		if (atmel_port->rts_high &&
> +		    atmel_port->rts_low)
> +			fmr |=	ATMEL_US_FRTSC |
> +				ATMEL_US_RXFTHRES(atmel_port->rts_high) |
> +				ATMEL_US_RXFTHRES2(atmel_port->rts_low);
> +
> +		atmel_uart_writel(port, ATMEL_US_FMR, fmr);
> +	}
> +
>  	/* Save current CSR for comparison in atmel_tasklet_func() */
>  	atmel_port->irq_status_prev = atmel_get_lines_status(port);
>  	atmel_port->irq_status = atmel_port->irq_status_prev;
> @@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
>  	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>  		cpu_relax();
>  
> -	return atmel_uart_readl(port, ATMEL_US_RHR);
> +	return atmel_uart_readb(port, ATMEL_US_RHR);
>  }
>  
>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
> @@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>  	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
>  
> -	atmel_uart_writel(port, ATMEL_US_THR, ch);
> +	atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>  #endif
>  
> @@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
>  {
>  	while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>  		cpu_relax();
> -	atmel_uart_writel(port, ATMEL_US_THR, ch);
> +	atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>  
>  /*
> @@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
>  	return 0;
>  }
>  
> +static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
> +				     struct platform_device *pdev)
> +{
> +	port->fifo_size = 0;
> +	port->rts_low = 0;
> +	port->rts_high = 0;
> +
> +	if (of_property_read_u32(pdev->dev.of_node,
> +				 "atmel,fifo-size",
> +				 &port->fifo_size))
> +		return;
> +
> +	if (!port->fifo_size)
> +		return;
> +
> +	if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
> +		port->fifo_size = 0;
> +		dev_err(&pdev->dev, "Invalid FIFO size\n");
> +		return;
> +	}
> +
> +	/*
> +	 * 0 <= rts_low <= rts_high <= fifo_size
> +	 * Once their CTS line asserted by the remote peer, some x86 UARTs tend
> +	 * to flush their internal TX FIFO, commonly up to 16 data, before
> +	 * actually stopping to send new data. So we try to set the RTS High
> +	 * Threshold to a reasonably high value respecting this 16 data
> +	 * empirical rule when possible.
> +	 */
> +	port->rts_high = max_t(int, port->fifo_size >> 1,
> +			       port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
> +	port->rts_low  = max_t(int, port->fifo_size >> 2,
> +			       port->fifo_size - ATMEL_RTS_LOW_OFFSET);
> +
> +	dev_info(&pdev->dev, "Using FIFO (%u data)\n",
> +		 port->fifo_size);
> +	dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
> +		port->rts_high);
> +	dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
> +		port->rts_low);
> +}
> +
>  static int atmel_serial_probe(struct platform_device *pdev)
>  {
>  	struct atmel_uart_port *port;
> @@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
>  	port = &atmel_ports[ret];
>  	port->backup_imr = 0;
>  	port->uart.line = ret;
> +	atmel_serial_probe_fifos(port, pdev);
>  
>  	spin_lock_init(&port->lock_suspended);
>  
> diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
> index c384c21d65f0..ee696d7e8a43 100644
> --- a/include/linux/atmel_serial.h
> +++ b/include/linux/atmel_serial.h
> @@ -35,6 +35,11 @@
>  #define	ATMEL_US_DTRDIS		BIT(17)	/* Data Terminal Ready Disable */
>  #define	ATMEL_US_RTSEN		BIT(18)	/* Request To Send Enable */
>  #define	ATMEL_US_RTSDIS		BIT(19)	/* Request To Send Disable */
> +#define	ATMEL_US_TXFCLR		BIT(24)	/* Transmit FIFO Clear */
> +#define	ATMEL_US_RXFCLR		BIT(25)	/* Receive FIFO Clear */
> +#define	ATMEL_US_TXFLCLR	BIT(26)	/* Transmit FIFO Lock Clear */
> +#define	ATMEL_US_FIFOEN		BIT(30)	/* FIFO enable */
> +#define	ATMEL_US_FIFODIS	BIT(31)	/* FIFO disable */
>  
>  #define ATMEL_US_MR		0x04	/* Mode Register */
>  #define	ATMEL_US_USMODE		GENMASK(3, 0)	/* Mode of the USART */
> @@ -124,6 +129,37 @@
>  #define ATMEL_US_NER		0x44	/* Number of Errors Register */
>  #define ATMEL_US_IF		0x4c	/* IrDA Filter Register */
>  
> +#define ATMEL_US_CMPR		0x90	/* Comparaison Register */
> +#define ATMEL_US_FMR		0xa0	/* FIFO Mode Register */
> +#define	ATMEL_US_TXRDYM(data)	(((data) & 0x3) << 0)	/* TX Ready Mode */
> +#define	ATMEL_US_RXRDYM(data)	(((data) & 0x3) << 4)	/* RX Ready Mode */
> +#define		ATMEL_US_ONE_DATA	0x0
> +#define		ATMEL_US_TWO_DATA	0x1
> +#define		ATMEL_US_FOUR_DATA	0x2
> +#define	ATMEL_US_FRTSC		BIT(7)	/* FIFO RTS pin Control */
> +#define	ATMEL_US_TXFTHRES(thr)	(((thr) & 0x3f) << 8)	/* TX FIFO Threshold */
> +#define	ATMEL_US_RXFTHRES(thr)	(((thr) & 0x3f) << 16)	/* RX FIFO Threshold */
> +#define	ATMEL_US_RXFTHRES2(thr)	(((thr) & 0x3f) << 24)	/* RX FIFO Threshold2 */
> +
> +#define ATMEL_US_FLR		0xa4	/* FIFO Level Register */
> +#define	ATMEL_US_TXFL(reg)	(((reg) >> 0) & 0x3f)	/* TX FIFO Level */
> +#define	ATMEL_US_RXFL(reg)	(((reg) >> 16) & 0x3f)	/* RX FIFO Level */
> +
> +#define ATMEL_US_FIER		0xa8	/* FIFO Interrupt Enable Register */
> +#define ATMEL_US_FIDR		0xac	/* FIFO Interrupt Disable Register */
> +#define ATMEL_US_FIMR		0xb0	/* FIFO Interrupt Mask Register */
> +#define ATMEL_US_FESR		0xb4	/* FIFO Event Status Register */
> +#define	ATMEL_US_TXFEF		BIT(0)	/* Transmit FIFO Empty Flag */
> +#define	ATMEL_US_TXFFF		BIT(1)	/* Transmit FIFO Full Flag */
> +#define	ATMEL_US_TXFTHF		BIT(2)	/* Transmit FIFO Threshold Flag */
> +#define	ATMEL_US_RXFEF		BIT(3)	/* Receive FIFO Empty Flag */
> +#define	ATMEL_US_RXFFF		BIT(4)	/* Receive FIFO Full Flag */
> +#define	ATMEL_US_RXFTHF		BIT(5)	/* Receive FIFO Threshold Flag */
> +#define	ATMEL_US_TXFPTEF	BIT(6)	/* Transmit FIFO Pointer Error Flag */
> +#define	ATMEL_US_RXFPTEF	BIT(7)	/* Receive FIFO Pointer Error Flag */
> +#define	ATMEL_US_TXFLOCK	BIT(8)	/* Transmit FIFO Lock (FESR only) */
> +#define	ATMEL_US_RXFTHF2	BIT(9)	/* Receive FIFO Threshold Flag 2 */
> +
>  #define ATMEL_US_NAME		0xf0	/* Ip Name */
>  #define ATMEL_US_VERSION	0xfc	/* Ip Version */
>  
> 


-- 
Nicolas Ferre

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

* Re: [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-29 14:51     ` Andy Shevchenko
  0 siblings, 0 replies; 35+ messages in thread
From: Andy Shevchenko @ 2015-07-29 14:51 UTC (permalink / raw)
  To: Cyrille Pitchen
  Cc: Nicolas Ferre, Greg Kroah-Hartman, wenyou.yang,
	ludovic.desroches, leilei.zhao, josh.wu, alexandre.belloni,
	linux-serial, linux-kernel, linux-arm Mailing List, devicetree,
	Kumar Gala, ijc+devicetree, Mark Rutland, Pawel Moll,
	Rob Herring

On Thu, Jul 2, 2015 at 4:18 PM, Cyrille Pitchen
<cyrille.pitchen@atmel.com> wrote:
> Depending on the hardware, TX and RX FIFOs may be available. The RX
> FIFO can avoid receive overruns, especially when DMA transfers are
> not used to read data from the Receive Holding Register. For heavy
> system load, The CPU is likely not be able to fetch data fast enough
> from the RHR.

This patch broke avr32 console (as seen in today's linux-next) on ATNGW100.
Reverting helps. I'm pretty sure the issue is in 8 bit vs. 32 bit I/O access.

# uname -a
Linux buildroot 4.2.0-rc4-next-20150729+ #97 Wed Jul 29 17:50:11 EEST
2015 avr32 GNU/Linux

Do you, guys, have that board (NGW100) or it's officially unsupported?
If the latter is the case I would really appreciate if you remove the
support from the kernel side.

>
> In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
> line when the Hardware Handshaking mode is enabled. Two thresholds
> are to be set for that purpose:
> - When the number of data in the RX FIFO crosses and becomes lower
>   than or equal to the low threshold, the RTS line is set to low
>   level: the remote peer is requested to send data.
> - When the number of data in the RX FIFO crosses and becomes greater
>   than or equal to the high threshold, the RTS line is set to high
>   level: the remote peer should stop sending new data.
> - low threshold <= high threshold
> Once these two thresholds are set properly, this new feature is
> enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.
>
> FIFOs also introduce a new multiple data mode: the USART works either
> in multiple data mode or in single data (legacy) mode.
>
> If MODE9 bit is set into the Mode Register or if USMODE is set to
> either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
> data mode. Otherwise, they operate in multiple data mode.
>
> In this new multiple data mode, accesses to the Receive Holding
> Register or Transmit Holding Register slightly change.
>
> Since this driver implements neither the 9bit data feature (MODE9 bit
> set into the Mode Register) nor LIN modes, the USART works in
> multiple data mode whenever FIFOs are available and enabled. We also
> assume that data are 8bit wide.
>
> In single data mode, 32bit access CAN be used to read a single data
> from RHR or write a single data into THR.
> However in multiple data mode, a 32bit access to RHR now allows us to
> read four consecutive data from RX FIFO. Also a 32bit access to THR
> now allows to write four consecutive data into TX FIFO. So we MUST
> use 8bit access whenever only one data have to be read/written at a
> time.
>
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
> ---
>  drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
>  include/linux/atmel_serial.h      |  36 ++++++++++++++
>  2 files changed, 130 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index e7c337de31d1..87de21f0c7a3 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -56,6 +56,15 @@
>  /* Revisit: We should calculate this based on the actual port settings */
>  #define PDC_RX_TIMEOUT         (3 * 10)                /* 3 bytes */
>
> +/* The minium number of data FIFOs should be able to contain */
> +#define ATMEL_MIN_FIFO_SIZE    8
> +/*
> + * These two offsets are substracted from the RX FIFO size to define the RTS
> + * high and low thresholds
> + */
> +#define ATMEL_RTS_HIGH_OFFSET  16
> +#define ATMEL_RTS_LOW_OFFSET   20
> +
>  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>  #define SUPPORT_SYSRQ
>  #endif
> @@ -141,6 +150,9 @@ struct atmel_uart_port {
>         struct mctrl_gpios      *gpios;
>         int                     gpio_irq[UART_GPIO_MAX];
>         unsigned int            tx_done_mask;
> +       u32                     fifo_size;
> +       u32                     rts_high;
> +       u32                     rts_low;
>         bool                    ms_irq_enabled;
>         bool                    is_usart;       /* usart or uart */
>         struct timer_list       uart_timer;     /* uart timer */
> @@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
>         __raw_writel(value, port->membase + reg);
>  }
>
> +static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
> +{
> +       return __raw_readb(port->membase + reg);
> +}
> +
> +static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
> +{
> +       __raw_writeb(value, port->membase + reg);
> +}
> +
>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>  static bool atmel_use_pdc_rx(struct uart_port *port)
>  {
> @@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
>
>         status = atmel_uart_readl(port, ATMEL_US_CSR);
>         while (status & ATMEL_US_RXRDY) {
> -               ch = atmel_uart_readl(port, ATMEL_US_RHR);
> +               ch = atmel_uart_readb(port, ATMEL_US_RHR);
>
>                 /*
>                  * note that the error handling code is
> @@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
>
>         if (port->x_char &&
>             (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
> -               atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
> +               atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
>                 port->icount.tx++;
>                 port->x_char = 0;
>         }
> @@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
>
>         while (atmel_uart_readl(port, ATMEL_US_CSR) &
>                atmel_port->tx_done_mask) {
> -               atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
> +               atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>                 port->icount.tx++;
>                 if (uart_circ_empty(xmit))
> @@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
>                         atmel_set_ops(port);
>         }
>
> +       /*
> +        * Enable FIFO when available
> +        */
> +       if (atmel_port->fifo_size) {
> +               unsigned int txrdym = ATMEL_US_ONE_DATA;
> +               unsigned int rxrdym = ATMEL_US_ONE_DATA;
> +               unsigned int fmr;
> +
> +               atmel_uart_writel(port, ATMEL_US_CR,
> +                                 ATMEL_US_FIFOEN |
> +                                 ATMEL_US_RXFCLR |
> +                                 ATMEL_US_TXFLCLR);
> +
> +               fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
> +               if (atmel_port->rts_high &&
> +                   atmel_port->rts_low)
> +                       fmr |=  ATMEL_US_FRTSC |
> +                               ATMEL_US_RXFTHRES(atmel_port->rts_high) |
> +                               ATMEL_US_RXFTHRES2(atmel_port->rts_low);
> +
> +               atmel_uart_writel(port, ATMEL_US_FMR, fmr);
> +       }
> +
>         /* Save current CSR for comparison in atmel_tasklet_func() */
>         atmel_port->irq_status_prev = atmel_get_lines_status(port);
>         atmel_port->irq_status = atmel_port->irq_status_prev;
> @@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>                 cpu_relax();
>
> -       return atmel_uart_readl(port, ATMEL_US_RHR);
> +       return atmel_uart_readb(port, ATMEL_US_RHR);
>  }
>
>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
> @@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>                 cpu_relax();
>
> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>  #endif
>
> @@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
>  {
>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>                 cpu_relax();
> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>
>  /*
> @@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
>         return 0;
>  }
>
> +static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
> +                                    struct platform_device *pdev)
> +{
> +       port->fifo_size = 0;
> +       port->rts_low = 0;
> +       port->rts_high = 0;
> +
> +       if (of_property_read_u32(pdev->dev.of_node,
> +                                "atmel,fifo-size",
> +                                &port->fifo_size))
> +               return;
> +
> +       if (!port->fifo_size)
> +               return;
> +
> +       if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
> +               port->fifo_size = 0;
> +               dev_err(&pdev->dev, "Invalid FIFO size\n");
> +               return;
> +       }
> +
> +       /*
> +        * 0 <= rts_low <= rts_high <= fifo_size
> +        * Once their CTS line asserted by the remote peer, some x86 UARTs tend
> +        * to flush their internal TX FIFO, commonly up to 16 data, before
> +        * actually stopping to send new data. So we try to set the RTS High
> +        * Threshold to a reasonably high value respecting this 16 data
> +        * empirical rule when possible.
> +        */
> +       port->rts_high = max_t(int, port->fifo_size >> 1,
> +                              port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
> +       port->rts_low  = max_t(int, port->fifo_size >> 2,
> +                              port->fifo_size - ATMEL_RTS_LOW_OFFSET);
> +
> +       dev_info(&pdev->dev, "Using FIFO (%u data)\n",
> +                port->fifo_size);
> +       dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
> +               port->rts_high);
> +       dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
> +               port->rts_low);
> +}
> +
>  static int atmel_serial_probe(struct platform_device *pdev)
>  {
>         struct atmel_uart_port *port;
> @@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
>         port = &atmel_ports[ret];
>         port->backup_imr = 0;
>         port->uart.line = ret;
> +       atmel_serial_probe_fifos(port, pdev);
>
>         spin_lock_init(&port->lock_suspended);
>
> diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
> index c384c21d65f0..ee696d7e8a43 100644
> --- a/include/linux/atmel_serial.h
> +++ b/include/linux/atmel_serial.h
> @@ -35,6 +35,11 @@
>  #define        ATMEL_US_DTRDIS         BIT(17) /* Data Terminal Ready Disable */
>  #define        ATMEL_US_RTSEN          BIT(18) /* Request To Send Enable */
>  #define        ATMEL_US_RTSDIS         BIT(19) /* Request To Send Disable */
> +#define        ATMEL_US_TXFCLR         BIT(24) /* Transmit FIFO Clear */
> +#define        ATMEL_US_RXFCLR         BIT(25) /* Receive FIFO Clear */
> +#define        ATMEL_US_TXFLCLR        BIT(26) /* Transmit FIFO Lock Clear */
> +#define        ATMEL_US_FIFOEN         BIT(30) /* FIFO enable */
> +#define        ATMEL_US_FIFODIS        BIT(31) /* FIFO disable */
>
>  #define ATMEL_US_MR            0x04    /* Mode Register */
>  #define        ATMEL_US_USMODE         GENMASK(3, 0)   /* Mode of the USART */
> @@ -124,6 +129,37 @@
>  #define ATMEL_US_NER           0x44    /* Number of Errors Register */
>  #define ATMEL_US_IF            0x4c    /* IrDA Filter Register */
>
> +#define ATMEL_US_CMPR          0x90    /* Comparaison Register */
> +#define ATMEL_US_FMR           0xa0    /* FIFO Mode Register */
> +#define        ATMEL_US_TXRDYM(data)   (((data) & 0x3) << 0)   /* TX Ready Mode */
> +#define        ATMEL_US_RXRDYM(data)   (((data) & 0x3) << 4)   /* RX Ready Mode */
> +#define                ATMEL_US_ONE_DATA       0x0
> +#define                ATMEL_US_TWO_DATA       0x1
> +#define                ATMEL_US_FOUR_DATA      0x2
> +#define        ATMEL_US_FRTSC          BIT(7)  /* FIFO RTS pin Control */
> +#define        ATMEL_US_TXFTHRES(thr)  (((thr) & 0x3f) << 8)   /* TX FIFO Threshold */
> +#define        ATMEL_US_RXFTHRES(thr)  (((thr) & 0x3f) << 16)  /* RX FIFO Threshold */
> +#define        ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24)  /* RX FIFO Threshold2 */
> +
> +#define ATMEL_US_FLR           0xa4    /* FIFO Level Register */
> +#define        ATMEL_US_TXFL(reg)      (((reg) >> 0) & 0x3f)   /* TX FIFO Level */
> +#define        ATMEL_US_RXFL(reg)      (((reg) >> 16) & 0x3f)  /* RX FIFO Level */
> +
> +#define ATMEL_US_FIER          0xa8    /* FIFO Interrupt Enable Register */
> +#define ATMEL_US_FIDR          0xac    /* FIFO Interrupt Disable Register */
> +#define ATMEL_US_FIMR          0xb0    /* FIFO Interrupt Mask Register */
> +#define ATMEL_US_FESR          0xb4    /* FIFO Event Status Register */
> +#define        ATMEL_US_TXFEF          BIT(0)  /* Transmit FIFO Empty Flag */
> +#define        ATMEL_US_TXFFF          BIT(1)  /* Transmit FIFO Full Flag */
> +#define        ATMEL_US_TXFTHF         BIT(2)  /* Transmit FIFO Threshold Flag */
> +#define        ATMEL_US_RXFEF          BIT(3)  /* Receive FIFO Empty Flag */
> +#define        ATMEL_US_RXFFF          BIT(4)  /* Receive FIFO Full Flag */
> +#define        ATMEL_US_RXFTHF         BIT(5)  /* Receive FIFO Threshold Flag */
> +#define        ATMEL_US_TXFPTEF        BIT(6)  /* Transmit FIFO Pointer Error Flag */
> +#define        ATMEL_US_RXFPTEF        BIT(7)  /* Receive FIFO Pointer Error Flag */
> +#define        ATMEL_US_TXFLOCK        BIT(8)  /* Transmit FIFO Lock (FESR only) */
> +#define        ATMEL_US_RXFTHF2        BIT(9)  /* Receive FIFO Threshold Flag 2 */
> +
>  #define ATMEL_US_NAME          0xf0    /* Ip Name */
>  #define ATMEL_US_VERSION       0xfc    /* Ip Version */
>
> --
> 1.8.2.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/



-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-29 14:51     ` Andy Shevchenko
  0 siblings, 0 replies; 35+ messages in thread
From: Andy Shevchenko @ 2015-07-29 14:51 UTC (permalink / raw)
  To: Cyrille Pitchen
  Cc: Nicolas Ferre, Greg Kroah-Hartman,
	wenyou.yang-AIFe0yeh4nAAvxtiuMwx3w, ludovic.desroches,
	leilei.zhao-AIFe0yeh4nAAvxtiuMwx3w,
	josh.wu-AIFe0yeh4nAAvxtiuMwx3w,
	alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-arm Mailing List,
	devicetree, Kumar Gala, ijc+devicetree, Mark Rutland, Pawel Moll,
	Rob Herring

On Thu, Jul 2, 2015 at 4:18 PM, Cyrille Pitchen
<cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org> wrote:
> Depending on the hardware, TX and RX FIFOs may be available. The RX
> FIFO can avoid receive overruns, especially when DMA transfers are
> not used to read data from the Receive Holding Register. For heavy
> system load, The CPU is likely not be able to fetch data fast enough
> from the RHR.

This patch broke avr32 console (as seen in today's linux-next) on ATNGW100.
Reverting helps. I'm pretty sure the issue is in 8 bit vs. 32 bit I/O access.

# uname -a
Linux buildroot 4.2.0-rc4-next-20150729+ #97 Wed Jul 29 17:50:11 EEST
2015 avr32 GNU/Linux

Do you, guys, have that board (NGW100) or it's officially unsupported?
If the latter is the case I would really appreciate if you remove the
support from the kernel side.

>
> In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
> line when the Hardware Handshaking mode is enabled. Two thresholds
> are to be set for that purpose:
> - When the number of data in the RX FIFO crosses and becomes lower
>   than or equal to the low threshold, the RTS line is set to low
>   level: the remote peer is requested to send data.
> - When the number of data in the RX FIFO crosses and becomes greater
>   than or equal to the high threshold, the RTS line is set to high
>   level: the remote peer should stop sending new data.
> - low threshold <= high threshold
> Once these two thresholds are set properly, this new feature is
> enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.
>
> FIFOs also introduce a new multiple data mode: the USART works either
> in multiple data mode or in single data (legacy) mode.
>
> If MODE9 bit is set into the Mode Register or if USMODE is set to
> either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
> data mode. Otherwise, they operate in multiple data mode.
>
> In this new multiple data mode, accesses to the Receive Holding
> Register or Transmit Holding Register slightly change.
>
> Since this driver implements neither the 9bit data feature (MODE9 bit
> set into the Mode Register) nor LIN modes, the USART works in
> multiple data mode whenever FIFOs are available and enabled. We also
> assume that data are 8bit wide.
>
> In single data mode, 32bit access CAN be used to read a single data
> from RHR or write a single data into THR.
> However in multiple data mode, a 32bit access to RHR now allows us to
> read four consecutive data from RX FIFO. Also a 32bit access to THR
> now allows to write four consecutive data into TX FIFO. So we MUST
> use 8bit access whenever only one data have to be read/written at a
> time.
>
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
>  include/linux/atmel_serial.h      |  36 ++++++++++++++
>  2 files changed, 130 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index e7c337de31d1..87de21f0c7a3 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -56,6 +56,15 @@
>  /* Revisit: We should calculate this based on the actual port settings */
>  #define PDC_RX_TIMEOUT         (3 * 10)                /* 3 bytes */
>
> +/* The minium number of data FIFOs should be able to contain */
> +#define ATMEL_MIN_FIFO_SIZE    8
> +/*
> + * These two offsets are substracted from the RX FIFO size to define the RTS
> + * high and low thresholds
> + */
> +#define ATMEL_RTS_HIGH_OFFSET  16
> +#define ATMEL_RTS_LOW_OFFSET   20
> +
>  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>  #define SUPPORT_SYSRQ
>  #endif
> @@ -141,6 +150,9 @@ struct atmel_uart_port {
>         struct mctrl_gpios      *gpios;
>         int                     gpio_irq[UART_GPIO_MAX];
>         unsigned int            tx_done_mask;
> +       u32                     fifo_size;
> +       u32                     rts_high;
> +       u32                     rts_low;
>         bool                    ms_irq_enabled;
>         bool                    is_usart;       /* usart or uart */
>         struct timer_list       uart_timer;     /* uart timer */
> @@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
>         __raw_writel(value, port->membase + reg);
>  }
>
> +static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
> +{
> +       return __raw_readb(port->membase + reg);
> +}
> +
> +static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
> +{
> +       __raw_writeb(value, port->membase + reg);
> +}
> +
>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>  static bool atmel_use_pdc_rx(struct uart_port *port)
>  {
> @@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
>
>         status = atmel_uart_readl(port, ATMEL_US_CSR);
>         while (status & ATMEL_US_RXRDY) {
> -               ch = atmel_uart_readl(port, ATMEL_US_RHR);
> +               ch = atmel_uart_readb(port, ATMEL_US_RHR);
>
>                 /*
>                  * note that the error handling code is
> @@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
>
>         if (port->x_char &&
>             (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
> -               atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
> +               atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
>                 port->icount.tx++;
>                 port->x_char = 0;
>         }
> @@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
>
>         while (atmel_uart_readl(port, ATMEL_US_CSR) &
>                atmel_port->tx_done_mask) {
> -               atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
> +               atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>                 port->icount.tx++;
>                 if (uart_circ_empty(xmit))
> @@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
>                         atmel_set_ops(port);
>         }
>
> +       /*
> +        * Enable FIFO when available
> +        */
> +       if (atmel_port->fifo_size) {
> +               unsigned int txrdym = ATMEL_US_ONE_DATA;
> +               unsigned int rxrdym = ATMEL_US_ONE_DATA;
> +               unsigned int fmr;
> +
> +               atmel_uart_writel(port, ATMEL_US_CR,
> +                                 ATMEL_US_FIFOEN |
> +                                 ATMEL_US_RXFCLR |
> +                                 ATMEL_US_TXFLCLR);
> +
> +               fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
> +               if (atmel_port->rts_high &&
> +                   atmel_port->rts_low)
> +                       fmr |=  ATMEL_US_FRTSC |
> +                               ATMEL_US_RXFTHRES(atmel_port->rts_high) |
> +                               ATMEL_US_RXFTHRES2(atmel_port->rts_low);
> +
> +               atmel_uart_writel(port, ATMEL_US_FMR, fmr);
> +       }
> +
>         /* Save current CSR for comparison in atmel_tasklet_func() */
>         atmel_port->irq_status_prev = atmel_get_lines_status(port);
>         atmel_port->irq_status = atmel_port->irq_status_prev;
> @@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>                 cpu_relax();
>
> -       return atmel_uart_readl(port, ATMEL_US_RHR);
> +       return atmel_uart_readb(port, ATMEL_US_RHR);
>  }
>
>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
> @@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>                 cpu_relax();
>
> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>  #endif
>
> @@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
>  {
>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>                 cpu_relax();
> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>
>  /*
> @@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
>         return 0;
>  }
>
> +static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
> +                                    struct platform_device *pdev)
> +{
> +       port->fifo_size = 0;
> +       port->rts_low = 0;
> +       port->rts_high = 0;
> +
> +       if (of_property_read_u32(pdev->dev.of_node,
> +                                "atmel,fifo-size",
> +                                &port->fifo_size))
> +               return;
> +
> +       if (!port->fifo_size)
> +               return;
> +
> +       if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
> +               port->fifo_size = 0;
> +               dev_err(&pdev->dev, "Invalid FIFO size\n");
> +               return;
> +       }
> +
> +       /*
> +        * 0 <= rts_low <= rts_high <= fifo_size
> +        * Once their CTS line asserted by the remote peer, some x86 UARTs tend
> +        * to flush their internal TX FIFO, commonly up to 16 data, before
> +        * actually stopping to send new data. So we try to set the RTS High
> +        * Threshold to a reasonably high value respecting this 16 data
> +        * empirical rule when possible.
> +        */
> +       port->rts_high = max_t(int, port->fifo_size >> 1,
> +                              port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
> +       port->rts_low  = max_t(int, port->fifo_size >> 2,
> +                              port->fifo_size - ATMEL_RTS_LOW_OFFSET);
> +
> +       dev_info(&pdev->dev, "Using FIFO (%u data)\n",
> +                port->fifo_size);
> +       dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
> +               port->rts_high);
> +       dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
> +               port->rts_low);
> +}
> +
>  static int atmel_serial_probe(struct platform_device *pdev)
>  {
>         struct atmel_uart_port *port;
> @@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
>         port = &atmel_ports[ret];
>         port->backup_imr = 0;
>         port->uart.line = ret;
> +       atmel_serial_probe_fifos(port, pdev);
>
>         spin_lock_init(&port->lock_suspended);
>
> diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
> index c384c21d65f0..ee696d7e8a43 100644
> --- a/include/linux/atmel_serial.h
> +++ b/include/linux/atmel_serial.h
> @@ -35,6 +35,11 @@
>  #define        ATMEL_US_DTRDIS         BIT(17) /* Data Terminal Ready Disable */
>  #define        ATMEL_US_RTSEN          BIT(18) /* Request To Send Enable */
>  #define        ATMEL_US_RTSDIS         BIT(19) /* Request To Send Disable */
> +#define        ATMEL_US_TXFCLR         BIT(24) /* Transmit FIFO Clear */
> +#define        ATMEL_US_RXFCLR         BIT(25) /* Receive FIFO Clear */
> +#define        ATMEL_US_TXFLCLR        BIT(26) /* Transmit FIFO Lock Clear */
> +#define        ATMEL_US_FIFOEN         BIT(30) /* FIFO enable */
> +#define        ATMEL_US_FIFODIS        BIT(31) /* FIFO disable */
>
>  #define ATMEL_US_MR            0x04    /* Mode Register */
>  #define        ATMEL_US_USMODE         GENMASK(3, 0)   /* Mode of the USART */
> @@ -124,6 +129,37 @@
>  #define ATMEL_US_NER           0x44    /* Number of Errors Register */
>  #define ATMEL_US_IF            0x4c    /* IrDA Filter Register */
>
> +#define ATMEL_US_CMPR          0x90    /* Comparaison Register */
> +#define ATMEL_US_FMR           0xa0    /* FIFO Mode Register */
> +#define        ATMEL_US_TXRDYM(data)   (((data) & 0x3) << 0)   /* TX Ready Mode */
> +#define        ATMEL_US_RXRDYM(data)   (((data) & 0x3) << 4)   /* RX Ready Mode */
> +#define                ATMEL_US_ONE_DATA       0x0
> +#define                ATMEL_US_TWO_DATA       0x1
> +#define                ATMEL_US_FOUR_DATA      0x2
> +#define        ATMEL_US_FRTSC          BIT(7)  /* FIFO RTS pin Control */
> +#define        ATMEL_US_TXFTHRES(thr)  (((thr) & 0x3f) << 8)   /* TX FIFO Threshold */
> +#define        ATMEL_US_RXFTHRES(thr)  (((thr) & 0x3f) << 16)  /* RX FIFO Threshold */
> +#define        ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24)  /* RX FIFO Threshold2 */
> +
> +#define ATMEL_US_FLR           0xa4    /* FIFO Level Register */
> +#define        ATMEL_US_TXFL(reg)      (((reg) >> 0) & 0x3f)   /* TX FIFO Level */
> +#define        ATMEL_US_RXFL(reg)      (((reg) >> 16) & 0x3f)  /* RX FIFO Level */
> +
> +#define ATMEL_US_FIER          0xa8    /* FIFO Interrupt Enable Register */
> +#define ATMEL_US_FIDR          0xac    /* FIFO Interrupt Disable Register */
> +#define ATMEL_US_FIMR          0xb0    /* FIFO Interrupt Mask Register */
> +#define ATMEL_US_FESR          0xb4    /* FIFO Event Status Register */
> +#define        ATMEL_US_TXFEF          BIT(0)  /* Transmit FIFO Empty Flag */
> +#define        ATMEL_US_TXFFF          BIT(1)  /* Transmit FIFO Full Flag */
> +#define        ATMEL_US_TXFTHF         BIT(2)  /* Transmit FIFO Threshold Flag */
> +#define        ATMEL_US_RXFEF          BIT(3)  /* Receive FIFO Empty Flag */
> +#define        ATMEL_US_RXFFF          BIT(4)  /* Receive FIFO Full Flag */
> +#define        ATMEL_US_RXFTHF         BIT(5)  /* Receive FIFO Threshold Flag */
> +#define        ATMEL_US_TXFPTEF        BIT(6)  /* Transmit FIFO Pointer Error Flag */
> +#define        ATMEL_US_RXFPTEF        BIT(7)  /* Receive FIFO Pointer Error Flag */
> +#define        ATMEL_US_TXFLOCK        BIT(8)  /* Transmit FIFO Lock (FESR only) */
> +#define        ATMEL_US_RXFTHF2        BIT(9)  /* Receive FIFO Threshold Flag 2 */
> +
>  #define ATMEL_US_NAME          0xf0    /* Ip Name */
>  #define ATMEL_US_VERSION       0xfc    /* Ip Version */
>
> --
> 1.8.2.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/



-- 
With Best Regards,
Andy Shevchenko
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-29 14:51     ` Andy Shevchenko
  0 siblings, 0 replies; 35+ messages in thread
From: Andy Shevchenko @ 2015-07-29 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 2, 2015 at 4:18 PM, Cyrille Pitchen
<cyrille.pitchen@atmel.com> wrote:
> Depending on the hardware, TX and RX FIFOs may be available. The RX
> FIFO can avoid receive overruns, especially when DMA transfers are
> not used to read data from the Receive Holding Register. For heavy
> system load, The CPU is likely not be able to fetch data fast enough
> from the RHR.

This patch broke avr32 console (as seen in today's linux-next) on ATNGW100.
Reverting helps. I'm pretty sure the issue is in 8 bit vs. 32 bit I/O access.

# uname -a
Linux buildroot 4.2.0-rc4-next-20150729+ #97 Wed Jul 29 17:50:11 EEST
2015 avr32 GNU/Linux

Do you, guys, have that board (NGW100) or it's officially unsupported?
If the latter is the case I would really appreciate if you remove the
support from the kernel side.

>
> In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
> line when the Hardware Handshaking mode is enabled. Two thresholds
> are to be set for that purpose:
> - When the number of data in the RX FIFO crosses and becomes lower
>   than or equal to the low threshold, the RTS line is set to low
>   level: the remote peer is requested to send data.
> - When the number of data in the RX FIFO crosses and becomes greater
>   than or equal to the high threshold, the RTS line is set to high
>   level: the remote peer should stop sending new data.
> - low threshold <= high threshold
> Once these two thresholds are set properly, this new feature is
> enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.
>
> FIFOs also introduce a new multiple data mode: the USART works either
> in multiple data mode or in single data (legacy) mode.
>
> If MODE9 bit is set into the Mode Register or if USMODE is set to
> either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
> data mode. Otherwise, they operate in multiple data mode.
>
> In this new multiple data mode, accesses to the Receive Holding
> Register or Transmit Holding Register slightly change.
>
> Since this driver implements neither the 9bit data feature (MODE9 bit
> set into the Mode Register) nor LIN modes, the USART works in
> multiple data mode whenever FIFOs are available and enabled. We also
> assume that data are 8bit wide.
>
> In single data mode, 32bit access CAN be used to read a single data
> from RHR or write a single data into THR.
> However in multiple data mode, a 32bit access to RHR now allows us to
> read four consecutive data from RX FIFO. Also a 32bit access to THR
> now allows to write four consecutive data into TX FIFO. So we MUST
> use 8bit access whenever only one data have to be read/written at a
> time.
>
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
> ---
>  drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
>  include/linux/atmel_serial.h      |  36 ++++++++++++++
>  2 files changed, 130 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index e7c337de31d1..87de21f0c7a3 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -56,6 +56,15 @@
>  /* Revisit: We should calculate this based on the actual port settings */
>  #define PDC_RX_TIMEOUT         (3 * 10)                /* 3 bytes */
>
> +/* The minium number of data FIFOs should be able to contain */
> +#define ATMEL_MIN_FIFO_SIZE    8
> +/*
> + * These two offsets are substracted from the RX FIFO size to define the RTS
> + * high and low thresholds
> + */
> +#define ATMEL_RTS_HIGH_OFFSET  16
> +#define ATMEL_RTS_LOW_OFFSET   20
> +
>  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>  #define SUPPORT_SYSRQ
>  #endif
> @@ -141,6 +150,9 @@ struct atmel_uart_port {
>         struct mctrl_gpios      *gpios;
>         int                     gpio_irq[UART_GPIO_MAX];
>         unsigned int            tx_done_mask;
> +       u32                     fifo_size;
> +       u32                     rts_high;
> +       u32                     rts_low;
>         bool                    ms_irq_enabled;
>         bool                    is_usart;       /* usart or uart */
>         struct timer_list       uart_timer;     /* uart timer */
> @@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
>         __raw_writel(value, port->membase + reg);
>  }
>
> +static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
> +{
> +       return __raw_readb(port->membase + reg);
> +}
> +
> +static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
> +{
> +       __raw_writeb(value, port->membase + reg);
> +}
> +
>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>  static bool atmel_use_pdc_rx(struct uart_port *port)
>  {
> @@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
>
>         status = atmel_uart_readl(port, ATMEL_US_CSR);
>         while (status & ATMEL_US_RXRDY) {
> -               ch = atmel_uart_readl(port, ATMEL_US_RHR);
> +               ch = atmel_uart_readb(port, ATMEL_US_RHR);
>
>                 /*
>                  * note that the error handling code is
> @@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
>
>         if (port->x_char &&
>             (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
> -               atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
> +               atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
>                 port->icount.tx++;
>                 port->x_char = 0;
>         }
> @@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
>
>         while (atmel_uart_readl(port, ATMEL_US_CSR) &
>                atmel_port->tx_done_mask) {
> -               atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
> +               atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>                 port->icount.tx++;
>                 if (uart_circ_empty(xmit))
> @@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
>                         atmel_set_ops(port);
>         }
>
> +       /*
> +        * Enable FIFO when available
> +        */
> +       if (atmel_port->fifo_size) {
> +               unsigned int txrdym = ATMEL_US_ONE_DATA;
> +               unsigned int rxrdym = ATMEL_US_ONE_DATA;
> +               unsigned int fmr;
> +
> +               atmel_uart_writel(port, ATMEL_US_CR,
> +                                 ATMEL_US_FIFOEN |
> +                                 ATMEL_US_RXFCLR |
> +                                 ATMEL_US_TXFLCLR);
> +
> +               fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
> +               if (atmel_port->rts_high &&
> +                   atmel_port->rts_low)
> +                       fmr |=  ATMEL_US_FRTSC |
> +                               ATMEL_US_RXFTHRES(atmel_port->rts_high) |
> +                               ATMEL_US_RXFTHRES2(atmel_port->rts_low);
> +
> +               atmel_uart_writel(port, ATMEL_US_FMR, fmr);
> +       }
> +
>         /* Save current CSR for comparison in atmel_tasklet_func() */
>         atmel_port->irq_status_prev = atmel_get_lines_status(port);
>         atmel_port->irq_status = atmel_port->irq_status_prev;
> @@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>                 cpu_relax();
>
> -       return atmel_uart_readl(port, ATMEL_US_RHR);
> +       return atmel_uart_readb(port, ATMEL_US_RHR);
>  }
>
>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
> @@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>                 cpu_relax();
>
> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>  #endif
>
> @@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
>  {
>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>                 cpu_relax();
> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>  }
>
>  /*
> @@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
>         return 0;
>  }
>
> +static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
> +                                    struct platform_device *pdev)
> +{
> +       port->fifo_size = 0;
> +       port->rts_low = 0;
> +       port->rts_high = 0;
> +
> +       if (of_property_read_u32(pdev->dev.of_node,
> +                                "atmel,fifo-size",
> +                                &port->fifo_size))
> +               return;
> +
> +       if (!port->fifo_size)
> +               return;
> +
> +       if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
> +               port->fifo_size = 0;
> +               dev_err(&pdev->dev, "Invalid FIFO size\n");
> +               return;
> +       }
> +
> +       /*
> +        * 0 <= rts_low <= rts_high <= fifo_size
> +        * Once their CTS line asserted by the remote peer, some x86 UARTs tend
> +        * to flush their internal TX FIFO, commonly up to 16 data, before
> +        * actually stopping to send new data. So we try to set the RTS High
> +        * Threshold to a reasonably high value respecting this 16 data
> +        * empirical rule when possible.
> +        */
> +       port->rts_high = max_t(int, port->fifo_size >> 1,
> +                              port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
> +       port->rts_low  = max_t(int, port->fifo_size >> 2,
> +                              port->fifo_size - ATMEL_RTS_LOW_OFFSET);
> +
> +       dev_info(&pdev->dev, "Using FIFO (%u data)\n",
> +                port->fifo_size);
> +       dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
> +               port->rts_high);
> +       dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
> +               port->rts_low);
> +}
> +
>  static int atmel_serial_probe(struct platform_device *pdev)
>  {
>         struct atmel_uart_port *port;
> @@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
>         port = &atmel_ports[ret];
>         port->backup_imr = 0;
>         port->uart.line = ret;
> +       atmel_serial_probe_fifos(port, pdev);
>
>         spin_lock_init(&port->lock_suspended);
>
> diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
> index c384c21d65f0..ee696d7e8a43 100644
> --- a/include/linux/atmel_serial.h
> +++ b/include/linux/atmel_serial.h
> @@ -35,6 +35,11 @@
>  #define        ATMEL_US_DTRDIS         BIT(17) /* Data Terminal Ready Disable */
>  #define        ATMEL_US_RTSEN          BIT(18) /* Request To Send Enable */
>  #define        ATMEL_US_RTSDIS         BIT(19) /* Request To Send Disable */
> +#define        ATMEL_US_TXFCLR         BIT(24) /* Transmit FIFO Clear */
> +#define        ATMEL_US_RXFCLR         BIT(25) /* Receive FIFO Clear */
> +#define        ATMEL_US_TXFLCLR        BIT(26) /* Transmit FIFO Lock Clear */
> +#define        ATMEL_US_FIFOEN         BIT(30) /* FIFO enable */
> +#define        ATMEL_US_FIFODIS        BIT(31) /* FIFO disable */
>
>  #define ATMEL_US_MR            0x04    /* Mode Register */
>  #define        ATMEL_US_USMODE         GENMASK(3, 0)   /* Mode of the USART */
> @@ -124,6 +129,37 @@
>  #define ATMEL_US_NER           0x44    /* Number of Errors Register */
>  #define ATMEL_US_IF            0x4c    /* IrDA Filter Register */
>
> +#define ATMEL_US_CMPR          0x90    /* Comparaison Register */
> +#define ATMEL_US_FMR           0xa0    /* FIFO Mode Register */
> +#define        ATMEL_US_TXRDYM(data)   (((data) & 0x3) << 0)   /* TX Ready Mode */
> +#define        ATMEL_US_RXRDYM(data)   (((data) & 0x3) << 4)   /* RX Ready Mode */
> +#define                ATMEL_US_ONE_DATA       0x0
> +#define                ATMEL_US_TWO_DATA       0x1
> +#define                ATMEL_US_FOUR_DATA      0x2
> +#define        ATMEL_US_FRTSC          BIT(7)  /* FIFO RTS pin Control */
> +#define        ATMEL_US_TXFTHRES(thr)  (((thr) & 0x3f) << 8)   /* TX FIFO Threshold */
> +#define        ATMEL_US_RXFTHRES(thr)  (((thr) & 0x3f) << 16)  /* RX FIFO Threshold */
> +#define        ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24)  /* RX FIFO Threshold2 */
> +
> +#define ATMEL_US_FLR           0xa4    /* FIFO Level Register */
> +#define        ATMEL_US_TXFL(reg)      (((reg) >> 0) & 0x3f)   /* TX FIFO Level */
> +#define        ATMEL_US_RXFL(reg)      (((reg) >> 16) & 0x3f)  /* RX FIFO Level */
> +
> +#define ATMEL_US_FIER          0xa8    /* FIFO Interrupt Enable Register */
> +#define ATMEL_US_FIDR          0xac    /* FIFO Interrupt Disable Register */
> +#define ATMEL_US_FIMR          0xb0    /* FIFO Interrupt Mask Register */
> +#define ATMEL_US_FESR          0xb4    /* FIFO Event Status Register */
> +#define        ATMEL_US_TXFEF          BIT(0)  /* Transmit FIFO Empty Flag */
> +#define        ATMEL_US_TXFFF          BIT(1)  /* Transmit FIFO Full Flag */
> +#define        ATMEL_US_TXFTHF         BIT(2)  /* Transmit FIFO Threshold Flag */
> +#define        ATMEL_US_RXFEF          BIT(3)  /* Receive FIFO Empty Flag */
> +#define        ATMEL_US_RXFFF          BIT(4)  /* Receive FIFO Full Flag */
> +#define        ATMEL_US_RXFTHF         BIT(5)  /* Receive FIFO Threshold Flag */
> +#define        ATMEL_US_TXFPTEF        BIT(6)  /* Transmit FIFO Pointer Error Flag */
> +#define        ATMEL_US_RXFPTEF        BIT(7)  /* Receive FIFO Pointer Error Flag */
> +#define        ATMEL_US_TXFLOCK        BIT(8)  /* Transmit FIFO Lock (FESR only) */
> +#define        ATMEL_US_RXFTHF2        BIT(9)  /* Receive FIFO Threshold Flag 2 */
> +
>  #define ATMEL_US_NAME          0xf0    /* Ip Name */
>  #define ATMEL_US_VERSION       0xfc    /* Ip Version */
>
> --
> 1.8.2.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/



-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-29 15:07       ` Alexandre Belloni
  0 siblings, 0 replies; 35+ messages in thread
From: Alexandre Belloni @ 2015-07-29 15:07 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Cyrille Pitchen, Nicolas Ferre, Greg Kroah-Hartman, wenyou.yang,
	ludovic.desroches, leilei.zhao, josh.wu, linux-serial,
	linux-kernel, linux-arm Mailing List, devicetree, Kumar Gala,
	ijc+devicetree, Mark Rutland, Pawel Moll, Rob Herring

Hi Andy,

On 29/07/2015 at 17:51:38 +0300, Andy Shevchenko wrote :
> On Thu, Jul 2, 2015 at 4:18 PM, Cyrille Pitchen
> <cyrille.pitchen@atmel.com> wrote:
> > Depending on the hardware, TX and RX FIFOs may be available. The RX
> > FIFO can avoid receive overruns, especially when DMA transfers are
> > not used to read data from the Receive Holding Register. For heavy
> > system load, The CPU is likely not be able to fetch data fast enough
> > from the RHR.
> 
> This patch broke avr32 console (as seen in today's linux-next) on ATNGW100.
> Reverting helps. I'm pretty sure the issue is in 8 bit vs. 32 bit I/O access.
> 
> # uname -a
> Linux buildroot 4.2.0-rc4-next-20150729+ #97 Wed Jul 29 17:50:11 EEST
> 2015 avr32 GNU/Linux
> 
> Do you, guys, have that board (NGW100) or it's officially unsupported?
> If the latter is the case I would really appreciate if you remove the
> support from the kernel side.
> 

The main issue here is that the main atmel arm developers don't have
access to any avr32 board. I'd say that everything that is done is best
effort to not break avr32 but it is not tested at all.

Don't hesitate to submit patches when something breaks...

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

* Re: [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-29 15:07       ` Alexandre Belloni
  0 siblings, 0 replies; 35+ messages in thread
From: Alexandre Belloni @ 2015-07-29 15:07 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Cyrille Pitchen, Nicolas Ferre, Greg Kroah-Hartman,
	wenyou.yang-AIFe0yeh4nAAvxtiuMwx3w, ludovic.desroches,
	leilei.zhao-AIFe0yeh4nAAvxtiuMwx3w,
	josh.wu-AIFe0yeh4nAAvxtiuMwx3w,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-arm Mailing List,
	devicetree, Kumar Gala, ijc+devicetree, Mark Rutland, Pawel Moll,
	Rob Herring

Hi Andy,

On 29/07/2015 at 17:51:38 +0300, Andy Shevchenko wrote :
> On Thu, Jul 2, 2015 at 4:18 PM, Cyrille Pitchen
> <cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org> wrote:
> > Depending on the hardware, TX and RX FIFOs may be available. The RX
> > FIFO can avoid receive overruns, especially when DMA transfers are
> > not used to read data from the Receive Holding Register. For heavy
> > system load, The CPU is likely not be able to fetch data fast enough
> > from the RHR.
> 
> This patch broke avr32 console (as seen in today's linux-next) on ATNGW100.
> Reverting helps. I'm pretty sure the issue is in 8 bit vs. 32 bit I/O access.
> 
> # uname -a
> Linux buildroot 4.2.0-rc4-next-20150729+ #97 Wed Jul 29 17:50:11 EEST
> 2015 avr32 GNU/Linux
> 
> Do you, guys, have that board (NGW100) or it's officially unsupported?
> If the latter is the case I would really appreciate if you remove the
> support from the kernel side.
> 

The main issue here is that the main atmel arm developers don't have
access to any avr32 board. I'd say that everything that is done is best
effort to not break avr32 but it is not tested at all.

Don't hesitate to submit patches when something breaks...

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-29 15:07       ` Alexandre Belloni
  0 siblings, 0 replies; 35+ messages in thread
From: Alexandre Belloni @ 2015-07-29 15:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Andy,

On 29/07/2015 at 17:51:38 +0300, Andy Shevchenko wrote :
> On Thu, Jul 2, 2015 at 4:18 PM, Cyrille Pitchen
> <cyrille.pitchen@atmel.com> wrote:
> > Depending on the hardware, TX and RX FIFOs may be available. The RX
> > FIFO can avoid receive overruns, especially when DMA transfers are
> > not used to read data from the Receive Holding Register. For heavy
> > system load, The CPU is likely not be able to fetch data fast enough
> > from the RHR.
> 
> This patch broke avr32 console (as seen in today's linux-next) on ATNGW100.
> Reverting helps. I'm pretty sure the issue is in 8 bit vs. 32 bit I/O access.
> 
> # uname -a
> Linux buildroot 4.2.0-rc4-next-20150729+ #97 Wed Jul 29 17:50:11 EEST
> 2015 avr32 GNU/Linux
> 
> Do you, guys, have that board (NGW100) or it's officially unsupported?
> If the latter is the case I would really appreciate if you remove the
> support from the kernel side.
> 

The main issue here is that the main atmel arm developers don't have
access to any avr32 board. I'd say that everything that is done is best
effort to not break avr32 but it is not tested at all.

Don't hesitate to submit patches when something breaks...

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

* Re: [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
  2015-07-29 14:51     ` Andy Shevchenko
@ 2015-07-29 15:09       ` Nicolas Ferre
  -1 siblings, 0 replies; 35+ messages in thread
From: Nicolas Ferre @ 2015-07-29 15:09 UTC (permalink / raw)
  To: Andy Shevchenko, Cyrille Pitchen, Greg Kroah-Hartman,
	Hans-Christian Egtvedt
  Cc: Mark Rutland, devicetree, Pawel Moll, ijc+devicetree,
	linux-kernel, Rob Herring, wenyou.yang, josh.wu,
	ludovic.desroches, alexandre.belloni, linux-serial, Kumar Gala,
	leilei.zhao, linux-arm Mailing List

Le 29/07/2015 16:51, Andy Shevchenko a écrit :
> On Thu, Jul 2, 2015 at 4:18 PM, Cyrille Pitchen
> <cyrille.pitchen@atmel.com> wrote:
>> Depending on the hardware, TX and RX FIFOs may be available. The RX
>> FIFO can avoid receive overruns, especially when DMA transfers are
>> not used to read data from the Receive Holding Register. For heavy
>> system load, The CPU is likely not be able to fetch data fast enough
>> from the RHR.
> 
> This patch broke avr32 console (as seen in today's linux-next) on ATNGW100.
> Reverting helps. I'm pretty sure the issue is in 8 bit vs. 32 bit I/O access.

I would like that we don't revert the patch.
We'll try to blindly find the cause for this issue.

> # uname -a
> Linux buildroot 4.2.0-rc4-next-20150729+ #97 Wed Jul 29 17:50:11 EEST
> 2015 avr32 GNU/Linux
> 
> Do you, guys, have that board (NGW100) or it's officially unsupported?

Sorry but we don't have AVR32-based board in our office. Hans-Christian
kindly helps us fixing the issues that we find and we tend to rely on
the community for this architecture support...

> If the latter is the case I would really appreciate if you remove the
> support from the kernel side.

I won't decide for its removal. Only the maintainers with feedback from
the user base can.

>> In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
>> line when the Hardware Handshaking mode is enabled. Two thresholds
>> are to be set for that purpose:
>> - When the number of data in the RX FIFO crosses and becomes lower
>>   than or equal to the low threshold, the RTS line is set to low
>>   level: the remote peer is requested to send data.
>> - When the number of data in the RX FIFO crosses and becomes greater
>>   than or equal to the high threshold, the RTS line is set to high
>>   level: the remote peer should stop sending new data.
>> - low threshold <= high threshold
>> Once these two thresholds are set properly, this new feature is
>> enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.
>>
>> FIFOs also introduce a new multiple data mode: the USART works either
>> in multiple data mode or in single data (legacy) mode.
>>
>> If MODE9 bit is set into the Mode Register or if USMODE is set to
>> either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
>> data mode. Otherwise, they operate in multiple data mode.
>>
>> In this new multiple data mode, accesses to the Receive Holding
>> Register or Transmit Holding Register slightly change.
>>
>> Since this driver implements neither the 9bit data feature (MODE9 bit
>> set into the Mode Register) nor LIN modes, the USART works in
>> multiple data mode whenever FIFOs are available and enabled. We also
>> assume that data are 8bit wide.
>>
>> In single data mode, 32bit access CAN be used to read a single data
>> from RHR or write a single data into THR.
>> However in multiple data mode, a 32bit access to RHR now allows us to
>> read four consecutive data from RX FIFO. Also a 32bit access to THR
>> now allows to write four consecutive data into TX FIFO. So we MUST
>> use 8bit access whenever only one data have to be read/written at a
>> time.
>>
>> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
>> ---
>>  drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
>>  include/linux/atmel_serial.h      |  36 ++++++++++++++
>>  2 files changed, 130 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
>> index e7c337de31d1..87de21f0c7a3 100644
>> --- a/drivers/tty/serial/atmel_serial.c
>> +++ b/drivers/tty/serial/atmel_serial.c
>> @@ -56,6 +56,15 @@
>>  /* Revisit: We should calculate this based on the actual port settings */
>>  #define PDC_RX_TIMEOUT         (3 * 10)                /* 3 bytes */
>>
>> +/* The minium number of data FIFOs should be able to contain */
>> +#define ATMEL_MIN_FIFO_SIZE    8
>> +/*
>> + * These two offsets are substracted from the RX FIFO size to define the RTS
>> + * high and low thresholds
>> + */
>> +#define ATMEL_RTS_HIGH_OFFSET  16
>> +#define ATMEL_RTS_LOW_OFFSET   20
>> +
>>  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>>  #define SUPPORT_SYSRQ
>>  #endif
>> @@ -141,6 +150,9 @@ struct atmel_uart_port {
>>         struct mctrl_gpios      *gpios;
>>         int                     gpio_irq[UART_GPIO_MAX];
>>         unsigned int            tx_done_mask;
>> +       u32                     fifo_size;
>> +       u32                     rts_high;
>> +       u32                     rts_low;
>>         bool                    ms_irq_enabled;
>>         bool                    is_usart;       /* usart or uart */
>>         struct timer_list       uart_timer;     /* uart timer */
>> @@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
>>         __raw_writel(value, port->membase + reg);
>>  }
>>
>> +static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
>> +{
>> +       return __raw_readb(port->membase + reg);
>> +}
>> +
>> +static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
>> +{
>> +       __raw_writeb(value, port->membase + reg);
>> +}
>> +
>>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>>  static bool atmel_use_pdc_rx(struct uart_port *port)
>>  {
>> @@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
>>
>>         status = atmel_uart_readl(port, ATMEL_US_CSR);
>>         while (status & ATMEL_US_RXRDY) {
>> -               ch = atmel_uart_readl(port, ATMEL_US_RHR);
>> +               ch = atmel_uart_readb(port, ATMEL_US_RHR);
>>
>>                 /*
>>                  * note that the error handling code is
>> @@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
>>
>>         if (port->x_char &&
>>             (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
>> -               atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
>> +               atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
>>                 port->icount.tx++;
>>                 port->x_char = 0;
>>         }
>> @@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
>>
>>         while (atmel_uart_readl(port, ATMEL_US_CSR) &
>>                atmel_port->tx_done_mask) {
>> -               atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>> +               atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>>                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>>                 port->icount.tx++;
>>                 if (uart_circ_empty(xmit))
>> @@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
>>                         atmel_set_ops(port);
>>         }
>>
>> +       /*
>> +        * Enable FIFO when available
>> +        */
>> +       if (atmel_port->fifo_size) {
>> +               unsigned int txrdym = ATMEL_US_ONE_DATA;
>> +               unsigned int rxrdym = ATMEL_US_ONE_DATA;
>> +               unsigned int fmr;
>> +
>> +               atmel_uart_writel(port, ATMEL_US_CR,
>> +                                 ATMEL_US_FIFOEN |
>> +                                 ATMEL_US_RXFCLR |
>> +                                 ATMEL_US_TXFLCLR);
>> +
>> +               fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
>> +               if (atmel_port->rts_high &&
>> +                   atmel_port->rts_low)
>> +                       fmr |=  ATMEL_US_FRTSC |
>> +                               ATMEL_US_RXFTHRES(atmel_port->rts_high) |
>> +                               ATMEL_US_RXFTHRES2(atmel_port->rts_low);
>> +
>> +               atmel_uart_writel(port, ATMEL_US_FMR, fmr);
>> +       }
>> +
>>         /* Save current CSR for comparison in atmel_tasklet_func() */
>>         atmel_port->irq_status_prev = atmel_get_lines_status(port);
>>         atmel_port->irq_status = atmel_port->irq_status_prev;
>> @@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>>                 cpu_relax();
>>
>> -       return atmel_uart_readl(port, ATMEL_US_RHR);
>> +       return atmel_uart_readb(port, ATMEL_US_RHR);
>>  }
>>
>>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>> @@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>>                 cpu_relax();
>>
>> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
>> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>>  }
>>  #endif
>>
>> @@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
>>  {
>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>>                 cpu_relax();
>> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
>> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>>  }
>>
>>  /*
>> @@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
>>         return 0;
>>  }
>>
>> +static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
>> +                                    struct platform_device *pdev)
>> +{
>> +       port->fifo_size = 0;
>> +       port->rts_low = 0;
>> +       port->rts_high = 0;
>> +
>> +       if (of_property_read_u32(pdev->dev.of_node,
>> +                                "atmel,fifo-size",
>> +                                &port->fifo_size))
>> +               return;
>> +
>> +       if (!port->fifo_size)
>> +               return;
>> +
>> +       if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
>> +               port->fifo_size = 0;
>> +               dev_err(&pdev->dev, "Invalid FIFO size\n");
>> +               return;
>> +       }
>> +
>> +       /*
>> +        * 0 <= rts_low <= rts_high <= fifo_size
>> +        * Once their CTS line asserted by the remote peer, some x86 UARTs tend
>> +        * to flush their internal TX FIFO, commonly up to 16 data, before
>> +        * actually stopping to send new data. So we try to set the RTS High
>> +        * Threshold to a reasonably high value respecting this 16 data
>> +        * empirical rule when possible.
>> +        */
>> +       port->rts_high = max_t(int, port->fifo_size >> 1,
>> +                              port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
>> +       port->rts_low  = max_t(int, port->fifo_size >> 2,
>> +                              port->fifo_size - ATMEL_RTS_LOW_OFFSET);
>> +
>> +       dev_info(&pdev->dev, "Using FIFO (%u data)\n",
>> +                port->fifo_size);
>> +       dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
>> +               port->rts_high);
>> +       dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
>> +               port->rts_low);
>> +}
>> +
>>  static int atmel_serial_probe(struct platform_device *pdev)
>>  {
>>         struct atmel_uart_port *port;
>> @@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
>>         port = &atmel_ports[ret];
>>         port->backup_imr = 0;
>>         port->uart.line = ret;
>> +       atmel_serial_probe_fifos(port, pdev);
>>
>>         spin_lock_init(&port->lock_suspended);
>>
>> diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
>> index c384c21d65f0..ee696d7e8a43 100644
>> --- a/include/linux/atmel_serial.h
>> +++ b/include/linux/atmel_serial.h
>> @@ -35,6 +35,11 @@
>>  #define        ATMEL_US_DTRDIS         BIT(17) /* Data Terminal Ready Disable */
>>  #define        ATMEL_US_RTSEN          BIT(18) /* Request To Send Enable */
>>  #define        ATMEL_US_RTSDIS         BIT(19) /* Request To Send Disable */
>> +#define        ATMEL_US_TXFCLR         BIT(24) /* Transmit FIFO Clear */
>> +#define        ATMEL_US_RXFCLR         BIT(25) /* Receive FIFO Clear */
>> +#define        ATMEL_US_TXFLCLR        BIT(26) /* Transmit FIFO Lock Clear */
>> +#define        ATMEL_US_FIFOEN         BIT(30) /* FIFO enable */
>> +#define        ATMEL_US_FIFODIS        BIT(31) /* FIFO disable */
>>
>>  #define ATMEL_US_MR            0x04    /* Mode Register */
>>  #define        ATMEL_US_USMODE         GENMASK(3, 0)   /* Mode of the USART */
>> @@ -124,6 +129,37 @@
>>  #define ATMEL_US_NER           0x44    /* Number of Errors Register */
>>  #define ATMEL_US_IF            0x4c    /* IrDA Filter Register */
>>
>> +#define ATMEL_US_CMPR          0x90    /* Comparaison Register */
>> +#define ATMEL_US_FMR           0xa0    /* FIFO Mode Register */
>> +#define        ATMEL_US_TXRDYM(data)   (((data) & 0x3) << 0)   /* TX Ready Mode */
>> +#define        ATMEL_US_RXRDYM(data)   (((data) & 0x3) << 4)   /* RX Ready Mode */
>> +#define                ATMEL_US_ONE_DATA       0x0
>> +#define                ATMEL_US_TWO_DATA       0x1
>> +#define                ATMEL_US_FOUR_DATA      0x2
>> +#define        ATMEL_US_FRTSC          BIT(7)  /* FIFO RTS pin Control */
>> +#define        ATMEL_US_TXFTHRES(thr)  (((thr) & 0x3f) << 8)   /* TX FIFO Threshold */
>> +#define        ATMEL_US_RXFTHRES(thr)  (((thr) & 0x3f) << 16)  /* RX FIFO Threshold */
>> +#define        ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24)  /* RX FIFO Threshold2 */
>> +
>> +#define ATMEL_US_FLR           0xa4    /* FIFO Level Register */
>> +#define        ATMEL_US_TXFL(reg)      (((reg) >> 0) & 0x3f)   /* TX FIFO Level */
>> +#define        ATMEL_US_RXFL(reg)      (((reg) >> 16) & 0x3f)  /* RX FIFO Level */
>> +
>> +#define ATMEL_US_FIER          0xa8    /* FIFO Interrupt Enable Register */
>> +#define ATMEL_US_FIDR          0xac    /* FIFO Interrupt Disable Register */
>> +#define ATMEL_US_FIMR          0xb0    /* FIFO Interrupt Mask Register */
>> +#define ATMEL_US_FESR          0xb4    /* FIFO Event Status Register */
>> +#define        ATMEL_US_TXFEF          BIT(0)  /* Transmit FIFO Empty Flag */
>> +#define        ATMEL_US_TXFFF          BIT(1)  /* Transmit FIFO Full Flag */
>> +#define        ATMEL_US_TXFTHF         BIT(2)  /* Transmit FIFO Threshold Flag */
>> +#define        ATMEL_US_RXFEF          BIT(3)  /* Receive FIFO Empty Flag */
>> +#define        ATMEL_US_RXFFF          BIT(4)  /* Receive FIFO Full Flag */
>> +#define        ATMEL_US_RXFTHF         BIT(5)  /* Receive FIFO Threshold Flag */
>> +#define        ATMEL_US_TXFPTEF        BIT(6)  /* Transmit FIFO Pointer Error Flag */
>> +#define        ATMEL_US_RXFPTEF        BIT(7)  /* Receive FIFO Pointer Error Flag */
>> +#define        ATMEL_US_TXFLOCK        BIT(8)  /* Transmit FIFO Lock (FESR only) */
>> +#define        ATMEL_US_RXFTHF2        BIT(9)  /* Receive FIFO Threshold Flag 2 */
>> +
>>  #define ATMEL_US_NAME          0xf0    /* Ip Name */
>>  #define ATMEL_US_VERSION       0xfc    /* Ip Version */
>>
>> --
>> 1.8.2.2
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
> 
> 
> 


-- 
Nicolas Ferre

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-29 15:09       ` Nicolas Ferre
  0 siblings, 0 replies; 35+ messages in thread
From: Nicolas Ferre @ 2015-07-29 15:09 UTC (permalink / raw)
  To: linux-arm-kernel

Le 29/07/2015 16:51, Andy Shevchenko a ?crit :
> On Thu, Jul 2, 2015 at 4:18 PM, Cyrille Pitchen
> <cyrille.pitchen@atmel.com> wrote:
>> Depending on the hardware, TX and RX FIFOs may be available. The RX
>> FIFO can avoid receive overruns, especially when DMA transfers are
>> not used to read data from the Receive Holding Register. For heavy
>> system load, The CPU is likely not be able to fetch data fast enough
>> from the RHR.
> 
> This patch broke avr32 console (as seen in today's linux-next) on ATNGW100.
> Reverting helps. I'm pretty sure the issue is in 8 bit vs. 32 bit I/O access.

I would like that we don't revert the patch.
We'll try to blindly find the cause for this issue.

> # uname -a
> Linux buildroot 4.2.0-rc4-next-20150729+ #97 Wed Jul 29 17:50:11 EEST
> 2015 avr32 GNU/Linux
> 
> Do you, guys, have that board (NGW100) or it's officially unsupported?

Sorry but we don't have AVR32-based board in our office. Hans-Christian
kindly helps us fixing the issues that we find and we tend to rely on
the community for this architecture support...

> If the latter is the case I would really appreciate if you remove the
> support from the kernel side.

I won't decide for its removal. Only the maintainers with feedback from
the user base can.

>> In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
>> line when the Hardware Handshaking mode is enabled. Two thresholds
>> are to be set for that purpose:
>> - When the number of data in the RX FIFO crosses and becomes lower
>>   than or equal to the low threshold, the RTS line is set to low
>>   level: the remote peer is requested to send data.
>> - When the number of data in the RX FIFO crosses and becomes greater
>>   than or equal to the high threshold, the RTS line is set to high
>>   level: the remote peer should stop sending new data.
>> - low threshold <= high threshold
>> Once these two thresholds are set properly, this new feature is
>> enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.
>>
>> FIFOs also introduce a new multiple data mode: the USART works either
>> in multiple data mode or in single data (legacy) mode.
>>
>> If MODE9 bit is set into the Mode Register or if USMODE is set to
>> either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
>> data mode. Otherwise, they operate in multiple data mode.
>>
>> In this new multiple data mode, accesses to the Receive Holding
>> Register or Transmit Holding Register slightly change.
>>
>> Since this driver implements neither the 9bit data feature (MODE9 bit
>> set into the Mode Register) nor LIN modes, the USART works in
>> multiple data mode whenever FIFOs are available and enabled. We also
>> assume that data are 8bit wide.
>>
>> In single data mode, 32bit access CAN be used to read a single data
>> from RHR or write a single data into THR.
>> However in multiple data mode, a 32bit access to RHR now allows us to
>> read four consecutive data from RX FIFO. Also a 32bit access to THR
>> now allows to write four consecutive data into TX FIFO. So we MUST
>> use 8bit access whenever only one data have to be read/written at a
>> time.
>>
>> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
>> ---
>>  drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
>>  include/linux/atmel_serial.h      |  36 ++++++++++++++
>>  2 files changed, 130 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
>> index e7c337de31d1..87de21f0c7a3 100644
>> --- a/drivers/tty/serial/atmel_serial.c
>> +++ b/drivers/tty/serial/atmel_serial.c
>> @@ -56,6 +56,15 @@
>>  /* Revisit: We should calculate this based on the actual port settings */
>>  #define PDC_RX_TIMEOUT         (3 * 10)                /* 3 bytes */
>>
>> +/* The minium number of data FIFOs should be able to contain */
>> +#define ATMEL_MIN_FIFO_SIZE    8
>> +/*
>> + * These two offsets are substracted from the RX FIFO size to define the RTS
>> + * high and low thresholds
>> + */
>> +#define ATMEL_RTS_HIGH_OFFSET  16
>> +#define ATMEL_RTS_LOW_OFFSET   20
>> +
>>  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>>  #define SUPPORT_SYSRQ
>>  #endif
>> @@ -141,6 +150,9 @@ struct atmel_uart_port {
>>         struct mctrl_gpios      *gpios;
>>         int                     gpio_irq[UART_GPIO_MAX];
>>         unsigned int            tx_done_mask;
>> +       u32                     fifo_size;
>> +       u32                     rts_high;
>> +       u32                     rts_low;
>>         bool                    ms_irq_enabled;
>>         bool                    is_usart;       /* usart or uart */
>>         struct timer_list       uart_timer;     /* uart timer */
>> @@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
>>         __raw_writel(value, port->membase + reg);
>>  }
>>
>> +static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
>> +{
>> +       return __raw_readb(port->membase + reg);
>> +}
>> +
>> +static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
>> +{
>> +       __raw_writeb(value, port->membase + reg);
>> +}
>> +
>>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>>  static bool atmel_use_pdc_rx(struct uart_port *port)
>>  {
>> @@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
>>
>>         status = atmel_uart_readl(port, ATMEL_US_CSR);
>>         while (status & ATMEL_US_RXRDY) {
>> -               ch = atmel_uart_readl(port, ATMEL_US_RHR);
>> +               ch = atmel_uart_readb(port, ATMEL_US_RHR);
>>
>>                 /*
>>                  * note that the error handling code is
>> @@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
>>
>>         if (port->x_char &&
>>             (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
>> -               atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
>> +               atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
>>                 port->icount.tx++;
>>                 port->x_char = 0;
>>         }
>> @@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
>>
>>         while (atmel_uart_readl(port, ATMEL_US_CSR) &
>>                atmel_port->tx_done_mask) {
>> -               atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>> +               atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>>                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>>                 port->icount.tx++;
>>                 if (uart_circ_empty(xmit))
>> @@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
>>                         atmel_set_ops(port);
>>         }
>>
>> +       /*
>> +        * Enable FIFO when available
>> +        */
>> +       if (atmel_port->fifo_size) {
>> +               unsigned int txrdym = ATMEL_US_ONE_DATA;
>> +               unsigned int rxrdym = ATMEL_US_ONE_DATA;
>> +               unsigned int fmr;
>> +
>> +               atmel_uart_writel(port, ATMEL_US_CR,
>> +                                 ATMEL_US_FIFOEN |
>> +                                 ATMEL_US_RXFCLR |
>> +                                 ATMEL_US_TXFLCLR);
>> +
>> +               fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
>> +               if (atmel_port->rts_high &&
>> +                   atmel_port->rts_low)
>> +                       fmr |=  ATMEL_US_FRTSC |
>> +                               ATMEL_US_RXFTHRES(atmel_port->rts_high) |
>> +                               ATMEL_US_RXFTHRES2(atmel_port->rts_low);
>> +
>> +               atmel_uart_writel(port, ATMEL_US_FMR, fmr);
>> +       }
>> +
>>         /* Save current CSR for comparison in atmel_tasklet_func() */
>>         atmel_port->irq_status_prev = atmel_get_lines_status(port);
>>         atmel_port->irq_status = atmel_port->irq_status_prev;
>> @@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>>                 cpu_relax();
>>
>> -       return atmel_uart_readl(port, ATMEL_US_RHR);
>> +       return atmel_uart_readb(port, ATMEL_US_RHR);
>>  }
>>
>>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>> @@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>>                 cpu_relax();
>>
>> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
>> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>>  }
>>  #endif
>>
>> @@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
>>  {
>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>>                 cpu_relax();
>> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
>> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>>  }
>>
>>  /*
>> @@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
>>         return 0;
>>  }
>>
>> +static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
>> +                                    struct platform_device *pdev)
>> +{
>> +       port->fifo_size = 0;
>> +       port->rts_low = 0;
>> +       port->rts_high = 0;
>> +
>> +       if (of_property_read_u32(pdev->dev.of_node,
>> +                                "atmel,fifo-size",
>> +                                &port->fifo_size))
>> +               return;
>> +
>> +       if (!port->fifo_size)
>> +               return;
>> +
>> +       if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
>> +               port->fifo_size = 0;
>> +               dev_err(&pdev->dev, "Invalid FIFO size\n");
>> +               return;
>> +       }
>> +
>> +       /*
>> +        * 0 <= rts_low <= rts_high <= fifo_size
>> +        * Once their CTS line asserted by the remote peer, some x86 UARTs tend
>> +        * to flush their internal TX FIFO, commonly up to 16 data, before
>> +        * actually stopping to send new data. So we try to set the RTS High
>> +        * Threshold to a reasonably high value respecting this 16 data
>> +        * empirical rule when possible.
>> +        */
>> +       port->rts_high = max_t(int, port->fifo_size >> 1,
>> +                              port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
>> +       port->rts_low  = max_t(int, port->fifo_size >> 2,
>> +                              port->fifo_size - ATMEL_RTS_LOW_OFFSET);
>> +
>> +       dev_info(&pdev->dev, "Using FIFO (%u data)\n",
>> +                port->fifo_size);
>> +       dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
>> +               port->rts_high);
>> +       dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
>> +               port->rts_low);
>> +}
>> +
>>  static int atmel_serial_probe(struct platform_device *pdev)
>>  {
>>         struct atmel_uart_port *port;
>> @@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
>>         port = &atmel_ports[ret];
>>         port->backup_imr = 0;
>>         port->uart.line = ret;
>> +       atmel_serial_probe_fifos(port, pdev);
>>
>>         spin_lock_init(&port->lock_suspended);
>>
>> diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
>> index c384c21d65f0..ee696d7e8a43 100644
>> --- a/include/linux/atmel_serial.h
>> +++ b/include/linux/atmel_serial.h
>> @@ -35,6 +35,11 @@
>>  #define        ATMEL_US_DTRDIS         BIT(17) /* Data Terminal Ready Disable */
>>  #define        ATMEL_US_RTSEN          BIT(18) /* Request To Send Enable */
>>  #define        ATMEL_US_RTSDIS         BIT(19) /* Request To Send Disable */
>> +#define        ATMEL_US_TXFCLR         BIT(24) /* Transmit FIFO Clear */
>> +#define        ATMEL_US_RXFCLR         BIT(25) /* Receive FIFO Clear */
>> +#define        ATMEL_US_TXFLCLR        BIT(26) /* Transmit FIFO Lock Clear */
>> +#define        ATMEL_US_FIFOEN         BIT(30) /* FIFO enable */
>> +#define        ATMEL_US_FIFODIS        BIT(31) /* FIFO disable */
>>
>>  #define ATMEL_US_MR            0x04    /* Mode Register */
>>  #define        ATMEL_US_USMODE         GENMASK(3, 0)   /* Mode of the USART */
>> @@ -124,6 +129,37 @@
>>  #define ATMEL_US_NER           0x44    /* Number of Errors Register */
>>  #define ATMEL_US_IF            0x4c    /* IrDA Filter Register */
>>
>> +#define ATMEL_US_CMPR          0x90    /* Comparaison Register */
>> +#define ATMEL_US_FMR           0xa0    /* FIFO Mode Register */
>> +#define        ATMEL_US_TXRDYM(data)   (((data) & 0x3) << 0)   /* TX Ready Mode */
>> +#define        ATMEL_US_RXRDYM(data)   (((data) & 0x3) << 4)   /* RX Ready Mode */
>> +#define                ATMEL_US_ONE_DATA       0x0
>> +#define                ATMEL_US_TWO_DATA       0x1
>> +#define                ATMEL_US_FOUR_DATA      0x2
>> +#define        ATMEL_US_FRTSC          BIT(7)  /* FIFO RTS pin Control */
>> +#define        ATMEL_US_TXFTHRES(thr)  (((thr) & 0x3f) << 8)   /* TX FIFO Threshold */
>> +#define        ATMEL_US_RXFTHRES(thr)  (((thr) & 0x3f) << 16)  /* RX FIFO Threshold */
>> +#define        ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24)  /* RX FIFO Threshold2 */
>> +
>> +#define ATMEL_US_FLR           0xa4    /* FIFO Level Register */
>> +#define        ATMEL_US_TXFL(reg)      (((reg) >> 0) & 0x3f)   /* TX FIFO Level */
>> +#define        ATMEL_US_RXFL(reg)      (((reg) >> 16) & 0x3f)  /* RX FIFO Level */
>> +
>> +#define ATMEL_US_FIER          0xa8    /* FIFO Interrupt Enable Register */
>> +#define ATMEL_US_FIDR          0xac    /* FIFO Interrupt Disable Register */
>> +#define ATMEL_US_FIMR          0xb0    /* FIFO Interrupt Mask Register */
>> +#define ATMEL_US_FESR          0xb4    /* FIFO Event Status Register */
>> +#define        ATMEL_US_TXFEF          BIT(0)  /* Transmit FIFO Empty Flag */
>> +#define        ATMEL_US_TXFFF          BIT(1)  /* Transmit FIFO Full Flag */
>> +#define        ATMEL_US_TXFTHF         BIT(2)  /* Transmit FIFO Threshold Flag */
>> +#define        ATMEL_US_RXFEF          BIT(3)  /* Receive FIFO Empty Flag */
>> +#define        ATMEL_US_RXFFF          BIT(4)  /* Receive FIFO Full Flag */
>> +#define        ATMEL_US_RXFTHF         BIT(5)  /* Receive FIFO Threshold Flag */
>> +#define        ATMEL_US_TXFPTEF        BIT(6)  /* Transmit FIFO Pointer Error Flag */
>> +#define        ATMEL_US_RXFPTEF        BIT(7)  /* Receive FIFO Pointer Error Flag */
>> +#define        ATMEL_US_TXFLOCK        BIT(8)  /* Transmit FIFO Lock (FESR only) */
>> +#define        ATMEL_US_RXFTHF2        BIT(9)  /* Receive FIFO Threshold Flag 2 */
>> +
>>  #define ATMEL_US_NAME          0xf0    /* Ip Name */
>>  #define ATMEL_US_VERSION       0xfc    /* Ip Version */
>>
>> --
>> 1.8.2.2
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
> 
> 
> 


-- 
Nicolas Ferre

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

* Re: [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-29 15:34         ` Hans-Christian Egtvedt
  0 siblings, 0 replies; 35+ messages in thread
From: Hans-Christian Egtvedt @ 2015-07-29 15:34 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Andy Shevchenko, Cyrille Pitchen, Greg Kroah-Hartman,
	wenyou.yang, ludovic.desroches, leilei.zhao, josh.wu,
	alexandre.belloni, linux-serial, linux-kernel,
	linux-arm Mailing List, devicetree, Kumar Gala, ijc+devicetree,
	Mark Rutland, Pawel Moll, Rob Herring

Around Wed 29 Jul 2015 17:09:59 +0200 or thereabout, Nicolas Ferre wrote:
> Le 29/07/2015 16:51, Andy Shevchenko a écrit :
>> On Thu, Jul 2, 2015 at 4:18 PM, Cyrille Pitchen
>> <cyrille.pitchen@atmel.com> wrote:
>>> Depending on the hardware, TX and RX FIFOs may be available. The RX
>>> FIFO can avoid receive overruns, especially when DMA transfers are
>>> not used to read data from the Receive Holding Register. For heavy
>>> system load, The CPU is likely not be able to fetch data fast enough
>>> from the RHR.
>> 
>> This patch broke avr32 console (as seen in today's linux-next) on ATNGW100.
>> Reverting helps. I'm pretty sure the issue is in 8 bit vs. 32 bit I/O access.

Highly likely, you can not do I/O read/write in 8-bit operations on AVR32,
only 32-bit operations are supported. If you do 8-bit or 16-bit operations
you will read and write garbage data.

> I would like that we don't revert the patch.
> We'll try to blindly find the cause for this issue.
> 
>> # uname -a
>> Linux buildroot 4.2.0-rc4-next-20150729+ #97 Wed Jul 29 17:50:11 EEST
>> 2015 avr32 GNU/Linux
>> 
>> Do you, guys, have that board (NGW100) or it's officially unsupported?
> 
> Sorry but we don't have AVR32-based board in our office. Hans-Christian
> kindly helps us fixing the issues that we find and we tend to rely on
> the community for this architecture support...
> 
>> If the latter is the case I would really appreciate if you remove the
>> support from the kernel side.
> 
> I won't decide for its removal. Only the maintainers with feedback from
> the user base can.

I still use my board every now and then, and there are that odd request every
now and then.

>>> In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
>>> line when the Hardware Handshaking mode is enabled. Two thresholds
>>> are to be set for that purpose:
>>> - When the number of data in the RX FIFO crosses and becomes lower
>>>   than or equal to the low threshold, the RTS line is set to low
>>>   level: the remote peer is requested to send data.
>>> - When the number of data in the RX FIFO crosses and becomes greater
>>>   than or equal to the high threshold, the RTS line is set to high
>>>   level: the remote peer should stop sending new data.
>>> - low threshold <= high threshold
>>> Once these two thresholds are set properly, this new feature is
>>> enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.
>>>
>>> FIFOs also introduce a new multiple data mode: the USART works either
>>> in multiple data mode or in single data (legacy) mode.
>>>
>>> If MODE9 bit is set into the Mode Register or if USMODE is set to
>>> either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
>>> data mode. Otherwise, they operate in multiple data mode.
>>>
>>> In this new multiple data mode, accesses to the Receive Holding
>>> Register or Transmit Holding Register slightly change.
>>>
>>> Since this driver implements neither the 9bit data feature (MODE9 bit
>>> set into the Mode Register) nor LIN modes, the USART works in
>>> multiple data mode whenever FIFOs are available and enabled. We also
>>> assume that data are 8bit wide.
>>>
>>> In single data mode, 32bit access CAN be used to read a single data
>>> from RHR or write a single data into THR.
>>> However in multiple data mode, a 32bit access to RHR now allows us to
>>> read four consecutive data from RX FIFO. Also a 32bit access to THR
>>> now allows to write four consecutive data into TX FIFO. So we MUST
>>> use 8bit access whenever only one data have to be read/written at a
>>> time.

Hmm, does AVR32 even have this feature?

>>> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
>>> ---
>>>  drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
>>>  include/linux/atmel_serial.h      |  36 ++++++++++++++
>>>  2 files changed, 130 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
>>> index e7c337de31d1..87de21f0c7a3 100644
>>> --- a/drivers/tty/serial/atmel_serial.c
>>> +++ b/drivers/tty/serial/atmel_serial.c
>>> @@ -56,6 +56,15 @@
>>>  /* Revisit: We should calculate this based on the actual port settings */
>>>  #define PDC_RX_TIMEOUT         (3 * 10)                /* 3 bytes */
>>>
>>> +/* The minium number of data FIFOs should be able to contain */
>>> +#define ATMEL_MIN_FIFO_SIZE    8
>>> +/*
>>> + * These two offsets are substracted from the RX FIFO size to define the RTS
>>> + * high and low thresholds
>>> + */
>>> +#define ATMEL_RTS_HIGH_OFFSET  16
>>> +#define ATMEL_RTS_LOW_OFFSET   20
>>> +
>>>  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>>>  #define SUPPORT_SYSRQ
>>>  #endif
>>> @@ -141,6 +150,9 @@ struct atmel_uart_port {
>>>         struct mctrl_gpios      *gpios;
>>>         int                     gpio_irq[UART_GPIO_MAX];
>>>         unsigned int            tx_done_mask;
>>> +       u32                     fifo_size;
>>> +       u32                     rts_high;
>>> +       u32                     rts_low;
>>>         bool                    ms_irq_enabled;
>>>         bool                    is_usart;       /* usart or uart */
>>>         struct timer_list       uart_timer;     /* uart timer */
>>> @@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
>>>         __raw_writel(value, port->membase + reg);
>>>  }
>>>
>>> +static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
>>> +{
>>> +       return __raw_readb(port->membase + reg);
>>> +}
>>> +
>>> +static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
>>> +{
>>> +       __raw_writeb(value, port->membase + reg);
>>> +}
>>> +

These functions will not fly on AVR32. I would even assume some AT91 devices
would struggle with this. IIRC the internal bus architecture is similar.

>>>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>>>  static bool atmel_use_pdc_rx(struct uart_port *port)
>>>  {
>>> @@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
>>>
>>>         status = atmel_uart_readl(port, ATMEL_US_CSR);
>>>         while (status & ATMEL_US_RXRDY) {
>>> -               ch = atmel_uart_readl(port, ATMEL_US_RHR);
>>> +               ch = atmel_uart_readb(port, ATMEL_US_RHR);
>>>
>>>                 /*
>>>                  * note that the error handling code is
>>> @@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
>>>
>>>         if (port->x_char &&
>>>             (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
>>> -               atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
>>> +               atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
>>>                 port->icount.tx++;
>>>                 port->x_char = 0;
>>>         }
>>> @@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
>>>
>>>         while (atmel_uart_readl(port, ATMEL_US_CSR) &
>>>                atmel_port->tx_done_mask) {
>>> -               atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>>> +               atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>>>                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>>>                 port->icount.tx++;
>>>                 if (uart_circ_empty(xmit))
>>> @@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
>>>                         atmel_set_ops(port);
>>>         }
>>>
>>> +       /*
>>> +        * Enable FIFO when available
>>> +        */
>>> +       if (atmel_port->fifo_size) {
>>> +               unsigned int txrdym = ATMEL_US_ONE_DATA;
>>> +               unsigned int rxrdym = ATMEL_US_ONE_DATA;
>>> +               unsigned int fmr;
>>> +
>>> +               atmel_uart_writel(port, ATMEL_US_CR,
>>> +                                 ATMEL_US_FIFOEN |
>>> +                                 ATMEL_US_RXFCLR |
>>> +                                 ATMEL_US_TXFLCLR);
>>> +
>>> +               fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
>>> +               if (atmel_port->rts_high &&
>>> +                   atmel_port->rts_low)
>>> +                       fmr |=  ATMEL_US_FRTSC |
>>> +                               ATMEL_US_RXFTHRES(atmel_port->rts_high) |
>>> +                               ATMEL_US_RXFTHRES2(atmel_port->rts_low);
>>> +
>>> +               atmel_uart_writel(port, ATMEL_US_FMR, fmr);
>>> +       }
>>> +
>>>         /* Save current CSR for comparison in atmel_tasklet_func() */
>>>         atmel_port->irq_status_prev = atmel_get_lines_status(port);
>>>         atmel_port->irq_status = atmel_port->irq_status_prev;
>>> @@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
>>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>>>                 cpu_relax();
>>>
>>> -       return atmel_uart_readl(port, ATMEL_US_RHR);
>>> +       return atmel_uart_readb(port, ATMEL_US_RHR);
>>>  }
>>>
>>>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>>> @@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>>>                 cpu_relax();
>>>
>>> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
>>> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>>>  }
>>>  #endif
>>>
>>> @@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
>>>  {
>>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>>>                 cpu_relax();
>>> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
>>> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>>>  }
>>>
>>>  /*
>>> @@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
>>>         return 0;
>>>  }
>>>
>>> +static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
>>> +                                    struct platform_device *pdev)
>>> +{
>>> +       port->fifo_size = 0;
>>> +       port->rts_low = 0;
>>> +       port->rts_high = 0;
>>> +
>>> +       if (of_property_read_u32(pdev->dev.of_node,
>>> +                                "atmel,fifo-size",
>>> +                                &port->fifo_size))
>>> +               return;
>>> +
>>> +       if (!port->fifo_size)
>>> +               return;
>>> +
>>> +       if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
>>> +               port->fifo_size = 0;
>>> +               dev_err(&pdev->dev, "Invalid FIFO size\n");
>>> +               return;
>>> +       }
>>> +
>>> +       /*
>>> +        * 0 <= rts_low <= rts_high <= fifo_size
>>> +        * Once their CTS line asserted by the remote peer, some x86 UARTs tend
>>> +        * to flush their internal TX FIFO, commonly up to 16 data, before
>>> +        * actually stopping to send new data. So we try to set the RTS High
>>> +        * Threshold to a reasonably high value respecting this 16 data
>>> +        * empirical rule when possible.
>>> +        */
>>> +       port->rts_high = max_t(int, port->fifo_size >> 1,
>>> +                              port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
>>> +       port->rts_low  = max_t(int, port->fifo_size >> 2,
>>> +                              port->fifo_size - ATMEL_RTS_LOW_OFFSET);
>>> +
>>> +       dev_info(&pdev->dev, "Using FIFO (%u data)\n",
>>> +                port->fifo_size);
>>> +       dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
>>> +               port->rts_high);
>>> +       dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
>>> +               port->rts_low);
>>> +}
>>> +
>>>  static int atmel_serial_probe(struct platform_device *pdev)
>>>  {
>>>         struct atmel_uart_port *port;
>>> @@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
>>>         port = &atmel_ports[ret];
>>>         port->backup_imr = 0;
>>>         port->uart.line = ret;
>>> +       atmel_serial_probe_fifos(port, pdev);
>>>
>>>         spin_lock_init(&port->lock_suspended);
>>>
>>> diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
>>> index c384c21d65f0..ee696d7e8a43 100644
>>> --- a/include/linux/atmel_serial.h
>>> +++ b/include/linux/atmel_serial.h
>>> @@ -35,6 +35,11 @@
>>>  #define        ATMEL_US_DTRDIS         BIT(17) /* Data Terminal Ready Disable */
>>>  #define        ATMEL_US_RTSEN          BIT(18) /* Request To Send Enable */
>>>  #define        ATMEL_US_RTSDIS         BIT(19) /* Request To Send Disable */
>>> +#define        ATMEL_US_TXFCLR         BIT(24) /* Transmit FIFO Clear */
>>> +#define        ATMEL_US_RXFCLR         BIT(25) /* Receive FIFO Clear */
>>> +#define        ATMEL_US_TXFLCLR        BIT(26) /* Transmit FIFO Lock Clear */
>>> +#define        ATMEL_US_FIFOEN         BIT(30) /* FIFO enable */
>>> +#define        ATMEL_US_FIFODIS        BIT(31) /* FIFO disable */
>>>
>>>  #define ATMEL_US_MR            0x04    /* Mode Register */
>>>  #define        ATMEL_US_USMODE         GENMASK(3, 0)   /* Mode of the USART */
>>> @@ -124,6 +129,37 @@
>>>  #define ATMEL_US_NER           0x44    /* Number of Errors Register */
>>>  #define ATMEL_US_IF            0x4c    /* IrDA Filter Register */
>>>
>>> +#define ATMEL_US_CMPR          0x90    /* Comparaison Register */
>>> +#define ATMEL_US_FMR           0xa0    /* FIFO Mode Register */
>>> +#define        ATMEL_US_TXRDYM(data)   (((data) & 0x3) << 0)   /* TX Ready Mode */
>>> +#define        ATMEL_US_RXRDYM(data)   (((data) & 0x3) << 4)   /* RX Ready Mode */
>>> +#define                ATMEL_US_ONE_DATA       0x0
>>> +#define                ATMEL_US_TWO_DATA       0x1
>>> +#define                ATMEL_US_FOUR_DATA      0x2
>>> +#define        ATMEL_US_FRTSC          BIT(7)  /* FIFO RTS pin Control */
>>> +#define        ATMEL_US_TXFTHRES(thr)  (((thr) & 0x3f) << 8)   /* TX FIFO Threshold */
>>> +#define        ATMEL_US_RXFTHRES(thr)  (((thr) & 0x3f) << 16)  /* RX FIFO Threshold */
>>> +#define        ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24)  /* RX FIFO Threshold2 */
>>> +
>>> +#define ATMEL_US_FLR           0xa4    /* FIFO Level Register */
>>> +#define        ATMEL_US_TXFL(reg)      (((reg) >> 0) & 0x3f)   /* TX FIFO Level */
>>> +#define        ATMEL_US_RXFL(reg)      (((reg) >> 16) & 0x3f)  /* RX FIFO Level */
>>> +
>>> +#define ATMEL_US_FIER          0xa8    /* FIFO Interrupt Enable Register */
>>> +#define ATMEL_US_FIDR          0xac    /* FIFO Interrupt Disable Register */
>>> +#define ATMEL_US_FIMR          0xb0    /* FIFO Interrupt Mask Register */
>>> +#define ATMEL_US_FESR          0xb4    /* FIFO Event Status Register */
>>> +#define        ATMEL_US_TXFEF          BIT(0)  /* Transmit FIFO Empty Flag */
>>> +#define        ATMEL_US_TXFFF          BIT(1)  /* Transmit FIFO Full Flag */
>>> +#define        ATMEL_US_TXFTHF         BIT(2)  /* Transmit FIFO Threshold Flag */
>>> +#define        ATMEL_US_RXFEF          BIT(3)  /* Receive FIFO Empty Flag */
>>> +#define        ATMEL_US_RXFFF          BIT(4)  /* Receive FIFO Full Flag */
>>> +#define        ATMEL_US_RXFTHF         BIT(5)  /* Receive FIFO Threshold Flag */
>>> +#define        ATMEL_US_TXFPTEF        BIT(6)  /* Transmit FIFO Pointer Error Flag */
>>> +#define        ATMEL_US_RXFPTEF        BIT(7)  /* Receive FIFO Pointer Error Flag */
>>> +#define        ATMEL_US_TXFLOCK        BIT(8)  /* Transmit FIFO Lock (FESR only) */
>>> +#define        ATMEL_US_RXFTHF2        BIT(9)  /* Receive FIFO Threshold Flag 2 */
>>> +
>>>  #define ATMEL_US_NAME          0xf0    /* Ip Name */
>>>  #define ATMEL_US_VERSION       0xfc    /* Ip Version */
>>>
>>> --
>>> 1.8.2.2
>>>
-- 
mvh
Hans-Christian Egtvedt

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

* Re: [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-29 15:34         ` Hans-Christian Egtvedt
  0 siblings, 0 replies; 35+ messages in thread
From: Hans-Christian Egtvedt @ 2015-07-29 15:34 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Andy Shevchenko, Cyrille Pitchen, Greg Kroah-Hartman,
	wenyou.yang-AIFe0yeh4nAAvxtiuMwx3w, ludovic.desroches,
	leilei.zhao-AIFe0yeh4nAAvxtiuMwx3w,
	josh.wu-AIFe0yeh4nAAvxtiuMwx3w,
	alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-arm Mailing List,
	devicetree, Kumar Gala, ijc+devicetree, Mark Rutland, Pawel Moll,
	Rob Herring

Around Wed 29 Jul 2015 17:09:59 +0200 or thereabout, Nicolas Ferre wrote:
> Le 29/07/2015 16:51, Andy Shevchenko a écrit :
>> On Thu, Jul 2, 2015 at 4:18 PM, Cyrille Pitchen
>> <cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org> wrote:
>>> Depending on the hardware, TX and RX FIFOs may be available. The RX
>>> FIFO can avoid receive overruns, especially when DMA transfers are
>>> not used to read data from the Receive Holding Register. For heavy
>>> system load, The CPU is likely not be able to fetch data fast enough
>>> from the RHR.
>> 
>> This patch broke avr32 console (as seen in today's linux-next) on ATNGW100.
>> Reverting helps. I'm pretty sure the issue is in 8 bit vs. 32 bit I/O access.

Highly likely, you can not do I/O read/write in 8-bit operations on AVR32,
only 32-bit operations are supported. If you do 8-bit or 16-bit operations
you will read and write garbage data.

> I would like that we don't revert the patch.
> We'll try to blindly find the cause for this issue.
> 
>> # uname -a
>> Linux buildroot 4.2.0-rc4-next-20150729+ #97 Wed Jul 29 17:50:11 EEST
>> 2015 avr32 GNU/Linux
>> 
>> Do you, guys, have that board (NGW100) or it's officially unsupported?
> 
> Sorry but we don't have AVR32-based board in our office. Hans-Christian
> kindly helps us fixing the issues that we find and we tend to rely on
> the community for this architecture support...
> 
>> If the latter is the case I would really appreciate if you remove the
>> support from the kernel side.
> 
> I won't decide for its removal. Only the maintainers with feedback from
> the user base can.

I still use my board every now and then, and there are that odd request every
now and then.

>>> In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
>>> line when the Hardware Handshaking mode is enabled. Two thresholds
>>> are to be set for that purpose:
>>> - When the number of data in the RX FIFO crosses and becomes lower
>>>   than or equal to the low threshold, the RTS line is set to low
>>>   level: the remote peer is requested to send data.
>>> - When the number of data in the RX FIFO crosses and becomes greater
>>>   than or equal to the high threshold, the RTS line is set to high
>>>   level: the remote peer should stop sending new data.
>>> - low threshold <= high threshold
>>> Once these two thresholds are set properly, this new feature is
>>> enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.
>>>
>>> FIFOs also introduce a new multiple data mode: the USART works either
>>> in multiple data mode or in single data (legacy) mode.
>>>
>>> If MODE9 bit is set into the Mode Register or if USMODE is set to
>>> either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
>>> data mode. Otherwise, they operate in multiple data mode.
>>>
>>> In this new multiple data mode, accesses to the Receive Holding
>>> Register or Transmit Holding Register slightly change.
>>>
>>> Since this driver implements neither the 9bit data feature (MODE9 bit
>>> set into the Mode Register) nor LIN modes, the USART works in
>>> multiple data mode whenever FIFOs are available and enabled. We also
>>> assume that data are 8bit wide.
>>>
>>> In single data mode, 32bit access CAN be used to read a single data
>>> from RHR or write a single data into THR.
>>> However in multiple data mode, a 32bit access to RHR now allows us to
>>> read four consecutive data from RX FIFO. Also a 32bit access to THR
>>> now allows to write four consecutive data into TX FIFO. So we MUST
>>> use 8bit access whenever only one data have to be read/written at a
>>> time.

Hmm, does AVR32 even have this feature?

>>> Signed-off-by: Cyrille Pitchen <cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org>
>>> ---
>>>  drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
>>>  include/linux/atmel_serial.h      |  36 ++++++++++++++
>>>  2 files changed, 130 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
>>> index e7c337de31d1..87de21f0c7a3 100644
>>> --- a/drivers/tty/serial/atmel_serial.c
>>> +++ b/drivers/tty/serial/atmel_serial.c
>>> @@ -56,6 +56,15 @@
>>>  /* Revisit: We should calculate this based on the actual port settings */
>>>  #define PDC_RX_TIMEOUT         (3 * 10)                /* 3 bytes */
>>>
>>> +/* The minium number of data FIFOs should be able to contain */
>>> +#define ATMEL_MIN_FIFO_SIZE    8
>>> +/*
>>> + * These two offsets are substracted from the RX FIFO size to define the RTS
>>> + * high and low thresholds
>>> + */
>>> +#define ATMEL_RTS_HIGH_OFFSET  16
>>> +#define ATMEL_RTS_LOW_OFFSET   20
>>> +
>>>  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>>>  #define SUPPORT_SYSRQ
>>>  #endif
>>> @@ -141,6 +150,9 @@ struct atmel_uart_port {
>>>         struct mctrl_gpios      *gpios;
>>>         int                     gpio_irq[UART_GPIO_MAX];
>>>         unsigned int            tx_done_mask;
>>> +       u32                     fifo_size;
>>> +       u32                     rts_high;
>>> +       u32                     rts_low;
>>>         bool                    ms_irq_enabled;
>>>         bool                    is_usart;       /* usart or uart */
>>>         struct timer_list       uart_timer;     /* uart timer */
>>> @@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
>>>         __raw_writel(value, port->membase + reg);
>>>  }
>>>
>>> +static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
>>> +{
>>> +       return __raw_readb(port->membase + reg);
>>> +}
>>> +
>>> +static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
>>> +{
>>> +       __raw_writeb(value, port->membase + reg);
>>> +}
>>> +

These functions will not fly on AVR32. I would even assume some AT91 devices
would struggle with this. IIRC the internal bus architecture is similar.

>>>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>>>  static bool atmel_use_pdc_rx(struct uart_port *port)
>>>  {
>>> @@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
>>>
>>>         status = atmel_uart_readl(port, ATMEL_US_CSR);
>>>         while (status & ATMEL_US_RXRDY) {
>>> -               ch = atmel_uart_readl(port, ATMEL_US_RHR);
>>> +               ch = atmel_uart_readb(port, ATMEL_US_RHR);
>>>
>>>                 /*
>>>                  * note that the error handling code is
>>> @@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
>>>
>>>         if (port->x_char &&
>>>             (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
>>> -               atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
>>> +               atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
>>>                 port->icount.tx++;
>>>                 port->x_char = 0;
>>>         }
>>> @@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
>>>
>>>         while (atmel_uart_readl(port, ATMEL_US_CSR) &
>>>                atmel_port->tx_done_mask) {
>>> -               atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>>> +               atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>>>                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>>>                 port->icount.tx++;
>>>                 if (uart_circ_empty(xmit))
>>> @@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
>>>                         atmel_set_ops(port);
>>>         }
>>>
>>> +       /*
>>> +        * Enable FIFO when available
>>> +        */
>>> +       if (atmel_port->fifo_size) {
>>> +               unsigned int txrdym = ATMEL_US_ONE_DATA;
>>> +               unsigned int rxrdym = ATMEL_US_ONE_DATA;
>>> +               unsigned int fmr;
>>> +
>>> +               atmel_uart_writel(port, ATMEL_US_CR,
>>> +                                 ATMEL_US_FIFOEN |
>>> +                                 ATMEL_US_RXFCLR |
>>> +                                 ATMEL_US_TXFLCLR);
>>> +
>>> +               fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
>>> +               if (atmel_port->rts_high &&
>>> +                   atmel_port->rts_low)
>>> +                       fmr |=  ATMEL_US_FRTSC |
>>> +                               ATMEL_US_RXFTHRES(atmel_port->rts_high) |
>>> +                               ATMEL_US_RXFTHRES2(atmel_port->rts_low);
>>> +
>>> +               atmel_uart_writel(port, ATMEL_US_FMR, fmr);
>>> +       }
>>> +
>>>         /* Save current CSR for comparison in atmel_tasklet_func() */
>>>         atmel_port->irq_status_prev = atmel_get_lines_status(port);
>>>         atmel_port->irq_status = atmel_port->irq_status_prev;
>>> @@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
>>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>>>                 cpu_relax();
>>>
>>> -       return atmel_uart_readl(port, ATMEL_US_RHR);
>>> +       return atmel_uart_readb(port, ATMEL_US_RHR);
>>>  }
>>>
>>>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>>> @@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>>>                 cpu_relax();
>>>
>>> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
>>> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>>>  }
>>>  #endif
>>>
>>> @@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
>>>  {
>>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>>>                 cpu_relax();
>>> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
>>> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>>>  }
>>>
>>>  /*
>>> @@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
>>>         return 0;
>>>  }
>>>
>>> +static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
>>> +                                    struct platform_device *pdev)
>>> +{
>>> +       port->fifo_size = 0;
>>> +       port->rts_low = 0;
>>> +       port->rts_high = 0;
>>> +
>>> +       if (of_property_read_u32(pdev->dev.of_node,
>>> +                                "atmel,fifo-size",
>>> +                                &port->fifo_size))
>>> +               return;
>>> +
>>> +       if (!port->fifo_size)
>>> +               return;
>>> +
>>> +       if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
>>> +               port->fifo_size = 0;
>>> +               dev_err(&pdev->dev, "Invalid FIFO size\n");
>>> +               return;
>>> +       }
>>> +
>>> +       /*
>>> +        * 0 <= rts_low <= rts_high <= fifo_size
>>> +        * Once their CTS line asserted by the remote peer, some x86 UARTs tend
>>> +        * to flush their internal TX FIFO, commonly up to 16 data, before
>>> +        * actually stopping to send new data. So we try to set the RTS High
>>> +        * Threshold to a reasonably high value respecting this 16 data
>>> +        * empirical rule when possible.
>>> +        */
>>> +       port->rts_high = max_t(int, port->fifo_size >> 1,
>>> +                              port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
>>> +       port->rts_low  = max_t(int, port->fifo_size >> 2,
>>> +                              port->fifo_size - ATMEL_RTS_LOW_OFFSET);
>>> +
>>> +       dev_info(&pdev->dev, "Using FIFO (%u data)\n",
>>> +                port->fifo_size);
>>> +       dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
>>> +               port->rts_high);
>>> +       dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
>>> +               port->rts_low);
>>> +}
>>> +
>>>  static int atmel_serial_probe(struct platform_device *pdev)
>>>  {
>>>         struct atmel_uart_port *port;
>>> @@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
>>>         port = &atmel_ports[ret];
>>>         port->backup_imr = 0;
>>>         port->uart.line = ret;
>>> +       atmel_serial_probe_fifos(port, pdev);
>>>
>>>         spin_lock_init(&port->lock_suspended);
>>>
>>> diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
>>> index c384c21d65f0..ee696d7e8a43 100644
>>> --- a/include/linux/atmel_serial.h
>>> +++ b/include/linux/atmel_serial.h
>>> @@ -35,6 +35,11 @@
>>>  #define        ATMEL_US_DTRDIS         BIT(17) /* Data Terminal Ready Disable */
>>>  #define        ATMEL_US_RTSEN          BIT(18) /* Request To Send Enable */
>>>  #define        ATMEL_US_RTSDIS         BIT(19) /* Request To Send Disable */
>>> +#define        ATMEL_US_TXFCLR         BIT(24) /* Transmit FIFO Clear */
>>> +#define        ATMEL_US_RXFCLR         BIT(25) /* Receive FIFO Clear */
>>> +#define        ATMEL_US_TXFLCLR        BIT(26) /* Transmit FIFO Lock Clear */
>>> +#define        ATMEL_US_FIFOEN         BIT(30) /* FIFO enable */
>>> +#define        ATMEL_US_FIFODIS        BIT(31) /* FIFO disable */
>>>
>>>  #define ATMEL_US_MR            0x04    /* Mode Register */
>>>  #define        ATMEL_US_USMODE         GENMASK(3, 0)   /* Mode of the USART */
>>> @@ -124,6 +129,37 @@
>>>  #define ATMEL_US_NER           0x44    /* Number of Errors Register */
>>>  #define ATMEL_US_IF            0x4c    /* IrDA Filter Register */
>>>
>>> +#define ATMEL_US_CMPR          0x90    /* Comparaison Register */
>>> +#define ATMEL_US_FMR           0xa0    /* FIFO Mode Register */
>>> +#define        ATMEL_US_TXRDYM(data)   (((data) & 0x3) << 0)   /* TX Ready Mode */
>>> +#define        ATMEL_US_RXRDYM(data)   (((data) & 0x3) << 4)   /* RX Ready Mode */
>>> +#define                ATMEL_US_ONE_DATA       0x0
>>> +#define                ATMEL_US_TWO_DATA       0x1
>>> +#define                ATMEL_US_FOUR_DATA      0x2
>>> +#define        ATMEL_US_FRTSC          BIT(7)  /* FIFO RTS pin Control */
>>> +#define        ATMEL_US_TXFTHRES(thr)  (((thr) & 0x3f) << 8)   /* TX FIFO Threshold */
>>> +#define        ATMEL_US_RXFTHRES(thr)  (((thr) & 0x3f) << 16)  /* RX FIFO Threshold */
>>> +#define        ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24)  /* RX FIFO Threshold2 */
>>> +
>>> +#define ATMEL_US_FLR           0xa4    /* FIFO Level Register */
>>> +#define        ATMEL_US_TXFL(reg)      (((reg) >> 0) & 0x3f)   /* TX FIFO Level */
>>> +#define        ATMEL_US_RXFL(reg)      (((reg) >> 16) & 0x3f)  /* RX FIFO Level */
>>> +
>>> +#define ATMEL_US_FIER          0xa8    /* FIFO Interrupt Enable Register */
>>> +#define ATMEL_US_FIDR          0xac    /* FIFO Interrupt Disable Register */
>>> +#define ATMEL_US_FIMR          0xb0    /* FIFO Interrupt Mask Register */
>>> +#define ATMEL_US_FESR          0xb4    /* FIFO Event Status Register */
>>> +#define        ATMEL_US_TXFEF          BIT(0)  /* Transmit FIFO Empty Flag */
>>> +#define        ATMEL_US_TXFFF          BIT(1)  /* Transmit FIFO Full Flag */
>>> +#define        ATMEL_US_TXFTHF         BIT(2)  /* Transmit FIFO Threshold Flag */
>>> +#define        ATMEL_US_RXFEF          BIT(3)  /* Receive FIFO Empty Flag */
>>> +#define        ATMEL_US_RXFFF          BIT(4)  /* Receive FIFO Full Flag */
>>> +#define        ATMEL_US_RXFTHF         BIT(5)  /* Receive FIFO Threshold Flag */
>>> +#define        ATMEL_US_TXFPTEF        BIT(6)  /* Transmit FIFO Pointer Error Flag */
>>> +#define        ATMEL_US_RXFPTEF        BIT(7)  /* Receive FIFO Pointer Error Flag */
>>> +#define        ATMEL_US_TXFLOCK        BIT(8)  /* Transmit FIFO Lock (FESR only) */
>>> +#define        ATMEL_US_RXFTHF2        BIT(9)  /* Receive FIFO Threshold Flag 2 */
>>> +
>>>  #define ATMEL_US_NAME          0xf0    /* Ip Name */
>>>  #define ATMEL_US_VERSION       0xfc    /* Ip Version */
>>>
>>> --
>>> 1.8.2.2
>>>
-- 
mvh
Hans-Christian Egtvedt
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v4 4/5] tty/serial: at91: add support to FIFOs
@ 2015-07-29 15:34         ` Hans-Christian Egtvedt
  0 siblings, 0 replies; 35+ messages in thread
From: Hans-Christian Egtvedt @ 2015-07-29 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

Around Wed 29 Jul 2015 17:09:59 +0200 or thereabout, Nicolas Ferre wrote:
> Le 29/07/2015 16:51, Andy Shevchenko a ?crit :
>> On Thu, Jul 2, 2015 at 4:18 PM, Cyrille Pitchen
>> <cyrille.pitchen@atmel.com> wrote:
>>> Depending on the hardware, TX and RX FIFOs may be available. The RX
>>> FIFO can avoid receive overruns, especially when DMA transfers are
>>> not used to read data from the Receive Holding Register. For heavy
>>> system load, The CPU is likely not be able to fetch data fast enough
>>> from the RHR.
>> 
>> This patch broke avr32 console (as seen in today's linux-next) on ATNGW100.
>> Reverting helps. I'm pretty sure the issue is in 8 bit vs. 32 bit I/O access.

Highly likely, you can not do I/O read/write in 8-bit operations on AVR32,
only 32-bit operations are supported. If you do 8-bit or 16-bit operations
you will read and write garbage data.

> I would like that we don't revert the patch.
> We'll try to blindly find the cause for this issue.
> 
>> # uname -a
>> Linux buildroot 4.2.0-rc4-next-20150729+ #97 Wed Jul 29 17:50:11 EEST
>> 2015 avr32 GNU/Linux
>> 
>> Do you, guys, have that board (NGW100) or it's officially unsupported?
> 
> Sorry but we don't have AVR32-based board in our office. Hans-Christian
> kindly helps us fixing the issues that we find and we tend to rely on
> the community for this architecture support...
> 
>> If the latter is the case I would really appreciate if you remove the
>> support from the kernel side.
> 
> I won't decide for its removal. Only the maintainers with feedback from
> the user base can.

I still use my board every now and then, and there are that odd request every
now and then.

>>> In addition, the RX FIFO can supersede the DMA/PDC to control the RTS
>>> line when the Hardware Handshaking mode is enabled. Two thresholds
>>> are to be set for that purpose:
>>> - When the number of data in the RX FIFO crosses and becomes lower
>>>   than or equal to the low threshold, the RTS line is set to low
>>>   level: the remote peer is requested to send data.
>>> - When the number of data in the RX FIFO crosses and becomes greater
>>>   than or equal to the high threshold, the RTS line is set to high
>>>   level: the remote peer should stop sending new data.
>>> - low threshold <= high threshold
>>> Once these two thresholds are set properly, this new feature is
>>> enabled by setting the FIFO RTS Control bit of the FIFO Mode Register.
>>>
>>> FIFOs also introduce a new multiple data mode: the USART works either
>>> in multiple data mode or in single data (legacy) mode.
>>>
>>> If MODE9 bit is set into the Mode Register or if USMODE is set to
>>> either LIN_MASTER, LIN_SLAVE or LON_MODE, FIFOs operate in single
>>> data mode. Otherwise, they operate in multiple data mode.
>>>
>>> In this new multiple data mode, accesses to the Receive Holding
>>> Register or Transmit Holding Register slightly change.
>>>
>>> Since this driver implements neither the 9bit data feature (MODE9 bit
>>> set into the Mode Register) nor LIN modes, the USART works in
>>> multiple data mode whenever FIFOs are available and enabled. We also
>>> assume that data are 8bit wide.
>>>
>>> In single data mode, 32bit access CAN be used to read a single data
>>> from RHR or write a single data into THR.
>>> However in multiple data mode, a 32bit access to RHR now allows us to
>>> read four consecutive data from RX FIFO. Also a 32bit access to THR
>>> now allows to write four consecutive data into TX FIFO. So we MUST
>>> use 8bit access whenever only one data have to be read/written at a
>>> time.

Hmm, does AVR32 even have this feature?

>>> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
>>> ---
>>>  drivers/tty/serial/atmel_serial.c | 100 +++++++++++++++++++++++++++++++++++---
>>>  include/linux/atmel_serial.h      |  36 ++++++++++++++
>>>  2 files changed, 130 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
>>> index e7c337de31d1..87de21f0c7a3 100644
>>> --- a/drivers/tty/serial/atmel_serial.c
>>> +++ b/drivers/tty/serial/atmel_serial.c
>>> @@ -56,6 +56,15 @@
>>>  /* Revisit: We should calculate this based on the actual port settings */
>>>  #define PDC_RX_TIMEOUT         (3 * 10)                /* 3 bytes */
>>>
>>> +/* The minium number of data FIFOs should be able to contain */
>>> +#define ATMEL_MIN_FIFO_SIZE    8
>>> +/*
>>> + * These two offsets are substracted from the RX FIFO size to define the RTS
>>> + * high and low thresholds
>>> + */
>>> +#define ATMEL_RTS_HIGH_OFFSET  16
>>> +#define ATMEL_RTS_LOW_OFFSET   20
>>> +
>>>  #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
>>>  #define SUPPORT_SYSRQ
>>>  #endif
>>> @@ -141,6 +150,9 @@ struct atmel_uart_port {
>>>         struct mctrl_gpios      *gpios;
>>>         int                     gpio_irq[UART_GPIO_MAX];
>>>         unsigned int            tx_done_mask;
>>> +       u32                     fifo_size;
>>> +       u32                     rts_high;
>>> +       u32                     rts_low;
>>>         bool                    ms_irq_enabled;
>>>         bool                    is_usart;       /* usart or uart */
>>>         struct timer_list       uart_timer;     /* uart timer */
>>> @@ -191,6 +203,16 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
>>>         __raw_writel(value, port->membase + reg);
>>>  }
>>>
>>> +static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg)
>>> +{
>>> +       return __raw_readb(port->membase + reg);
>>> +}
>>> +
>>> +static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value)
>>> +{
>>> +       __raw_writeb(value, port->membase + reg);
>>> +}
>>> +

These functions will not fly on AVR32. I would even assume some AT91 devices
would struggle with this. IIRC the internal bus architecture is similar.

>>>  #ifdef CONFIG_SERIAL_ATMEL_PDC
>>>  static bool atmel_use_pdc_rx(struct uart_port *port)
>>>  {
>>> @@ -635,7 +657,7 @@ static void atmel_rx_chars(struct uart_port *port)
>>>
>>>         status = atmel_uart_readl(port, ATMEL_US_CSR);
>>>         while (status & ATMEL_US_RXRDY) {
>>> -               ch = atmel_uart_readl(port, ATMEL_US_RHR);
>>> +               ch = atmel_uart_readb(port, ATMEL_US_RHR);
>>>
>>>                 /*
>>>                  * note that the error handling code is
>>> @@ -686,7 +708,7 @@ static void atmel_tx_chars(struct uart_port *port)
>>>
>>>         if (port->x_char &&
>>>             (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
>>> -               atmel_uart_writel(port, ATMEL_US_THR, port->x_char);
>>> +               atmel_uart_writeb(port, ATMEL_US_THR, port->x_char);
>>>                 port->icount.tx++;
>>>                 port->x_char = 0;
>>>         }
>>> @@ -695,7 +717,7 @@ static void atmel_tx_chars(struct uart_port *port)
>>>
>>>         while (atmel_uart_readl(port, ATMEL_US_CSR) &
>>>                atmel_port->tx_done_mask) {
>>> -               atmel_uart_writel(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>>> +               atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]);
>>>                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>>>                 port->icount.tx++;
>>>                 if (uart_circ_empty(xmit))
>>> @@ -1796,6 +1818,29 @@ static int atmel_startup(struct uart_port *port)
>>>                         atmel_set_ops(port);
>>>         }
>>>
>>> +       /*
>>> +        * Enable FIFO when available
>>> +        */
>>> +       if (atmel_port->fifo_size) {
>>> +               unsigned int txrdym = ATMEL_US_ONE_DATA;
>>> +               unsigned int rxrdym = ATMEL_US_ONE_DATA;
>>> +               unsigned int fmr;
>>> +
>>> +               atmel_uart_writel(port, ATMEL_US_CR,
>>> +                                 ATMEL_US_FIFOEN |
>>> +                                 ATMEL_US_RXFCLR |
>>> +                                 ATMEL_US_TXFLCLR);
>>> +
>>> +               fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
>>> +               if (atmel_port->rts_high &&
>>> +                   atmel_port->rts_low)
>>> +                       fmr |=  ATMEL_US_FRTSC |
>>> +                               ATMEL_US_RXFTHRES(atmel_port->rts_high) |
>>> +                               ATMEL_US_RXFTHRES2(atmel_port->rts_low);
>>> +
>>> +               atmel_uart_writel(port, ATMEL_US_FMR, fmr);
>>> +       }
>>> +
>>>         /* Save current CSR for comparison in atmel_tasklet_func() */
>>>         atmel_port->irq_status_prev = atmel_get_lines_status(port);
>>>         atmel_port->irq_status = atmel_port->irq_status_prev;
>>> @@ -2213,7 +2258,7 @@ static int atmel_poll_get_char(struct uart_port *port)
>>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
>>>                 cpu_relax();
>>>
>>> -       return atmel_uart_readl(port, ATMEL_US_RHR);
>>> +       return atmel_uart_readb(port, ATMEL_US_RHR);
>>>  }
>>>
>>>  static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>>> @@ -2221,7 +2266,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
>>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>>>                 cpu_relax();
>>>
>>> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
>>> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>>>  }
>>>  #endif
>>>
>>> @@ -2328,7 +2373,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
>>>  {
>>>         while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
>>>                 cpu_relax();
>>> -       atmel_uart_writel(port, ATMEL_US_THR, ch);
>>> +       atmel_uart_writeb(port, ATMEL_US_THR, ch);
>>>  }
>>>
>>>  /*
>>> @@ -2603,6 +2648,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
>>>         return 0;
>>>  }
>>>
>>> +static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
>>> +                                    struct platform_device *pdev)
>>> +{
>>> +       port->fifo_size = 0;
>>> +       port->rts_low = 0;
>>> +       port->rts_high = 0;
>>> +
>>> +       if (of_property_read_u32(pdev->dev.of_node,
>>> +                                "atmel,fifo-size",
>>> +                                &port->fifo_size))
>>> +               return;
>>> +
>>> +       if (!port->fifo_size)
>>> +               return;
>>> +
>>> +       if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
>>> +               port->fifo_size = 0;
>>> +               dev_err(&pdev->dev, "Invalid FIFO size\n");
>>> +               return;
>>> +       }
>>> +
>>> +       /*
>>> +        * 0 <= rts_low <= rts_high <= fifo_size
>>> +        * Once their CTS line asserted by the remote peer, some x86 UARTs tend
>>> +        * to flush their internal TX FIFO, commonly up to 16 data, before
>>> +        * actually stopping to send new data. So we try to set the RTS High
>>> +        * Threshold to a reasonably high value respecting this 16 data
>>> +        * empirical rule when possible.
>>> +        */
>>> +       port->rts_high = max_t(int, port->fifo_size >> 1,
>>> +                              port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
>>> +       port->rts_low  = max_t(int, port->fifo_size >> 2,
>>> +                              port->fifo_size - ATMEL_RTS_LOW_OFFSET);
>>> +
>>> +       dev_info(&pdev->dev, "Using FIFO (%u data)\n",
>>> +                port->fifo_size);
>>> +       dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
>>> +               port->rts_high);
>>> +       dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
>>> +               port->rts_low);
>>> +}
>>> +
>>>  static int atmel_serial_probe(struct platform_device *pdev)
>>>  {
>>>         struct atmel_uart_port *port;
>>> @@ -2639,6 +2726,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
>>>         port = &atmel_ports[ret];
>>>         port->backup_imr = 0;
>>>         port->uart.line = ret;
>>> +       atmel_serial_probe_fifos(port, pdev);
>>>
>>>         spin_lock_init(&port->lock_suspended);
>>>
>>> diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
>>> index c384c21d65f0..ee696d7e8a43 100644
>>> --- a/include/linux/atmel_serial.h
>>> +++ b/include/linux/atmel_serial.h
>>> @@ -35,6 +35,11 @@
>>>  #define        ATMEL_US_DTRDIS         BIT(17) /* Data Terminal Ready Disable */
>>>  #define        ATMEL_US_RTSEN          BIT(18) /* Request To Send Enable */
>>>  #define        ATMEL_US_RTSDIS         BIT(19) /* Request To Send Disable */
>>> +#define        ATMEL_US_TXFCLR         BIT(24) /* Transmit FIFO Clear */
>>> +#define        ATMEL_US_RXFCLR         BIT(25) /* Receive FIFO Clear */
>>> +#define        ATMEL_US_TXFLCLR        BIT(26) /* Transmit FIFO Lock Clear */
>>> +#define        ATMEL_US_FIFOEN         BIT(30) /* FIFO enable */
>>> +#define        ATMEL_US_FIFODIS        BIT(31) /* FIFO disable */
>>>
>>>  #define ATMEL_US_MR            0x04    /* Mode Register */
>>>  #define        ATMEL_US_USMODE         GENMASK(3, 0)   /* Mode of the USART */
>>> @@ -124,6 +129,37 @@
>>>  #define ATMEL_US_NER           0x44    /* Number of Errors Register */
>>>  #define ATMEL_US_IF            0x4c    /* IrDA Filter Register */
>>>
>>> +#define ATMEL_US_CMPR          0x90    /* Comparaison Register */
>>> +#define ATMEL_US_FMR           0xa0    /* FIFO Mode Register */
>>> +#define        ATMEL_US_TXRDYM(data)   (((data) & 0x3) << 0)   /* TX Ready Mode */
>>> +#define        ATMEL_US_RXRDYM(data)   (((data) & 0x3) << 4)   /* RX Ready Mode */
>>> +#define                ATMEL_US_ONE_DATA       0x0
>>> +#define                ATMEL_US_TWO_DATA       0x1
>>> +#define                ATMEL_US_FOUR_DATA      0x2
>>> +#define        ATMEL_US_FRTSC          BIT(7)  /* FIFO RTS pin Control */
>>> +#define        ATMEL_US_TXFTHRES(thr)  (((thr) & 0x3f) << 8)   /* TX FIFO Threshold */
>>> +#define        ATMEL_US_RXFTHRES(thr)  (((thr) & 0x3f) << 16)  /* RX FIFO Threshold */
>>> +#define        ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24)  /* RX FIFO Threshold2 */
>>> +
>>> +#define ATMEL_US_FLR           0xa4    /* FIFO Level Register */
>>> +#define        ATMEL_US_TXFL(reg)      (((reg) >> 0) & 0x3f)   /* TX FIFO Level */
>>> +#define        ATMEL_US_RXFL(reg)      (((reg) >> 16) & 0x3f)  /* RX FIFO Level */
>>> +
>>> +#define ATMEL_US_FIER          0xa8    /* FIFO Interrupt Enable Register */
>>> +#define ATMEL_US_FIDR          0xac    /* FIFO Interrupt Disable Register */
>>> +#define ATMEL_US_FIMR          0xb0    /* FIFO Interrupt Mask Register */
>>> +#define ATMEL_US_FESR          0xb4    /* FIFO Event Status Register */
>>> +#define        ATMEL_US_TXFEF          BIT(0)  /* Transmit FIFO Empty Flag */
>>> +#define        ATMEL_US_TXFFF          BIT(1)  /* Transmit FIFO Full Flag */
>>> +#define        ATMEL_US_TXFTHF         BIT(2)  /* Transmit FIFO Threshold Flag */
>>> +#define        ATMEL_US_RXFEF          BIT(3)  /* Receive FIFO Empty Flag */
>>> +#define        ATMEL_US_RXFFF          BIT(4)  /* Receive FIFO Full Flag */
>>> +#define        ATMEL_US_RXFTHF         BIT(5)  /* Receive FIFO Threshold Flag */
>>> +#define        ATMEL_US_TXFPTEF        BIT(6)  /* Transmit FIFO Pointer Error Flag */
>>> +#define        ATMEL_US_RXFPTEF        BIT(7)  /* Receive FIFO Pointer Error Flag */
>>> +#define        ATMEL_US_TXFLOCK        BIT(8)  /* Transmit FIFO Lock (FESR only) */
>>> +#define        ATMEL_US_RXFTHF2        BIT(9)  /* Receive FIFO Threshold Flag 2 */
>>> +
>>>  #define ATMEL_US_NAME          0xf0    /* Ip Name */
>>>  #define ATMEL_US_VERSION       0xfc    /* Ip Version */
>>>
>>> --
>>> 1.8.2.2
>>>
-- 
mvh
Hans-Christian Egtvedt

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

end of thread, other threads:[~2015-07-29 15:34 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-02 13:18 [PATCH v4 0/5] tty/serial: at91: add support to FIFOs Cyrille Pitchen
2015-07-02 13:18 ` Cyrille Pitchen
2015-07-02 13:18 ` Cyrille Pitchen
2015-07-02 13:18 ` [PATCH v4 1/5] ARM: at91/dt: add a new DT property to support FIFOs on Atmel USARTs Cyrille Pitchen
2015-07-02 13:18   ` Cyrille Pitchen
2015-07-02 13:18   ` Cyrille Pitchen
2015-07-02 13:18 ` [PATCH v4 2/5] tty/serial: at91: fix some macro definitions to fit coding style Cyrille Pitchen
2015-07-02 13:18   ` Cyrille Pitchen
2015-07-02 13:18   ` Cyrille Pitchen
2015-07-02 13:18 ` [PATCH v4 3/5] tty/serial: at91: remove bunch of macros to access UART registers Cyrille Pitchen
2015-07-02 13:18   ` Cyrille Pitchen
2015-07-02 13:18   ` Cyrille Pitchen
2015-07-20 12:24   ` Nicolas Ferre
2015-07-20 12:24     ` Nicolas Ferre
2015-07-20 12:24     ` Nicolas Ferre
2015-07-02 13:18 ` [PATCH v4 4/5] tty/serial: at91: add support to FIFOs Cyrille Pitchen
2015-07-02 13:18   ` Cyrille Pitchen
2015-07-02 13:18   ` Cyrille Pitchen
2015-07-20 12:25   ` Nicolas Ferre
2015-07-20 12:25     ` Nicolas Ferre
2015-07-20 12:25     ` Nicolas Ferre
2015-07-29 14:51   ` Andy Shevchenko
2015-07-29 14:51     ` Andy Shevchenko
2015-07-29 14:51     ` Andy Shevchenko
2015-07-29 15:07     ` Alexandre Belloni
2015-07-29 15:07       ` Alexandre Belloni
2015-07-29 15:07       ` Alexandre Belloni
2015-07-29 15:09     ` Nicolas Ferre
2015-07-29 15:09       ` Nicolas Ferre
2015-07-29 15:34       ` Hans-Christian Egtvedt
2015-07-29 15:34         ` Hans-Christian Egtvedt
2015-07-29 15:34         ` Hans-Christian Egtvedt
2015-07-02 13:18 ` [PATCH v4 5/5] tty/serial: at91: use 32bit writes into TX FIFO when DMA is enabled Cyrille Pitchen
2015-07-02 13:18   ` Cyrille Pitchen
2015-07-02 13:18   ` Cyrille Pitchen

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.