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)
