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
*s3c24xx_port_to_info(struct uart_port
*port
)
204 return to_ourport(port
)->info
;
207 static inline struct s3c2410_uartcfg
*s3c24xx_port_to_cfg(struct uart_port
*port
)
209 struct s3c24xx_uart_port
*ourport
;
211 if (port
->dev
== NULL
)
214 ourport
= container_of(port
, struct s3c24xx_uart_port
, port
);
218 static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port
*ourport
,
219 unsigned long ufstat
)
221 struct s3c24xx_uart_info
*info
= ourport
->info
;
223 if (ufstat
& info
->rx_fifofull
)
224 return ourport
->port
.fifosize
;
226 return (ufstat
& info
->rx_fifomask
) >> info
->rx_fifoshift
;
230 /* ? - where has parity gone?? */
231 #define S3C2410_UERSTAT_PARITY (0x1000)
234 s3c24xx_serial_rx_chars(int irq
, void *dev_id
)
236 struct s3c24xx_uart_port
*ourport
= dev_id
;
237 struct uart_port
*port
= &ourport
->port
;
238 unsigned int ufcon
, ch
, flag
, ufstat
, uerstat
;
242 spin_lock_irqsave(&port
->lock
, flags
);
244 while (max_count
-- > 0) {
245 ufcon
= rd_regl(port
, S3C2410_UFCON
);
246 ufstat
= rd_regl(port
, S3C2410_UFSTAT
);
248 if (s3c24xx_serial_rx_fifocnt(ourport
, ufstat
) == 0)
251 uerstat
= rd_regl(port
, S3C2410_UERSTAT
);
252 ch
= rd_regb(port
, S3C2410_URXH
);
254 if (port
->flags
& UPF_CONS_FLOW
) {
255 int txe
= s3c24xx_serial_txempty_nofifo(port
);
257 if (rx_enabled(port
)) {
259 rx_enabled(port
) = 0;
264 ufcon
|= S3C2410_UFCON_RESETRX
;
265 wr_regl(port
, S3C2410_UFCON
, ufcon
);
266 rx_enabled(port
) = 1;
267 spin_unlock_irqrestore(&port
->lock
,
275 /* insert the character into the buffer */
280 if (unlikely(uerstat
& S3C2410_UERSTAT_ANY
)) {
281 dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
284 /* check for break */
285 if (uerstat
& S3C2410_UERSTAT_BREAK
) {
288 if (uart_handle_break(port
))
292 if (uerstat
& S3C2410_UERSTAT_FRAME
)
293 port
->icount
.frame
++;
294 if (uerstat
& S3C2410_UERSTAT_OVERRUN
)
295 port
->icount
.overrun
++;
297 uerstat
&= port
->read_status_mask
;
299 if (uerstat
& S3C2410_UERSTAT_BREAK
)
301 else if (uerstat
& S3C2410_UERSTAT_PARITY
)
303 else if (uerstat
& (S3C2410_UERSTAT_FRAME
|
304 S3C2410_UERSTAT_OVERRUN
))
308 if (uart_handle_sysrq_char(port
, ch
))
311 uart_insert_char(port
, uerstat
, S3C2410_UERSTAT_OVERRUN
,
318 spin_unlock_irqrestore(&port
->lock
, flags
);
319 tty_flip_buffer_push(&port
->state
->port
);
325 static irqreturn_t
s3c24xx_serial_tx_chars(int irq
, void *id
)
327 struct s3c24xx_uart_port
*ourport
= id
;
328 struct uart_port
*port
= &ourport
->port
;
329 struct circ_buf
*xmit
= &port
->state
->xmit
;
333 spin_lock_irqsave(&port
->lock
, flags
);
336 wr_regb(port
, S3C2410_UTXH
, port
->x_char
);
342 /* if there isn't anything more to transmit, or the uart is now
343 * stopped, disable the uart and exit
346 if (uart_circ_empty(xmit
) || uart_tx_stopped(port
)) {
347 s3c24xx_serial_stop_tx(port
);
351 /* try and drain the buffer... */
353 while (!uart_circ_empty(xmit
) && count
-- > 0) {
354 if (rd_regl(port
, S3C2410_UFSTAT
) & ourport
->info
->tx_fifofull
)
357 wr_regb(port
, S3C2410_UTXH
, xmit
->buf
[xmit
->tail
]);
358 xmit
->tail
= (xmit
->tail
+ 1) & (UART_XMIT_SIZE
- 1);
362 if (uart_circ_chars_pending(xmit
) < WAKEUP_CHARS
) {
363 spin_unlock(&port
->lock
);
364 uart_write_wakeup(port
);
365 spin_lock(&port
->lock
);
368 if (uart_circ_empty(xmit
))
369 s3c24xx_serial_stop_tx(port
);
372 spin_unlock_irqrestore(&port
->lock
, flags
);
376 /* interrupt handler for s3c64xx and later SoC's.*/
377 static irqreturn_t
s3c64xx_serial_handle_irq(int irq
, void *id
)
379 struct s3c24xx_uart_port
*ourport
= id
;
380 struct uart_port
*port
= &ourport
->port
;
381 unsigned int pend
= rd_regl(port
, S3C64XX_UINTP
);
382 irqreturn_t ret
= IRQ_HANDLED
;
384 if (pend
& S3C64XX_UINTM_RXD_MSK
) {
385 ret
= s3c24xx_serial_rx_chars(irq
, id
);
386 wr_regl(port
, S3C64XX_UINTP
, S3C64XX_UINTM_RXD_MSK
);
388 if (pend
& S3C64XX_UINTM_TXD_MSK
) {
389 ret
= s3c24xx_serial_tx_chars(irq
, id
);
390 wr_regl(port
, S3C64XX_UINTP
, S3C64XX_UINTM_TXD_MSK
);
395 static unsigned int s3c24xx_serial_tx_empty(struct uart_port
*port
)
397 struct s3c24xx_uart_info
*info
= s3c24xx_port_to_info(port
);
398 unsigned long ufstat
= rd_regl(port
, S3C2410_UFSTAT
);
399 unsigned long ufcon
= rd_regl(port
, S3C2410_UFCON
);
401 if (ufcon
& S3C2410_UFCON_FIFOMODE
) {
402 if ((ufstat
& info
->tx_fifomask
) != 0 ||
403 (ufstat
& info
->tx_fifofull
))
409 return s3c24xx_serial_txempty_nofifo(port
);
412 /* no modem control lines */
413 static unsigned int s3c24xx_serial_get_mctrl(struct uart_port
*port
)
415 unsigned int umstat
= rd_regb(port
, S3C2410_UMSTAT
);
417 if (umstat
& S3C2410_UMSTAT_CTS
)
418 return TIOCM_CAR
| TIOCM_DSR
| TIOCM_CTS
;
420 return TIOCM_CAR
| TIOCM_DSR
;
423 static void s3c24xx_serial_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
425 unsigned int umcon
= rd_regl(port
, S3C2410_UMCON
);
427 if (mctrl
& TIOCM_RTS
)
428 umcon
|= S3C2410_UMCOM_RTS_LOW
;
430 umcon
&= ~S3C2410_UMCOM_RTS_LOW
;
432 wr_regl(port
, S3C2410_UMCON
, umcon
);
435 static void s3c24xx_serial_break_ctl(struct uart_port
*port
, int break_state
)
440 spin_lock_irqsave(&port
->lock
, flags
);
442 ucon
= rd_regl(port
, S3C2410_UCON
);
445 ucon
|= S3C2410_UCON_SBREAK
;
447 ucon
&= ~S3C2410_UCON_SBREAK
;
449 wr_regl(port
, S3C2410_UCON
, ucon
);
451 spin_unlock_irqrestore(&port
->lock
, flags
);
454 static void s3c24xx_serial_shutdown(struct uart_port
*port
)
456 struct s3c24xx_uart_port
*ourport
= to_ourport(port
);
458 if (ourport
->tx_claimed
) {
459 if (!s3c24xx_serial_has_interrupt_mask(port
))
460 free_irq(ourport
->tx_irq
, ourport
);
461 tx_enabled(port
) = 0;
462 ourport
->tx_claimed
= 0;
465 if (ourport
->rx_claimed
) {
466 if (!s3c24xx_serial_has_interrupt_mask(port
))
467 free_irq(ourport
->rx_irq
, ourport
);
468 ourport
->rx_claimed
= 0;
469 rx_enabled(port
) = 0;
472 /* Clear pending interrupts and mask all interrupts */
473 if (s3c24xx_serial_has_interrupt_mask(port
)) {
474 free_irq(port
->irq
, ourport
);
476 wr_regl(port
, S3C64XX_UINTP
, 0xf);
477 wr_regl(port
, S3C64XX_UINTM
, 0xf);
481 static int s3c24xx_serial_startup(struct uart_port
*port
)
483 struct s3c24xx_uart_port
*ourport
= to_ourport(port
);
486 dbg("s3c24xx_serial_startup: port=%p (%08llx,%p)\n",
487 port
, (unsigned long long)port
->mapbase
, port
->membase
);
489 rx_enabled(port
) = 1;
491 ret
= request_irq(ourport
->rx_irq
, s3c24xx_serial_rx_chars
, 0,
492 s3c24xx_serial_portname(port
), ourport
);
495 dev_err(port
->dev
, "cannot get irq %d\n", ourport
->rx_irq
);
499 ourport
->rx_claimed
= 1;
501 dbg("requesting tx irq...\n");
503 tx_enabled(port
) = 1;
505 ret
= request_irq(ourport
->tx_irq
, s3c24xx_serial_tx_chars
, 0,
506 s3c24xx_serial_portname(port
), ourport
);
509 dev_err(port
->dev
, "cannot get irq %d\n", ourport
->tx_irq
);
513 ourport
->tx_claimed
= 1;
515 dbg("s3c24xx_serial_startup ok\n");
517 /* the port reset code should have done the correct
518 * register setup for the port controls */
523 s3c24xx_serial_shutdown(port
);
527 static int s3c64xx_serial_startup(struct uart_port
*port
)
529 struct s3c24xx_uart_port
*ourport
= to_ourport(port
);
532 dbg("s3c64xx_serial_startup: port=%p (%08llx,%p)\n",
533 port
, (unsigned long long)port
->mapbase
, port
->membase
);
535 wr_regl(port
, S3C64XX_UINTM
, 0xf);
537 ret
= request_irq(port
->irq
, s3c64xx_serial_handle_irq
, IRQF_SHARED
,
538 s3c24xx_serial_portname(port
), ourport
);
540 dev_err(port
->dev
, "cannot get irq %d\n", port
->irq
);
544 /* For compatibility with s3c24xx Soc's */
545 rx_enabled(port
) = 1;
546 ourport
->rx_claimed
= 1;
547 tx_enabled(port
) = 0;
548 ourport
->tx_claimed
= 1;
550 /* Enable Rx Interrupt */
551 __clear_bit(S3C64XX_UINTM_RXD
, portaddrl(port
, S3C64XX_UINTM
));
552 dbg("s3c64xx_serial_startup ok\n");
556 /* power power management control */
558 static void s3c24xx_serial_pm(struct uart_port
*port
, unsigned int level
,
561 struct s3c24xx_uart_port
*ourport
= to_ourport(port
);
563 ourport
->pm_level
= level
;
567 if (!IS_ERR(ourport
->baudclk
))
568 clk_disable_unprepare(ourport
->baudclk
);
570 clk_disable_unprepare(ourport
->clk
);
574 clk_prepare_enable(ourport
->clk
);
576 if (!IS_ERR(ourport
->baudclk
))
577 clk_prepare_enable(ourport
->baudclk
);
581 dev_err(port
->dev
, "s3c24xx_serial: unknown pm %d\n", level
);
585 /* baud rate calculation
587 * The UARTs on the S3C2410/S3C2440 can take their clocks from a number
588 * of different sources, including the peripheral clock ("pclk") and an
589 * external clock ("uclk"). The S3C2440 also adds the core clock ("fclk")
590 * with a programmable extra divisor.
592 * The following code goes through the clock sources, and calculates the
593 * baud clocks (and the resultant actual baud rates) and then tries to
594 * pick the closest one and select that.
598 #define MAX_CLK_NAME_LENGTH 15
600 static inline int s3c24xx_serial_getsource(struct uart_port
*port
)
602 struct s3c24xx_uart_info
*info
= s3c24xx_port_to_info(port
);
605 if (info
->num_clks
== 1)
608 ucon
= rd_regl(port
, S3C2410_UCON
);
609 ucon
&= info
->clksel_mask
;
610 return ucon
>> info
->clksel_shift
;
613 static void s3c24xx_serial_setsource(struct uart_port
*port
,
614 unsigned int clk_sel
)
616 struct s3c24xx_uart_info
*info
= s3c24xx_port_to_info(port
);
619 if (info
->num_clks
== 1)
622 ucon
= rd_regl(port
, S3C2410_UCON
);
623 if ((ucon
& info
->clksel_mask
) >> info
->clksel_shift
== clk_sel
)
626 ucon
&= ~info
->clksel_mask
;
627 ucon
|= clk_sel
<< info
->clksel_shift
;
628 wr_regl(port
, S3C2410_UCON
, ucon
);
631 static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port
*ourport
,
632 unsigned int req_baud
, struct clk
**best_clk
,
633 unsigned int *clk_num
)
635 struct s3c24xx_uart_info
*info
= ourport
->info
;
638 unsigned int cnt
, baud
, quot
, clk_sel
, best_quot
= 0;
639 char clkname
[MAX_CLK_NAME_LENGTH
];
640 int calc_deviation
, deviation
= (1 << 30) - 1;
642 clk_sel
= (ourport
->cfg
->clk_sel
) ? ourport
->cfg
->clk_sel
:
643 ourport
->info
->def_clk_sel
;
644 for (cnt
= 0; cnt
< info
->num_clks
; cnt
++) {
645 if (!(clk_sel
& (1 << cnt
)))
648 sprintf(clkname
, "clk_uart_baud%d", cnt
);
649 clk
= clk_get(ourport
->port
.dev
, clkname
);
653 rate
= clk_get_rate(clk
);
657 if (ourport
->info
->has_divslot
) {
658 unsigned long div
= rate
/ req_baud
;
660 /* The UDIVSLOT register on the newer UARTs allows us to
661 * get a divisor adjustment of 1/16th on the baud clock.
663 * We don't keep the UDIVSLOT value (the 16ths we
664 * calculated by not multiplying the baud by 16) as it
665 * is easy enough to recalculate.
671 quot
= (rate
+ (8 * req_baud
)) / (16 * req_baud
);
672 baud
= rate
/ (quot
* 16);
676 calc_deviation
= req_baud
- baud
;
677 if (calc_deviation
< 0)
678 calc_deviation
= -calc_deviation
;
680 if (calc_deviation
< deviation
) {
684 deviation
= calc_deviation
;
693 * This table takes the fractional value of the baud divisor and gives
694 * the recommended setting for the UDIVSLOT register.
696 static u16 udivslot_table
[16] = {
715 static void s3c24xx_serial_set_termios(struct uart_port
*port
,
716 struct ktermios
*termios
,
717 struct ktermios
*old
)
719 struct s3c2410_uartcfg
*cfg
= s3c24xx_port_to_cfg(port
);
720 struct s3c24xx_uart_port
*ourport
= to_ourport(port
);
721 struct clk
*clk
= ERR_PTR(-EINVAL
);
723 unsigned int baud
, quot
, clk_sel
= 0;
726 unsigned int udivslot
= 0;
729 * We don't support modem control lines.
731 termios
->c_cflag
&= ~(HUPCL
| CMSPAR
);
732 termios
->c_cflag
|= CLOCAL
;
735 * Ask the core to calculate the divisor for us.
738 baud
= uart_get_baud_rate(port
, termios
, old
, 0, 115200*8);
739 quot
= s3c24xx_serial_getclk(ourport
, baud
, &clk
, &clk_sel
);
740 if (baud
== 38400 && (port
->flags
& UPF_SPD_MASK
) == UPF_SPD_CUST
)
741 quot
= port
->custom_divisor
;
745 /* check to see if we need to change clock source */
747 if (ourport
->baudclk
!= clk
) {
748 s3c24xx_serial_setsource(port
, clk_sel
);
750 if (!IS_ERR(ourport
->baudclk
)) {
751 clk_disable_unprepare(ourport
->baudclk
);
752 ourport
->baudclk
= ERR_PTR(-EINVAL
);
755 clk_prepare_enable(clk
);
757 ourport
->baudclk
= clk
;
758 ourport
->baudclk_rate
= clk
? clk_get_rate(clk
) : 0;
761 if (ourport
->info
->has_divslot
) {
762 unsigned int div
= ourport
->baudclk_rate
/ baud
;
764 if (cfg
->has_fracval
) {
765 udivslot
= (div
& 15);
766 dbg("fracval = %04x\n", udivslot
);
768 udivslot
= udivslot_table
[div
& 15];
769 dbg("udivslot = %04x (div %d)\n", udivslot
, div
& 15);
773 switch (termios
->c_cflag
& CSIZE
) {
775 dbg("config: 5bits/char\n");
776 ulcon
= S3C2410_LCON_CS5
;
779 dbg("config: 6bits/char\n");
780 ulcon
= S3C2410_LCON_CS6
;
783 dbg("config: 7bits/char\n");
784 ulcon
= S3C2410_LCON_CS7
;
788 dbg("config: 8bits/char\n");
789 ulcon
= S3C2410_LCON_CS8
;
793 /* preserve original lcon IR settings */
794 ulcon
|= (cfg
->ulcon
& S3C2410_LCON_IRM
);
796 if (termios
->c_cflag
& CSTOPB
)
797 ulcon
|= S3C2410_LCON_STOPB
;
799 if (termios
->c_cflag
& PARENB
) {
800 if (termios
->c_cflag
& PARODD
)
801 ulcon
|= S3C2410_LCON_PODD
;
803 ulcon
|= S3C2410_LCON_PEVEN
;
805 ulcon
|= S3C2410_LCON_PNONE
;
808 spin_lock_irqsave(&port
->lock
, flags
);
810 dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
811 ulcon
, quot
, udivslot
);
813 wr_regl(port
, S3C2410_ULCON
, ulcon
);
814 wr_regl(port
, S3C2410_UBRDIV
, quot
);
816 umcon
= rd_regl(port
, S3C2410_UMCON
);
817 if (termios
->c_cflag
& CRTSCTS
) {
818 umcon
|= S3C2410_UMCOM_AFC
;
819 /* Disable RTS when RX FIFO contains 63 bytes */
820 umcon
&= ~S3C2412_UMCON_AFC_8
;
822 umcon
&= ~S3C2410_UMCOM_AFC
;
824 wr_regl(port
, S3C2410_UMCON
, umcon
);
826 if (ourport
->info
->has_divslot
)
827 wr_regl(port
, S3C2443_DIVSLOT
, udivslot
);
829 dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
830 rd_regl(port
, S3C2410_ULCON
),
831 rd_regl(port
, S3C2410_UCON
),
832 rd_regl(port
, S3C2410_UFCON
));
835 * Update the per-port timeout.
837 uart_update_timeout(port
, termios
->c_cflag
, baud
);
840 * Which character status flags are we interested in?
842 port
->read_status_mask
= S3C2410_UERSTAT_OVERRUN
;
843 if (termios
->c_iflag
& INPCK
)
844 port
->read_status_mask
|= S3C2410_UERSTAT_FRAME
| S3C2410_UERSTAT_PARITY
;
847 * Which character status flags should we ignore?
849 port
->ignore_status_mask
= 0;
850 if (termios
->c_iflag
& IGNPAR
)
851 port
->ignore_status_mask
|= S3C2410_UERSTAT_OVERRUN
;
852 if (termios
->c_iflag
& IGNBRK
&& termios
->c_iflag
& IGNPAR
)
853 port
->ignore_status_mask
|= S3C2410_UERSTAT_FRAME
;
856 * Ignore all characters if CREAD is not set.
858 if ((termios
->c_cflag
& CREAD
) == 0)
859 port
->ignore_status_mask
|= RXSTAT_DUMMY_READ
;
861 spin_unlock_irqrestore(&port
->lock
, flags
);
864 static const char *s3c24xx_serial_type(struct uart_port
*port
)
866 switch (port
->type
) {
880 #define MAP_SIZE (0x100)
882 static void s3c24xx_serial_release_port(struct uart_port
*port
)
884 release_mem_region(port
->mapbase
, MAP_SIZE
);
887 static int s3c24xx_serial_request_port(struct uart_port
*port
)
889 const char *name
= s3c24xx_serial_portname(port
);
890 return request_mem_region(port
->mapbase
, MAP_SIZE
, name
) ? 0 : -EBUSY
;
893 static void s3c24xx_serial_config_port(struct uart_port
*port
, int flags
)
895 struct s3c24xx_uart_info
*info
= s3c24xx_port_to_info(port
);
897 if (flags
& UART_CONFIG_TYPE
&&
898 s3c24xx_serial_request_port(port
) == 0)
899 port
->type
= info
->type
;
903 * verify the new serial_struct (for TIOCSSERIAL).
906 s3c24xx_serial_verify_port(struct uart_port
*port
, struct serial_struct
*ser
)
908 struct s3c24xx_uart_info
*info
= s3c24xx_port_to_info(port
);
910 if (ser
->type
!= PORT_UNKNOWN
&& ser
->type
!= info
->type
)
917 #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
919 static struct console s3c24xx_serial_console
;
921 static int __init
s3c24xx_serial_console_init(void)
923 register_console(&s3c24xx_serial_console
);
926 console_initcall(s3c24xx_serial_console_init
);
928 #define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
930 #define S3C24XX_SERIAL_CONSOLE NULL
933 #if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
934 static int s3c24xx_serial_get_poll_char(struct uart_port
*port
);
935 static void s3c24xx_serial_put_poll_char(struct uart_port
*port
,
939 static struct uart_ops s3c24xx_serial_ops
= {
940 .pm
= s3c24xx_serial_pm
,
941 .tx_empty
= s3c24xx_serial_tx_empty
,
942 .get_mctrl
= s3c24xx_serial_get_mctrl
,
943 .set_mctrl
= s3c24xx_serial_set_mctrl
,
944 .stop_tx
= s3c24xx_serial_stop_tx
,
945 .start_tx
= s3c24xx_serial_start_tx
,
946 .stop_rx
= s3c24xx_serial_stop_rx
,
947 .break_ctl
= s3c24xx_serial_break_ctl
,
948 .startup
= s3c24xx_serial_startup
,
949 .shutdown
= s3c24xx_serial_shutdown
,
950 .set_termios
= s3c24xx_serial_set_termios
,
951 .type
= s3c24xx_serial_type
,
952 .release_port
= s3c24xx_serial_release_port
,
953 .request_port
= s3c24xx_serial_request_port
,
954 .config_port
= s3c24xx_serial_config_port
,
955 .verify_port
= s3c24xx_serial_verify_port
,
956 #if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
957 .poll_get_char
= s3c24xx_serial_get_poll_char
,
958 .poll_put_char
= s3c24xx_serial_put_poll_char
,
962 static struct uart_driver s3c24xx_uart_drv
= {
963 .owner
= THIS_MODULE
,
964 .driver_name
= "s3c2410_serial",
965 .nr
= CONFIG_SERIAL_SAMSUNG_UARTS
,
966 .cons
= S3C24XX_SERIAL_CONSOLE
,
967 .dev_name
= S3C24XX_SERIAL_NAME
,
968 .major
= S3C24XX_SERIAL_MAJOR
,
969 .minor
= S3C24XX_SERIAL_MINOR
,
972 static struct s3c24xx_uart_port s3c24xx_serial_ports
[CONFIG_SERIAL_SAMSUNG_UARTS
] = {
975 .lock
= __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports
[0].port
.lock
),
979 .ops
= &s3c24xx_serial_ops
,
980 .flags
= UPF_BOOT_AUTOCONF
,
986 .lock
= __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports
[1].port
.lock
),
990 .ops
= &s3c24xx_serial_ops
,
991 .flags
= UPF_BOOT_AUTOCONF
,
995 #if CONFIG_SERIAL_SAMSUNG_UARTS > 2
999 .lock
= __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports
[2].port
.lock
),
1003 .ops
= &s3c24xx_serial_ops
,
1004 .flags
= UPF_BOOT_AUTOCONF
,
1009 #if CONFIG_SERIAL_SAMSUNG_UARTS > 3
1012 .lock
= __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports
[3].port
.lock
),
1016 .ops
= &s3c24xx_serial_ops
,
1017 .flags
= UPF_BOOT_AUTOCONF
,
1024 /* s3c24xx_serial_resetport
1026 * reset the fifos and other the settings.
1029 static void s3c24xx_serial_resetport(struct uart_port
*port
,
1030 struct s3c2410_uartcfg
*cfg
)
1032 struct s3c24xx_uart_info
*info
= s3c24xx_port_to_info(port
);
1033 unsigned long ucon
= rd_regl(port
, S3C2410_UCON
);
1034 unsigned int ucon_mask
;
1036 ucon_mask
= info
->clksel_mask
;
1037 if (info
->type
== PORT_S3C2440
)
1038 ucon_mask
|= S3C2440_UCON0_DIVMASK
;
1041 wr_regl(port
, S3C2410_UCON
, ucon
| cfg
->ucon
);
1043 /* reset both fifos */
1044 wr_regl(port
, S3C2410_UFCON
, cfg
->ufcon
| S3C2410_UFCON_RESETBOTH
);
1045 wr_regl(port
, S3C2410_UFCON
, cfg
->ufcon
);
1047 /* some delay is required after fifo reset */
1052 #ifdef CONFIG_CPU_FREQ
1054 static int s3c24xx_serial_cpufreq_transition(struct notifier_block
*nb
,
1055 unsigned long val
, void *data
)
1057 struct s3c24xx_uart_port
*port
;
1058 struct uart_port
*uport
;
1060 port
= container_of(nb
, struct s3c24xx_uart_port
, freq_transition
);
1061 uport
= &port
->port
;
1063 /* check to see if port is enabled */
1065 if (port
->pm_level
!= 0)
1068 /* try and work out if the baudrate is changing, we can detect
1069 * a change in rate, but we do not have support for detecting
1070 * a disturbance in the clock-rate over the change.
1073 if (IS_ERR(port
->baudclk
))
1076 if (port
->baudclk_rate
== clk_get_rate(port
->baudclk
))
1079 if (val
== CPUFREQ_PRECHANGE
) {
1080 /* we should really shut the port down whilst the
1081 * frequency change is in progress. */
1083 } else if (val
== CPUFREQ_POSTCHANGE
) {
1084 struct ktermios
*termios
;
1085 struct tty_struct
*tty
;
1087 if (uport
->state
== NULL
)
1090 tty
= uport
->state
->port
.tty
;
1095 termios
= &tty
->termios
;
1097 if (termios
== NULL
) {
1098 dev_warn(uport
->dev
, "%s: no termios?\n", __func__
);
1102 s3c24xx_serial_set_termios(uport
, termios
, NULL
);
1109 static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port
*port
)
1111 port
->freq_transition
.notifier_call
= s3c24xx_serial_cpufreq_transition
;
1113 return cpufreq_register_notifier(&port
->freq_transition
,
1114 CPUFREQ_TRANSITION_NOTIFIER
);
1117 static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port
*port
)
1119 cpufreq_unregister_notifier(&port
->freq_transition
,
1120 CPUFREQ_TRANSITION_NOTIFIER
);
1124 static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port
*port
)
1129 static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port
*port
)
1134 /* s3c24xx_serial_init_port
1136 * initialise a single serial port from the platform device given
1139 static int s3c24xx_serial_init_port(struct s3c24xx_uart_port
*ourport
,
1140 struct platform_device
*platdev
)
1142 struct uart_port
*port
= &ourport
->port
;
1143 struct s3c2410_uartcfg
*cfg
= ourport
->cfg
;
1144 struct resource
*res
;
1147 dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port
, platdev
);
1149 if (platdev
== NULL
)
1152 if (port
->mapbase
!= 0)
1155 /* setup info for port */
1156 port
->dev
= &platdev
->dev
;
1158 /* Startup sequence is different for s3c64xx and higher SoC's */
1159 if (s3c24xx_serial_has_interrupt_mask(port
))
1160 s3c24xx_serial_ops
.startup
= s3c64xx_serial_startup
;
1164 if (cfg
->uart_flags
& UPF_CONS_FLOW
) {
1165 dbg("s3c24xx_serial_init_port: enabling flow control\n");
1166 port
->flags
|= UPF_CONS_FLOW
;
1169 /* sort our the physical and virtual addresses for each UART */
1171 res
= platform_get_resource(platdev
, IORESOURCE_MEM
, 0);
1173 dev_err(port
->dev
, "failed to find memory resource for uart\n");
1177 dbg("resource %pR)\n", res
);
1179 port
->membase
= devm_ioremap(port
->dev
, res
->start
, resource_size(res
));
1180 if (!port
->membase
) {
1181 dev_err(port
->dev
, "failed to remap controller address\n");
1185 port
->mapbase
= res
->start
;
1186 ret
= platform_get_irq(platdev
, 0);
1191 ourport
->rx_irq
= ret
;
1192 ourport
->tx_irq
= ret
+ 1;
1195 ret
= platform_get_irq(platdev
, 1);
1197 ourport
->tx_irq
= ret
;
1199 ourport
->clk
= clk_get(&platdev
->dev
, "uart");
1200 if (IS_ERR(ourport
->clk
)) {
1201 pr_err("%s: Controller clock not found\n",
1202 dev_name(&platdev
->dev
));
1203 return PTR_ERR(ourport
->clk
);
1206 ret
= clk_prepare_enable(ourport
->clk
);
1208 pr_err("uart: clock failed to prepare+enable: %d\n", ret
);
1209 clk_put(ourport
->clk
);
1213 /* Keep all interrupts masked and cleared */
1214 if (s3c24xx_serial_has_interrupt_mask(port
)) {
1215 wr_regl(port
, S3C64XX_UINTM
, 0xf);
1216 wr_regl(port
, S3C64XX_UINTP
, 0xf);
1217 wr_regl(port
, S3C64XX_UINTSP
, 0xf);
1220 dbg("port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n",
1221 &port
->mapbase
, port
->membase
, port
->irq
,
1222 ourport
->rx_irq
, ourport
->tx_irq
, port
->uartclk
);
1224 /* reset the fifos (and setup the uart) */
1225 s3c24xx_serial_resetport(port
, cfg
);
1229 #ifdef CONFIG_SAMSUNG_CLOCK
1230 static ssize_t
s3c24xx_serial_show_clksrc(struct device
*dev
,
1231 struct device_attribute
*attr
,
1234 struct uart_port
*port
= s3c24xx_dev_to_port(dev
);
1235 struct s3c24xx_uart_port
*ourport
= to_ourport(port
);
1237 if (IS_ERR(ourport
->baudclk
))
1240 return snprintf(buf
, PAGE_SIZE
, "* %s\n",
1241 ourport
->baudclk
->name
?: "(null)");
1244 static DEVICE_ATTR(clock_source
, S_IRUGO
, s3c24xx_serial_show_clksrc
, NULL
);
1247 /* Device driver serial port probe */
1249 static const struct of_device_id s3c24xx_uart_dt_match
[];
1250 static int probe_index
;
1252 static inline struct s3c24xx_serial_drv_data
*s3c24xx_get_driver_data(
1253 struct platform_device
*pdev
)
1256 if (pdev
->dev
.of_node
) {
1257 const struct of_device_id
*match
;
1258 match
= of_match_node(s3c24xx_uart_dt_match
, pdev
->dev
.of_node
);
1259 return (struct s3c24xx_serial_drv_data
*)match
->data
;
1262 return (struct s3c24xx_serial_drv_data
*)
1263 platform_get_device_id(pdev
)->driver_data
;
1266 static int s3c24xx_serial_probe(struct platform_device
*pdev
)
1268 struct device_node
*np
= pdev
->dev
.of_node
;
1269 struct s3c24xx_uart_port
*ourport
;
1270 int index
= probe_index
;
1274 ret
= of_alias_get_id(np
, "serial");
1279 dbg("s3c24xx_serial_probe(%p) %d\n", pdev
, index
);
1281 ourport
= &s3c24xx_serial_ports
[index
];
1283 ourport
->drv_data
= s3c24xx_get_driver_data(pdev
);
1284 if (!ourport
->drv_data
) {
1285 dev_err(&pdev
->dev
, "could not find driver data\n");
1289 ourport
->baudclk
= ERR_PTR(-EINVAL
);
1290 ourport
->info
= ourport
->drv_data
->info
;
1291 ourport
->cfg
= (dev_get_platdata(&pdev
->dev
)) ?
1292 dev_get_platdata(&pdev
->dev
) :
1293 ourport
->drv_data
->def_cfg
;
1296 of_property_read_u32(np
,
1297 "samsung,uart-fifosize", &ourport
->port
.fifosize
);
1299 if (!ourport
->port
.fifosize
) {
1300 ourport
->port
.fifosize
= (ourport
->info
->fifosize
) ?
1301 ourport
->info
->fifosize
:
1302 ourport
->drv_data
->fifosize
[index
];
1307 dbg("%s: initialising port %p...\n", __func__
, ourport
);
1309 ret
= s3c24xx_serial_init_port(ourport
, pdev
);
1313 if (!s3c24xx_uart_drv
.state
) {
1314 ret
= uart_register_driver(&s3c24xx_uart_drv
);
1316 pr_err("Failed to register Samsung UART driver\n");
1321 dbg("%s: adding port\n", __func__
);
1322 uart_add_one_port(&s3c24xx_uart_drv
, &ourport
->port
);
1323 platform_set_drvdata(pdev
, &ourport
->port
);
1326 * Deactivate the clock enabled in s3c24xx_serial_init_port here,
1327 * so that a potential re-enablement through the pm-callback overlaps
1328 * and keeps the clock enabled in this case.
1330 clk_disable_unprepare(ourport
->clk
);
1332 #ifdef CONFIG_SAMSUNG_CLOCK
1333 ret
= device_create_file(&pdev
->dev
, &dev_attr_clock_source
);
1335 dev_err(&pdev
->dev
, "failed to add clock source attr.\n");
1338 ret
= s3c24xx_serial_cpufreq_register(ourport
);
1340 dev_err(&pdev
->dev
, "failed to add cpufreq notifier\n");
1345 static int s3c24xx_serial_remove(struct platform_device
*dev
)
1347 struct uart_port
*port
= s3c24xx_dev_to_port(&dev
->dev
);
1350 s3c24xx_serial_cpufreq_deregister(to_ourport(port
));
1351 #ifdef CONFIG_SAMSUNG_CLOCK
1352 device_remove_file(&dev
->dev
, &dev_attr_clock_source
);
1354 uart_remove_one_port(&s3c24xx_uart_drv
, port
);
1357 uart_unregister_driver(&s3c24xx_uart_drv
);
1362 /* UART power management code */
1363 #ifdef CONFIG_PM_SLEEP
1364 static int s3c24xx_serial_suspend(struct device
*dev
)
1366 struct uart_port
*port
= s3c24xx_dev_to_port(dev
);
1369 uart_suspend_port(&s3c24xx_uart_drv
, port
);
1374 static int s3c24xx_serial_resume(struct device
*dev
)
1376 struct uart_port
*port
= s3c24xx_dev_to_port(dev
);
1377 struct s3c24xx_uart_port
*ourport
= to_ourport(port
);
1380 clk_prepare_enable(ourport
->clk
);
1381 s3c24xx_serial_resetport(port
, s3c24xx_port_to_cfg(port
));
1382 clk_disable_unprepare(ourport
->clk
);
1384 uart_resume_port(&s3c24xx_uart_drv
, port
);
1390 static int s3c24xx_serial_resume_noirq(struct device
*dev
)
1392 struct uart_port
*port
= s3c24xx_dev_to_port(dev
);
1395 /* restore IRQ mask */
1396 if (s3c24xx_serial_has_interrupt_mask(port
)) {
1397 unsigned int uintm
= 0xf;
1398 if (tx_enabled(port
))
1399 uintm
&= ~S3C64XX_UINTM_TXD_MSK
;
1400 if (rx_enabled(port
))
1401 uintm
&= ~S3C64XX_UINTM_RXD_MSK
;
1402 wr_regl(port
, S3C64XX_UINTM
, uintm
);
1409 static const struct dev_pm_ops s3c24xx_serial_pm_ops
= {
1410 .suspend
= s3c24xx_serial_suspend
,
1411 .resume
= s3c24xx_serial_resume
,
1412 .resume_noirq
= s3c24xx_serial_resume_noirq
,
1414 #define SERIAL_SAMSUNG_PM_OPS (&s3c24xx_serial_pm_ops)
1416 #else /* !CONFIG_PM_SLEEP */
1418 #define SERIAL_SAMSUNG_PM_OPS NULL
1419 #endif /* CONFIG_PM_SLEEP */
1423 #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
1425 static struct uart_port
*cons_uart
;
1428 s3c24xx_serial_console_txrdy(struct uart_port
*port
, unsigned int ufcon
)
1430 struct s3c24xx_uart_info
*info
= s3c24xx_port_to_info(port
);
1431 unsigned long ufstat
, utrstat
;
1433 if (ufcon
& S3C2410_UFCON_FIFOMODE
) {
1434 /* fifo mode - check amount of data in fifo registers... */
1436 ufstat
= rd_regl(port
, S3C2410_UFSTAT
);
1437 return (ufstat
& info
->tx_fifofull
) ? 0 : 1;
1440 /* in non-fifo mode, we go and use the tx buffer empty */
1442 utrstat
= rd_regl(port
, S3C2410_UTRSTAT
);
1443 return (utrstat
& S3C2410_UTRSTAT_TXE
) ? 1 : 0;
1447 s3c24xx_port_configured(unsigned int ucon
)
1449 /* consider the serial port configured if the tx/rx mode set */
1450 return (ucon
& 0xf) != 0;
1453 #ifdef CONFIG_CONSOLE_POLL
1455 * Console polling routines for writing and reading from the uart while
1456 * in an interrupt or debug context.
1459 static int s3c24xx_serial_get_poll_char(struct uart_port
*port
)
1461 struct s3c24xx_uart_port
*ourport
= to_ourport(port
);
1462 unsigned int ufstat
;
1464 ufstat
= rd_regl(port
, S3C2410_UFSTAT
);
1465 if (s3c24xx_serial_rx_fifocnt(ourport
, ufstat
) == 0)
1466 return NO_POLL_CHAR
;
1468 return rd_regb(port
, S3C2410_URXH
);
1471 static void s3c24xx_serial_put_poll_char(struct uart_port
*port
,
1474 unsigned int ufcon
= rd_regl(port
, S3C2410_UFCON
);
1475 unsigned int ucon
= rd_regl(port
, S3C2410_UCON
);
1477 /* not possible to xmit on unconfigured port */
1478 if (!s3c24xx_port_configured(ucon
))
1481 while (!s3c24xx_serial_console_txrdy(port
, ufcon
))
1483 wr_regb(port
, S3C2410_UTXH
, c
);
1486 #endif /* CONFIG_CONSOLE_POLL */
1489 s3c24xx_serial_console_putchar(struct uart_port
*port
, int ch
)
1491 unsigned int ufcon
= rd_regl(port
, S3C2410_UFCON
);
1493 while (!s3c24xx_serial_console_txrdy(port
, ufcon
))
1495 wr_regb(port
, S3C2410_UTXH
, ch
);
1499 s3c24xx_serial_console_write(struct console
*co
, const char *s
,
1502 unsigned int ucon
= rd_regl(cons_uart
, S3C2410_UCON
);
1504 /* not possible to xmit on unconfigured port */
1505 if (!s3c24xx_port_configured(ucon
))
1508 uart_console_write(cons_uart
, s
, count
, s3c24xx_serial_console_putchar
);
1512 s3c24xx_serial_get_options(struct uart_port
*port
, int *baud
,
1513 int *parity
, int *bits
)
1518 unsigned int ubrdiv
;
1520 unsigned int clk_sel
;
1521 char clk_name
[MAX_CLK_NAME_LENGTH
];
1523 ulcon
= rd_regl(port
, S3C2410_ULCON
);
1524 ucon
= rd_regl(port
, S3C2410_UCON
);
1525 ubrdiv
= rd_regl(port
, S3C2410_UBRDIV
);
1527 dbg("s3c24xx_serial_get_options: port=%p\n"
1528 "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
1529 port
, ulcon
, ucon
, ubrdiv
);
1531 if (s3c24xx_port_configured(ucon
)) {
1532 switch (ulcon
& S3C2410_LCON_CSMASK
) {
1533 case S3C2410_LCON_CS5
:
1536 case S3C2410_LCON_CS6
:
1539 case S3C2410_LCON_CS7
:
1542 case S3C2410_LCON_CS8
:
1548 switch (ulcon
& S3C2410_LCON_PMASK
) {
1549 case S3C2410_LCON_PEVEN
:
1553 case S3C2410_LCON_PODD
:
1557 case S3C2410_LCON_PNONE
:
1562 /* now calculate the baud rate */
1564 clk_sel
= s3c24xx_serial_getsource(port
);
1565 sprintf(clk_name
, "clk_uart_baud%d", clk_sel
);
1567 clk
= clk_get(port
->dev
, clk_name
);
1569 rate
= clk_get_rate(clk
);
1573 *baud
= rate
/ (16 * (ubrdiv
+ 1));
1574 dbg("calculated baud %d\n", *baud
);
1580 s3c24xx_serial_console_setup(struct console
*co
, char *options
)
1582 struct uart_port
*port
;
1588 dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n",
1589 co
, co
->index
, options
);
1591 /* is this a valid port */
1593 if (co
->index
== -1 || co
->index
>= CONFIG_SERIAL_SAMSUNG_UARTS
)
1596 port
= &s3c24xx_serial_ports
[co
->index
].port
;
1598 /* is the port configured? */
1600 if (port
->mapbase
== 0x0)
1605 dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port
, co
->index
);
1608 * Check whether an invalid uart number has been specified, and
1609 * if so, search for the first available port that does have
1613 uart_parse_options(options
, &baud
, &parity
, &bits
, &flow
);
1615 s3c24xx_serial_get_options(port
, &baud
, &parity
, &bits
);
1617 dbg("s3c24xx_serial_console_setup: baud %d\n", baud
);
1619 return uart_set_options(port
, co
, baud
, parity
, bits
, flow
);
1622 static struct console s3c24xx_serial_console
= {
1623 .name
= S3C24XX_SERIAL_NAME
,
1624 .device
= uart_console_device
,
1625 .flags
= CON_PRINTBUFFER
,
1627 .write
= s3c24xx_serial_console_write
,
1628 .setup
= s3c24xx_serial_console_setup
,
1629 .data
= &s3c24xx_uart_drv
,
1631 #endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */
1633 #ifdef CONFIG_CPU_S3C2410
1634 static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data
= {
1635 .info
= &(struct s3c24xx_uart_info
) {
1636 .name
= "Samsung S3C2410 UART",
1637 .type
= PORT_S3C2410
,
1639 .rx_fifomask
= S3C2410_UFSTAT_RXMASK
,
1640 .rx_fifoshift
= S3C2410_UFSTAT_RXSHIFT
,
1641 .rx_fifofull
= S3C2410_UFSTAT_RXFULL
,
1642 .tx_fifofull
= S3C2410_UFSTAT_TXFULL
,
1643 .tx_fifomask
= S3C2410_UFSTAT_TXMASK
,
1644 .tx_fifoshift
= S3C2410_UFSTAT_TXSHIFT
,
1645 .def_clk_sel
= S3C2410_UCON_CLKSEL0
,
1647 .clksel_mask
= S3C2410_UCON_CLKMASK
,
1648 .clksel_shift
= S3C2410_UCON_CLKSHIFT
,
1650 .def_cfg
= &(struct s3c2410_uartcfg
) {
1651 .ucon
= S3C2410_UCON_DEFAULT
,
1652 .ufcon
= S3C2410_UFCON_DEFAULT
,
1655 #define S3C2410_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2410_serial_drv_data)
1657 #define S3C2410_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1660 #ifdef CONFIG_CPU_S3C2412
1661 static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data
= {
1662 .info
= &(struct s3c24xx_uart_info
) {
1663 .name
= "Samsung S3C2412 UART",
1664 .type
= PORT_S3C2412
,
1667 .rx_fifomask
= S3C2440_UFSTAT_RXMASK
,
1668 .rx_fifoshift
= S3C2440_UFSTAT_RXSHIFT
,
1669 .rx_fifofull
= S3C2440_UFSTAT_RXFULL
,
1670 .tx_fifofull
= S3C2440_UFSTAT_TXFULL
,
1671 .tx_fifomask
= S3C2440_UFSTAT_TXMASK
,
1672 .tx_fifoshift
= S3C2440_UFSTAT_TXSHIFT
,
1673 .def_clk_sel
= S3C2410_UCON_CLKSEL2
,
1675 .clksel_mask
= S3C2412_UCON_CLKMASK
,
1676 .clksel_shift
= S3C2412_UCON_CLKSHIFT
,
1678 .def_cfg
= &(struct s3c2410_uartcfg
) {
1679 .ucon
= S3C2410_UCON_DEFAULT
,
1680 .ufcon
= S3C2410_UFCON_DEFAULT
,
1683 #define S3C2412_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2412_serial_drv_data)
1685 #define S3C2412_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1688 #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \
1689 defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2442)
1690 static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data
= {
1691 .info
= &(struct s3c24xx_uart_info
) {
1692 .name
= "Samsung S3C2440 UART",
1693 .type
= PORT_S3C2440
,
1696 .rx_fifomask
= S3C2440_UFSTAT_RXMASK
,
1697 .rx_fifoshift
= S3C2440_UFSTAT_RXSHIFT
,
1698 .rx_fifofull
= S3C2440_UFSTAT_RXFULL
,
1699 .tx_fifofull
= S3C2440_UFSTAT_TXFULL
,
1700 .tx_fifomask
= S3C2440_UFSTAT_TXMASK
,
1701 .tx_fifoshift
= S3C2440_UFSTAT_TXSHIFT
,
1702 .def_clk_sel
= S3C2410_UCON_CLKSEL2
,
1704 .clksel_mask
= S3C2412_UCON_CLKMASK
,
1705 .clksel_shift
= S3C2412_UCON_CLKSHIFT
,
1707 .def_cfg
= &(struct s3c2410_uartcfg
) {
1708 .ucon
= S3C2410_UCON_DEFAULT
,
1709 .ufcon
= S3C2410_UFCON_DEFAULT
,
1712 #define S3C2440_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2440_serial_drv_data)
1714 #define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1717 #if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
1718 static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data
= {
1719 .info
= &(struct s3c24xx_uart_info
) {
1720 .name
= "Samsung S3C6400 UART",
1721 .type
= PORT_S3C6400
,
1724 .rx_fifomask
= S3C2440_UFSTAT_RXMASK
,
1725 .rx_fifoshift
= S3C2440_UFSTAT_RXSHIFT
,
1726 .rx_fifofull
= S3C2440_UFSTAT_RXFULL
,
1727 .tx_fifofull
= S3C2440_UFSTAT_TXFULL
,
1728 .tx_fifomask
= S3C2440_UFSTAT_TXMASK
,
1729 .tx_fifoshift
= S3C2440_UFSTAT_TXSHIFT
,
1730 .def_clk_sel
= S3C2410_UCON_CLKSEL2
,
1732 .clksel_mask
= S3C6400_UCON_CLKMASK
,
1733 .clksel_shift
= S3C6400_UCON_CLKSHIFT
,
1735 .def_cfg
= &(struct s3c2410_uartcfg
) {
1736 .ucon
= S3C2410_UCON_DEFAULT
,
1737 .ufcon
= S3C2410_UFCON_DEFAULT
,
1740 #define S3C6400_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c6400_serial_drv_data)
1742 #define S3C6400_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1745 #ifdef CONFIG_CPU_S5PV210
1746 static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data
= {
1747 .info
= &(struct s3c24xx_uart_info
) {
1748 .name
= "Samsung S5PV210 UART",
1749 .type
= PORT_S3C6400
,
1751 .rx_fifomask
= S5PV210_UFSTAT_RXMASK
,
1752 .rx_fifoshift
= S5PV210_UFSTAT_RXSHIFT
,
1753 .rx_fifofull
= S5PV210_UFSTAT_RXFULL
,
1754 .tx_fifofull
= S5PV210_UFSTAT_TXFULL
,
1755 .tx_fifomask
= S5PV210_UFSTAT_TXMASK
,
1756 .tx_fifoshift
= S5PV210_UFSTAT_TXSHIFT
,
1757 .def_clk_sel
= S3C2410_UCON_CLKSEL0
,
1759 .clksel_mask
= S5PV210_UCON_CLKMASK
,
1760 .clksel_shift
= S5PV210_UCON_CLKSHIFT
,
1762 .def_cfg
= &(struct s3c2410_uartcfg
) {
1763 .ucon
= S5PV210_UCON_DEFAULT
,
1764 .ufcon
= S5PV210_UFCON_DEFAULT
,
1766 .fifosize
= { 256, 64, 16, 16 },
1768 #define S5PV210_SERIAL_DRV_DATA ((kernel_ulong_t)&s5pv210_serial_drv_data)
1770 #define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1773 #if defined(CONFIG_ARCH_EXYNOS)
1774 static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data
= {
1775 .info
= &(struct s3c24xx_uart_info
) {
1776 .name
= "Samsung Exynos4 UART",
1777 .type
= PORT_S3C6400
,
1779 .rx_fifomask
= S5PV210_UFSTAT_RXMASK
,
1780 .rx_fifoshift
= S5PV210_UFSTAT_RXSHIFT
,
1781 .rx_fifofull
= S5PV210_UFSTAT_RXFULL
,
1782 .tx_fifofull
= S5PV210_UFSTAT_TXFULL
,
1783 .tx_fifomask
= S5PV210_UFSTAT_TXMASK
,
1784 .tx_fifoshift
= S5PV210_UFSTAT_TXSHIFT
,
1785 .def_clk_sel
= S3C2410_UCON_CLKSEL0
,
1790 .def_cfg
= &(struct s3c2410_uartcfg
) {
1791 .ucon
= S5PV210_UCON_DEFAULT
,
1792 .ufcon
= S5PV210_UFCON_DEFAULT
,
1795 .fifosize
= { 256, 64, 16, 16 },
1797 #define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data)
1799 #define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1802 static struct platform_device_id s3c24xx_serial_driver_ids
[] = {
1804 .name
= "s3c2410-uart",
1805 .driver_data
= S3C2410_SERIAL_DRV_DATA
,
1807 .name
= "s3c2412-uart",
1808 .driver_data
= S3C2412_SERIAL_DRV_DATA
,
1810 .name
= "s3c2440-uart",
1811 .driver_data
= S3C2440_SERIAL_DRV_DATA
,
1813 .name
= "s3c6400-uart",
1814 .driver_data
= S3C6400_SERIAL_DRV_DATA
,
1816 .name
= "s5pv210-uart",
1817 .driver_data
= S5PV210_SERIAL_DRV_DATA
,
1819 .name
= "exynos4210-uart",
1820 .driver_data
= EXYNOS4210_SERIAL_DRV_DATA
,
1824 MODULE_DEVICE_TABLE(platform
, s3c24xx_serial_driver_ids
);
1827 static const struct of_device_id s3c24xx_uart_dt_match
[] = {
1828 { .compatible
= "samsung,s3c2410-uart",
1829 .data
= (void *)S3C2410_SERIAL_DRV_DATA
},
1830 { .compatible
= "samsung,s3c2412-uart",
1831 .data
= (void *)S3C2412_SERIAL_DRV_DATA
},
1832 { .compatible
= "samsung,s3c2440-uart",
1833 .data
= (void *)S3C2440_SERIAL_DRV_DATA
},
1834 { .compatible
= "samsung,s3c6400-uart",
1835 .data
= (void *)S3C6400_SERIAL_DRV_DATA
},
1836 { .compatible
= "samsung,s5pv210-uart",
1837 .data
= (void *)S5PV210_SERIAL_DRV_DATA
},
1838 { .compatible
= "samsung,exynos4210-uart",
1839 .data
= (void *)EXYNOS4210_SERIAL_DRV_DATA
},
1842 MODULE_DEVICE_TABLE(of
, s3c24xx_uart_dt_match
);
1845 static struct platform_driver samsung_serial_driver
= {
1846 .probe
= s3c24xx_serial_probe
,
1847 .remove
= s3c24xx_serial_remove
,
1848 .id_table
= s3c24xx_serial_driver_ids
,
1850 .name
= "samsung-uart",
1851 .owner
= THIS_MODULE
,
1852 .pm
= SERIAL_SAMSUNG_PM_OPS
,
1853 .of_match_table
= of_match_ptr(s3c24xx_uart_dt_match
),
1857 module_platform_driver(samsung_serial_driver
);
1859 MODULE_ALIAS("platform:samsung-uart");
1860 MODULE_DESCRIPTION("Samsung SoC Serial port driver");
1861 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
1862 MODULE_LICENSE("GPL v2");