diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2012-08-01 17:50:18 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2012-08-01 17:50:18 +0200 |
commit | a934d16a2aa402f9f417f8a533ea80abcf1d2771 (patch) | |
tree | 3ad455d393a0ef35b44ea2d6aa2ade676801250e /drivers | |
parent | 33838de7a241242c40f23fa3f95939d29c78544d (diff) | |
parent | d65926656c9e51419ec491a48f71017e3c9759cd (diff) | |
download | barebox-a934d16a2aa402f9f417f8a533ea80abcf1d2771.tar.gz barebox-a934d16a2aa402f9f417f8a533ea80abcf1d2771.tar.xz |
Merge branch 'for-next/samsung'
Conflicts:
arch/arm/Makefile
arch/arm/mach-samsung/Makefile
arch/arm/mach-samsung/include/mach/s5pcxx-iomap.h
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/serial/Kconfig | 4 | ||||
-rw-r--r-- | drivers/serial/serial_s3c.c | 71 |
2 files changed, 42 insertions, 33 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index a9383da9d7..2b9a9b941a 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -78,9 +78,13 @@ config DRIVER_SERIAL_PL010 help Enable this to get support for AMBA PL010 based serial devices +config DRIVER_SERIAL_S3C_IMPROVED + bool + config DRIVER_SERIAL_S3C bool "Samsung S3C serial driver" depends on ARCH_SAMSUNG + select DRIVER_SERIAL_S3C_IMPROVED if (CPU_S5PC110 || CPU_S5PV210) default y help Say Y here if you want to use the CONS on a Samsung S3C CPU diff --git a/drivers/serial/serial_s3c.c b/drivers/serial/serial_s3c.c index 7a9b355704..0a7b137d19 100644 --- a/drivers/serial/serial_s3c.c +++ b/drivers/serial/serial_s3c.c @@ -31,6 +31,8 @@ /* Note: Offsets are for little endian access */ #define ULCON 0x00 /* line control */ #define UCON 0x04 /* UART control */ +# define UCON_SET_CLK_SRC(x) (((x) & 0x03) << 10) +# define UCON_GET_CLK_SRC(x) (((x) >> 10) & 0x03) #define UFCON 0x08 /* FIFO control */ #define UMCON 0x0c /* modem control */ #define UTRSTAT 0x10 /* Rx/Tx status */ @@ -40,17 +42,8 @@ #define UTXH 0x20 /* transmitt */ #define URXH 0x24 /* receive */ #define UBRDIV 0x28 /* baudrate generator */ -#ifdef S3C_UART_HAS_UBRDIVSLOT -# define UBRDIVSLOT 0x2c /* baudrate slot generator */ -#endif -#ifdef S3C_UART_HAS_UINTM -# define UINTM 0x38 /* interrupt mask register */ -#endif - -#ifndef S3C_UART_CLKSEL -/* Use pclk */ -# define S3C_UART_CLKSEL 0 -#endif +#define UBRDIVSLOT 0x2c /* baudrate slot generator */ +#define UINTM 0x38 /* interrupt mask register */ struct s3c_uart { void __iomem *regs; @@ -59,14 +52,23 @@ struct s3c_uart { #define to_s3c_uart(c) container_of(c, struct s3c_uart, cdev) +/* each architecture has a preferred reference clock for its UARTs */ +static unsigned s3c_select_arch_input_clock(void) +{ + /* S3C24xx: 0=2=PCLK, 1=UEXTCLK, 3=FCLK/n */ + if (IS_ENABLED(CONFIG_ARCH_S3C24xx)) + return 0; /* use the internal PCLK */ + /* S5PCxx: 0=PCLK, 1=SCLK_UART */ + if (IS_ENABLED(CONFIG_ARCH_S5PCxx)) + return 0; /* use the internal PCLK */ +} + static unsigned s3c_get_arch_uart_input_clock(void __iomem *base) { unsigned reg = readw(base + UCON); - reg = (reg >> 10) & 0x3; - return s3c_get_uart_clk(reg); + return s3c_get_uart_clk(UCON_GET_CLK_SRC(reg)); } -#ifdef S3C_UART_HAS_UBRDIVSLOT /* * This table takes the fractional value of the baud divisor and gives * the recommended setting for the UDIVSLOT register. Refer the datasheet @@ -76,7 +78,6 @@ static const uint16_t udivslot_table[] __maybe_unused = { 0x0000, 0x0080, 0x0808, 0x0888, 0x2222, 0x4924, 0x4A52, 0x54AA, 0x5555, 0xD555, 0xD5D5, 0xDDD5, 0xDDDD, 0xDFDD, 0xDFDF, 0xFFDF, }; -#endif static int s3c_serial_setbaudrate(struct console_device *cdev, int baudrate) { @@ -84,10 +85,11 @@ static int s3c_serial_setbaudrate(struct console_device *cdev, int baudrate) void __iomem *base = priv->regs; unsigned val; -#ifdef S3C_UART_HAS_UBRDIVSLOT - val = s3c_get_arch_uart_input_clock(base) / baudrate; - writew(udivslot_table[val & 15], base + UBRDIVSLOT); -#endif + if (IS_ENABLED(CONFIG_DRIVER_SERIAL_S3C_IMPROVED)) { + val = s3c_get_arch_uart_input_clock(base) / baudrate; + writew(udivslot_table[val & 15], base + UBRDIVSLOT); + } + val = s3c_get_arch_uart_input_clock(base) / (16 * baudrate) - 1; writew(val, base + UBRDIV); @@ -106,20 +108,23 @@ static int s3c_serial_init_port(struct console_device *cdev) /* Normal,No parity,1 stop,8 bit */ writeb(0x03, base + ULCON); - /* tx=level,rx=edge,disable timeout int.,enable rx error int., - * normal, interrupt or polling, no pre-divider */ - writew(0x0245 | ((S3C_UART_CLKSEL) << 10), base + UCON); - -#ifdef S3C_UART_HAS_UINTM - /* 'interrupt or polling mode' for both directions */ - writeb(0xf, base + UINTM); -#endif - -#ifdef CONFIG_DRIVER_SERIAL_S3C_AUTOSYNC - writeb(0x10, base + UMCON); /* enable auto flow control */ -#else - writeb(0x01, base + UMCON); /* RTS up */ -#endif + /* + * S3C2440 SoC: + * - no clock divider + * all SoCs: + * - enable receive and transmit mode + */ + writew(0x0005 | UCON_SET_CLK_SRC(s3c_select_arch_input_clock()), + base + UCON); + + if (IS_ENABLED(CONFIG_DRIVER_SERIAL_S3C_IMPROVED)) + /* 'interrupt or polling mode' for both directions */ + writeb(0xf, base + UINTM); + + if (IS_ENABLED(CONFIG_DRIVER_SERIAL_S3C_AUTOSYNC)) + writeb(0x10, base + UMCON); /* enable auto flow control */ + else + writeb(0x01, base + UMCON); /* RTS up */ return 0; } |