[U-Boot] [RFC PATCH 01/13] serial: s5p: rework Samsung UART driver to get rid of uart.h

Andre Przywara andre.przywara at arm.com
Thu Nov 30 01:24:59 UTC 2017


At the moment the serial_s5p driver takes care of both Exynos UARTs
as well as those from older Samsung SoCs (s3c/s5p series).
Looking more closely the only difference between those two groups is
how the fractional baud rate is programmed: via a "divslot" (s3c) or as
a proper fractional value (Exynos).
Instead of intricately expressing this via a special header file (which
is otherwise identical), let's use the blessings of DT to tackle this:
The S5P series of SoCs use their own compatible string, in line with
what the official DTs from the Linux kernel do. We then switch between
divslot and fractional value based on the compatible string used.
This allows us to get rid of the uart.h header files and make the
driver more flexible.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/dts/s5pc1xx-goni.dts             |  2 +-
 arch/arm/dts/s5pc1xx-smdkc100.dts         |  2 +-
 arch/arm/mach-exynos/include/mach/uart.h  | 44 ------------------------------
 arch/arm/mach-s5pc1xx/include/mach/uart.h | 44 ------------------------------
 drivers/serial/serial_s5p.c               | 45 +++++++++++++++++++++++++++----
 5 files changed, 42 insertions(+), 95 deletions(-)
 delete mode 100644 arch/arm/mach-exynos/include/mach/uart.h
 delete mode 100644 arch/arm/mach-s5pc1xx/include/mach/uart.h

diff --git a/arch/arm/dts/s5pc1xx-goni.dts b/arch/arm/dts/s5pc1xx-goni.dts
index 182325a091..964c7a6b67 100644
--- a/arch/arm/dts/s5pc1xx-goni.dts
+++ b/arch/arm/dts/s5pc1xx-goni.dts
@@ -28,7 +28,7 @@
 	};
 
 	serial at e2900800 {
-		compatible = "samsung,exynos4210-uart";
+		compatible = "samsung,s5pv210-uart";
 		reg = <0xe2900800 0x400>;
 		id = <2>;
 	};
