[U-Boot] [RFC] ns16550: Add support for AUX regs usage on some ARC SoCs

Alexey Brodkin Alexey.Brodkin at synopsys.com
Wed Feb 21 12:26:05 UTC 2018


Synopsys Data Fusion subsystem (DFSS) is targeted to deeply built-in
use-cases and so to save some silicon area decision was made to
escape usage of any busses and use instead directly wired to CPU
peripherals. And one of those is DW APB UART.

Later DFSS became a part of larger and more complicated SoCs with
some other peripherals connected via common buses but default UART
is still used via ARC core's auxulary registers which are not mapped
to "normal" address space and we use very special instructions to access
them, thus we cannot simply reuse whatever accessor we have in 16550
UART as of now.

Also we cannot just switch inb()/outb() to access ARC AUX regs always
for DFSS because other peripherals have normal memory-mapped control
registers and we need to use normal accessors for them.

Frankly I don't like a lot what I did here but otherwise if I create
a special driver for this I'll need to reimplement
ns16550_serial_ops.putc()/getc() which will be pure copy-paseted from
ns16550.c because the only difference is only in
ns16550_{read|write}b().

As mentioned above we cannot remap those auxiliary registers to
normal memory address-space and thus we have to use very special
accessors write_aux_reg()/read_aux_reg() that directly use special
CPU intructions (namely LR/SR) for dealing with ARC AUX regs.

Also note here I just use a check for a particular SoC being selected
(CONFIG_ARCH_DFSS will be introduced shortly) but that is done just for
simplicity, otherwise it might be a slecial Kconfig option for NS16550
or anything else.

I'd like to know what people think about possible colutions here.
And as always any comments are much appreciated!

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Simon Glass <sjg at chromium.org>
Cc: Tom Rini <trini at konsulko.com>
Cc: Stefan Roese <sr at denx.de>
---
 drivers/serial/ns16550.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 6f9ce689cfff..75f342f337f1 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -13,6 +13,9 @@
 #include <watchdog.h>
 #include <linux/types.h>
 #include <asm/io.h>
+#ifdef CONFIG_ARCH_DFSS
+#include <asm/arcregs.h>
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -53,7 +56,9 @@ DECLARE_GLOBAL_DATA_PTR;
 
 static inline void serial_out_shift(void *addr, int shift, int value)
 {
-#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+#ifdef CONFIG_ARCH_DFSS
+	write_aux_reg((int)addr, value);
+#elif defined(CONFIG_SYS_NS16550_PORT_MAPPED)
 	outb(value, (ulong)addr);
 #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
 	out_le32(addr, value);
@@ -70,7 +75,9 @@ static inline void serial_out_shift(void *addr, int shift, int value)
 
 static inline int serial_in_shift(void *addr, int shift)
 {
-#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+#ifdef CONFIG_ARCH_DFSS
+	return read_aux_reg((int)addr);
+#elif defined(CONFIG_SYS_NS16550_PORT_MAPPED)
 	return inb((ulong)addr);
 #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
 	return in_le32(addr);
-- 
2.14.3



More information about the U-Boot mailing list