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.przyw...@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@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@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.k...@samsung.com> - * Heungjun Kim <riverful....@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.k...@samsung.com> - * Heungjun Kim <riverful....@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot