27 #if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
31 #include <linux/module.h>
38 #include <linux/tty.h>
40 #include <linux/serial_core.h>
41 #include <linux/serial.h>
49 #include <mach/hardware.h>
53 #include <plat/clock.h>
59 #define S3C24XX_SERIAL_NAME "ttySAC"
60 #define S3C24XX_SERIAL_MAJOR 204
61 #define S3C24XX_SERIAL_MINOR 64
65 #define tx_enabled(port) ((port)->unused[0])
66 #define rx_enabled(port) ((port)->unused[1])
69 #define RXSTAT_DUMMY_READ (0x10000000)
78 static inline const char *s3c24xx_serial_portname(
struct uart_port *
port)
83 static int s3c24xx_serial_txempty_nofifo(
struct uart_port *
port)
93 static int s3c24xx_serial_has_interrupt_mask(
struct uart_port *
port)
101 unsigned int ucon, ufcon;
106 while (--count && !s3c24xx_serial_txempty_nofifo(port))
118 spin_unlock_irqrestore(&port->
lock, flags);
121 static void s3c24xx_serial_rx_disable(
struct uart_port *port)
133 spin_unlock_irqrestore(&port->
lock, flags);
136 static void s3c24xx_serial_stop_tx(
struct uart_port *port)
141 if (s3c24xx_serial_has_interrupt_mask(port))
148 s3c24xx_serial_rx_enable(port);
152 static void s3c24xx_serial_start_tx(
struct uart_port *port)
158 s3c24xx_serial_rx_disable(port);
160 if (s3c24xx_serial_has_interrupt_mask(port))
169 static void s3c24xx_serial_stop_rx(
struct uart_port *port)
174 dbg(
"s3c24xx_serial_stop_rx: port=%p\n", port);
175 if (s3c24xx_serial_has_interrupt_mask(port))
184 static void s3c24xx_serial_enable_ms(
struct uart_port *port)
190 return to_ourport(port)->info;
205 unsigned long ufstat)
210 return ourport->
port.fifosize;
217 #define S3C2410_UERSTAT_PARITY (0x1000)
220 s3c24xx_serial_rx_chars(
int irq,
void *
dev_id)
225 unsigned int ufcon, ch,
flag, ufstat, uerstat;
228 while (max_count-- > 0) {
232 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
239 int txe = s3c24xx_serial_txempty_nofifo(port);
263 dbg(
"rxerr: port ch=0x%02x, rxs=0x%08x\n",
270 if (uart_handle_break(port))
281 if (uerstat & S3C2410_UERSTAT_BREAK)
285 else if (uerstat & (S3C2410_UERSTAT_FRAME |
286 S3C2410_UERSTAT_OVERRUN))
305 static irqreturn_t s3c24xx_serial_tx_chars(
int irq,
void *
id)
324 s3c24xx_serial_stop_tx(port);
343 s3c24xx_serial_stop_tx(port);
350 static irqreturn_t s3c64xx_serial_handle_irq(
int irq,
void *
id)
360 ret = s3c24xx_serial_rx_chars(irq,
id);
364 ret = s3c24xx_serial_tx_chars(irq,
id);
367 spin_unlock_irqrestore(&port->
lock, flags);
371 static unsigned int s3c24xx_serial_tx_empty(
struct uart_port *port)
385 return s3c24xx_serial_txempty_nofifo(port);
389 static unsigned int s3c24xx_serial_get_mctrl(
struct uart_port *port)
399 static void s3c24xx_serial_set_mctrl(
struct uart_port *port,
unsigned int mctrl)
404 static void s3c24xx_serial_break_ctl(
struct uart_port *port,
int break_state)
420 spin_unlock_irqrestore(&port->
lock, flags);
423 static void s3c24xx_serial_shutdown(
struct uart_port *port)
428 if (!s3c24xx_serial_has_interrupt_mask(port))
435 if (!s3c24xx_serial_has_interrupt_mask(port))
442 if (s3c24xx_serial_has_interrupt_mask(port)) {
448 static int s3c24xx_serial_startup(
struct uart_port *port)
453 dbg(
"s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
459 s3c24xx_serial_portname(port), ourport);
468 dbg(
"requesting tx irq...\n");
473 s3c24xx_serial_portname(port), ourport);
482 dbg(
"s3c24xx_serial_startup ok\n");
490 s3c24xx_serial_shutdown(port);
494 static int s3c64xx_serial_startup(
struct uart_port *port)
499 dbg(
"s3c64xx_serial_startup: port=%p (%08lx,%p)\n",
503 s3c24xx_serial_portname(port), ourport);
517 dbg(
"s3c64xx_serial_startup ok\n");
523 static void s3c24xx_serial_pm(
struct uart_port *port,
unsigned int level,
546 dev_err(port->
dev,
"s3c24xx_serial: unknown pm %d\n", level);
563 #define MAX_CLK_NAME_LENGTH 15
565 static inline int s3c24xx_serial_getsource(
struct uart_port *port)
578 static void s3c24xx_serial_setsource(
struct uart_port *port,
579 unsigned int clk_sel)
597 unsigned int req_baud,
struct clk **best_clk,
598 unsigned int *clk_num)
603 unsigned int cnt,
baud, quot, clk_sel, best_quot = 0;
605 int calc_deviation, deviation = (1 << 30) - 1;
607 clk_sel = (ourport->
cfg->clk_sel) ? ourport->
cfg->clk_sel :
608 ourport->
info->def_clk_sel;
610 if (!(clk_sel & (1 << cnt)))
613 sprintf(clkname,
"clk_uart_baud%d", cnt);
622 if (ourport->
info->has_divslot) {
623 unsigned long div = rate / req_baud;
636 quot = (rate + (8 * req_baud)) / (16 * req_baud);
637 baud = rate / (quot * 16);
641 calc_deviation = req_baud -
baud;
642 if (calc_deviation < 0)
643 calc_deviation = -calc_deviation;
645 if (calc_deviation < deviation) {
649 deviation = calc_deviation;
661 static u16 udivslot_table[16] = {
680 static void s3c24xx_serial_set_termios(
struct uart_port *port,
686 struct clk *clk = ERR_PTR(-
EINVAL);
688 unsigned int baud, quot, clk_sel = 0;
691 unsigned int udivslot = 0;
704 quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel);
713 s3c24xx_serial_setsource(port, clk_sel);
715 if (!IS_ERR(ourport->
baudclk)) {
726 if (ourport->
info->has_divslot) {
730 udivslot = (div & 15);
731 dbg(
"fracval = %04x\n", udivslot);
733 udivslot = udivslot_table[div & 15];
734 dbg(
"udivslot = %04x (div %d)\n", udivslot, div & 15);
740 dbg(
"config: 5bits/char\n");
744 dbg(
"config: 6bits/char\n");
748 dbg(
"config: 7bits/char\n");
753 dbg(
"config: 8bits/char\n");
777 dbg(
"setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
778 ulcon, quot, udivslot);
784 if (ourport->
info->has_divslot)
787 dbg(
"uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
819 spin_unlock_irqrestore(&port->
lock, flags);
822 static const char *s3c24xx_serial_type(
struct uart_port *port)
824 switch (port->
type) {
838 #define MAP_SIZE (0x100)
840 static void s3c24xx_serial_release_port(
struct uart_port *port)
845 static int s3c24xx_serial_request_port(
struct uart_port *port)
847 const char *
name = s3c24xx_serial_portname(port);
851 static void s3c24xx_serial_config_port(
struct uart_port *port,
int flags)
856 s3c24xx_serial_request_port(port) == 0)
875 #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
877 static struct console s3c24xx_serial_console;
879 static int __init s3c24xx_serial_console_init(
void)
886 #define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
888 #define S3C24XX_SERIAL_CONSOLE NULL
891 #ifdef CONFIG_CONSOLE_POLL
892 static int s3c24xx_serial_get_poll_char(
struct uart_port *port);
893 static void s3c24xx_serial_put_poll_char(
struct uart_port *port,
897 static struct uart_ops s3c24xx_serial_ops = {
898 .pm = s3c24xx_serial_pm,
899 .tx_empty = s3c24xx_serial_tx_empty,
900 .get_mctrl = s3c24xx_serial_get_mctrl,
901 .set_mctrl = s3c24xx_serial_set_mctrl,
902 .stop_tx = s3c24xx_serial_stop_tx,
903 .start_tx = s3c24xx_serial_start_tx,
904 .stop_rx = s3c24xx_serial_stop_rx,
905 .enable_ms = s3c24xx_serial_enable_ms,
906 .break_ctl = s3c24xx_serial_break_ctl,
907 .startup = s3c24xx_serial_startup,
908 .shutdown = s3c24xx_serial_shutdown,
909 .set_termios = s3c24xx_serial_set_termios,
910 .type = s3c24xx_serial_type,
911 .release_port = s3c24xx_serial_release_port,
912 .request_port = s3c24xx_serial_request_port,
913 .config_port = s3c24xx_serial_config_port,
914 .verify_port = s3c24xx_serial_verify_port,
915 #ifdef CONFIG_CONSOLE_POLL
916 .poll_get_char = s3c24xx_serial_get_poll_char,
917 .poll_put_char = s3c24xx_serial_put_poll_char,
923 .driver_name =
"s3c2410_serial",
924 .nr = CONFIG_SERIAL_SAMSUNG_UARTS,
931 static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
938 .ops = &s3c24xx_serial_ops,
949 .ops = &s3c24xx_serial_ops,
954 #if CONFIG_SERIAL_SAMSUNG_UARTS > 2
962 .ops = &s3c24xx_serial_ops,
968 #if CONFIG_SERIAL_SAMSUNG_UARTS > 3
975 .ops = &s3c24xx_serial_ops,
988 static void s3c24xx_serial_resetport(
struct uart_port *port,
993 unsigned int ucon_mask;
1012 #ifdef CONFIG_CPU_FREQ
1014 static int s3c24xx_serial_cpufreq_transition(
struct notifier_block *nb,
1015 unsigned long val,
void *
data)
1021 uport = &port->
port;
1050 tty = uport->
state->port.tty;
1055 termios = &tty->termios;
1057 if (termios ==
NULL) {
1058 dev_warn(uport->
dev,
"%s: no termios?\n", __func__);
1062 s3c24xx_serial_set_termios(uport, termios,
NULL);
1069 static inline int s3c24xx_serial_cpufreq_register(
struct s3c24xx_uart_port *port)
1071 port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition;
1077 static inline void s3c24xx_serial_cpufreq_deregister(
struct s3c24xx_uart_port *port)
1084 static inline int s3c24xx_serial_cpufreq_register(
struct s3c24xx_uart_port *port)
1089 static inline void s3c24xx_serial_cpufreq_deregister(
struct s3c24xx_uart_port *port)
1107 dbg(
"s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev);
1109 if (platdev ==
NULL)
1116 port->
dev = &platdev->
dev;
1119 if (s3c24xx_serial_has_interrupt_mask(port))
1120 s3c24xx_serial_ops.
startup = s3c64xx_serial_startup;
1125 dbg(
"s3c24xx_serial_init_port: enabling flow control\n");
1133 dev_err(port->
dev,
"failed to find memory resource for uart\n");
1137 dbg(
"resource %p (%lx..%lx)\n", res, res->
start, res->
end);
1147 ourport->
tx_irq = ret + 1;
1157 if (s3c24xx_serial_has_interrupt_mask(port)) {
1163 dbg(
"port: map=%08x, mem=%08x, irq=%d (%d,%d), clock=%ld\n",
1168 s3c24xx_serial_resetport(port, cfg);
1183 ourport->
baudclk->name ?:
"(null)");
1192 static int probe_index;
1198 if (pdev->
dev.of_node) {
1213 dbg(
"s3c24xx_serial_probe(%p) %d\n", pdev, probe_index);
1215 ourport = &s3c24xx_serial_ports[probe_index];
1217 ourport->
drv_data = s3c24xx_get_driver_data(pdev);
1219 dev_err(&pdev->
dev,
"could not find driver data\n");
1225 ourport->
cfg = (pdev->
dev.platform_data) ?
1229 ourport->
port.fifosize = (ourport->
info->fifosize) ?
1230 ourport->
info->fifosize :
1231 ourport->
drv_data->fifosize[probe_index];
1235 dbg(
"%s: initialising port %p...\n", __func__, ourport);
1237 ret = s3c24xx_serial_init_port(ourport, pdev);
1241 dbg(
"%s: adding port\n", __func__);
1243 platform_set_drvdata(pdev, &ourport->
port);
1247 dev_err(&pdev->
dev,
"failed to add clock source attr.\n");
1249 ret = s3c24xx_serial_cpufreq_register(ourport);
1251 dev_err(&pdev->
dev,
"failed to add cpufreq notifier\n");
1264 s3c24xx_serial_cpufreq_deregister(to_ourport(port));
1273 #ifdef CONFIG_PM_SLEEP
1274 static int s3c24xx_serial_suspend(
struct device *dev)
1284 static int s3c24xx_serial_resume(
struct device *dev)
1291 s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
1300 static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
1301 .
suspend = s3c24xx_serial_suspend,
1302 .resume = s3c24xx_serial_resume,
1304 #define SERIAL_SAMSUNG_PM_OPS (&s3c24xx_serial_pm_ops)
1308 #define SERIAL_SAMSUNG_PM_OPS NULL
1313 #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
1318 s3c24xx_serial_console_txrdy(
struct uart_port *port,
unsigned int ufcon)
1321 unsigned long ufstat, utrstat;
1323 if (ufcon & S3C2410_UFCON_FIFOMODE) {
1336 #ifdef CONFIG_CONSOLE_POLL
1342 static int s3c24xx_serial_get_poll_char(
struct uart_port *port)
1345 unsigned int ufstat;
1348 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
1354 static void s3c24xx_serial_put_poll_char(
struct uart_port *port,
1359 while (!s3c24xx_serial_console_txrdy(port, ufcon))
1367 s3c24xx_serial_console_putchar(
struct uart_port *port,
int ch)
1370 while (!s3c24xx_serial_console_txrdy(port, ufcon))
1376 s3c24xx_serial_console_write(
struct console *co,
const char *
s,
1383 s3c24xx_serial_get_options(
struct uart_port *port,
int *baud,
1384 int *parity,
int *
bits)
1389 unsigned int ubrdiv;
1391 unsigned int clk_sel;
1398 dbg(
"s3c24xx_serial_get_options: port=%p\n"
1399 "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
1400 port, ulcon, ucon, ubrdiv);
1402 if ((ucon & 0xf) != 0) {
1437 clk_sel = s3c24xx_serial_getsource(port);
1438 sprintf(clk_name,
"clk_uart_baud%d", clk_sel);
1446 *baud = rate / (16 * (ubrdiv + 1));
1447 dbg(
"calculated baud %d\n", *baud);
1461 dbg(
"s3c24xx_serial_console_setup: co=%p (%d), %s\n",
1462 co, co->
index, options);
1466 if (co->
index == -1 || co->
index >= CONFIG_SERIAL_SAMSUNG_UARTS)
1469 port = &s3c24xx_serial_ports[co->
index].
port;
1478 dbg(
"s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->
index);
1488 s3c24xx_serial_get_options(port, &baud, &parity, &bits);
1490 dbg(
"s3c24xx_serial_console_setup: baud %d\n", baud);
1495 static struct console s3c24xx_serial_console = {
1500 .write = s3c24xx_serial_console_write,
1501 .setup = s3c24xx_serial_console_setup,
1502 .data = &s3c24xx_uart_drv,
1506 #ifdef CONFIG_CPU_S3C2410
1509 .name =
"Samsung S3C2410 UART",
1528 #define S3C2410_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2410_serial_drv_data)
1530 #define S3C2410_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1533 #ifdef CONFIG_CPU_S3C2412
1536 .name =
"Samsung S3C2412 UART",
1556 #define S3C2412_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2412_serial_drv_data)
1558 #define S3C2412_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1561 #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \
1562 defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2442)
1565 .name =
"Samsung S3C2440 UART",
1585 #define S3C2440_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2440_serial_drv_data)
1587 #define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1590 #if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410) || \
1591 defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450) || \
1592 defined(CONFIG_CPU_S5PC100)
1595 .name =
"Samsung S3C6400 UART",
1615 #define S3C6400_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c6400_serial_drv_data)
1617 #define S3C6400_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1620 #ifdef CONFIG_CPU_S5PV210
1623 .name =
"Samsung S5PV210 UART",
1641 .fifosize = { 256, 64, 16, 16 },
1643 #define S5PV210_SERIAL_DRV_DATA ((kernel_ulong_t)&s5pv210_serial_drv_data)
1645 #define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1648 #if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212) || \
1649 defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250)
1652 .name =
"Samsung Exynos4 UART",
1671 .fifosize = { 256, 64, 16, 16 },
1673 #define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data)
1675 #define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1680 .name =
"s3c2410-uart",
1683 .name =
"s3c2412-uart",
1686 .name =
"s3c2440-uart",
1689 .name =
"s3c6400-uart",
1692 .name =
"s5pv210-uart",
1695 .name =
"exynos4210-uart",
1704 { .compatible =
"samsung,exynos4210-uart",
1710 #define s3c24xx_uart_dt_match NULL
1714 .probe = s3c24xx_serial_probe,
1716 .id_table = s3c24xx_serial_driver_ids,
1718 .
name =
"samsung-uart",
1727 static int __init s3c24xx_serial_modinit(
void)
1733 pr_err(
"Failed to register Samsung UART driver\n");
1740 static void __exit s3c24xx_serial_modexit(
void)