[PATCH DRAFT 2/2] drivers: serial: PL011: [DRAFT] implement register diverson for ZTE UART

Andre Przywara andre.przywara at arm.com
Mon Nov 2 04:24:02 PST 2015


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

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

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

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

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




More information about the linux-arm-kernel mailing list