2 * Driver core for Samsung SoC onboard UARTs.
4 * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
5 * http://armlinux.simtec.co.uk/
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 /* Hote on 2410 error handling
14 * The s3c2410 manual has a love/hate affair with the contents of the
15 * UERSTAT register in the UART blocks, and keeps marking some of the
16 * error bits as reserved. Having checked with the s3c2410x01,
17 * it copes with BREAKs properly, so I am happy to ignore the RESERVED
18 * feature from the latter versions of the manual.
20 * If it becomes aparrent that latter versions of the 2410 remove these
21 * bits, then action will have to be taken to differentiate the versions
22 * and change the policy on BREAK
27 #if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
31 #include <linux/module.h>
32 #include <linux/ioport.h>
34 #include <linux/platform_device.h>
35 #include <linux/init.h>
36 #include <linux/sysrq.h>
37 #include <linux/console.h>
38 #include <linux/tty.h>
39 #include <linux/tty_flip.h>
40 #include <linux/serial_core.h>
41 #include <linux/serial.h>
42 #include <linux/serial_s3c.h>
43 #include <linux/delay.h>
44 #include <linux/clk.h>
45 #include <linux/cpufreq.h>
52 #if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \
53 defined(CONFIG_DEBUG_LL) && \
56 extern void printascii(const char *);
59 static void dbg(const char *fmt, ...)
65 vscnprintf(buff, sizeof(buff), fmt, va);
72 #define dbg(fmt, ...) do { if (0) no_printk(fmt, ##__VA_ARGS__); } while (0)
75 /* UART name and device definitions */
77 #define S3C24XX_SERIAL_NAME "ttySAC"
78 #define S3C24XX_SERIAL_MAJOR 204
79 #define S3C24XX_SERIAL_MINOR 64
81 /* macros to change one thing to another */
83 #define tx_enabled(port) ((port)->unused[0])
84 #define rx_enabled(port) ((port)->unused[1])
86 /* flag to ignore all characters coming in */
87 #define RXSTAT_DUMMY_READ (0x10000000)
89 static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port)
91 return container_of(port, struct s3c24xx_uart_port, port);
94 /* translate a port to the device name */
96 static inline const char *s3c24xx_serial_portname(struct uart_port *port)
98 return to_platform_device(port->dev)->name;
101 static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
103 return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;
107 * s3c64xx and later SoC's include the interrupt mask and status registers in
108 * the controller itself, unlike the s3c24xx SoC's which have these registers
109 * in the interrupt controller. Check if the port type is s3c64xx or higher.
111 static int s3c24xx_serial_has_interrupt_mask(struct uart_port *port)
113 return to_ourport(port)->info->type == PORT_S3C6400;
116 static void s3c24xx_serial_rx_enable(struct uart_port *port)
119 unsigned int ucon, ufcon;
122 spin_lock_irqsave(&port->lock, flags);
124 while (--count && !s3c24xx_serial_txempty_nofifo(port))
127 ufcon = rd_regl(port, S3C2410_UFCON);
128 ufcon |= S3C2410_UFCON_RESETRX;
129 wr_regl(port, S3C2410_UFCON, ufcon);
131 ucon = rd_regl(port, S3C2410_UCON);
132 ucon |= S3C2410_UCON_RXIRQMODE;
133 wr_regl(port, S3C2410_UCON, ucon);
135 rx_enabled(port) = 1;
136 spin_unlock_irqrestore(&port->lock, flags);
139 static void s3c24xx_serial_rx_disable(struct uart_port *port)
144 spin_lock_irqsave(&port->lock, flags);
146 ucon = rd_regl(port, S3C2410_UCON);
147 ucon &= ~S3C2410_UCON_RXIRQMODE;
148 wr_regl(port, S3C2410_UCON, ucon);
150 rx_enabled(port) = 0;
151 spin_unlock_irqrestore(&port->lock, flags);
154 static void s3c24xx_serial_stop_tx(struct uart_port *port)
156 struct s3c24xx_uart_port *ourport = to_ourport(port);
158 if (tx_enabled(port)) {
159 if (s3c24xx_serial_has_interrupt_mask(port))
160 __set_bit(S3C64XX_UINTM_TXD,
161 portaddrl(port, S3C64XX_UINTM));
163 disable_irq_nosync(ourport->tx_irq);
164 tx_enabled(port) = 0;
165 if (port->flags & UPF_CONS_FLOW)
166 s3c24xx_serial_rx_enable(port);
170 static void s3c24xx_serial_start_tx(struct uart_port *port)
172 struct s3c24xx_uart_port *ourport = to_ourport(port);
174 if (!tx_enabled(port)) {
175 if (port->flags & UPF_CONS_FLOW)
176 s3c24xx_serial_rx_disable(port);
178 if (s3c24xx_serial_has_interrupt_mask(port))
179 __clear_bit(S3C64XX_UINTM_TXD,
180 portaddrl(port, S3C64XX_UINTM));
182 enable_irq(ourport->tx_irq);
183 tx_enabled(port) = 1;
187 static void s3c24xx_serial_stop_rx(struct uart_port *port)
189 struct s3c24xx_uart_port *ourport = to_ourport(port);
191 if (rx_enabled(port)) {
192 dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
193 if (s3c24xx_serial_has_interrupt_mask(port))
194 __set_bit(S3C64XX_UINTM_RXD,
195 portaddrl(port, S3C64XX_UINTM));
197 disable_irq_nosync(ourport->rx_irq);
198 rx_enabled(port) = 0;
202 static inline struct s3c24xx_uart_info
203 *s3c24xx_port_to_info(struct uart_port *port)
205 return to_ourport(port)->info;
208 static inline struct s3c2410_uartcfg
209 *s3c24xx_port_to_cfg(struct uart_port *port)
211 struct s3c24xx_uart_port *ourport;
213 if (port->dev == NULL)
216 ourport = container_of(port, struct s3c24xx_uart_port, port);
220 static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,
221 unsigned long ufstat)
223 struct s3c24xx_uart_info *info = ourport->info;
225 if (ufstat & info->rx_fifofull)
226 return ourport->port.fifosize;
228 return (ufstat & info->rx_fifomask) >> info->rx_fifoshift;
232 /* ? - where has parity gone?? */
233 #define S3C2410_UERSTAT_PARITY (0x1000)
236 s3c24xx_serial_rx_chars(int irq, void *dev_id)
238 struct s3c24xx_uart_port *ourport = dev_id;
239 struct uart_port *port = &ourport->port;
240 unsigned int ufcon, ch, flag, ufstat, uerstat;
242 int max_count = port->fifosize;
244 spin_lock_irqsave(&port->lock, flags);
246 while (max_count-- > 0) {
247 ufcon = rd_regl(port, S3C2410_UFCON);
248 ufstat = rd_regl(port, S3C2410_UFSTAT);
250 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
253 uerstat = rd_regl(port, S3C2410_UERSTAT);
254 ch = rd_regb(port, S3C2410_URXH);
256 if (port->flags & UPF_CONS_FLOW) {
257 int txe = s3c24xx_serial_txempty_nofifo(port);
259 if (rx_enabled(port)) {
261 rx_enabled(port) = 0;
266 ufcon |= S3C2410_UFCON_RESETRX;
267 wr_regl(port, S3C2410_UFCON, ufcon);
268 rx_enabled(port) = 1;
269 spin_unlock_irqrestore(&port->lock,
277 /* insert the character into the buffer */
282 if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
283 dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
286 /* check for break */
287 if (uerstat & S3C2410_UERSTAT_BREAK) {
290 if (uart_handle_break(port))
294 if (uerstat & S3C2410_UERSTAT_FRAME)
295 port->icount.frame++;
296 if (uerstat & S3C2410_UERSTAT_OVERRUN)
297 port->icount.overrun++;
299 uerstat &= port->read_status_mask;
301 if (uerstat & S3C2410_UERSTAT_BREAK)
303 else if (uerstat & S3C2410_UERSTAT_PARITY)
305 else if (uerstat & (S3C2410_UERSTAT_FRAME |
306 S3C2410_UERSTAT_OVERRUN))
310 if (uart_handle_sysrq_char(port, ch))
313 uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
320 spin_unlock_irqrestore(&port->lock, flags);
321 tty_flip_buffer_push(&port->state->port);
327 static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
329 struct s3c24xx_uart_port *ourport = id;
330 struct uart_port *port = &ourport->port;
331 struct circ_buf *xmit = &port->state->xmit;
333 int count = port->fifosize;
335 spin_lock_irqsave(&port->lock, flags);
338 wr_regb(port, S3C2410_UTXH, port->x_char);
344 /* if there isn't anything more to transmit, or the uart is now
345 * stopped, disable the uart and exit
348 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
349 s3c24xx_serial_stop_tx(port);
353 /* try and drain the buffer... */
355 while (!uart_circ_empty(xmit) && count-- > 0) {
356 if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
359 wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
360 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
364 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
365 spin_unlock(&port->lock);
366 uart_write_wakeup(port);
367 spin_lock(&port->lock);
370 if (uart_circ_empty(xmit))
371 s3c24xx_serial_stop_tx(port);
374 spin_unlock_irqrestore(&port->lock, flags);
378 /* interrupt handler for s3c64xx and later SoC's.*/
379 static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
381 struct s3c24xx_uart_port *ourport = id;
382 struct uart_port *port = &ourport->port;
383 unsigned int pend = rd_regl(port, S3C64XX_UINTP);
384 irqreturn_t ret = IRQ_HANDLED;
386 if (pend & S3C64XX_UINTM_RXD_MSK) {
387 ret = s3c24xx_serial_rx_chars(irq, id);
388 wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK);
390 if (pend & S3C64XX_UINTM_TXD_MSK) {
391 ret = s3c24xx_serial_tx_chars(irq, id);
392 wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK);
397 static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
399 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
400 unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT);
401 unsigned long ufcon = rd_regl(port, S3C2410_UFCON);
403 if (ufcon & S3C2410_UFCON_FIFOMODE) {
404 if ((ufstat & info->tx_fifomask) != 0 ||
405 (ufstat & info->tx_fifofull))
411 return s3c24xx_serial_txempty_nofifo(port);
414 /* no modem control lines */
415 static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
417 unsigned int umstat = rd_regb(port, S3C2410_UMSTAT);
419 if (umstat & S3C2410_UMSTAT_CTS)
420 return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
422 return TIOCM_CAR | TIOCM_DSR;
425 static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
427 unsigned int umcon = rd_regl(port, S3C2410_UMCON);
429 if (mctrl & TIOCM_RTS)
430 umcon |= S3C2410_UMCOM_RTS_LOW;
432 umcon &= ~S3C2410_UMCOM_RTS_LOW;
434 wr_regl(port, S3C2410_UMCON, umcon);
437 static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
442 spin_lock_irqsave(&port->lock, flags);
444 ucon = rd_regl(port, S3C2410_UCON);
447 ucon |= S3C2410_UCON_SBREAK;
449 ucon &= ~S3C2410_UCON_SBREAK;
451 wr_regl(port, S3C2410_UCON, ucon);
453 spin_unlock_irqrestore(&port->lock, flags);
456 static void s3c24xx_serial_shutdown(struct uart_port *port)
458 struct s3c24xx_uart_port *ourport = to_ourport(port);
460 if (ourport->tx_claimed) {
461 if (!s3c24xx_serial_has_interrupt_mask(port))
462 free_irq(ourport->tx_irq, ourport);
463 tx_enabled(port) = 0;
464 ourport->tx_claimed = 0;
467 if (ourport->rx_claimed) {
468 if (!s3c24xx_serial_has_interrupt_mask(port))
469 free_irq(ourport->rx_irq, ourport);
470 ourport->rx_claimed = 0;
471 rx_enabled(port) = 0;
474 /* Clear pending interrupts and mask all interrupts */
475 if (s3c24xx_serial_has_interrupt_mask(port)) {
476 free_irq(port->irq, ourport);
478 wr_regl(port, S3C64XX_UINTP, 0xf);
479 wr_regl(port, S3C64XX_UINTM, 0xf);
483 static int s3c24xx_serial_startup(struct uart_port *port)
485 struct s3c24xx_uart_port *ourport = to_ourport(port);
488 dbg("s3c24xx_serial_startup: port=%p (%08llx,%p)\n",
489 port, (unsigned long long)port->mapbase, port->membase);
491 rx_enabled(port) = 1;
493 ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,
494 s3c24xx_serial_portname(port), ourport);
497 dev_err(port->dev, "cannot get irq %d\n", ourport->rx_irq);
501 ourport->rx_claimed = 1;
503 dbg("requesting tx irq...\n");
505 tx_enabled(port) = 1;
507 ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,
508 s3c24xx_serial_portname(port), ourport);
511 dev_err(port->dev, "cannot get irq %d\n", ourport->tx_irq);
515 ourport->tx_claimed = 1;
517 dbg("s3c24xx_serial_startup ok\n");
519 /* the port reset code should have done the correct
520 * register setup for the port controls */
525 s3c24xx_serial_shutdown(port);
529 static int s3c64xx_serial_startup(struct uart_port *port)
531 struct s3c24xx_uart_port *ourport = to_ourport(port);
534 dbg("s3c64xx_serial_startup: port=%p (%08llx,%p)\n",
535 port, (unsigned long long)port->mapbase, port->membase);
537 wr_regl(port, S3C64XX_UINTM, 0xf);
539 ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED,
540 s3c24xx_serial_portname(port), ourport);
542 dev_err(port->dev, "cannot get irq %d\n", port->irq);
546 /* For compatibility with s3c24xx Soc's */
547 rx_enabled(port) = 1;
548 ourport->rx_claimed = 1;
549 tx_enabled(port) = 0;
550 ourport->tx_claimed = 1;
552 /* Enable Rx Interrupt */
553 __clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM));
554 dbg("s3c64xx_serial_startup ok\n");
558 /* power power management control */
560 static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
563 struct s3c24xx_uart_port *ourport = to_ourport(port);
566 ourport->pm_level = level;
570 while (--timeout && !s3c24xx_serial_txempty_nofifo(port))
573 if (!IS_ERR(ourport->baudclk))
574 clk_disable_unprepare(ourport->baudclk);
576 clk_disable_unprepare(ourport->clk);
580 clk_prepare_enable(ourport->clk);
582 if (!IS_ERR(ourport->baudclk))
583 clk_prepare_enable(ourport->baudclk);
587 dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level);
591 /* baud rate calculation
593 * The UARTs on the S3C2410/S3C2440 can take their clocks from a number
594 * of different sources, including the peripheral clock ("pclk") and an
595 * external clock ("uclk"). The S3C2440 also adds the core clock ("fclk")
596 * with a programmable extra divisor.
598 * The following code goes through the clock sources, and calculates the
599 * baud clocks (and the resultant actual baud rates) and then tries to
600 * pick the closest one and select that.
604 #define MAX_CLK_NAME_LENGTH 15
606 static inline int s3c24xx_serial_getsource(struct uart_port *port)
608 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
611 if (info->num_clks == 1)
614 ucon = rd_regl(port, S3C2410_UCON);
615 ucon &= info->clksel_mask;
616 return ucon >> info->clksel_shift;
619 static void s3c24xx_serial_setsource(struct uart_port *port,
620 unsigned int clk_sel)
622 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
625 if (info->num_clks == 1)
628 ucon = rd_regl(port, S3C2410_UCON);
629 if ((ucon & info->clksel_mask) >> info->clksel_shift == clk_sel)
632 ucon &= ~info->clksel_mask;
633 ucon |= clk_sel << info->clksel_shift;
634 wr_regl(port, S3C2410_UCON, ucon);
637 static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
638 unsigned int req_baud, struct clk **best_clk,
639 unsigned int *clk_num)
641 struct s3c24xx_uart_info *info = ourport->info;
644 unsigned int cnt, baud, quot, clk_sel, best_quot = 0;
645 char clkname[MAX_CLK_NAME_LENGTH];
646 int calc_deviation, deviation = (1 << 30) - 1;
648 clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel :
649 ourport->info->def_clk_sel;
650 for (cnt = 0; cnt < info->num_clks; cnt++) {
651 if (!(clk_sel & (1 << cnt)))
654 sprintf(clkname, "clk_uart_baud%d", cnt);
655 clk = clk_get(ourport->port.dev, clkname);
659 rate = clk_get_rate(clk);
663 if (ourport->info->has_divslot) {
664 unsigned long div = rate / req_baud;
666 /* The UDIVSLOT register on the newer UARTs allows us to
667 * get a divisor adjustment of 1/16th on the baud clock.
669 * We don't keep the UDIVSLOT value (the 16ths we
670 * calculated by not multiplying the baud by 16) as it
671 * is easy enough to recalculate.
677 quot = (rate + (8 * req_baud)) / (16 * req_baud);
678 baud = rate / (quot * 16);
682 calc_deviation = req_baud - baud;
683 if (calc_deviation < 0)
684 calc_deviation = -calc_deviation;
686 if (calc_deviation < deviation) {
690 deviation = calc_deviation;
699 * This table takes the fractional value of the baud divisor and gives
700 * the recommended setting for the UDIVSLOT register.
702 static u16 udivslot_table[16] = {
721 static void s3c24xx_serial_set_termios(struct uart_port *port,
722 struct ktermios *termios,
723 struct ktermios *old)
725 struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
726 struct s3c24xx_uart_port *ourport = to_ourport(port);
727 struct clk *clk = ERR_PTR(-EINVAL);
729 unsigned int baud, quot, clk_sel = 0;
732 unsigned int udivslot = 0;
735 * We don't support modem control lines.
737 termios->c_cflag &= ~(HUPCL | CMSPAR);
738 termios->c_cflag |= CLOCAL;
741 * Ask the core to calculate the divisor for us.
744 baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);
745 quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel);
746 if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
747 quot = port->custom_divisor;
751 /* check to see if we need to change clock source */
753 if (ourport->baudclk != clk) {
754 s3c24xx_serial_setsource(port, clk_sel);
756 if (!IS_ERR(ourport->baudclk)) {
757 clk_disable_unprepare(ourport->baudclk);
758 ourport->baudclk = ERR_PTR(-EINVAL);
761 clk_prepare_enable(clk);
763 ourport->baudclk = clk;
764 ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
767 if (ourport->info->has_divslot) {
768 unsigned int div = ourport->baudclk_rate / baud;
770 if (cfg->has_fracval) {
771 udivslot = (div & 15);
772 dbg("fracval = %04x\n", udivslot);
774 udivslot = udivslot_table[div & 15];
775 dbg("udivslot = %04x (div %d)\n", udivslot, div & 15);
779 switch (termios->c_cflag & CSIZE) {
781 dbg("config: 5bits/char\n");
782 ulcon = S3C2410_LCON_CS5;
785 dbg("config: 6bits/char\n");
786 ulcon = S3C2410_LCON_CS6;
789 dbg("config: 7bits/char\n");
790 ulcon = S3C2410_LCON_CS7;
794 dbg("config: 8bits/char\n");
795 ulcon = S3C2410_LCON_CS8;
799 /* preserve original lcon IR settings */
800 ulcon |= (cfg->ulcon & S3C2410_LCON_IRM);
802 if (termios->c_cflag & CSTOPB)
803 ulcon |= S3C2410_LCON_STOPB;
805 if (termios->c_cflag & PARENB) {
806 if (termios->c_cflag & PARODD)
807 ulcon |= S3C2410_LCON_PODD;
809 ulcon |= S3C2410_LCON_PEVEN;
811 ulcon |= S3C2410_LCON_PNONE;
814 spin_lock_irqsave(&port->lock, flags);
816 dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
817 ulcon, quot, udivslot);
819 wr_regl(port, S3C2410_ULCON, ulcon);
820 wr_regl(port, S3C2410_UBRDIV, quot);
822 umcon = rd_regl(port, S3C2410_UMCON);
823 if (termios->c_cflag & CRTSCTS) {
824 umcon |= S3C2410_UMCOM_AFC;
825 /* Disable RTS when RX FIFO contains 63 bytes */
826 umcon &= ~S3C2412_UMCON_AFC_8;
828 umcon &= ~S3C2410_UMCOM_AFC;
830 wr_regl(port, S3C2410_UMCON, umcon);
832 if (ourport->info->has_divslot)
833 wr_regl(port, S3C2443_DIVSLOT, udivslot);
835 dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
836 rd_regl(port, S3C2410_ULCON),
837 rd_regl(port, S3C2410_UCON),
838 rd_regl(port, S3C2410_UFCON));
841 * Update the per-port timeout.
843 uart_update_timeout(port, termios->c_cflag, baud);
846 * Which character status flags are we interested in?
848 port->read_status_mask = S3C2410_UERSTAT_OVERRUN;
849 if (termios->c_iflag & INPCK)
850 port->read_status_mask |= S3C2410_UERSTAT_FRAME |
851 S3C2410_UERSTAT_PARITY;
853 * Which character status flags should we ignore?
855 port->ignore_status_mask = 0;
856 if (termios->c_iflag & IGNPAR)
857 port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN;
858 if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
859 port->ignore_status_mask |= S3C2410_UERSTAT_FRAME;
862 * Ignore all characters if CREAD is not set.
864 if ((termios->c_cflag & CREAD) == 0)
865 port->ignore_status_mask |= RXSTAT_DUMMY_READ;
867 spin_unlock_irqrestore(&port->lock, flags);
870 static const char *s3c24xx_serial_type(struct uart_port *port)
872 switch (port->type) {
886 #define MAP_SIZE (0x100)
888 static void s3c24xx_serial_release_port(struct uart_port *port)
890 release_mem_region(port->mapbase, MAP_SIZE);
893 static int s3c24xx_serial_request_port(struct uart_port *port)
895 const char *name = s3c24xx_serial_portname(port);
896 return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY;
899 static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
901 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
903 if (flags & UART_CONFIG_TYPE &&
904 s3c24xx_serial_request_port(port) == 0)
905 port->type = info->type;
909 * verify the new serial_struct (for TIOCSSERIAL).
912 s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
914 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
916 if (ser->type != PORT_UNKNOWN && ser->type != info->type)
923 #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
925 static struct console s3c24xx_serial_console;
927 static int __init s3c24xx_serial_console_init(void)
929 register_console(&s3c24xx_serial_console);
932 console_initcall(s3c24xx_serial_console_init);
934 #define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
936 #define S3C24XX_SERIAL_CONSOLE NULL
939 #if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
940 static int s3c24xx_serial_get_poll_char(struct uart_port *port);
941 static void s3c24xx_serial_put_poll_char(struct uart_port *port,
945 static struct uart_ops s3c24xx_serial_ops = {
946 .pm = s3c24xx_serial_pm,
947 .tx_empty = s3c24xx_serial_tx_empty,
948 .get_mctrl = s3c24xx_serial_get_mctrl,
949 .set_mctrl = s3c24xx_serial_set_mctrl,
950 .stop_tx = s3c24xx_serial_stop_tx,
951 .start_tx = s3c24xx_serial_start_tx,
952 .stop_rx = s3c24xx_serial_stop_rx,
953 .break_ctl = s3c24xx_serial_break_ctl,
954 .startup = s3c24xx_serial_startup,
955 .shutdown = s3c24xx_serial_shutdown,
956 .set_termios = s3c24xx_serial_set_termios,
957 .type = s3c24xx_serial_type,
958 .release_port = s3c24xx_serial_release_port,
959 .request_port = s3c24xx_serial_request_port,
960 .config_port = s3c24xx_serial_config_port,
961 .verify_port = s3c24xx_serial_verify_port,
962 #if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
963 .poll_get_char = s3c24xx_serial_get_poll_char,
964 .poll_put_char = s3c24xx_serial_put_poll_char,
968 static struct uart_driver s3c24xx_uart_drv = {
969 .owner = THIS_MODULE,
970 .driver_name = "s3c2410_serial",
971 .nr = CONFIG_SERIAL_SAMSUNG_UARTS,
972 .cons = S3C24XX_SERIAL_CONSOLE,
973 .dev_name = S3C24XX_SERIAL_NAME,
974 .major = S3C24XX_SERIAL_MAJOR,
975 .minor = S3C24XX_SERIAL_MINOR,
978 #define __PORT_LOCK_UNLOCKED(i) \
979 __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[i].port.lock)
980 static struct s3c24xx_uart_port
981 s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
984 .lock = __PORT_LOCK_UNLOCKED(0),
988 .ops = &s3c24xx_serial_ops,
989 .flags = UPF_BOOT_AUTOCONF,
995 .lock = __PORT_LOCK_UNLOCKED(1),
999 .ops = &s3c24xx_serial_ops,
1000 .flags = UPF_BOOT_AUTOCONF,
1004 #if CONFIG_SERIAL_SAMSUNG_UARTS > 2
1008 .lock = __PORT_LOCK_UNLOCKED(2),
1012 .ops = &s3c24xx_serial_ops,
1013 .flags = UPF_BOOT_AUTOCONF,
1018 #if CONFIG_SERIAL_SAMSUNG_UARTS > 3
1021 .lock = __PORT_LOCK_UNLOCKED(3),
1025 .ops = &s3c24xx_serial_ops,
1026 .flags = UPF_BOOT_AUTOCONF,
1032 #undef __PORT_LOCK_UNLOCKED
1034 /* s3c24xx_serial_resetport
1036 * reset the fifos and other the settings.
1039 static void s3c24xx_serial_resetport(struct uart_port *port,
1040 struct s3c2410_uartcfg *cfg)
1042 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1043 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1044 unsigned int ucon_mask;
1046 ucon_mask = info->clksel_mask;
1047 if (info->type == PORT_S3C2440)
1048 ucon_mask |= S3C2440_UCON0_DIVMASK;
1051 wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
1053 /* reset both fifos */
1054 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
1055 wr_regl(port, S3C2410_UFCON, cfg->ufcon);
1057 /* some delay is required after fifo reset */
1062 #ifdef CONFIG_CPU_FREQ
1064 static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
1065 unsigned long val, void *data)
1067 struct s3c24xx_uart_port *port;
1068 struct uart_port *uport;
1070 port = container_of(nb, struct s3c24xx_uart_port, freq_transition);
1071 uport = &port->port;
1073 /* check to see if port is enabled */
1075 if (port->pm_level != 0)
1078 /* try and work out if the baudrate is changing, we can detect
1079 * a change in rate, but we do not have support for detecting
1080 * a disturbance in the clock-rate over the change.
1083 if (IS_ERR(port->baudclk))
1086 if (port->baudclk_rate == clk_get_rate(port->baudclk))
1089 if (val == CPUFREQ_PRECHANGE) {
1090 /* we should really shut the port down whilst the
1091 * frequency change is in progress. */
1093 } else if (val == CPUFREQ_POSTCHANGE) {
1094 struct ktermios *termios;
1095 struct tty_struct *tty;
1097 if (uport->state == NULL)
1100 tty = uport->state->port.tty;
1105 termios = &tty->termios;
1107 if (termios == NULL) {
1108 dev_warn(uport->dev, "%s: no termios?\n", __func__);
1112 s3c24xx_serial_set_termios(uport, termios, NULL);
1120 s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
1122 port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition;
1124 return cpufreq_register_notifier(&port->freq_transition,
1125 CPUFREQ_TRANSITION_NOTIFIER);
1129 s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
1131 cpufreq_unregister_notifier(&port->freq_transition,
1132 CPUFREQ_TRANSITION_NOTIFIER);
1137 s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
1143 s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
1148 /* s3c24xx_serial_init_port
1150 * initialise a single serial port from the platform device given
1153 static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
1154 struct platform_device *platdev)
1156 struct uart_port *port = &ourport->port;
1157 struct s3c2410_uartcfg *cfg = ourport->cfg;
1158 struct resource *res;
1161 dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev);
1163 if (platdev == NULL)
1166 if (port->mapbase != 0)
1169 /* setup info for port */
1170 port->dev = &platdev->dev;
1172 /* Startup sequence is different for s3c64xx and higher SoC's */
1173 if (s3c24xx_serial_has_interrupt_mask(port))
1174 s3c24xx_serial_ops.startup = s3c64xx_serial_startup;
1178 if (cfg->uart_flags & UPF_CONS_FLOW) {
1179 dbg("s3c24xx_serial_init_port: enabling flow control\n");
1180 port->flags |= UPF_CONS_FLOW;
1183 /* sort our the physical and virtual addresses for each UART */
1185 res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
1187 dev_err(port->dev, "failed to find memory resource for uart\n");
1191 dbg("resource %pR)\n", res);
1193 port->membase = devm_ioremap(port->dev, res->start, resource_size(res));
1194 if (!port->membase) {
1195 dev_err(port->dev, "failed to remap controller address\n");
1199 port->mapbase = res->start;
1200 ret = platform_get_irq(platdev, 0);
1205 ourport->rx_irq = ret;
1206 ourport->tx_irq = ret + 1;
1209 ret = platform_get_irq(platdev, 1);
1211 ourport->tx_irq = ret;
1213 ourport->clk = clk_get(&platdev->dev, "uart");
1214 if (IS_ERR(ourport->clk)) {
1215 pr_err("%s: Controller clock not found\n",
1216 dev_name(&platdev->dev));
1217 return PTR_ERR(ourport->clk);
1220 ret = clk_prepare_enable(ourport->clk);
1222 pr_err("uart: clock failed to prepare+enable: %d\n", ret);
1223 clk_put(ourport->clk);
1227 /* Keep all interrupts masked and cleared */
1228 if (s3c24xx_serial_has_interrupt_mask(port)) {
1229 wr_regl(port, S3C64XX_UINTM, 0xf);
1230 wr_regl(port, S3C64XX_UINTP, 0xf);
1231 wr_regl(port, S3C64XX_UINTSP, 0xf);
1234 dbg("port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n",
1235 &port->mapbase, port->membase, port->irq,
1236 ourport->rx_irq, ourport->tx_irq, port->uartclk);
1238 /* reset the fifos (and setup the uart) */
1239 s3c24xx_serial_resetport(port, cfg);
1243 /* Device driver serial port probe */
1245 static const struct of_device_id s3c24xx_uart_dt_match[];
1246 static int probe_index;
1248 static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data(
1249 struct platform_device *pdev)
1252 if (pdev->dev.of_node) {
1253 const struct of_device_id *match;
1254 match = of_match_node(s3c24xx_uart_dt_match, pdev->dev.of_node);
1255 return (struct s3c24xx_serial_drv_data *)match->data;
1258 return (struct s3c24xx_serial_drv_data *)
1259 platform_get_device_id(pdev)->driver_data;
1262 static int s3c24xx_serial_probe(struct platform_device *pdev)
1264 struct device_node *np = pdev->dev.of_node;
1265 struct s3c24xx_uart_port *ourport;
1266 int index = probe_index;
1270 ret = of_alias_get_id(np, "serial");
1275 dbg("s3c24xx_serial_probe(%p) %d\n", pdev, index);
1277 ourport = &s3c24xx_serial_ports[index];
1279 ourport->drv_data = s3c24xx_get_driver_data(pdev);
1280 if (!ourport->drv_data) {
1281 dev_err(&pdev->dev, "could not find driver data\n");
1285 ourport->baudclk = ERR_PTR(-EINVAL);
1286 ourport->info = ourport->drv_data->info;
1287 ourport->cfg = (dev_get_platdata(&pdev->dev)) ?
1288 dev_get_platdata(&pdev->dev) :
1289 ourport->drv_data->def_cfg;
1292 of_property_read_u32(np,
1293 "samsung,uart-fifosize", &ourport->port.fifosize);
1295 if (ourport->drv_data->fifosize[index])
1296 ourport->port.fifosize = ourport->drv_data->fifosize[index];
1297 else if (ourport->info->fifosize)
1298 ourport->port.fifosize = ourport->info->fifosize;
1302 dbg("%s: initialising port %p...\n", __func__, ourport);
1304 ret = s3c24xx_serial_init_port(ourport, pdev);
1308 if (!s3c24xx_uart_drv.state) {
1309 ret = uart_register_driver(&s3c24xx_uart_drv);
1311 pr_err("Failed to register Samsung UART driver\n");
1316 dbg("%s: adding port\n", __func__);
1317 uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
1318 platform_set_drvdata(pdev, &ourport->port);
1321 * Deactivate the clock enabled in s3c24xx_serial_init_port here,
1322 * so that a potential re-enablement through the pm-callback overlaps
1323 * and keeps the clock enabled in this case.
1325 clk_disable_unprepare(ourport->clk);
1327 ret = s3c24xx_serial_cpufreq_register(ourport);
1329 dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
1334 static int s3c24xx_serial_remove(struct platform_device *dev)
1336 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
1339 s3c24xx_serial_cpufreq_deregister(to_ourport(port));
1340 uart_remove_one_port(&s3c24xx_uart_drv, port);
1343 uart_unregister_driver(&s3c24xx_uart_drv);
1348 /* UART power management code */
1349 #ifdef CONFIG_PM_SLEEP
1350 static int s3c24xx_serial_suspend(struct device *dev)
1352 struct uart_port *port = s3c24xx_dev_to_port(dev);
1355 uart_suspend_port(&s3c24xx_uart_drv, port);
1360 static int s3c24xx_serial_resume(struct device *dev)
1362 struct uart_port *port = s3c24xx_dev_to_port(dev);
1363 struct s3c24xx_uart_port *ourport = to_ourport(port);
1366 clk_prepare_enable(ourport->clk);
1367 s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
1368 clk_disable_unprepare(ourport->clk);
1370 uart_resume_port(&s3c24xx_uart_drv, port);
1376 static int s3c24xx_serial_resume_noirq(struct device *dev)
1378 struct uart_port *port = s3c24xx_dev_to_port(dev);
1381 /* restore IRQ mask */
1382 if (s3c24xx_serial_has_interrupt_mask(port)) {
1383 unsigned int uintm = 0xf;
1384 if (tx_enabled(port))
1385 uintm &= ~S3C64XX_UINTM_TXD_MSK;
1386 if (rx_enabled(port))
1387 uintm &= ~S3C64XX_UINTM_RXD_MSK;
1388 wr_regl(port, S3C64XX_UINTM, uintm);
1395 static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
1396 .suspend = s3c24xx_serial_suspend,
1397 .resume = s3c24xx_serial_resume,
1398 .resume_noirq = s3c24xx_serial_resume_noirq,
1400 #define SERIAL_SAMSUNG_PM_OPS (&s3c24xx_serial_pm_ops)
1402 #else /* !CONFIG_PM_SLEEP */
1404 #define SERIAL_SAMSUNG_PM_OPS NULL
1405 #endif /* CONFIG_PM_SLEEP */
1409 #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
1411 static struct uart_port *cons_uart;
1414 s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
1416 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1417 unsigned long ufstat, utrstat;
1419 if (ufcon & S3C2410_UFCON_FIFOMODE) {
1420 /* fifo mode - check amount of data in fifo registers... */
1422 ufstat = rd_regl(port, S3C2410_UFSTAT);
1423 return (ufstat & info->tx_fifofull) ? 0 : 1;
1426 /* in non-fifo mode, we go and use the tx buffer empty */
1428 utrstat = rd_regl(port, S3C2410_UTRSTAT);
1429 return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
1433 s3c24xx_port_configured(unsigned int ucon)
1435 /* consider the serial port configured if the tx/rx mode set */
1436 return (ucon & 0xf) != 0;
1439 #ifdef CONFIG_CONSOLE_POLL
1441 * Console polling routines for writing and reading from the uart while
1442 * in an interrupt or debug context.
1445 static int s3c24xx_serial_get_poll_char(struct uart_port *port)
1447 struct s3c24xx_uart_port *ourport = to_ourport(port);
1448 unsigned int ufstat;
1450 ufstat = rd_regl(port, S3C2410_UFSTAT);
1451 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
1452 return NO_POLL_CHAR;
1454 return rd_regb(port, S3C2410_URXH);
1457 static void s3c24xx_serial_put_poll_char(struct uart_port *port,
1460 unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
1461 unsigned int ucon = rd_regl(port, S3C2410_UCON);
1463 /* not possible to xmit on unconfigured port */
1464 if (!s3c24xx_port_configured(ucon))
1467 while (!s3c24xx_serial_console_txrdy(port, ufcon))
1469 wr_regb(port, S3C2410_UTXH, c);
1472 #endif /* CONFIG_CONSOLE_POLL */
1475 s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
1477 unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
1479 while (!s3c24xx_serial_console_txrdy(port, ufcon))
1481 wr_regb(port, S3C2410_UTXH, ch);
1485 s3c24xx_serial_console_write(struct console *co, const char *s,
1488 unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
1490 /* not possible to xmit on unconfigured port */
1491 if (!s3c24xx_port_configured(ucon))
1494 uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
1498 s3c24xx_serial_get_options(struct uart_port *port, int *baud,
1499 int *parity, int *bits)
1504 unsigned int ubrdiv;
1506 unsigned int clk_sel;
1507 char clk_name[MAX_CLK_NAME_LENGTH];
1509 ulcon = rd_regl(port, S3C2410_ULCON);
1510 ucon = rd_regl(port, S3C2410_UCON);
1511 ubrdiv = rd_regl(port, S3C2410_UBRDIV);
1513 dbg("s3c24xx_serial_get_options: port=%p\n"
1514 "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
1515 port, ulcon, ucon, ubrdiv);
1517 if (s3c24xx_port_configured(ucon)) {
1518 switch (ulcon & S3C2410_LCON_CSMASK) {
1519 case S3C2410_LCON_CS5:
1522 case S3C2410_LCON_CS6:
1525 case S3C2410_LCON_CS7:
1528 case S3C2410_LCON_CS8:
1534 switch (ulcon & S3C2410_LCON_PMASK) {
1535 case S3C2410_LCON_PEVEN:
1539 case S3C2410_LCON_PODD:
1543 case S3C2410_LCON_PNONE:
1548 /* now calculate the baud rate */
1550 clk_sel = s3c24xx_serial_getsource(port);
1551 sprintf(clk_name, "clk_uart_baud%d", clk_sel);
1553 clk = clk_get(port->dev, clk_name);
1555 rate = clk_get_rate(clk);
1559 *baud = rate / (16 * (ubrdiv + 1));
1560 dbg("calculated baud %d\n", *baud);
1566 s3c24xx_serial_console_setup(struct console *co, char *options)
1568 struct uart_port *port;
1574 dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n",
1575 co, co->index, options);
1577 /* is this a valid port */
1579 if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS)
1582 port = &s3c24xx_serial_ports[co->index].port;
1584 /* is the port configured? */
1586 if (port->mapbase == 0x0)
1591 dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index);
1594 * Check whether an invalid uart number has been specified, and
1595 * if so, search for the first available port that does have
1599 uart_parse_options(options, &baud, &parity, &bits, &flow);
1601 s3c24xx_serial_get_options(port, &baud, &parity, &bits);
1603 dbg("s3c24xx_serial_console_setup: baud %d\n", baud);
1605 return uart_set_options(port, co, baud, parity, bits, flow);
1608 static struct console s3c24xx_serial_console = {
1609 .name = S3C24XX_SERIAL_NAME,
1610 .device = uart_console_device,
1611 .flags = CON_PRINTBUFFER,
1613 .write = s3c24xx_serial_console_write,
1614 .setup = s3c24xx_serial_console_setup,
1615 .data = &s3c24xx_uart_drv,
1617 #endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */
1619 #ifdef CONFIG_CPU_S3C2410
1620 static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = {
1621 .info = &(struct s3c24xx_uart_info) {
1622 .name = "Samsung S3C2410 UART",
1623 .type = PORT_S3C2410,
1625 .rx_fifomask = S3C2410_UFSTAT_RXMASK,
1626 .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
1627 .rx_fifofull = S3C2410_UFSTAT_RXFULL,
1628 .tx_fifofull = S3C2410_UFSTAT_TXFULL,
1629 .tx_fifomask = S3C2410_UFSTAT_TXMASK,
1630 .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
1631 .def_clk_sel = S3C2410_UCON_CLKSEL0,
1633 .clksel_mask = S3C2410_UCON_CLKMASK,
1634 .clksel_shift = S3C2410_UCON_CLKSHIFT,
1636 .def_cfg = &(struct s3c2410_uartcfg) {
1637 .ucon = S3C2410_UCON_DEFAULT,
1638 .ufcon = S3C2410_UFCON_DEFAULT,
1641 #define S3C2410_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2410_serial_drv_data)
1643 #define S3C2410_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1646 #ifdef CONFIG_CPU_S3C2412
1647 static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
1648 .info = &(struct s3c24xx_uart_info) {
1649 .name = "Samsung S3C2412 UART",
1650 .type = PORT_S3C2412,
1653 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
1654 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
1655 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
1656 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
1657 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
1658 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
1659 .def_clk_sel = S3C2410_UCON_CLKSEL2,
1661 .clksel_mask = S3C2412_UCON_CLKMASK,
1662 .clksel_shift = S3C2412_UCON_CLKSHIFT,
1664 .def_cfg = &(struct s3c2410_uartcfg) {
1665 .ucon = S3C2410_UCON_DEFAULT,
1666 .ufcon = S3C2410_UFCON_DEFAULT,
1669 #define S3C2412_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2412_serial_drv_data)
1671 #define S3C2412_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1674 #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \
1675 defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2442)
1676 static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
1677 .info = &(struct s3c24xx_uart_info) {
1678 .name = "Samsung S3C2440 UART",
1679 .type = PORT_S3C2440,
1682 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
1683 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
1684 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
1685 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
1686 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
1687 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
1688 .def_clk_sel = S3C2410_UCON_CLKSEL2,
1690 .clksel_mask = S3C2412_UCON_CLKMASK,
1691 .clksel_shift = S3C2412_UCON_CLKSHIFT,
1693 .def_cfg = &(struct s3c2410_uartcfg) {
1694 .ucon = S3C2410_UCON_DEFAULT,
1695 .ufcon = S3C2410_UFCON_DEFAULT,
1698 #define S3C2440_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2440_serial_drv_data)
1700 #define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1703 #if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
1704 static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
1705 .info = &(struct s3c24xx_uart_info) {
1706 .name = "Samsung S3C6400 UART",
1707 .type = PORT_S3C6400,
1710 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
1711 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
1712 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
1713 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
1714 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
1715 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
1716 .def_clk_sel = S3C2410_UCON_CLKSEL2,
1718 .clksel_mask = S3C6400_UCON_CLKMASK,
1719 .clksel_shift = S3C6400_UCON_CLKSHIFT,
1721 .def_cfg = &(struct s3c2410_uartcfg) {
1722 .ucon = S3C2410_UCON_DEFAULT,
1723 .ufcon = S3C2410_UFCON_DEFAULT,
1726 #define S3C6400_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c6400_serial_drv_data)
1728 #define S3C6400_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1731 #ifdef CONFIG_CPU_S5PV210
1732 static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
1733 .info = &(struct s3c24xx_uart_info) {
1734 .name = "Samsung S5PV210 UART",
1735 .type = PORT_S3C6400,
1737 .rx_fifomask = S5PV210_UFSTAT_RXMASK,
1738 .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
1739 .rx_fifofull = S5PV210_UFSTAT_RXFULL,
1740 .tx_fifofull = S5PV210_UFSTAT_TXFULL,
1741 .tx_fifomask = S5PV210_UFSTAT_TXMASK,
1742 .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
1743 .def_clk_sel = S3C2410_UCON_CLKSEL0,
1745 .clksel_mask = S5PV210_UCON_CLKMASK,
1746 .clksel_shift = S5PV210_UCON_CLKSHIFT,
1748 .def_cfg = &(struct s3c2410_uartcfg) {
1749 .ucon = S5PV210_UCON_DEFAULT,
1750 .ufcon = S5PV210_UFCON_DEFAULT,
1752 .fifosize = { 256, 64, 16, 16 },
1754 #define S5PV210_SERIAL_DRV_DATA ((kernel_ulong_t)&s5pv210_serial_drv_data)
1756 #define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1759 #if defined(CONFIG_ARCH_EXYNOS)
1760 static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
1761 .info = &(struct s3c24xx_uart_info) {
1762 .name = "Samsung Exynos4 UART",
1763 .type = PORT_S3C6400,
1765 .rx_fifomask = S5PV210_UFSTAT_RXMASK,
1766 .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
1767 .rx_fifofull = S5PV210_UFSTAT_RXFULL,
1768 .tx_fifofull = S5PV210_UFSTAT_TXFULL,
1769 .tx_fifomask = S5PV210_UFSTAT_TXMASK,
1770 .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
1771 .def_clk_sel = S3C2410_UCON_CLKSEL0,
1776 .def_cfg = &(struct s3c2410_uartcfg) {
1777 .ucon = S5PV210_UCON_DEFAULT,
1778 .ufcon = S5PV210_UFCON_DEFAULT,
1781 .fifosize = { 256, 64, 16, 16 },
1783 #define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data)
1785 #define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1788 static struct platform_device_id s3c24xx_serial_driver_ids[] = {
1790 .name = "s3c2410-uart",
1791 .driver_data = S3C2410_SERIAL_DRV_DATA,
1793 .name = "s3c2412-uart",
1794 .driver_data = S3C2412_SERIAL_DRV_DATA,
1796 .name = "s3c2440-uart",
1797 .driver_data = S3C2440_SERIAL_DRV_DATA,
1799 .name = "s3c6400-uart",
1800 .driver_data = S3C6400_SERIAL_DRV_DATA,
1802 .name = "s5pv210-uart",
1803 .driver_data = S5PV210_SERIAL_DRV_DATA,
1805 .name = "exynos4210-uart",
1806 .driver_data = EXYNOS4210_SERIAL_DRV_DATA,
1810 MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids);
1813 static const struct of_device_id s3c24xx_uart_dt_match[] = {
1814 { .compatible = "samsung,s3c2410-uart",
1815 .data = (void *)S3C2410_SERIAL_DRV_DATA },
1816 { .compatible = "samsung,s3c2412-uart",
1817 .data = (void *)S3C2412_SERIAL_DRV_DATA },
1818 { .compatible = "samsung,s3c2440-uart",
1819 .data = (void *)S3C2440_SERIAL_DRV_DATA },
1820 { .compatible = "samsung,s3c6400-uart",
1821 .data = (void *)S3C6400_SERIAL_DRV_DATA },
1822 { .compatible = "samsung,s5pv210-uart",
1823 .data = (void *)S5PV210_SERIAL_DRV_DATA },
1824 { .compatible = "samsung,exynos4210-uart",
1825 .data = (void *)EXYNOS4210_SERIAL_DRV_DATA },
1828 MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
1831 static struct platform_driver samsung_serial_driver = {
1832 .probe = s3c24xx_serial_probe,
1833 .remove = s3c24xx_serial_remove,
1834 .id_table = s3c24xx_serial_driver_ids,
1836 .name = "samsung-uart",
1837 .pm = SERIAL_SAMSUNG_PM_OPS,
1838 .of_match_table = of_match_ptr(s3c24xx_uart_dt_match),
1842 module_platform_driver(samsung_serial_driver);
1844 MODULE_ALIAS("platform:samsung-uart");
1845 MODULE_DESCRIPTION("Samsung SoC Serial port driver");
1846 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
1847 MODULE_LICENSE("GPL v2");