serial: s3c: add missing register definitions
[linux-2.6-block.git] / drivers / tty / serial / samsung.c
CommitLineData
99edb3d1 1/*
b497549a
BD
2 * Driver core for Samsung SoC onboard UARTs.
3 *
ccae941e 4 * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
b497549a
BD
5 * http://armlinux.simtec.co.uk/
6 *
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.
10*/
11
12/* Hote on 2410 error handling
13 *
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.
19 *
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
23 *
24 * BJD, 04-Nov-2004
25*/
26
27#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
28#define SUPPORT_SYSRQ
29#endif
30
31#include <linux/module.h>
32#include <linux/ioport.h>
33#include <linux/io.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>
9ee51f01 42#include <linux/serial_s3c.h>
b497549a
BD
43#include <linux/delay.h>
44#include <linux/clk.h>
30555476 45#include <linux/cpufreq.h>
26c919e1 46#include <linux/of.h>
b497549a
BD
47
48#include <asm/irq.h>
49
b497549a
BD
50#include "samsung.h"
51
e4ac92df
JP
52#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \
53 defined(CONFIG_DEBUG_LL) && \
54 !defined(MODULE)
55
56extern void printascii(const char *);
57
58__printf(1, 2)
59static void dbg(const char *fmt, ...)
60{
61 va_list va;
62 char buff[256];
63
64 va_start(va, fmt);
a859c8b2 65 vscnprintf(buff, sizeof(buff), fmt, va);
e4ac92df
JP
66 va_end(va);
67
68 printascii(buff);
69}
70
71#else
72#define dbg(fmt, ...) do { if (0) no_printk(fmt, ##__VA_ARGS__); } while (0)
73#endif
74
b497549a
BD
75/* UART name and device definitions */
76
77#define S3C24XX_SERIAL_NAME "ttySAC"
78#define S3C24XX_SERIAL_MAJOR 204
79#define S3C24XX_SERIAL_MINOR 64
80
b497549a
BD
81/* macros to change one thing to another */
82
83#define tx_enabled(port) ((port)->unused[0])
84#define rx_enabled(port) ((port)->unused[1])
85
25985edc 86/* flag to ignore all characters coming in */
b497549a
BD
87#define RXSTAT_DUMMY_READ (0x10000000)
88
89static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port)
90{
91 return container_of(port, struct s3c24xx_uart_port, port);
92}
93
94/* translate a port to the device name */
95
96static inline const char *s3c24xx_serial_portname(struct uart_port *port)
97{
98 return to_platform_device(port->dev)->name;
99}
100
101static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
102{
9303ac15 103 return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;
b497549a
BD
104}
105
88bb4ea1
TA
106/*
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.
110 */
111static int s3c24xx_serial_has_interrupt_mask(struct uart_port *port)
112{
113 return to_ourport(port)->info->type == PORT_S3C6400;
114}
115
b497549a
BD
116static void s3c24xx_serial_rx_enable(struct uart_port *port)
117{
118 unsigned long flags;
119 unsigned int ucon, ufcon;
120 int count = 10000;
121
122 spin_lock_irqsave(&port->lock, flags);
123
124 while (--count && !s3c24xx_serial_txempty_nofifo(port))
125 udelay(100);
126
127 ufcon = rd_regl(port, S3C2410_UFCON);
128 ufcon |= S3C2410_UFCON_RESETRX;
129 wr_regl(port, S3C2410_UFCON, ufcon);
130
131 ucon = rd_regl(port, S3C2410_UCON);
132 ucon |= S3C2410_UCON_RXIRQMODE;
133 wr_regl(port, S3C2410_UCON, ucon);
134
135 rx_enabled(port) = 1;
136 spin_unlock_irqrestore(&port->lock, flags);
137}
138
139static void s3c24xx_serial_rx_disable(struct uart_port *port)
140{
141 unsigned long flags;
142 unsigned int ucon;
143
144 spin_lock_irqsave(&port->lock, flags);
145
146 ucon = rd_regl(port, S3C2410_UCON);
147 ucon &= ~S3C2410_UCON_RXIRQMODE;
148 wr_regl(port, S3C2410_UCON, ucon);
149
150 rx_enabled(port) = 0;
151 spin_unlock_irqrestore(&port->lock, flags);
152}
153
154static void s3c24xx_serial_stop_tx(struct uart_port *port)
155{
b73c289c
BD
156 struct s3c24xx_uart_port *ourport = to_ourport(port);
157
b497549a 158 if (tx_enabled(port)) {
88bb4ea1
TA
159 if (s3c24xx_serial_has_interrupt_mask(port))
160 __set_bit(S3C64XX_UINTM_TXD,
161 portaddrl(port, S3C64XX_UINTM));
162 else
163 disable_irq_nosync(ourport->tx_irq);
b497549a
BD
164 tx_enabled(port) = 0;
165 if (port->flags & UPF_CONS_FLOW)
166 s3c24xx_serial_rx_enable(port);
167 }
168}
169
170static void s3c24xx_serial_start_tx(struct uart_port *port)
171{
b73c289c
BD
172 struct s3c24xx_uart_port *ourport = to_ourport(port);
173
b497549a
BD
174 if (!tx_enabled(port)) {
175 if (port->flags & UPF_CONS_FLOW)
176 s3c24xx_serial_rx_disable(port);
177
88bb4ea1
TA
178 if (s3c24xx_serial_has_interrupt_mask(port))
179 __clear_bit(S3C64XX_UINTM_TXD,
180 portaddrl(port, S3C64XX_UINTM));
181 else
182 enable_irq(ourport->tx_irq);
b497549a
BD
183 tx_enabled(port) = 1;
184 }
185}
186
b497549a
BD
187static void s3c24xx_serial_stop_rx(struct uart_port *port)
188{
b73c289c
BD
189 struct s3c24xx_uart_port *ourport = to_ourport(port);
190
b497549a
BD
191 if (rx_enabled(port)) {
192 dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
88bb4ea1
TA
193 if (s3c24xx_serial_has_interrupt_mask(port))
194 __set_bit(S3C64XX_UINTM_RXD,
195 portaddrl(port, S3C64XX_UINTM));
196 else
197 disable_irq_nosync(ourport->rx_irq);
b497549a
BD
198 rx_enabled(port) = 0;
199 }
200}
201
ef4aca70
RB
202static inline struct s3c24xx_uart_info
203 *s3c24xx_port_to_info(struct uart_port *port)
b497549a
BD
204{
205 return to_ourport(port)->info;
206}
207
ef4aca70
RB
208static inline struct s3c2410_uartcfg
209 *s3c24xx_port_to_cfg(struct uart_port *port)
b497549a 210{
4d84e970
TA
211 struct s3c24xx_uart_port *ourport;
212
b497549a
BD
213 if (port->dev == NULL)
214 return NULL;
215
4d84e970
TA
216 ourport = container_of(port, struct s3c24xx_uart_port, port);
217 return ourport->cfg;
b497549a
BD
218}
219
220static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,
221 unsigned long ufstat)
222{
223 struct s3c24xx_uart_info *info = ourport->info;
224
225 if (ufstat & info->rx_fifofull)
da121506 226 return ourport->port.fifosize;
b497549a
BD
227
228 return (ufstat & info->rx_fifomask) >> info->rx_fifoshift;
229}
230
231
232/* ? - where has parity gone?? */
233#define S3C2410_UERSTAT_PARITY (0x1000)
234
235static irqreturn_t
236s3c24xx_serial_rx_chars(int irq, void *dev_id)
237{
238 struct s3c24xx_uart_port *ourport = dev_id;
239 struct uart_port *port = &ourport->port;
b497549a 240 unsigned int ufcon, ch, flag, ufstat, uerstat;
c15c3747 241 unsigned long flags;
57850a50 242 int max_count = port->fifosize;
b497549a 243
c15c3747
TA
244 spin_lock_irqsave(&port->lock, flags);
245
b497549a
BD
246 while (max_count-- > 0) {
247 ufcon = rd_regl(port, S3C2410_UFCON);
248 ufstat = rd_regl(port, S3C2410_UFSTAT);
249
250 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
251 break;
252
253 uerstat = rd_regl(port, S3C2410_UERSTAT);
254 ch = rd_regb(port, S3C2410_URXH);
255
256 if (port->flags & UPF_CONS_FLOW) {
257 int txe = s3c24xx_serial_txempty_nofifo(port);
258
259 if (rx_enabled(port)) {
260 if (!txe) {
261 rx_enabled(port) = 0;
262 continue;
263 }
264 } else {
265 if (txe) {
266 ufcon |= S3C2410_UFCON_RESETRX;
267 wr_regl(port, S3C2410_UFCON, ufcon);
268 rx_enabled(port) = 1;
f5693ea2
VK
269 spin_unlock_irqrestore(&port->lock,
270 flags);
b497549a
BD
271 goto out;
272 }
273 continue;
274 }
275 }
276
277 /* insert the character into the buffer */
278
279 flag = TTY_NORMAL;
280 port->icount.rx++;
281
282 if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
283 dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
284 ch, uerstat);
285
286 /* check for break */
287 if (uerstat & S3C2410_UERSTAT_BREAK) {
288 dbg("break!\n");
289 port->icount.brk++;
290 if (uart_handle_break(port))
9303ac15 291 goto ignore_char;
b497549a
BD
292 }
293
294 if (uerstat & S3C2410_UERSTAT_FRAME)
295 port->icount.frame++;
296 if (uerstat & S3C2410_UERSTAT_OVERRUN)
297 port->icount.overrun++;
298
299 uerstat &= port->read_status_mask;
300
301 if (uerstat & S3C2410_UERSTAT_BREAK)
302 flag = TTY_BREAK;
303 else if (uerstat & S3C2410_UERSTAT_PARITY)
304 flag = TTY_PARITY;
305 else if (uerstat & (S3C2410_UERSTAT_FRAME |
306 S3C2410_UERSTAT_OVERRUN))
307 flag = TTY_FRAME;
308 }
309
310 if (uart_handle_sysrq_char(port, ch))
311 goto ignore_char;
312
313 uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
314 ch, flag);
315
ef4aca70 316ignore_char:
b497549a
BD
317 continue;
318 }
f5693ea2
VK
319
320 spin_unlock_irqrestore(&port->lock, flags);
2e124b4a 321 tty_flip_buffer_push(&port->state->port);
b497549a 322
ef4aca70 323out:
b497549a
BD
324 return IRQ_HANDLED;
325}
326
327static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
328{
329 struct s3c24xx_uart_port *ourport = id;
330 struct uart_port *port = &ourport->port;
ebd2c8f6 331 struct circ_buf *xmit = &port->state->xmit;
c15c3747 332 unsigned long flags;
57850a50 333 int count = port->fifosize;
b497549a 334
c15c3747
TA
335 spin_lock_irqsave(&port->lock, flags);
336
b497549a
BD
337 if (port->x_char) {
338 wr_regb(port, S3C2410_UTXH, port->x_char);
339 port->icount.tx++;
340 port->x_char = 0;
341 goto out;
342 }
343
25985edc 344 /* if there isn't anything more to transmit, or the uart is now
b497549a
BD
345 * stopped, disable the uart and exit
346 */
347
348 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
349 s3c24xx_serial_stop_tx(port);
350 goto out;
351 }
352
353 /* try and drain the buffer... */
354
355 while (!uart_circ_empty(xmit) && count-- > 0) {
356 if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
357 break;
358
359 wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
360 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
361 port->icount.tx++;
362 }
363
c15c3747
TA
364 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
365 spin_unlock(&port->lock);
b497549a 366 uart_write_wakeup(port);
c15c3747
TA
367 spin_lock(&port->lock);
368 }
b497549a
BD
369
370 if (uart_circ_empty(xmit))
371 s3c24xx_serial_stop_tx(port);
372
ef4aca70 373out:
c15c3747 374 spin_unlock_irqrestore(&port->lock, flags);
b497549a
BD
375 return IRQ_HANDLED;
376}
377
88bb4ea1
TA
378/* interrupt handler for s3c64xx and later SoC's.*/
379static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
380{
381 struct s3c24xx_uart_port *ourport = id;
382 struct uart_port *port = &ourport->port;
383 unsigned int pend = rd_regl(port, S3C64XX_UINTP);
88bb4ea1
TA
384 irqreturn_t ret = IRQ_HANDLED;
385
88bb4ea1
TA
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);
389 }
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);
393 }
88bb4ea1
TA
394 return ret;
395}
396
b497549a
BD
397static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
398{
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);
402
403 if (ufcon & S3C2410_UFCON_FIFOMODE) {
404 if ((ufstat & info->tx_fifomask) != 0 ||
405 (ufstat & info->tx_fifofull))
406 return 0;
407
408 return 1;
409 }
410
411 return s3c24xx_serial_txempty_nofifo(port);
412}
413
414/* no modem control lines */
415static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
416{
417 unsigned int umstat = rd_regb(port, S3C2410_UMSTAT);
418
419 if (umstat & S3C2410_UMSTAT_CTS)
420 return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
421 else
422 return TIOCM_CAR | TIOCM_DSR;
423}
424
425static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
426{
2d1e5a48
JMG
427 unsigned int umcon = rd_regl(port, S3C2410_UMCON);
428
429 if (mctrl & TIOCM_RTS)
430 umcon |= S3C2410_UMCOM_RTS_LOW;
431 else
432 umcon &= ~S3C2410_UMCOM_RTS_LOW;
433
434 wr_regl(port, S3C2410_UMCON, umcon);
b497549a
BD
435}
436
437static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
438{
439 unsigned long flags;
440 unsigned int ucon;
441
442 spin_lock_irqsave(&port->lock, flags);
443
444 ucon = rd_regl(port, S3C2410_UCON);
445
446 if (break_state)
447 ucon |= S3C2410_UCON_SBREAK;
448 else
449 ucon &= ~S3C2410_UCON_SBREAK;
450
451 wr_regl(port, S3C2410_UCON, ucon);
452
453 spin_unlock_irqrestore(&port->lock, flags);
454}
455
456static void s3c24xx_serial_shutdown(struct uart_port *port)
457{
458 struct s3c24xx_uart_port *ourport = to_ourport(port);
459
460 if (ourport->tx_claimed) {
88bb4ea1
TA
461 if (!s3c24xx_serial_has_interrupt_mask(port))
462 free_irq(ourport->tx_irq, ourport);
b497549a
BD
463 tx_enabled(port) = 0;
464 ourport->tx_claimed = 0;
465 }
466
467 if (ourport->rx_claimed) {
88bb4ea1
TA
468 if (!s3c24xx_serial_has_interrupt_mask(port))
469 free_irq(ourport->rx_irq, ourport);
b497549a
BD
470 ourport->rx_claimed = 0;
471 rx_enabled(port) = 0;
472 }
b497549a 473
88bb4ea1
TA
474 /* Clear pending interrupts and mask all interrupts */
475 if (s3c24xx_serial_has_interrupt_mask(port)) {
b6ad2935
TF
476 free_irq(port->irq, ourport);
477
88bb4ea1
TA
478 wr_regl(port, S3C64XX_UINTP, 0xf);
479 wr_regl(port, S3C64XX_UINTM, 0xf);
480 }
481}
b497549a
BD
482
483static int s3c24xx_serial_startup(struct uart_port *port)
484{
485 struct s3c24xx_uart_port *ourport = to_ourport(port);
486 int ret;
487
e4ac92df
JP
488 dbg("s3c24xx_serial_startup: port=%p (%08llx,%p)\n",
489 port, (unsigned long long)port->mapbase, port->membase);
b497549a
BD
490
491 rx_enabled(port) = 1;
492
b73c289c 493 ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,
b497549a
BD
494 s3c24xx_serial_portname(port), ourport);
495
496 if (ret != 0) {
d20925e1 497 dev_err(port->dev, "cannot get irq %d\n", ourport->rx_irq);
b497549a
BD
498 return ret;
499 }
500
501 ourport->rx_claimed = 1;
502
503 dbg("requesting tx irq...\n");
504
505 tx_enabled(port) = 1;
506
b73c289c 507 ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,
b497549a
BD
508 s3c24xx_serial_portname(port), ourport);
509
510 if (ret) {
d20925e1 511 dev_err(port->dev, "cannot get irq %d\n", ourport->tx_irq);
b497549a
BD
512 goto err;
513 }
514
515 ourport->tx_claimed = 1;
516
517 dbg("s3c24xx_serial_startup ok\n");
518
519 /* the port reset code should have done the correct
520 * register setup for the port controls */
521
522 return ret;
523
ef4aca70 524err:
b497549a
BD
525 s3c24xx_serial_shutdown(port);
526 return ret;
527}
528
88bb4ea1
TA
529static int s3c64xx_serial_startup(struct uart_port *port)
530{
531 struct s3c24xx_uart_port *ourport = to_ourport(port);
532 int ret;
533
e4ac92df
JP
534 dbg("s3c64xx_serial_startup: port=%p (%08llx,%p)\n",
535 port, (unsigned long long)port->mapbase, port->membase);
88bb4ea1 536
b6ad2935
TF
537 wr_regl(port, S3C64XX_UINTM, 0xf);
538
88bb4ea1
TA
539 ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED,
540 s3c24xx_serial_portname(port), ourport);
541 if (ret) {
d20925e1 542 dev_err(port->dev, "cannot get irq %d\n", port->irq);
88bb4ea1
TA
543 return ret;
544 }
545
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;
551
552 /* Enable Rx Interrupt */
553 __clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM));
554 dbg("s3c64xx_serial_startup ok\n");
555 return ret;
556}
557
b497549a
BD
558/* power power management control */
559
560static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
561 unsigned int old)
562{
563 struct s3c24xx_uart_port *ourport = to_ourport(port);
1ff383a4 564 int timeout = 10000;
b497549a 565
30555476
BD
566 ourport->pm_level = level;
567
b497549a
BD
568 switch (level) {
569 case 3:
1ff383a4
RB
570 while (--timeout && !s3c24xx_serial_txempty_nofifo(port))
571 udelay(100);
572
7cd88831 573 if (!IS_ERR(ourport->baudclk))
9484b009 574 clk_disable_unprepare(ourport->baudclk);
b497549a 575
9484b009 576 clk_disable_unprepare(ourport->clk);
b497549a
BD
577 break;
578
579 case 0:
9484b009 580 clk_prepare_enable(ourport->clk);
b497549a 581
7cd88831 582 if (!IS_ERR(ourport->baudclk))
9484b009 583 clk_prepare_enable(ourport->baudclk);
b497549a
BD
584
585 break;
586 default:
d20925e1 587 dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level);
b497549a
BD
588 }
589}
590
591/* baud rate calculation
592 *
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.
597 *
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.
601 *
602*/
603
5f5a7a55 604#define MAX_CLK_NAME_LENGTH 15
b497549a 605
5f5a7a55 606static inline int s3c24xx_serial_getsource(struct uart_port *port)
b497549a
BD
607{
608 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
5f5a7a55 609 unsigned int ucon;
b497549a 610
5f5a7a55
TA
611 if (info->num_clks == 1)
612 return 0;
b497549a 613
5f5a7a55
TA
614 ucon = rd_regl(port, S3C2410_UCON);
615 ucon &= info->clksel_mask;
616 return ucon >> info->clksel_shift;
b497549a
BD
617}
618
5f5a7a55
TA
619static void s3c24xx_serial_setsource(struct uart_port *port,
620 unsigned int clk_sel)
b497549a 621{
5f5a7a55
TA
622 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
623 unsigned int ucon;
b497549a 624
5f5a7a55
TA
625 if (info->num_clks == 1)
626 return;
090f848d 627
5f5a7a55
TA
628 ucon = rd_regl(port, S3C2410_UCON);
629 if ((ucon & info->clksel_mask) >> info->clksel_shift == clk_sel)
630 return;
b497549a 631
5f5a7a55
TA
632 ucon &= ~info->clksel_mask;
633 ucon |= clk_sel << info->clksel_shift;
634 wr_regl(port, S3C2410_UCON, ucon);
b497549a
BD
635}
636
5f5a7a55
TA
637static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
638 unsigned int req_baud, struct clk **best_clk,
639 unsigned int *clk_num)
b497549a 640{
5f5a7a55
TA
641 struct s3c24xx_uart_info *info = ourport->info;
642 struct clk *clk;
643 unsigned long rate;
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;
647
5f5a7a55
TA
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)))
652 continue;
653
654 sprintf(clkname, "clk_uart_baud%d", cnt);
655 clk = clk_get(ourport->port.dev, clkname);
7cd88831 656 if (IS_ERR(clk))
5f5a7a55
TA
657 continue;
658
659 rate = clk_get_rate(clk);
660 if (!rate)
661 continue;
662
663 if (ourport->info->has_divslot) {
664 unsigned long div = rate / req_baud;
665
666 /* The UDIVSLOT register on the newer UARTs allows us to
667 * get a divisor adjustment of 1/16th on the baud clock.
668 *
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.
672 */
673
674 quot = div / 16;
675 baud = rate / div;
676 } else {
677 quot = (rate + (8 * req_baud)) / (16 * req_baud);
678 baud = rate / (quot * 16);
b497549a 679 }
5f5a7a55 680 quot--;
b497549a 681
5f5a7a55
TA
682 calc_deviation = req_baud - baud;
683 if (calc_deviation < 0)
684 calc_deviation = -calc_deviation;
b497549a 685
5f5a7a55
TA
686 if (calc_deviation < deviation) {
687 *best_clk = clk;
688 best_quot = quot;
689 *clk_num = cnt;
690 deviation = calc_deviation;
b497549a
BD
691 }
692 }
693
5f5a7a55 694 return best_quot;
b497549a
BD
695}
696
090f848d
BD
697/* udivslot_table[]
698 *
699 * This table takes the fractional value of the baud divisor and gives
700 * the recommended setting for the UDIVSLOT register.
701 */
702static u16 udivslot_table[16] = {
703 [0] = 0x0000,
704 [1] = 0x0080,
705 [2] = 0x0808,
706 [3] = 0x0888,
707 [4] = 0x2222,
708 [5] = 0x4924,
709 [6] = 0x4A52,
710 [7] = 0x54AA,
711 [8] = 0x5555,
712 [9] = 0xD555,
713 [10] = 0xD5D5,
714 [11] = 0xDDD5,
715 [12] = 0xDDDD,
716 [13] = 0xDFDD,
717 [14] = 0xDFDF,
718 [15] = 0xFFDF,
719};
720
b497549a
BD
721static void s3c24xx_serial_set_termios(struct uart_port *port,
722 struct ktermios *termios,
723 struct ktermios *old)
724{
725 struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
726 struct s3c24xx_uart_port *ourport = to_ourport(port);
7cd88831 727 struct clk *clk = ERR_PTR(-EINVAL);
b497549a 728 unsigned long flags;
5f5a7a55 729 unsigned int baud, quot, clk_sel = 0;
b497549a
BD
730 unsigned int ulcon;
731 unsigned int umcon;
090f848d 732 unsigned int udivslot = 0;
b497549a
BD
733
734 /*
735 * We don't support modem control lines.
736 */
737 termios->c_cflag &= ~(HUPCL | CMSPAR);
738 termios->c_cflag |= CLOCAL;
739
740 /*
741 * Ask the core to calculate the divisor for us.
742 */
743
744 baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);
5f5a7a55 745 quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel);
b497549a
BD
746 if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
747 quot = port->custom_divisor;
7cd88831 748 if (IS_ERR(clk))
5f5a7a55 749 return;
b497549a
BD
750
751 /* check to see if we need to change clock source */
752
5f5a7a55
TA
753 if (ourport->baudclk != clk) {
754 s3c24xx_serial_setsource(port, clk_sel);
b497549a 755
7cd88831 756 if (!IS_ERR(ourport->baudclk)) {
9484b009 757 clk_disable_unprepare(ourport->baudclk);
7cd88831 758 ourport->baudclk = ERR_PTR(-EINVAL);
b497549a
BD
759 }
760
9484b009 761 clk_prepare_enable(clk);
b497549a 762
b497549a 763 ourport->baudclk = clk;
30555476 764 ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
b497549a
BD
765 }
766
090f848d
BD
767 if (ourport->info->has_divslot) {
768 unsigned int div = ourport->baudclk_rate / baud;
769
8b526ae4
JL
770 if (cfg->has_fracval) {
771 udivslot = (div & 15);
772 dbg("fracval = %04x\n", udivslot);
773 } else {
774 udivslot = udivslot_table[div & 15];
775 dbg("udivslot = %04x (div %d)\n", udivslot, div & 15);
776 }
090f848d
BD
777 }
778
b497549a
BD
779 switch (termios->c_cflag & CSIZE) {
780 case CS5:
781 dbg("config: 5bits/char\n");
782 ulcon = S3C2410_LCON_CS5;
783 break;
784 case CS6:
785 dbg("config: 6bits/char\n");
786 ulcon = S3C2410_LCON_CS6;
787 break;
788 case CS7:
789 dbg("config: 7bits/char\n");
790 ulcon = S3C2410_LCON_CS7;
791 break;
792 case CS8:
793 default:
794 dbg("config: 8bits/char\n");
795 ulcon = S3C2410_LCON_CS8;
796 break;
797 }
798
799 /* preserve original lcon IR settings */
800 ulcon |= (cfg->ulcon & S3C2410_LCON_IRM);
801
802 if (termios->c_cflag & CSTOPB)
803 ulcon |= S3C2410_LCON_STOPB;
804
b497549a
BD
805 if (termios->c_cflag & PARENB) {
806 if (termios->c_cflag & PARODD)
807 ulcon |= S3C2410_LCON_PODD;
808 else
809 ulcon |= S3C2410_LCON_PEVEN;
810 } else {
811 ulcon |= S3C2410_LCON_PNONE;
812 }
813
814 spin_lock_irqsave(&port->lock, flags);
815
090f848d
BD
816 dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
817 ulcon, quot, udivslot);
b497549a
BD
818
819 wr_regl(port, S3C2410_ULCON, ulcon);
820 wr_regl(port, S3C2410_UBRDIV, quot);
2d1e5a48
JMG
821
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;
827 } else {
828 umcon &= ~S3C2410_UMCOM_AFC;
829 }
b497549a
BD
830 wr_regl(port, S3C2410_UMCON, umcon);
831
090f848d
BD
832 if (ourport->info->has_divslot)
833 wr_regl(port, S3C2443_DIVSLOT, udivslot);
834
b497549a
BD
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));
839
840 /*
841 * Update the per-port timeout.
842 */
843 uart_update_timeout(port, termios->c_cflag, baud);
844
845 /*
846 * Which character status flags are we interested in?
847 */
848 port->read_status_mask = S3C2410_UERSTAT_OVERRUN;
849 if (termios->c_iflag & INPCK)
ef4aca70
RB
850 port->read_status_mask |= S3C2410_UERSTAT_FRAME |
851 S3C2410_UERSTAT_PARITY;
b497549a
BD
852 /*
853 * Which character status flags should we ignore?
854 */
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;
860
861 /*
862 * Ignore all characters if CREAD is not set.
863 */
864 if ((termios->c_cflag & CREAD) == 0)
865 port->ignore_status_mask |= RXSTAT_DUMMY_READ;
866
867 spin_unlock_irqrestore(&port->lock, flags);
868}
869
870static const char *s3c24xx_serial_type(struct uart_port *port)
871{
872 switch (port->type) {
873 case PORT_S3C2410:
874 return "S3C2410";
875 case PORT_S3C2440:
876 return "S3C2440";
877 case PORT_S3C2412:
878 return "S3C2412";
b690ace5
BD
879 case PORT_S3C6400:
880 return "S3C6400/10";
b497549a
BD
881 default:
882 return NULL;
883 }
884}
885
886#define MAP_SIZE (0x100)
887
888static void s3c24xx_serial_release_port(struct uart_port *port)
889{
890 release_mem_region(port->mapbase, MAP_SIZE);
891}
892
893static int s3c24xx_serial_request_port(struct uart_port *port)
894{
895 const char *name = s3c24xx_serial_portname(port);
896 return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY;
897}
898
899static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
900{
901 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
902
903 if (flags & UART_CONFIG_TYPE &&
904 s3c24xx_serial_request_port(port) == 0)
905 port->type = info->type;
906}
907
908/*
909 * verify the new serial_struct (for TIOCSSERIAL).
910 */
911static int
912s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
913{
914 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
915
916 if (ser->type != PORT_UNKNOWN && ser->type != info->type)
917 return -EINVAL;
918
919 return 0;
920}
921
922
923#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
924
925static struct console s3c24xx_serial_console;
926
93b5c032
JP
927static int __init s3c24xx_serial_console_init(void)
928{
929 register_console(&s3c24xx_serial_console);
930 return 0;
931}
932console_initcall(s3c24xx_serial_console_init);
933
b497549a
BD
934#define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
935#else
936#define S3C24XX_SERIAL_CONSOLE NULL
937#endif
938
84f57d9e 939#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
93b5c032
JP
940static int s3c24xx_serial_get_poll_char(struct uart_port *port);
941static void s3c24xx_serial_put_poll_char(struct uart_port *port,
942 unsigned char c);
943#endif
944
b497549a
BD
945static 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,
b497549a
BD
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,
84f57d9e 962#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
93b5c032
JP
963 .poll_get_char = s3c24xx_serial_get_poll_char,
964 .poll_put_char = s3c24xx_serial_put_poll_char,
965#endif
b497549a
BD
966};
967
b497549a
BD
968static struct uart_driver s3c24xx_uart_drv = {
969 .owner = THIS_MODULE,
2cf0c58e 970 .driver_name = "s3c2410_serial",
bdd4915a 971 .nr = CONFIG_SERIAL_SAMSUNG_UARTS,
b497549a 972 .cons = S3C24XX_SERIAL_CONSOLE,
2cf0c58e 973 .dev_name = S3C24XX_SERIAL_NAME,
b497549a
BD
974 .major = S3C24XX_SERIAL_MAJOR,
975 .minor = S3C24XX_SERIAL_MINOR,
976};
977
ef4aca70
RB
978#define __PORT_LOCK_UNLOCKED(i) \
979 __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[i].port.lock)
980static struct s3c24xx_uart_port
981s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
b497549a
BD
982 [0] = {
983 .port = {
ef4aca70 984 .lock = __PORT_LOCK_UNLOCKED(0),
b497549a 985 .iotype = UPIO_MEM,
b497549a
BD
986 .uartclk = 0,
987 .fifosize = 16,
988 .ops = &s3c24xx_serial_ops,
989 .flags = UPF_BOOT_AUTOCONF,
990 .line = 0,
991 }
992 },
993 [1] = {
994 .port = {
ef4aca70 995 .lock = __PORT_LOCK_UNLOCKED(1),
b497549a 996 .iotype = UPIO_MEM,
b497549a
BD
997 .uartclk = 0,
998 .fifosize = 16,
999 .ops = &s3c24xx_serial_ops,
1000 .flags = UPF_BOOT_AUTOCONF,
1001 .line = 1,
1002 }
1003 },
03d5e77b 1004#if CONFIG_SERIAL_SAMSUNG_UARTS > 2
b497549a
BD
1005
1006 [2] = {
1007 .port = {
ef4aca70 1008 .lock = __PORT_LOCK_UNLOCKED(2),
b497549a 1009 .iotype = UPIO_MEM,
b497549a
BD
1010 .uartclk = 0,
1011 .fifosize = 16,
1012 .ops = &s3c24xx_serial_ops,
1013 .flags = UPF_BOOT_AUTOCONF,
1014 .line = 2,
1015 }
03d5e77b
BD
1016 },
1017#endif
1018#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
1019 [3] = {
1020 .port = {
ef4aca70 1021 .lock = __PORT_LOCK_UNLOCKED(3),
03d5e77b 1022 .iotype = UPIO_MEM,
03d5e77b
BD
1023 .uartclk = 0,
1024 .fifosize = 16,
1025 .ops = &s3c24xx_serial_ops,
1026 .flags = UPF_BOOT_AUTOCONF,
1027 .line = 3,
1028 }
b497549a
BD
1029 }
1030#endif
1031};
ef4aca70 1032#undef __PORT_LOCK_UNLOCKED
b497549a
BD
1033
1034/* s3c24xx_serial_resetport
1035 *
0dfb3b41 1036 * reset the fifos and other the settings.
b497549a
BD
1037*/
1038
0dfb3b41
TA
1039static void s3c24xx_serial_resetport(struct uart_port *port,
1040 struct s3c2410_uartcfg *cfg)
b497549a
BD
1041{
1042 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
0dfb3b41
TA
1043 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1044 unsigned int ucon_mask;
b497549a 1045
0dfb3b41
TA
1046 ucon_mask = info->clksel_mask;
1047 if (info->type == PORT_S3C2440)
1048 ucon_mask |= S3C2440_UCON0_DIVMASK;
1049
1050 ucon &= ucon_mask;
1051 wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
1052
1053 /* reset both fifos */
1054 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
1055 wr_regl(port, S3C2410_UFCON, cfg->ufcon);
1056
1057 /* some delay is required after fifo reset */
1058 udelay(1);
b497549a
BD
1059}
1060
30555476
BD
1061
1062#ifdef CONFIG_CPU_FREQ
1063
1064static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
1065 unsigned long val, void *data)
1066{
1067 struct s3c24xx_uart_port *port;
1068 struct uart_port *uport;
1069
1070 port = container_of(nb, struct s3c24xx_uart_port, freq_transition);
1071 uport = &port->port;
1072
1073 /* check to see if port is enabled */
1074
1075 if (port->pm_level != 0)
1076 return 0;
1077
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.
1081 */
1082
25f04ad4 1083 if (IS_ERR(port->baudclk))
30555476
BD
1084 goto exit;
1085
25f04ad4 1086 if (port->baudclk_rate == clk_get_rate(port->baudclk))
30555476
BD
1087 goto exit;
1088
1089 if (val == CPUFREQ_PRECHANGE) {
1090 /* we should really shut the port down whilst the
1091 * frequency change is in progress. */
1092
1093 } else if (val == CPUFREQ_POSTCHANGE) {
1094 struct ktermios *termios;
1095 struct tty_struct *tty;
1096
ebd2c8f6 1097 if (uport->state == NULL)
30555476 1098 goto exit;
30555476 1099
ebd2c8f6 1100 tty = uport->state->port.tty;
30555476 1101
7de40c21 1102 if (tty == NULL)
30555476 1103 goto exit;
30555476 1104
adc8d746 1105 termios = &tty->termios;
30555476
BD
1106
1107 if (termios == NULL) {
d20925e1 1108 dev_warn(uport->dev, "%s: no termios?\n", __func__);
30555476
BD
1109 goto exit;
1110 }
1111
1112 s3c24xx_serial_set_termios(uport, termios, NULL);
1113 }
1114
ef4aca70 1115exit:
30555476
BD
1116 return 0;
1117}
1118
ef4aca70
RB
1119static inline int
1120s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
30555476
BD
1121{
1122 port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition;
1123
1124 return cpufreq_register_notifier(&port->freq_transition,
1125 CPUFREQ_TRANSITION_NOTIFIER);
1126}
1127
ef4aca70
RB
1128static inline void
1129s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
30555476
BD
1130{
1131 cpufreq_unregister_notifier(&port->freq_transition,
1132 CPUFREQ_TRANSITION_NOTIFIER);
1133}
1134
1135#else
ef4aca70
RB
1136static inline int
1137s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
30555476
BD
1138{
1139 return 0;
1140}
1141
ef4aca70
RB
1142static inline void
1143s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
30555476
BD
1144{
1145}
1146#endif
1147
b497549a
BD
1148/* s3c24xx_serial_init_port
1149 *
1150 * initialise a single serial port from the platform device given
1151 */
1152
1153static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
b497549a
BD
1154 struct platform_device *platdev)
1155{
1156 struct uart_port *port = &ourport->port;
da121506 1157 struct s3c2410_uartcfg *cfg = ourport->cfg;
b497549a
BD
1158 struct resource *res;
1159 int ret;
1160
1161 dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev);
1162
1163 if (platdev == NULL)
1164 return -ENODEV;
1165
b497549a
BD
1166 if (port->mapbase != 0)
1167 return 0;
1168
b497549a
BD
1169 /* setup info for port */
1170 port->dev = &platdev->dev;
b497549a 1171
88bb4ea1
TA
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;
1175
b497549a
BD
1176 port->uartclk = 1;
1177
1178 if (cfg->uart_flags & UPF_CONS_FLOW) {
1179 dbg("s3c24xx_serial_init_port: enabling flow control\n");
1180 port->flags |= UPF_CONS_FLOW;
1181 }
1182
1183 /* sort our the physical and virtual addresses for each UART */
1184
1185 res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
1186 if (res == NULL) {
d20925e1 1187 dev_err(port->dev, "failed to find memory resource for uart\n");
b497549a
BD
1188 return -EINVAL;
1189 }
1190
e4ac92df 1191 dbg("resource %pR)\n", res);
b497549a 1192
41147bfd
TA
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");
1196 return -EBUSY;
1197 }
1198
b690ace5 1199 port->mapbase = res->start;
b497549a
BD
1200 ret = platform_get_irq(platdev, 0);
1201 if (ret < 0)
1202 port->irq = 0;
b73c289c 1203 else {
b497549a 1204 port->irq = ret;
b73c289c
BD
1205 ourport->rx_irq = ret;
1206 ourport->tx_irq = ret + 1;
1207 }
9303ac15 1208
b73c289c
BD
1209 ret = platform_get_irq(platdev, 1);
1210 if (ret > 0)
1211 ourport->tx_irq = ret;
658c9d2b
RB
1212 /*
1213 * DMA is currently supported only on DT platforms, if DMA properties
1214 * are specified.
1215 */
1216 if (platdev->dev.of_node && of_find_property(platdev->dev.of_node,
1217 "dmas", NULL)) {
1218 ourport->dma = devm_kzalloc(port->dev,
1219 sizeof(*ourport->dma),
1220 GFP_KERNEL);
1221 if (!ourport->dma)
1222 return -ENOMEM;
1223 }
b497549a
BD
1224
1225 ourport->clk = clk_get(&platdev->dev, "uart");
60e93575
CK
1226 if (IS_ERR(ourport->clk)) {
1227 pr_err("%s: Controller clock not found\n",
1228 dev_name(&platdev->dev));
1229 return PTR_ERR(ourport->clk);
1230 }
1231
1232 ret = clk_prepare_enable(ourport->clk);
1233 if (ret) {
1234 pr_err("uart: clock failed to prepare+enable: %d\n", ret);
1235 clk_put(ourport->clk);
1236 return ret;
1237 }
b497549a 1238
88bb4ea1
TA
1239 /* Keep all interrupts masked and cleared */
1240 if (s3c24xx_serial_has_interrupt_mask(port)) {
1241 wr_regl(port, S3C64XX_UINTM, 0xf);
1242 wr_regl(port, S3C64XX_UINTP, 0xf);
1243 wr_regl(port, S3C64XX_UINTSP, 0xf);
1244 }
1245
1ff5b64d
FE
1246 dbg("port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n",
1247 &port->mapbase, port->membase, port->irq,
b73c289c 1248 ourport->rx_irq, ourport->tx_irq, port->uartclk);
b497549a
BD
1249
1250 /* reset the fifos (and setup the uart) */
1251 s3c24xx_serial_resetport(port, cfg);
1252 return 0;
1253}
1254
b497549a
BD
1255/* Device driver serial port probe */
1256
26c919e1 1257static const struct of_device_id s3c24xx_uart_dt_match[];
b497549a
BD
1258static int probe_index;
1259
26c919e1
TA
1260static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data(
1261 struct platform_device *pdev)
1262{
1263#ifdef CONFIG_OF
1264 if (pdev->dev.of_node) {
1265 const struct of_device_id *match;
1266 match = of_match_node(s3c24xx_uart_dt_match, pdev->dev.of_node);
1267 return (struct s3c24xx_serial_drv_data *)match->data;
1268 }
1269#endif
1270 return (struct s3c24xx_serial_drv_data *)
1271 platform_get_device_id(pdev)->driver_data;
1272}
1273
da121506 1274static int s3c24xx_serial_probe(struct platform_device *pdev)
b497549a 1275{
4622eb68 1276 struct device_node *np = pdev->dev.of_node;
b497549a 1277 struct s3c24xx_uart_port *ourport;
13a9f6c6 1278 int index = probe_index;
b497549a
BD
1279 int ret;
1280
4622eb68
NKC
1281 if (np) {
1282 ret = of_alias_get_id(np, "serial");
13a9f6c6
TF
1283 if (ret >= 0)
1284 index = ret;
1285 }
1286
1287 dbg("s3c24xx_serial_probe(%p) %d\n", pdev, index);
b497549a 1288
13a9f6c6 1289 ourport = &s3c24xx_serial_ports[index];
da121506 1290
26c919e1
TA
1291 ourport->drv_data = s3c24xx_get_driver_data(pdev);
1292 if (!ourport->drv_data) {
1293 dev_err(&pdev->dev, "could not find driver data\n");
1294 return -ENODEV;
1295 }
da121506 1296
7cd88831 1297 ourport->baudclk = ERR_PTR(-EINVAL);
da121506 1298 ourport->info = ourport->drv_data->info;
574de559 1299 ourport->cfg = (dev_get_platdata(&pdev->dev)) ?
d4aab206 1300 dev_get_platdata(&pdev->dev) :
da121506
TA
1301 ourport->drv_data->def_cfg;
1302
4622eb68
NKC
1303 if (np)
1304 of_property_read_u32(np,
135f07c3
NKC
1305 "samsung,uart-fifosize", &ourport->port.fifosize);
1306
2f1ba72d
RB
1307 if (ourport->drv_data->fifosize[index])
1308 ourport->port.fifosize = ourport->drv_data->fifosize[index];
1309 else if (ourport->info->fifosize)
1310 ourport->port.fifosize = ourport->info->fifosize;
da121506 1311
b497549a
BD
1312 probe_index++;
1313
1314 dbg("%s: initialising port %p...\n", __func__, ourport);
1315
da121506 1316 ret = s3c24xx_serial_init_port(ourport, pdev);
b497549a 1317 if (ret < 0)
8ad711a9 1318 return ret;
b497549a 1319
6f134c3c
TB
1320 if (!s3c24xx_uart_drv.state) {
1321 ret = uart_register_driver(&s3c24xx_uart_drv);
1322 if (ret < 0) {
1323 pr_err("Failed to register Samsung UART driver\n");
1324 return ret;
1325 }
1326 }
1327
b497549a
BD
1328 dbg("%s: adding port\n", __func__);
1329 uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
da121506 1330 platform_set_drvdata(pdev, &ourport->port);
b497549a 1331
0da3336f
HS
1332 /*
1333 * Deactivate the clock enabled in s3c24xx_serial_init_port here,
1334 * so that a potential re-enablement through the pm-callback overlaps
1335 * and keeps the clock enabled in this case.
1336 */
1337 clk_disable_unprepare(ourport->clk);
1338
30555476
BD
1339 ret = s3c24xx_serial_cpufreq_register(ourport);
1340 if (ret < 0)
da121506 1341 dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
30555476 1342
b497549a 1343 return 0;
b497549a
BD
1344}
1345
ae8d8a14 1346static int s3c24xx_serial_remove(struct platform_device *dev)
b497549a
BD
1347{
1348 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
1349
1350 if (port) {
30555476 1351 s3c24xx_serial_cpufreq_deregister(to_ourport(port));
b497549a
BD
1352 uart_remove_one_port(&s3c24xx_uart_drv, port);
1353 }
1354
6f134c3c
TB
1355 uart_unregister_driver(&s3c24xx_uart_drv);
1356
b497549a
BD
1357 return 0;
1358}
1359
b497549a 1360/* UART power management code */
aef7fe52
MH
1361#ifdef CONFIG_PM_SLEEP
1362static int s3c24xx_serial_suspend(struct device *dev)
b497549a 1363{
aef7fe52 1364 struct uart_port *port = s3c24xx_dev_to_port(dev);
b497549a
BD
1365
1366 if (port)
1367 uart_suspend_port(&s3c24xx_uart_drv, port);
1368
1369 return 0;
1370}
1371
aef7fe52 1372static int s3c24xx_serial_resume(struct device *dev)
b497549a 1373{
aef7fe52 1374 struct uart_port *port = s3c24xx_dev_to_port(dev);
b497549a
BD
1375 struct s3c24xx_uart_port *ourport = to_ourport(port);
1376
1377 if (port) {
9484b009 1378 clk_prepare_enable(ourport->clk);
b497549a 1379 s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
9484b009 1380 clk_disable_unprepare(ourport->clk);
b497549a
BD
1381
1382 uart_resume_port(&s3c24xx_uart_drv, port);
1383 }
1384
1385 return 0;
1386}
aef7fe52 1387
d09a7308
MS
1388static int s3c24xx_serial_resume_noirq(struct device *dev)
1389{
1390 struct uart_port *port = s3c24xx_dev_to_port(dev);
1391
1392 if (port) {
1393 /* restore IRQ mask */
1394 if (s3c24xx_serial_has_interrupt_mask(port)) {
1395 unsigned int uintm = 0xf;
1396 if (tx_enabled(port))
1397 uintm &= ~S3C64XX_UINTM_TXD_MSK;
1398 if (rx_enabled(port))
1399 uintm &= ~S3C64XX_UINTM_RXD_MSK;
1400 wr_regl(port, S3C64XX_UINTM, uintm);
1401 }
1402 }
1403
1404 return 0;
1405}
1406
aef7fe52
MH
1407static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
1408 .suspend = s3c24xx_serial_suspend,
1409 .resume = s3c24xx_serial_resume,
d09a7308 1410 .resume_noirq = s3c24xx_serial_resume_noirq,
aef7fe52 1411};
b882fc1b
KK
1412#define SERIAL_SAMSUNG_PM_OPS (&s3c24xx_serial_pm_ops)
1413
aef7fe52 1414#else /* !CONFIG_PM_SLEEP */
b882fc1b
KK
1415
1416#define SERIAL_SAMSUNG_PM_OPS NULL
aef7fe52 1417#endif /* CONFIG_PM_SLEEP */
b497549a 1418
b497549a
BD
1419/* Console code */
1420
1421#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
1422
1423static struct uart_port *cons_uart;
1424
1425static int
1426s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
1427{
1428 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1429 unsigned long ufstat, utrstat;
1430
1431 if (ufcon & S3C2410_UFCON_FIFOMODE) {
9ddc5b6f 1432 /* fifo mode - check amount of data in fifo registers... */
b497549a
BD
1433
1434 ufstat = rd_regl(port, S3C2410_UFSTAT);
1435 return (ufstat & info->tx_fifofull) ? 0 : 1;
1436 }
1437
1438 /* in non-fifo mode, we go and use the tx buffer empty */
1439
1440 utrstat = rd_regl(port, S3C2410_UTRSTAT);
1441 return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
1442}
1443
38adbc54
MS
1444static bool
1445s3c24xx_port_configured(unsigned int ucon)
1446{
1447 /* consider the serial port configured if the tx/rx mode set */
1448 return (ucon & 0xf) != 0;
1449}
1450
93b5c032
JP
1451#ifdef CONFIG_CONSOLE_POLL
1452/*
1453 * Console polling routines for writing and reading from the uart while
1454 * in an interrupt or debug context.
1455 */
1456
1457static int s3c24xx_serial_get_poll_char(struct uart_port *port)
1458{
1459 struct s3c24xx_uart_port *ourport = to_ourport(port);
1460 unsigned int ufstat;
1461
1462 ufstat = rd_regl(port, S3C2410_UFSTAT);
1463 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
1464 return NO_POLL_CHAR;
1465
1466 return rd_regb(port, S3C2410_URXH);
1467}
1468
1469static void s3c24xx_serial_put_poll_char(struct uart_port *port,
1470 unsigned char c)
1471{
bb7f09ba
DA
1472 unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
1473 unsigned int ucon = rd_regl(port, S3C2410_UCON);
38adbc54
MS
1474
1475 /* not possible to xmit on unconfigured port */
1476 if (!s3c24xx_port_configured(ucon))
1477 return;
93b5c032
JP
1478
1479 while (!s3c24xx_serial_console_txrdy(port, ufcon))
1480 cpu_relax();
bb7f09ba 1481 wr_regb(port, S3C2410_UTXH, c);
93b5c032
JP
1482}
1483
1484#endif /* CONFIG_CONSOLE_POLL */
1485
b497549a
BD
1486static void
1487s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
1488{
bb7f09ba 1489 unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
38adbc54 1490
b497549a 1491 while (!s3c24xx_serial_console_txrdy(port, ufcon))
f94b0572 1492 cpu_relax();
bb7f09ba 1493 wr_regb(port, S3C2410_UTXH, ch);
b497549a
BD
1494}
1495
1496static void
1497s3c24xx_serial_console_write(struct console *co, const char *s,
1498 unsigned int count)
1499{
ab88c8dc
DA
1500 unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
1501
1502 /* not possible to xmit on unconfigured port */
1503 if (!s3c24xx_port_configured(ucon))
1504 return;
1505
b497549a
BD
1506 uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
1507}
1508
1509static void __init
1510s3c24xx_serial_get_options(struct uart_port *port, int *baud,
1511 int *parity, int *bits)
1512{
b497549a
BD
1513 struct clk *clk;
1514 unsigned int ulcon;
1515 unsigned int ucon;
1516 unsigned int ubrdiv;
1517 unsigned long rate;
5f5a7a55
TA
1518 unsigned int clk_sel;
1519 char clk_name[MAX_CLK_NAME_LENGTH];
b497549a
BD
1520
1521 ulcon = rd_regl(port, S3C2410_ULCON);
1522 ucon = rd_regl(port, S3C2410_UCON);
1523 ubrdiv = rd_regl(port, S3C2410_UBRDIV);
1524
1525 dbg("s3c24xx_serial_get_options: port=%p\n"
1526 "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
1527 port, ulcon, ucon, ubrdiv);
1528
38adbc54 1529 if (s3c24xx_port_configured(ucon)) {
b497549a
BD
1530 switch (ulcon & S3C2410_LCON_CSMASK) {
1531 case S3C2410_LCON_CS5:
1532 *bits = 5;
1533 break;
1534 case S3C2410_LCON_CS6:
1535 *bits = 6;
1536 break;
1537 case S3C2410_LCON_CS7:
1538 *bits = 7;
1539 break;
b497549a 1540 case S3C2410_LCON_CS8:
3bcce591 1541 default:
b497549a
BD
1542 *bits = 8;
1543 break;
1544 }
1545
1546 switch (ulcon & S3C2410_LCON_PMASK) {
1547 case S3C2410_LCON_PEVEN:
1548 *parity = 'e';
1549 break;
1550
1551 case S3C2410_LCON_PODD:
1552 *parity = 'o';
1553 break;
1554
1555 case S3C2410_LCON_PNONE:
1556 default:
1557 *parity = 'n';
1558 }
1559
1560 /* now calculate the baud rate */
1561
5f5a7a55
TA
1562 clk_sel = s3c24xx_serial_getsource(port);
1563 sprintf(clk_name, "clk_uart_baud%d", clk_sel);
b497549a 1564
5f5a7a55 1565 clk = clk_get(port->dev, clk_name);
7cd88831 1566 if (!IS_ERR(clk))
5f5a7a55 1567 rate = clk_get_rate(clk);
b497549a
BD
1568 else
1569 rate = 1;
1570
b497549a
BD
1571 *baud = rate / (16 * (ubrdiv + 1));
1572 dbg("calculated baud %d\n", *baud);
1573 }
1574
1575}
1576
b497549a
BD
1577static int __init
1578s3c24xx_serial_console_setup(struct console *co, char *options)
1579{
1580 struct uart_port *port;
1581 int baud = 9600;
1582 int bits = 8;
1583 int parity = 'n';
1584 int flow = 'n';
1585
1586 dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n",
1587 co, co->index, options);
1588
1589 /* is this a valid port */
1590
03d5e77b 1591 if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS)
b497549a
BD
1592 co->index = 0;
1593
1594 port = &s3c24xx_serial_ports[co->index].port;
1595
1596 /* is the port configured? */
1597
ee430f16
TA
1598 if (port->mapbase == 0x0)
1599 return -ENODEV;
b497549a
BD
1600
1601 cons_uart = port;
1602
1603 dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index);
1604
1605 /*
1606 * Check whether an invalid uart number has been specified, and
1607 * if so, search for the first available port that does have
1608 * console support.
1609 */
1610 if (options)
1611 uart_parse_options(options, &baud, &parity, &bits, &flow);
1612 else
1613 s3c24xx_serial_get_options(port, &baud, &parity, &bits);
1614
1615 dbg("s3c24xx_serial_console_setup: baud %d\n", baud);
1616
1617 return uart_set_options(port, co, baud, parity, bits, flow);
1618}
1619
b497549a
BD
1620static struct console s3c24xx_serial_console = {
1621 .name = S3C24XX_SERIAL_NAME,
1622 .device = uart_console_device,
1623 .flags = CON_PRINTBUFFER,
1624 .index = -1,
1625 .write = s3c24xx_serial_console_write,
5822a5df
TA
1626 .setup = s3c24xx_serial_console_setup,
1627 .data = &s3c24xx_uart_drv,
b497549a 1628};
da121506
TA
1629#endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */
1630
1631#ifdef CONFIG_CPU_S3C2410
1632static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = {
1633 .info = &(struct s3c24xx_uart_info) {
1634 .name = "Samsung S3C2410 UART",
1635 .type = PORT_S3C2410,
1636 .fifosize = 16,
1637 .rx_fifomask = S3C2410_UFSTAT_RXMASK,
1638 .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
1639 .rx_fifofull = S3C2410_UFSTAT_RXFULL,
1640 .tx_fifofull = S3C2410_UFSTAT_TXFULL,
1641 .tx_fifomask = S3C2410_UFSTAT_TXMASK,
1642 .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
1643 .def_clk_sel = S3C2410_UCON_CLKSEL0,
1644 .num_clks = 2,
1645 .clksel_mask = S3C2410_UCON_CLKMASK,
1646 .clksel_shift = S3C2410_UCON_CLKSHIFT,
1647 },
1648 .def_cfg = &(struct s3c2410_uartcfg) {
1649 .ucon = S3C2410_UCON_DEFAULT,
1650 .ufcon = S3C2410_UFCON_DEFAULT,
1651 },
1652};
1653#define S3C2410_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2410_serial_drv_data)
1654#else
1655#define S3C2410_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1656#endif
b497549a 1657
da121506
TA
1658#ifdef CONFIG_CPU_S3C2412
1659static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
1660 .info = &(struct s3c24xx_uart_info) {
1661 .name = "Samsung S3C2412 UART",
1662 .type = PORT_S3C2412,
1663 .fifosize = 64,
1664 .has_divslot = 1,
1665 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
1666 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
1667 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
1668 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
1669 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
1670 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
1671 .def_clk_sel = S3C2410_UCON_CLKSEL2,
1672 .num_clks = 4,
1673 .clksel_mask = S3C2412_UCON_CLKMASK,
1674 .clksel_shift = S3C2412_UCON_CLKSHIFT,
1675 },
1676 .def_cfg = &(struct s3c2410_uartcfg) {
1677 .ucon = S3C2410_UCON_DEFAULT,
1678 .ufcon = S3C2410_UFCON_DEFAULT,
1679 },
1680};
1681#define S3C2412_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2412_serial_drv_data)
1682#else
1683#define S3C2412_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1684#endif
b497549a 1685
da121506 1686#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \
b26469a8 1687 defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2442)
da121506
TA
1688static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
1689 .info = &(struct s3c24xx_uart_info) {
1690 .name = "Samsung S3C2440 UART",
1691 .type = PORT_S3C2440,
1692 .fifosize = 64,
1693 .has_divslot = 1,
1694 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
1695 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
1696 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
1697 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
1698 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
1699 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
1700 .def_clk_sel = S3C2410_UCON_CLKSEL2,
1701 .num_clks = 4,
1702 .clksel_mask = S3C2412_UCON_CLKMASK,
1703 .clksel_shift = S3C2412_UCON_CLKSHIFT,
1704 },
1705 .def_cfg = &(struct s3c2410_uartcfg) {
1706 .ucon = S3C2410_UCON_DEFAULT,
1707 .ufcon = S3C2410_UFCON_DEFAULT,
1708 },
1709};
1710#define S3C2440_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2440_serial_drv_data)
1711#else
1712#define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1713#endif
b497549a 1714
953b53a7 1715#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
da121506
TA
1716static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
1717 .info = &(struct s3c24xx_uart_info) {
1718 .name = "Samsung S3C6400 UART",
1719 .type = PORT_S3C6400,
1720 .fifosize = 64,
1721 .has_divslot = 1,
1722 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
1723 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
1724 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
1725 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
1726 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
1727 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
1728 .def_clk_sel = S3C2410_UCON_CLKSEL2,
1729 .num_clks = 4,
1730 .clksel_mask = S3C6400_UCON_CLKMASK,
1731 .clksel_shift = S3C6400_UCON_CLKSHIFT,
1732 },
1733 .def_cfg = &(struct s3c2410_uartcfg) {
1734 .ucon = S3C2410_UCON_DEFAULT,
1735 .ufcon = S3C2410_UFCON_DEFAULT,
1736 },
1737};
1738#define S3C6400_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c6400_serial_drv_data)
1739#else
1740#define S3C6400_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1741#endif
b497549a 1742
da121506
TA
1743#ifdef CONFIG_CPU_S5PV210
1744static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
1745 .info = &(struct s3c24xx_uart_info) {
1746 .name = "Samsung S5PV210 UART",
1747 .type = PORT_S3C6400,
1748 .has_divslot = 1,
1749 .rx_fifomask = S5PV210_UFSTAT_RXMASK,
1750 .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
1751 .rx_fifofull = S5PV210_UFSTAT_RXFULL,
1752 .tx_fifofull = S5PV210_UFSTAT_TXFULL,
1753 .tx_fifomask = S5PV210_UFSTAT_TXMASK,
1754 .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
1755 .def_clk_sel = S3C2410_UCON_CLKSEL0,
1756 .num_clks = 2,
1757 .clksel_mask = S5PV210_UCON_CLKMASK,
1758 .clksel_shift = S5PV210_UCON_CLKSHIFT,
1759 },
1760 .def_cfg = &(struct s3c2410_uartcfg) {
1761 .ucon = S5PV210_UCON_DEFAULT,
1762 .ufcon = S5PV210_UFCON_DEFAULT,
1763 },
1764 .fifosize = { 256, 64, 16, 16 },
1765};
1766#define S5PV210_SERIAL_DRV_DATA ((kernel_ulong_t)&s5pv210_serial_drv_data)
1767#else
1768#define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1769#endif
b497549a 1770
33f88136 1771#if defined(CONFIG_ARCH_EXYNOS)
da121506
TA
1772static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
1773 .info = &(struct s3c24xx_uart_info) {
1774 .name = "Samsung Exynos4 UART",
1775 .type = PORT_S3C6400,
1776 .has_divslot = 1,
1777 .rx_fifomask = S5PV210_UFSTAT_RXMASK,
1778 .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
1779 .rx_fifofull = S5PV210_UFSTAT_RXFULL,
1780 .tx_fifofull = S5PV210_UFSTAT_TXFULL,
1781 .tx_fifomask = S5PV210_UFSTAT_TXMASK,
1782 .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
1783 .def_clk_sel = S3C2410_UCON_CLKSEL0,
1784 .num_clks = 1,
1785 .clksel_mask = 0,
1786 .clksel_shift = 0,
1787 },
1788 .def_cfg = &(struct s3c2410_uartcfg) {
1789 .ucon = S5PV210_UCON_DEFAULT,
1790 .ufcon = S5PV210_UFCON_DEFAULT,
1791 .has_fracval = 1,
1792 },
1793 .fifosize = { 256, 64, 16, 16 },
1794};
1795#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data)
1796#else
1797#define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
1798#endif
b497549a 1799
da121506
TA
1800static struct platform_device_id s3c24xx_serial_driver_ids[] = {
1801 {
1802 .name = "s3c2410-uart",
1803 .driver_data = S3C2410_SERIAL_DRV_DATA,
1804 }, {
1805 .name = "s3c2412-uart",
1806 .driver_data = S3C2412_SERIAL_DRV_DATA,
1807 }, {
1808 .name = "s3c2440-uart",
1809 .driver_data = S3C2440_SERIAL_DRV_DATA,
1810 }, {
1811 .name = "s3c6400-uart",
1812 .driver_data = S3C6400_SERIAL_DRV_DATA,
1813 }, {
1814 .name = "s5pv210-uart",
1815 .driver_data = S5PV210_SERIAL_DRV_DATA,
1816 }, {
1817 .name = "exynos4210-uart",
1818 .driver_data = EXYNOS4210_SERIAL_DRV_DATA,
1819 },
1820 { },
1821};
1822MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids);
1823
26c919e1
TA
1824#ifdef CONFIG_OF
1825static const struct of_device_id s3c24xx_uart_dt_match[] = {
666ca0b9
HS
1826 { .compatible = "samsung,s3c2410-uart",
1827 .data = (void *)S3C2410_SERIAL_DRV_DATA },
1828 { .compatible = "samsung,s3c2412-uart",
1829 .data = (void *)S3C2412_SERIAL_DRV_DATA },
1830 { .compatible = "samsung,s3c2440-uart",
1831 .data = (void *)S3C2440_SERIAL_DRV_DATA },
1832 { .compatible = "samsung,s3c6400-uart",
1833 .data = (void *)S3C6400_SERIAL_DRV_DATA },
1834 { .compatible = "samsung,s5pv210-uart",
1835 .data = (void *)S5PV210_SERIAL_DRV_DATA },
26c919e1 1836 { .compatible = "samsung,exynos4210-uart",
a169a888 1837 .data = (void *)EXYNOS4210_SERIAL_DRV_DATA },
26c919e1
TA
1838 {},
1839};
1840MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
26c919e1
TA
1841#endif
1842
da121506
TA
1843static struct platform_driver samsung_serial_driver = {
1844 .probe = s3c24xx_serial_probe,
2d47b716 1845 .remove = s3c24xx_serial_remove,
da121506
TA
1846 .id_table = s3c24xx_serial_driver_ids,
1847 .driver = {
1848 .name = "samsung-uart",
da121506 1849 .pm = SERIAL_SAMSUNG_PM_OPS,
905f4ba2 1850 .of_match_table = of_match_ptr(s3c24xx_uart_dt_match),
da121506
TA
1851 },
1852};
b497549a 1853
6f134c3c 1854module_platform_driver(samsung_serial_driver);
b497549a 1855
da121506 1856MODULE_ALIAS("platform:samsung-uart");
b497549a
BD
1857MODULE_DESCRIPTION("Samsung SoC Serial port driver");
1858MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
1859MODULE_LICENSE("GPL v2");