The S5L87xx UART peripheral does not support UDIVSLOT, also it needs
the NCLK bit to be set (clock source selection).

Signed-off-by: Vencislav Atanasov <[email protected]>
---
 MAINTAINERS                              |  5 ++++
 arch/arm/include/asm/arch-s5l87xx/uart.h | 29 +++++++++++++++++++
 drivers/serial/Kconfig                   |  4 +--
 drivers/serial/serial_s5p.c              | 49 +++++++++++++++++++++-----------
 4 files changed, 69 insertions(+), 18 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 95b1f3b5ab3..da8e413dd35 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -600,6 +600,11 @@ F: drivers/clk/exynos/clk-exynos850.c
 F:     drivers/phy/phy-exynos-usbdrd.c
 F:     drivers/pinctrl/exynos/pinctrl-exynos850.c
 
+ARM SAMSUNG S5L87XX SOC
+M:     Vencislav Atanasov <[email protected]>
+S:     Maintained
+F:     arch/arm/include/asm/arch-s5l87*
+
 ARM SAMSUNG SOC DRIVERS
 M:     Sam Protsenko <[email protected]>
 S:     Maintained
diff --git a/arch/arm/include/asm/arch-s5l87xx/uart.h 
b/arch/arm/include/asm/arch-s5l87xx/uart.h
new file mode 100644
index 00000000000..61b7cf43890
--- /dev/null
+++ b/arch/arm/include/asm/arch-s5l87xx/uart.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2009 Samsung Electronics
+ * Minkyu Kang <[email protected]>
+ * Heungjun Kim <[email protected]>
+ */
+
+#ifndef __ASM_ARCH_S5L87XX_UART_H_
+#define __ASM_ARCH_S5L87XX_UART_H_
+
+#ifndef __ASSEMBLY__
+
+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 int    utxh;
+       unsigned int    urxh;
+       unsigned int    ubrdiv;
+};
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_ARCH_S5L87XX_UART_H_ */
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index bcb0c865437..fa1959b2c30 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -321,7 +321,7 @@ config DEBUG_SBI_CONSOLE
 
 config DEBUG_UART_S5P
        bool "Samsung S5P"
-       depends on ARCH_APPLE || ARCH_EXYNOS || ARCH_S5PC1XX
+       depends on ARCH_APPLE || ARCH_EXYNOS || ARCH_S5PC1XX || ARCH_S5L87XX
        help
          Select this to enable a debug UART using the serial_s5p driver. You
          will need to provide parameters to make this work. The driver will
@@ -905,7 +905,7 @@ config ROCKCHIP_SERIAL
 
 config S5P_SERIAL
        bool "Support for Samsung S5P UART"
-       depends on ARCH_APPLE || ARCH_EXYNOS || ARCH_S5PC1XX
+       depends on ARCH_APPLE || ARCH_EXYNOS || ARCH_S5PC1XX || ARCH_S5L87XX
        default y
        help
          Select this to enable Samsung S5P UART support.
diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c
index d46a88610ab..eec0fa0a10f 100644
--- a/drivers/serial/serial_s5p.c
+++ b/drivers/serial/serial_s5p.c
@@ -13,10 +13,14 @@
 #include <asm/global_data.h>
 #include <linux/compiler.h>
 #include <asm/io.h>
-#if !IS_ENABLED(CONFIG_ARCH_APPLE)
+#if !IS_ENABLED(CONFIG_ARCH_APPLE) && !IS_ENABLED(CONFIG_ARCH_S5L87XX)
 #include <asm/arch/clk.h>
 #endif
+#if IS_ENABLED(CONFIG_ARCH_S5L87XX)
+#include <asm/arch-s5l87xx/uart.h>
+#else
 #include <asm/arch/uart.h>
+#endif
 #include <serial.h>
 #include <clk.h>
 