diff --git a/arch/arm/dts/s5pc1xx-smdkc100.dts b/arch/arm/dts/s5pc1xx-smdkc100.dts
index 95f15ed48d..9f813eadbc 100644
--- a/arch/arm/dts/s5pc1xx-smdkc100.dts
+++ b/arch/arm/dts/s5pc1xx-smdkc100.dts
@@ -27,7 +27,7 @@
 	};
 
 	serial at ec000000 {
-		compatible = "samsung,exynos4210-uart";
+		compatible = "samsung,s5pv210-uart";
 		reg = <0xec000000 0x100>;
 		interrupts = <0 51 0>;
 		id = <0>;
diff --git a/arch/arm/mach-exynos/include/mach/uart.h b/arch/arm/mach-exynos/include/mach/uart.h
deleted file mode 100644
index 33d6ba3b64..0000000000
--- a/arch/arm/mach-exynos/include/mach/uart.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * (C) Copyright 2009 Samsung Electronics
- * Minkyu Kang <mk7.kang at samsung.com>
- * Heungjun Kim <riverful.kim at samsung.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __ASM_ARCH_UART_H_
-#define __ASM_ARCH_UART_H_
-
-#ifndef __ASSEMBLY__
-/* baudrate rest value */
-union br_rest {
-	unsigned short	slot;		/* udivslot */
-	unsigned char	value;		/* ufracval */
-};
-
-struct s5p_uart {
-	unsigned int	ulcon;
-	unsigned int	ucon;
-	unsigned int	ufcon;
-	unsigned int	umcon;
-	unsigned int	utrstat;
-	unsigned int	uerstat;
-	unsigned int	ufstat;
-	unsigned int	umstat;
-	unsigned char	utxh;
-	unsigned char	res1[3];
-	unsigned char	urxh;
-	unsigned char	res2[3];
-	unsigned int	ubrdiv;
-	union br_rest	rest;
-	unsigned char	res3[0xffd0];
-};
-
-static inline int s5p_uart_divslot(void)
-{
-	return 0;
-}
-
-#endif	/* __ASSEMBLY__ */
-
-#endif
diff --git a/arch/arm/mach-s5pc1xx/include/mach/uart.h b/arch/arm/mach-s5pc1xx/include/mach/uart.h
deleted file mode 100644
index 26db098842..0000000000
--- a/arch/arm/mach-s5pc1xx/include/mach/uart.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * (C) Copyright 2009 Samsung Electronics
- * Minkyu Kang <mk7.kang at samsung.com>
- * Heungjun Kim <riverful.kim at samsung.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __ASM_ARCH_UART_H_
-#define __ASM_ARCH_UART_H_
-
-#ifndef __ASSEMBLY__
-/* baudrate rest value */
-union br_rest {
-	unsigned short	slot;		/* udivslot */
-	unsigned char	value;		/* ufracval */
-};
-
-struct s5p_uart {
-	unsigned int	ulcon;
-	unsigned int	ucon;
-	unsigned int	ufcon;
-	unsigned int	umcon;
-	unsigned int	utrstat;
-	unsigned int	uerstat;
-	unsigned int	ufstat;
-	unsigned int	umstat;
-	unsigned char	utxh;
-	unsigned char	res1[3];
-	unsigned char	urxh;
-	unsigned char	res2[3];
-	unsigned int	ubrdiv;
-	union br_rest	rest;
-	unsigned char	res3[0x3d0];
-};
-
-static inline int s5p_uart_divslot(void)
-{
-	return 1;
-}
-
-#endif	/* __ASSEMBLY__ */
-
-#endif
diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c
index a2f692bf05..8f46cd149e 100644
--- a/drivers/serial/serial_s5p.c
+++ b/drivers/serial/serial_s5p.c
@@ -15,12 +15,34 @@
 #include <linux/compiler.h>
 #include <asm/io.h>
 #include <asm/arch/clk.h>
-#include <asm/arch/uart.h>
 #include <serial.h>
 #include <clk.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* baudrate rest value */
+union br_rest {
+	unsigned short	slot;		/* udivslot */
+	unsigned char	value;		/* ufracval */
+};
+
+struct s5p_uart {
+	unsigned int	ulcon;
+	unsigned int	ucon;
+	unsigned int	ufcon;
+	unsigned int	umcon;
+	unsigned int	utrstat;
+	unsigned int	uerstat;
+	unsigned int	ufstat;
+	unsigned int	umstat;
+	unsigned char	utxh;
+	unsigned char	res1[3];
+	unsigned char	urxh;
+	unsigned char	res2[3];
+	unsigned int	ubrdiv;
+	union br_rest	rest;
+};
+
 #define RX_FIFO_COUNT_SHIFT	0
 #define RX_FIFO_COUNT_MASK	(0xff << RX_FIFO_COUNT_SHIFT)
 #define RX_FIFO_FULL		(1 << 8)
@@ -28,10 +50,13 @@ DECLARE_GLOBAL_DATA_PTR;
 #define TX_FIFO_COUNT_MASK	(0xff << TX_FIFO_COUNT_SHIFT)
 #define TX_FIFO_FULL		(1 << 24)
 
+#define UART_HAS_DIVSLOT	1
+
 /* Information about a serial port */
 struct s5p_serial_platdata {
 	struct s5p_uart *reg;  /* address of registers in physical memory */
 	u8 port_id;     /* uart port number */
+	bool has_divslot;
 };
 
 /*
@@ -72,7 +97,7 @@ static void __maybe_unused s5p_serial_init(struct s5p_uart *uart)
 }
 
 static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, uint uclk,
-					   int baudrate)
+					   int baudrate, bool has_divslot)
 {
 	u32 val;
 
@@ -80,7 +105,7 @@ static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, uint uclk,
 
 	writel(val / 16 - 1, &uart->ubrdiv);
 
-	if (s5p_uart_divslot())
+	if (has_divslot)
 		writew(udivslot[val % 16], &uart->rest.slot);
 	else
 		writeb(val % 16, &uart->rest.value);
@@ -105,7 +130,7 @@ int s5p_serial_setbrg(struct udevice *dev, int baudrate)
 	uclk = get_uart_clk(plat->port_id);
 #endif
 
-	s5p_serial_baud(uart, uclk, baudrate);
+	s5p_serial_baud(uart, uclk, baudrate, plat->has_divslot);
 
 	return 0;
 }
@@ -180,6 +205,7 @@ static int s5p_serial_pending(struct udevice *dev, bool input)
 static int s5p_serial_ofdata_to_platdata(struct udevice *dev)
 {
 	struct s5p_serial_platdata *plat = dev->platdata;
+	unsigned long driver_data;
 	fdt_addr_t addr;
 
 	addr = devfdt_get_addr(dev);
@@ -189,6 +215,10 @@ static int s5p_serial_ofdata_to_platdata(struct udevice *dev)
 	plat->reg = (struct s5p_uart *)addr;
 	plat->port_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 					"id", dev->seq);
+
+	driver_data = dev_get_driver_data(dev);
+	plat->has_divslot = driver_data & UART_HAS_DIVSLOT;
+
 	return 0;
 }
 
@@ -200,7 +230,12 @@ static const struct dm_serial_ops s5p_serial_ops = {
 };
 
 static const struct udevice_id s5p_serial_ids[] = {
-	{ .compatible = "samsung,exynos4210-uart" },
+	{ .compatible = "samsung,s3c2412-uart", .data = UART_HAS_DIVSLOT },
+	{ .compatible = "samsung,s3c2440-uart", .data = UART_HAS_DIVSLOT },
+	{ .compatible = "samsung,s3c6400-uart", .data = UART_HAS_DIVSLOT },
+	{ .compatible = "samsung,s5pv210-uart", .data = UART_HAS_DIVSLOT },
+	{ .compatible = "samsung,exynos4210-uart", .data = 0 },
+	{ .compatible = "samsung,exynos5433-uart", .data = 0 },
 	{ }
 };
 
-- 
2.14.1



More information about the U-Boot mailing list