@@ -40,6 +44,7 @@ enum {
 #define S5L_TX_FIFO_COUNT_SHIFT        4
 #define S5L_TX_FIFO_COUNT_MASK (0xf << S5L_TX_FIFO_COUNT_SHIFT)
 #define S5L_TX_FIFO_FULL       BIT(9)
+#define S5L_CLK_NCLK           BIT(10)
 
 #define S5P_RX_FIFO_COUNT_SHIFT        0
 #define S5P_RX_FIFO_COUNT_MASK (0xff << S5P_RX_FIFO_COUNT_SHIFT)
@@ -61,6 +66,7 @@ struct s5p_serial_plat {
        u32 tx_fifo_full;
 };
 
+#if !IS_ENABLED(CONFIG_ARCH_S5L87XX)
 /*
  * The coefficient, used to calculate the baudrate on S5P UARTs is
  * calculated as
@@ -86,6 +92,7 @@ static const int udivslot[] = {
        0xdfdf,
        0xffdf,
 };
+#endif
 
 static void __maybe_unused s5p_serial_init(struct s5p_uart *uart)
 {
@@ -98,6 +105,14 @@ static void __maybe_unused s5p_serial_init(struct s5p_uart 
*uart)
        /* No interrupts, no DMA, pure polling */
        writel(UCON_RX_IRQ_OR_POLLING | UCON_TX_IRQ_OR_POLLING |
               UCON_RX_ERR_IRQ_EN | UCON_TX_IRQ_LEVEL, &uart->ucon);
+
+       if (IS_ENABLED(CONFIG_ARCH_S5L87XX)) {
+               u32 val;
+
+               val = readl(&uart->ucon);
+               val |= S5L_CLK_NCLK;
+               writel(val, &uart->ucon);
+       }
 }
 
 static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, u8 reg_width,
@@ -109,12 +124,14 @@ static void __maybe_unused s5p_serial_baud(struct 
s5p_uart *uart, u8 reg_width,
 
        writel(val / 16 - 1, &uart->ubrdiv);
 
+#if !IS_ENABLED(CONFIG_ARCH_S5L87XX)
        if (s5p_uart_divslot())
                writew(udivslot[val % 16], &uart->rest.slot);
        else if (reg_width == 4)
                writel(val % 16, &uart->rest.value);
        else
                writeb(val % 16, &uart->rest.value);
+#endif
 }
 
 #ifndef CONFIG_XPL_BUILD
@@ -124,7 +141,8 @@ int s5p_serial_setbrg(struct udevice *dev, int baudrate)
        struct s5p_uart *const uart = plat->reg;
        u32 uclk;
 
-#if IS_ENABLED(CONFIG_CLK_EXYNOS) || IS_ENABLED(CONFIG_ARCH_APPLE)
+#if IS_ENABLED(CONFIG_CLK_EXYNOS) || IS_ENABLED(CONFIG_ARCH_APPLE) || \
+       IS_ENABLED(CONFIG_ARCH_S5L87XX)
        struct clk clk;
        int ret;
 
@@ -286,26 +304,25 @@ static inline void _debug_uart_init(void)
        struct s5p_uart *uart = (struct s5p_uart *)CONFIG_VAL(DEBUG_UART_BASE);
 
        s5p_serial_init(uart);
-#if IS_ENABLED(CONFIG_ARCH_APPLE)
-       s5p_serial_baud(uart, 4, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
-#else
-       s5p_serial_baud(uart, 1, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
-#endif
+       if (IS_ENABLED(CONFIG_ARCH_APPLE) || IS_ENABLED(CONFIG_ARCH_S5L87XX))
+               s5p_serial_baud(uart, 4, CONFIG_DEBUG_UART_CLOCK, 
CONFIG_BAUDRATE);
+       else
+               s5p_serial_baud(uart, 1, CONFIG_DEBUG_UART_CLOCK, 
CONFIG_BAUDRATE);
 }
 
 static inline void _debug_uart_putc(int ch)
 {
        struct s5p_uart *uart = (struct s5p_uart *)CONFIG_VAL(DEBUG_UART_BASE);
 
-#if IS_ENABLED(CONFIG_ARCH_APPLE)
-       while (readl(&uart->ufstat) & S5L_TX_FIFO_FULL)
-               ;
-       writel(ch, &uart->utxh);
-#else
-       while (readl(&uart->ufstat) & S5P_TX_FIFO_FULL)
-               ;
-       writeb(ch, &uart->utxh);
-#endif
+       if (IS_ENABLED(CONFIG_ARCH_APPLE) || IS_ENABLED(CONFIG_ARCH_S5L87XX)) {
+               while (readl(&uart->ufstat) & S5L_TX_FIFO_FULL)
+                       ;
+               writel(ch, &uart->utxh);
+       } else {
+               while (readl(&uart->ufstat) & S5P_TX_FIFO_FULL)
+                       ;
+               writeb(ch, &uart->utxh);
+       }
 }
 
 DEBUG_UART_FUNCS

-- 
Git-157)

Reply via email to