1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/dmaengine.h>
25#include <linux/dma-mapping.h>
26#include <linux/slab.h>
27#include <linux/module.h>
28#include <linux/ioport.h>
29#include <linux/io.h>
30#include <linux/platform_device.h>
31#include <linux/init.h>
32#include <linux/sysrq.h>
33#include <linux/console.h>
34#include <linux/tty.h>
35#include <linux/tty_flip.h>
36#include <linux/serial_core.h>
37#include <linux/serial.h>
38#include <linux/serial_s3c.h>
39#include <linux/delay.h>
40#include <linux/clk.h>
41#include <linux/cpufreq.h>
42#include <linux/of.h>
43#include <asm/irq.h>
44
45
46
47#define S3C24XX_SERIAL_NAME "ttySAC"
48#define S3C24XX_SERIAL_MAJOR 204
49#define S3C24XX_SERIAL_MINOR 64
50
51#define S3C24XX_TX_PIO 1
52#define S3C24XX_TX_DMA 2
53#define S3C24XX_RX_PIO 1
54#define S3C24XX_RX_DMA 2
55
56
57#define RXSTAT_DUMMY_READ (0x10000000)
58
59enum s3c24xx_port_type {
60 TYPE_S3C24XX,
61 TYPE_S3C6400,
62 TYPE_APPLE_S5L,
63};
64
65struct s3c24xx_uart_info {
66 char *name;
67 enum s3c24xx_port_type type;
68 unsigned int has_usi;
69 unsigned int port_type;
70 unsigned int fifosize;
71 unsigned long rx_fifomask;
72 unsigned long rx_fifoshift;
73 unsigned long rx_fifofull;
74 unsigned long tx_fifomask;
75 unsigned long tx_fifoshift;
76 unsigned long tx_fifofull;
77 unsigned int def_clk_sel;
78 unsigned long num_clks;
79 unsigned long clksel_mask;
80 unsigned long clksel_shift;
81 unsigned long ucon_mask;
82
83
84
85 unsigned int has_divslot:1;
86};
87
88struct s3c24xx_serial_drv_data {
89 struct s3c24xx_uart_info *info;
90 struct s3c2410_uartcfg *def_cfg;
91 unsigned int fifosize[CONFIG_SERIAL_SAMSUNG_UARTS];
92};
93
94struct s3c24xx_uart_dma {
95 unsigned int rx_chan_id;
96 unsigned int tx_chan_id;
97
98 struct dma_slave_config rx_conf;
99 struct dma_slave_config tx_conf;
100
101 struct dma_chan *rx_chan;
102 struct dma_chan *tx_chan;
103
104 dma_addr_t rx_addr;
105 dma_addr_t tx_addr;
106
107 dma_cookie_t rx_cookie;
108 dma_cookie_t tx_cookie;
109
110 char *rx_buf;
111
112 dma_addr_t tx_transfer_addr;
113
114 size_t rx_size;
115 size_t tx_size;
116
117 struct dma_async_tx_descriptor *tx_desc;
118 struct dma_async_tx_descriptor *rx_desc;
119
120 int tx_bytes_requested;
121 int rx_bytes_requested;
122};
123
124struct s3c24xx_uart_port {
125 unsigned char rx_claimed;
126 unsigned char tx_claimed;
127 unsigned char rx_enabled;
128 unsigned char tx_enabled;
129 unsigned int pm_level;
130 unsigned long baudclk_rate;
131 unsigned int min_dma_size;
132
133 unsigned int rx_irq;
134 unsigned int tx_irq;
135
136 unsigned int tx_in_progress;
137 unsigned int tx_mode;
138 unsigned int rx_mode;
139
140 struct s3c24xx_uart_info *info;
141 struct clk *clk;
142 struct clk *baudclk;
143 struct uart_port port;
144 struct s3c24xx_serial_drv_data *drv_data;
145
146
147 struct s3c2410_uartcfg *cfg;
148
149 struct s3c24xx_uart_dma *dma;
150
151#ifdef CONFIG_ARM_S3C24XX_CPUFREQ
152 struct notifier_block freq_transition;
153#endif
154};
155
156static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport);
157
158
159
160#define s3c24xx_dev_to_port(__dev) dev_get_drvdata(__dev)
161
162
163
164#define portaddr(port, reg) ((port)->membase + (reg))
165#define portaddrl(port, reg) \
166 ((unsigned long *)(unsigned long)((port)->membase + (reg)))
167
168static u32 rd_reg(struct uart_port *port, u32 reg)
169{
170 switch (port->iotype) {
171 case UPIO_MEM:
172 return readb_relaxed(portaddr(port, reg));
173 case UPIO_MEM32:
174 return readl_relaxed(portaddr(port, reg));
175 default:
176 return 0;
177 }
178 return 0;
179}
180
181#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg)))
182
183static void wr_reg(struct uart_port *port, u32 reg, u32 val)
184{
185 switch (port->iotype) {
186 case UPIO_MEM:
187 writeb_relaxed(val, portaddr(port, reg));
188 break;
189 case UPIO_MEM32:
190 writel_relaxed(val, portaddr(port, reg));
191 break;
192 }
193}
194
195#define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg))
196
197
198
199static inline void s3c24xx_set_bit(struct uart_port *port, int idx,
200 unsigned int reg)
201{
202 unsigned long flags;
203 u32 val;
204
205 local_irq_save(flags);
206 val = rd_regl(port, reg);
207 val |= (1 << idx);
208 wr_regl(port, reg, val);
209 local_irq_restore(flags);
210}
211
212static inline void s3c24xx_clear_bit(struct uart_port *port, int idx,
213 unsigned int reg)
214{
215 unsigned long flags;
216 u32 val;
217
218 local_irq_save(flags);
219 val = rd_regl(port, reg);
220 val &= ~(1 << idx);
221 wr_regl(port, reg, val);
222 local_irq_restore(flags);
223}
224
225static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port)
226{
227 return container_of(port, struct s3c24xx_uart_port, port);
228}
229
230
231
232static inline const char *s3c24xx_serial_portname(struct uart_port *port)
233{
234 return to_platform_device(port->dev)->name;
235}
236
237static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
238{
239 return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;
240}
241
242static void s3c24xx_serial_rx_enable(struct uart_port *port)
243{
244 struct s3c24xx_uart_port *ourport = to_ourport(port);
245 unsigned long flags;
246 unsigned int ucon, ufcon;
247 int count = 10000;
248
249 spin_lock_irqsave(&port->lock, flags);
250
251 while (--count && !s3c24xx_serial_txempty_nofifo(port))
252 udelay(100);
253
254 ufcon = rd_regl(port, S3C2410_UFCON);
255 ufcon |= S3C2410_UFCON_RESETRX;
256 wr_regl(port, S3C2410_UFCON, ufcon);
257
258 ucon = rd_regl(port, S3C2410_UCON);
259 ucon |= S3C2410_UCON_RXIRQMODE;
260 wr_regl(port, S3C2410_UCON, ucon);
261
262 ourport->rx_enabled = 1;
263 spin_unlock_irqrestore(&port->lock, flags);
264}
265
266static void s3c24xx_serial_rx_disable(struct uart_port *port)
267{
268 struct s3c24xx_uart_port *ourport = to_ourport(port);
269 unsigned long flags;
270 unsigned int ucon;
271
272 spin_lock_irqsave(&port->lock, flags);
273
274 ucon = rd_regl(port, S3C2410_UCON);
275 ucon &= ~S3C2410_UCON_RXIRQMODE;
276 wr_regl(port, S3C2410_UCON, ucon);
277
278 ourport->rx_enabled = 0;
279 spin_unlock_irqrestore(&port->lock, flags);
280}
281
282static void s3c24xx_serial_stop_tx(struct uart_port *port)
283{
284 struct s3c24xx_uart_port *ourport = to_ourport(port);
285 struct s3c24xx_uart_dma *dma = ourport->dma;
286 struct circ_buf *xmit = &port->state->xmit;
287 struct dma_tx_state state;
288 int count;
289
290 if (!ourport->tx_enabled)
291 return;
292
293 switch (ourport->info->type) {
294 case TYPE_S3C6400:
295 s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
296 break;
297 case TYPE_APPLE_S5L:
298 s3c24xx_clear_bit(port, APPLE_S5L_UCON_TXTHRESH_ENA, S3C2410_UCON);
299 break;
300 default:
301 disable_irq_nosync(ourport->tx_irq);
302 break;
303 }
304
305 if (dma && dma->tx_chan && ourport->tx_in_progress == S3C24XX_TX_DMA) {
306 dmaengine_pause(dma->tx_chan);
307 dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state);
308 dmaengine_terminate_all(dma->tx_chan);
309 dma_sync_single_for_cpu(dma->tx_chan->device->dev,
310 dma->tx_transfer_addr, dma->tx_size,
311 DMA_TO_DEVICE);
312 async_tx_ack(dma->tx_desc);
313 count = dma->tx_bytes_requested - state.residue;
314 xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
315 port->icount.tx += count;
316 }
317
318 ourport->tx_enabled = 0;
319 ourport->tx_in_progress = 0;
320
321 if (port->flags & UPF_CONS_FLOW)
322 s3c24xx_serial_rx_enable(port);
323
324 ourport->tx_mode = 0;
325}
326
327static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport);
328
329static void s3c24xx_serial_tx_dma_complete(void *args)
330{
331 struct s3c24xx_uart_port *ourport = args;
332 struct uart_port *port = &ourport->port;
333 struct circ_buf *xmit = &port->state->xmit;
334 struct s3c24xx_uart_dma *dma = ourport->dma;
335 struct dma_tx_state state;
336 unsigned long flags;
337 int count;
338
339 dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state);
340 count = dma->tx_bytes_requested - state.residue;
341 async_tx_ack(dma->tx_desc);
342
343 dma_sync_single_for_cpu(dma->tx_chan->device->dev,
344 dma->tx_transfer_addr, dma->tx_size,
345 DMA_TO_DEVICE);
346
347 spin_lock_irqsave(&port->lock, flags);
348
349 xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
350 port->icount.tx += count;
351 ourport->tx_in_progress = 0;
352
353 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
354 uart_write_wakeup(port);
355
356 s3c24xx_serial_start_next_tx(ourport);
357 spin_unlock_irqrestore(&port->lock, flags);
358}
359
360static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
361{
362 struct uart_port *port = &ourport->port;
363 u32 ucon;
364
365
366 switch (ourport->info->type) {
367 case TYPE_S3C6400:
368 s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
369 break;
370 case TYPE_APPLE_S5L:
371 WARN_ON(1);
372 break;
373 default:
374 disable_irq_nosync(ourport->tx_irq);
375 break;
376 }
377
378
379 ucon = rd_regl(port, S3C2410_UCON);
380 ucon &= ~(S3C64XX_UCON_TXBURST_MASK | S3C64XX_UCON_TXMODE_MASK);
381 ucon |= (dma_get_cache_alignment() >= 16) ?
382 S3C64XX_UCON_TXBURST_16 : S3C64XX_UCON_TXBURST_1;
383 ucon |= S3C64XX_UCON_TXMODE_DMA;
384 wr_regl(port, S3C2410_UCON, ucon);
385
386 ourport->tx_mode = S3C24XX_TX_DMA;
387}
388
389static void enable_tx_pio(struct s3c24xx_uart_port *ourport)
390{
391 struct uart_port *port = &ourport->port;
392 u32 ucon, ufcon;
393
394
395 ourport->tx_in_progress = S3C24XX_TX_PIO;
396 ufcon = rd_regl(port, S3C2410_UFCON);
397 wr_regl(port, S3C2410_UFCON, ufcon);
398
399
400 ucon = rd_regl(port, S3C2410_UCON);
401 ucon &= ~(S3C64XX_UCON_TXMODE_MASK);
402 ucon |= S3C64XX_UCON_TXMODE_CPU;
403 wr_regl(port, S3C2410_UCON, ucon);
404
405
406 switch (ourport->info->type) {
407 case TYPE_S3C6400:
408 s3c24xx_clear_bit(port, S3C64XX_UINTM_TXD,
409 S3C64XX_UINTM);
410 break;
411 case TYPE_APPLE_S5L:
412 ucon |= APPLE_S5L_UCON_TXTHRESH_ENA_MSK;
413 wr_regl(port, S3C2410_UCON, ucon);
414 break;
415 default:
416 enable_irq(ourport->tx_irq);
417 break;
418 }
419
420 ourport->tx_mode = S3C24XX_TX_PIO;
421
422
423
424
425
426 if (ourport->info->type == TYPE_APPLE_S5L)
427 s3c24xx_serial_tx_chars(ourport);
428}
429
430static void s3c24xx_serial_start_tx_pio(struct s3c24xx_uart_port *ourport)
431{
432 if (ourport->tx_mode != S3C24XX_TX_PIO)
433 enable_tx_pio(ourport);
434}
435
436static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
437 unsigned int count)
438{
439 struct uart_port *port = &ourport->port;
440 struct circ_buf *xmit = &port->state->xmit;
441 struct s3c24xx_uart_dma *dma = ourport->dma;
442
443 if (ourport->tx_mode != S3C24XX_TX_DMA)
444 enable_tx_dma(ourport);
445
446 dma->tx_size = count & ~(dma_get_cache_alignment() - 1);
447 dma->tx_transfer_addr = dma->tx_addr + xmit->tail;
448
449 dma_sync_single_for_device(dma->tx_chan->device->dev,
450 dma->tx_transfer_addr, dma->tx_size,
451 DMA_TO_DEVICE);
452
453 dma->tx_desc = dmaengine_prep_slave_single(dma->tx_chan,
454 dma->tx_transfer_addr, dma->tx_size,
455 DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
456 if (!dma->tx_desc) {
457 dev_err(ourport->port.dev, "Unable to get desc for Tx\n");
458 return -EIO;
459 }
460
461 dma->tx_desc->callback = s3c24xx_serial_tx_dma_complete;
462 dma->tx_desc->callback_param = ourport;
463 dma->tx_bytes_requested = dma->tx_size;
464
465 ourport->tx_in_progress = S3C24XX_TX_DMA;
466 dma->tx_cookie = dmaengine_submit(dma->tx_desc);
467 dma_async_issue_pending(dma->tx_chan);
468 return 0;
469}
470
471static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport)
472{
473 struct uart_port *port = &ourport->port;
474 struct circ_buf *xmit = &port->state->xmit;
475 unsigned long count;
476
477
478 count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
479
480 if (!count) {
481 s3c24xx_serial_stop_tx(port);
482 return;
483 }
484
485 if (!ourport->dma || !ourport->dma->tx_chan ||
486 count < ourport->min_dma_size ||
487 xmit->tail & (dma_get_cache_alignment() - 1))
488 s3c24xx_serial_start_tx_pio(ourport);
489 else
490 s3c24xx_serial_start_tx_dma(ourport, count);
491}
492
493static void s3c24xx_serial_start_tx(struct uart_port *port)
494{
495 struct s3c24xx_uart_port *ourport = to_ourport(port);
496 struct circ_buf *xmit = &port->state->xmit;
497
498 if (!ourport->tx_enabled) {
499 if (port->flags & UPF_CONS_FLOW)
500 s3c24xx_serial_rx_disable(port);
501
502 ourport->tx_enabled = 1;
503 if (!ourport->dma || !ourport->dma->tx_chan)
504 s3c24xx_serial_start_tx_pio(ourport);
505 }
506
507 if (ourport->dma && ourport->dma->tx_chan) {
508 if (!uart_circ_empty(xmit) && !ourport->tx_in_progress)
509 s3c24xx_serial_start_next_tx(ourport);
510 }
511}
512
513static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport,
514 struct tty_port *tty, int count)
515{
516 struct s3c24xx_uart_dma *dma = ourport->dma;
517 int copied;
518
519 if (!count)
520 return;
521
522 dma_sync_single_for_cpu(dma->rx_chan->device->dev, dma->rx_addr,
523 dma->rx_size, DMA_FROM_DEVICE);
524
525 ourport->port.icount.rx += count;
526 if (!tty) {
527 dev_err(ourport->port.dev, "No tty port\n");
528 return;
529 }
530 copied = tty_insert_flip_string(tty,
531 ((unsigned char *)(ourport->dma->rx_buf)), count);
532 if (copied != count) {
533 WARN_ON(1);
534 dev_err(ourport->port.dev, "RxData copy to tty layer failed\n");
535 }
536}
537
538static void s3c24xx_serial_stop_rx(struct uart_port *port)
539{
540 struct s3c24xx_uart_port *ourport = to_ourport(port);
541 struct s3c24xx_uart_dma *dma = ourport->dma;
542 struct tty_port *t = &port->state->port;
543 struct dma_tx_state state;
544 enum dma_status dma_status;
545 unsigned int received;
546
547 if (ourport->rx_enabled) {
548 dev_dbg(port->dev, "stopping rx\n");
549 switch (ourport->info->type) {
550 case TYPE_S3C6400:
551 s3c24xx_set_bit(port, S3C64XX_UINTM_RXD,
552 S3C64XX_UINTM);
553 break;
554 case TYPE_APPLE_S5L:
555 s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
556 s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON);
557 break;
558 default:
559 disable_irq_nosync(ourport->rx_irq);
560 break;
561 }
562 ourport->rx_enabled = 0;
563 }
564 if (dma && dma->rx_chan) {
565 dmaengine_pause(dma->tx_chan);
566 dma_status = dmaengine_tx_status(dma->rx_chan,
567 dma->rx_cookie, &state);
568 if (dma_status == DMA_IN_PROGRESS ||
569 dma_status == DMA_PAUSED) {
570 received = dma->rx_bytes_requested - state.residue;
571 dmaengine_terminate_all(dma->rx_chan);
572 s3c24xx_uart_copy_rx_to_tty(ourport, t, received);
573 }
574 }
575}
576
577static inline struct s3c24xx_uart_info
578 *s3c24xx_port_to_info(struct uart_port *port)
579{
580 return to_ourport(port)->info;
581}
582
583static inline struct s3c2410_uartcfg
584 *s3c24xx_port_to_cfg(struct uart_port *port)
585{
586 struct s3c24xx_uart_port *ourport;
587
588 if (port->dev == NULL)
589 return NULL;
590
591 ourport = container_of(port, struct s3c24xx_uart_port, port);
592 return ourport->cfg;
593}
594
595static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,
596 unsigned long ufstat)
597{
598 struct s3c24xx_uart_info *info = ourport->info;
599
600 if (ufstat & info->rx_fifofull)
601 return ourport->port.fifosize;
602
603 return (ufstat & info->rx_fifomask) >> info->rx_fifoshift;
604}
605
606static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport);
607static void s3c24xx_serial_rx_dma_complete(void *args)
608{
609 struct s3c24xx_uart_port *ourport = args;
610 struct uart_port *port = &ourport->port;
611
612 struct s3c24xx_uart_dma *dma = ourport->dma;
613 struct tty_port *t = &port->state->port;
614 struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port);
615
616 struct dma_tx_state state;
617 unsigned long flags;
618 int received;
619
620 dmaengine_tx_status(dma->rx_chan, dma->rx_cookie, &state);
621 received = dma->rx_bytes_requested - state.residue;
622 async_tx_ack(dma->rx_desc);
623
624 spin_lock_irqsave(&port->lock, flags);
625
626 if (received)
627 s3c24xx_uart_copy_rx_to_tty(ourport, t, received);
628
629 if (tty) {
630 tty_flip_buffer_push(t);
631 tty_kref_put(tty);
632 }
633
634 s3c64xx_start_rx_dma(ourport);
635
636 spin_unlock_irqrestore(&port->lock, flags);
637}
638
639static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)
640{
641 struct s3c24xx_uart_dma *dma = ourport->dma;
642
643 dma_sync_single_for_device(dma->rx_chan->device->dev, dma->rx_addr,
644 dma->rx_size, DMA_FROM_DEVICE);
645
646 dma->rx_desc = dmaengine_prep_slave_single(dma->rx_chan,
647 dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM,
648 DMA_PREP_INTERRUPT);
649 if (!dma->rx_desc) {
650 dev_err(ourport->port.dev, "Unable to get desc for Rx\n");
651 return;
652 }
653
654 dma->rx_desc->callback = s3c24xx_serial_rx_dma_complete;
655 dma->rx_desc->callback_param = ourport;
656 dma->rx_bytes_requested = dma->rx_size;
657
658 dma->rx_cookie = dmaengine_submit(dma->rx_desc);
659 dma_async_issue_pending(dma->rx_chan);
660}
661
662
663#define S3C2410_UERSTAT_PARITY (0x1000)
664
665static void enable_rx_dma(struct s3c24xx_uart_port *ourport)
666{
667 struct uart_port *port = &ourport->port;
668 unsigned int ucon;
669
670
671 ucon = rd_regl(port, S3C2410_UCON);
672 ucon &= ~(S3C64XX_UCON_RXBURST_MASK |
673 S3C64XX_UCON_TIMEOUT_MASK |
674 S3C64XX_UCON_EMPTYINT_EN |
675 S3C64XX_UCON_DMASUS_EN |
676 S3C64XX_UCON_TIMEOUT_EN |
677 S3C64XX_UCON_RXMODE_MASK);
678 ucon |= S3C64XX_UCON_RXBURST_16 |
679 0xf << S3C64XX_UCON_TIMEOUT_SHIFT |
680 S3C64XX_UCON_EMPTYINT_EN |
681 S3C64XX_UCON_TIMEOUT_EN |
682 S3C64XX_UCON_RXMODE_DMA;
683 wr_regl(port, S3C2410_UCON, ucon);
684
685 ourport->rx_mode = S3C24XX_RX_DMA;
686}
687
688static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
689{
690 struct uart_port *port = &ourport->port;
691 unsigned int ucon;
692
693
694 ucon = rd_regl(port, S3C2410_UCON);
695 ucon &= ~S3C64XX_UCON_RXMODE_MASK;
696 ucon |= S3C64XX_UCON_RXMODE_CPU;
697
698
699 if (ourport->info->type != TYPE_APPLE_S5L) {
700 ucon &= ~(S3C64XX_UCON_TIMEOUT_MASK |
701 S3C64XX_UCON_EMPTYINT_EN |
702 S3C64XX_UCON_DMASUS_EN |
703 S3C64XX_UCON_TIMEOUT_EN);
704 ucon |= 0xf << S3C64XX_UCON_TIMEOUT_SHIFT |
705 S3C64XX_UCON_TIMEOUT_EN;
706 }
707 wr_regl(port, S3C2410_UCON, ucon);
708
709 ourport->rx_mode = S3C24XX_RX_PIO;
710}
711
712static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport);
713
714static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
715{
716 unsigned int utrstat, received;
717 struct s3c24xx_uart_port *ourport = dev_id;
718 struct uart_port *port = &ourport->port;
719 struct s3c24xx_uart_dma *dma = ourport->dma;
720 struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port);
721 struct tty_port *t = &port->state->port;
722 struct dma_tx_state state;
723
724 utrstat = rd_regl(port, S3C2410_UTRSTAT);
725 rd_regl(port, S3C2410_UFSTAT);
726
727 spin_lock(&port->lock);
728
729 if (!(utrstat & S3C2410_UTRSTAT_TIMEOUT)) {
730 s3c64xx_start_rx_dma(ourport);
731 if (ourport->rx_mode == S3C24XX_RX_PIO)
732 enable_rx_dma(ourport);
733 goto finish;
734 }
735
736 if (ourport->rx_mode == S3C24XX_RX_DMA) {
737 dmaengine_pause(dma->rx_chan);
738 dmaengine_tx_status(dma->rx_chan, dma->rx_cookie, &state);
739 dmaengine_terminate_all(dma->rx_chan);
740 received = dma->rx_bytes_requested - state.residue;
741 s3c24xx_uart_copy_rx_to_tty(ourport, t, received);
742
743 enable_rx_pio(ourport);
744 }
745
746 s3c24xx_serial_rx_drain_fifo(ourport);
747
748 if (tty) {
749 tty_flip_buffer_push(t);
750 tty_kref_put(tty);
751 }
752
753 wr_regl(port, S3C2410_UTRSTAT, S3C2410_UTRSTAT_TIMEOUT);
754
755finish:
756 spin_unlock(&port->lock);
757
758 return IRQ_HANDLED;
759}
760
761static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
762{
763 struct uart_port *port = &ourport->port;
764 unsigned int ufcon, ch, flag, ufstat, uerstat;
765 unsigned int fifocnt = 0;
766 int max_count = port->fifosize;
767
768 while (max_count-- > 0) {
769
770
771
772
773 if (fifocnt == 0) {
774 ufstat = rd_regl(port, S3C2410_UFSTAT);
775 fifocnt = s3c24xx_serial_rx_fifocnt(ourport, ufstat);
776 if (fifocnt == 0)
777 break;
778 }
779 fifocnt--;
780
781 uerstat = rd_regl(port, S3C2410_UERSTAT);
782 ch = rd_reg(port, S3C2410_URXH);
783
784 if (port->flags & UPF_CONS_FLOW) {
785 int txe = s3c24xx_serial_txempty_nofifo(port);
786
787 if (ourport->rx_enabled) {
788 if (!txe) {
789 ourport->rx_enabled = 0;
790 continue;
791 }
792 } else {
793 if (txe) {
794 ufcon = rd_regl(port, S3C2410_UFCON);
795 ufcon |= S3C2410_UFCON_RESETRX;
796 wr_regl(port, S3C2410_UFCON, ufcon);
797 ourport->rx_enabled = 1;
798 return;
799 }
800 continue;
801 }
802 }
803
804
805
806 flag = TTY_NORMAL;
807 port->icount.rx++;
808
809 if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
810 dev_dbg(port->dev,
811 "rxerr: port ch=0x%02x, rxs=0x%08x\n",
812 ch, uerstat);
813
814
815 if (uerstat & S3C2410_UERSTAT_BREAK) {
816 dev_dbg(port->dev, "break!\n");
817 port->icount.brk++;
818 if (uart_handle_break(port))
819 continue;
820 }
821
822 if (uerstat & S3C2410_UERSTAT_FRAME)
823 port->icount.frame++;
824 if (uerstat & S3C2410_UERSTAT_OVERRUN)
825 port->icount.overrun++;
826
827 uerstat &= port->read_status_mask;
828
829 if (uerstat & S3C2410_UERSTAT_BREAK)
830 flag = TTY_BREAK;
831 else if (uerstat & S3C2410_UERSTAT_PARITY)
832 flag = TTY_PARITY;
833 else if (uerstat & (S3C2410_UERSTAT_FRAME |
834 S3C2410_UERSTAT_OVERRUN))
835 flag = TTY_FRAME;
836 }
837
838 if (uart_handle_sysrq_char(port, ch))
839 continue;
840
841 uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
842 ch, flag);
843 }
844
845 tty_flip_buffer_push(&port->state->port);
846}
847
848static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id)
849{
850 struct s3c24xx_uart_port *ourport = dev_id;
851 struct uart_port *port = &ourport->port;
852
853 spin_lock(&port->lock);
854 s3c24xx_serial_rx_drain_fifo(ourport);
855 spin_unlock(&port->lock);
856
857 return IRQ_HANDLED;
858}
859
860static irqreturn_t s3c24xx_serial_rx_irq(int irq, void *dev_id)
861{
862 struct s3c24xx_uart_port *ourport = dev_id;
863
864 if (ourport->dma && ourport->dma->rx_chan)
865 return s3c24xx_serial_rx_chars_dma(dev_id);
866 return s3c24xx_serial_rx_chars_pio(dev_id);
867}
868
869static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
870{
871 struct uart_port *port = &ourport->port;
872 struct circ_buf *xmit = &port->state->xmit;
873 int count, dma_count = 0;
874
875 count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
876
877 if (ourport->dma && ourport->dma->tx_chan &&
878 count >= ourport->min_dma_size) {
879 int align = dma_get_cache_alignment() -
880 (xmit->tail & (dma_get_cache_alignment() - 1));
881 if (count - align >= ourport->min_dma_size) {
882 dma_count = count - align;
883 count = align;
884 }
885 }
886
887 if (port->x_char) {
888 wr_reg(port, S3C2410_UTXH, port->x_char);
889 port->icount.tx++;
890 port->x_char = 0;
891 return;
892 }
893
894
895
896
897
898 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
899 s3c24xx_serial_stop_tx(port);
900 return;
901 }
902
903
904
905 if (count > port->fifosize) {
906 count = port->fifosize;
907 dma_count = 0;
908 }
909
910 while (!uart_circ_empty(xmit) && count > 0) {
911 if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
912 break;
913
914 wr_reg(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
915 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
916 port->icount.tx++;
917 count--;
918 }
919
920 if (!count && dma_count) {
921 s3c24xx_serial_start_tx_dma(ourport, dma_count);
922 return;
923 }
924
925 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
926 spin_unlock(&port->lock);
927 uart_write_wakeup(port);
928 spin_lock(&port->lock);
929 }
930
931 if (uart_circ_empty(xmit))
932 s3c24xx_serial_stop_tx(port);
933}
934
935static irqreturn_t s3c24xx_serial_tx_irq(int irq, void *id)
936{
937 struct s3c24xx_uart_port *ourport = id;
938 struct uart_port *port = &ourport->port;
939
940 spin_lock(&port->lock);
941
942 s3c24xx_serial_tx_chars(ourport);
943
944 spin_unlock(&port->lock);
945 return IRQ_HANDLED;
946}
947
948
949static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
950{
951 struct s3c24xx_uart_port *ourport = id;
952 struct uart_port *port = &ourport->port;
953 unsigned int pend = rd_regl(port, S3C64XX_UINTP);
954 irqreturn_t ret = IRQ_HANDLED;
955
956 if (pend & S3C64XX_UINTM_RXD_MSK) {
957 ret = s3c24xx_serial_rx_irq(irq, id);
958 wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK);
959 }
960 if (pend & S3C64XX_UINTM_TXD_MSK) {
961 ret = s3c24xx_serial_tx_irq(irq, id);
962 wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK);
963 }
964 return ret;
965}
966
967
968static irqreturn_t apple_serial_handle_irq(int irq, void *id)
969{
970 struct s3c24xx_uart_port *ourport = id;
971 struct uart_port *port = &ourport->port;
972 unsigned int pend = rd_regl(port, S3C2410_UTRSTAT);
973 irqreturn_t ret = IRQ_NONE;
974
975 if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO)) {
976 wr_regl(port, S3C2410_UTRSTAT,
977 APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO);
978 ret = s3c24xx_serial_rx_irq(irq, id);
979 }
980 if (pend & APPLE_S5L_UTRSTAT_TXTHRESH) {
981 wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_TXTHRESH);
982 ret = s3c24xx_serial_tx_irq(irq, id);
983 }
984
985 return ret;
986}
987
988static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
989{
990 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
991 unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT);
992 unsigned long ufcon = rd_regl(port, S3C2410_UFCON);
993
994 if (ufcon & S3C2410_UFCON_FIFOMODE) {
995 if ((ufstat & info->tx_fifomask) != 0 ||
996 (ufstat & info->tx_fifofull))
997 return 0;
998
999 return 1;
1000 }
1001
1002 return s3c24xx_serial_txempty_nofifo(port);
1003}
1004
1005
1006static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
1007{
1008 unsigned int umstat = rd_reg(port, S3C2410_UMSTAT);
1009
1010 if (umstat & S3C2410_UMSTAT_CTS)
1011 return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
1012 else
1013 return TIOCM_CAR | TIOCM_DSR;
1014}
1015
1016static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
1017{
1018 unsigned int umcon = rd_regl(port, S3C2410_UMCON);
1019
1020 if (mctrl & TIOCM_RTS)
1021 umcon |= S3C2410_UMCOM_RTS_LOW;
1022 else
1023 umcon &= ~S3C2410_UMCOM_RTS_LOW;
1024
1025 wr_regl(port, S3C2410_UMCON, umcon);
1026}
1027
1028static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
1029{
1030 unsigned long flags;
1031 unsigned int ucon;
1032
1033 spin_lock_irqsave(&port->lock, flags);
1034
1035 ucon = rd_regl(port, S3C2410_UCON);
1036
1037 if (break_state)
1038 ucon |= S3C2410_UCON_SBREAK;
1039 else
1040 ucon &= ~S3C2410_UCON_SBREAK;
1041
1042 wr_regl(port, S3C2410_UCON, ucon);
1043
1044 spin_unlock_irqrestore(&port->lock, flags);
1045}
1046
1047static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
1048{
1049 struct s3c24xx_uart_dma *dma = p->dma;
1050 struct dma_slave_caps dma_caps;
1051 const char *reason = NULL;
1052 int ret;
1053
1054
1055 dma->rx_conf.direction = DMA_DEV_TO_MEM;
1056 dma->rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
1057 dma->rx_conf.src_addr = p->port.mapbase + S3C2410_URXH;
1058 dma->rx_conf.src_maxburst = 1;
1059
1060 dma->tx_conf.direction = DMA_MEM_TO_DEV;
1061 dma->tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
1062 dma->tx_conf.dst_addr = p->port.mapbase + S3C2410_UTXH;
1063 dma->tx_conf.dst_maxburst = 1;
1064
1065 dma->rx_chan = dma_request_chan(p->port.dev, "rx");
1066
1067 if (IS_ERR(dma->rx_chan)) {
1068 reason = "DMA RX channel request failed";
1069 ret = PTR_ERR(dma->rx_chan);
1070 goto err_warn;
1071 }
1072
1073 ret = dma_get_slave_caps(dma->rx_chan, &dma_caps);
1074 if (ret < 0 ||
1075 dma_caps.residue_granularity < DMA_RESIDUE_GRANULARITY_BURST) {
1076 reason = "insufficient DMA RX engine capabilities";
1077 ret = -EOPNOTSUPP;
1078 goto err_release_rx;
1079 }
1080
1081 dmaengine_slave_config(dma->rx_chan, &dma->rx_conf);
1082
1083 dma->tx_chan = dma_request_chan(p->port.dev, "tx");
1084 if (IS_ERR(dma->tx_chan)) {
1085 reason = "DMA TX channel request failed";
1086 ret = PTR_ERR(dma->tx_chan);
1087 goto err_release_rx;
1088 }
1089
1090 ret = dma_get_slave_caps(dma->tx_chan, &dma_caps);
1091 if (ret < 0 ||
1092 dma_caps.residue_granularity < DMA_RESIDUE_GRANULARITY_BURST) {
1093 reason = "insufficient DMA TX engine capabilities";
1094 ret = -EOPNOTSUPP;
1095 goto err_release_tx;
1096 }
1097
1098 dmaengine_slave_config(dma->tx_chan, &dma->tx_conf);
1099
1100
1101 dma->rx_size = PAGE_SIZE;
1102
1103 dma->rx_buf = kmalloc(dma->rx_size, GFP_KERNEL);
1104 if (!dma->rx_buf) {
1105 ret = -ENOMEM;
1106 goto err_release_tx;
1107 }
1108
1109 dma->rx_addr = dma_map_single(dma->rx_chan->device->dev, dma->rx_buf,
1110 dma->rx_size, DMA_FROM_DEVICE);
1111 if (dma_mapping_error(dma->rx_chan->device->dev, dma->rx_addr)) {
1112 reason = "DMA mapping error for RX buffer";
1113 ret = -EIO;
1114 goto err_free_rx;
1115 }
1116
1117
1118 dma->tx_addr = dma_map_single(dma->tx_chan->device->dev,
1119 p->port.state->xmit.buf, UART_XMIT_SIZE,
1120 DMA_TO_DEVICE);
1121 if (dma_mapping_error(dma->tx_chan->device->dev, dma->tx_addr)) {
1122 reason = "DMA mapping error for TX buffer";
1123 ret = -EIO;
1124 goto err_unmap_rx;
1125 }
1126
1127 return 0;
1128
1129err_unmap_rx:
1130 dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
1131 dma->rx_size, DMA_FROM_DEVICE);
1132err_free_rx:
1133 kfree(dma->rx_buf);
1134err_release_tx:
1135 dma_release_channel(dma->tx_chan);
1136err_release_rx:
1137 dma_release_channel(dma->rx_chan);
1138err_warn:
1139 if (reason)
1140 dev_warn(p->port.dev, "%s, DMA will not be used\n", reason);
1141 return ret;
1142}
1143
1144static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
1145{
1146 struct s3c24xx_uart_dma *dma = p->dma;
1147
1148 if (dma->rx_chan) {
1149 dmaengine_terminate_all(dma->rx_chan);
1150 dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
1151 dma->rx_size, DMA_FROM_DEVICE);
1152 kfree(dma->rx_buf);
1153 dma_release_channel(dma->rx_chan);
1154 dma->rx_chan = NULL;
1155 }
1156
1157 if (dma->tx_chan) {
1158 dmaengine_terminate_all(dma->tx_chan);
1159 dma_unmap_single(dma->tx_chan->device->dev, dma->tx_addr,
1160 UART_XMIT_SIZE, DMA_TO_DEVICE);
1161 dma_release_channel(dma->tx_chan);
1162 dma->tx_chan = NULL;
1163 }
1164}
1165
1166static void s3c24xx_serial_shutdown(struct uart_port *port)
1167{
1168 struct s3c24xx_uart_port *ourport = to_ourport(port);
1169
1170 if (ourport->tx_claimed) {
1171 free_irq(ourport->tx_irq, ourport);
1172 ourport->tx_enabled = 0;
1173 ourport->tx_claimed = 0;
1174 ourport->tx_mode = 0;
1175 }
1176
1177 if (ourport->rx_claimed) {
1178 free_irq(ourport->rx_irq, ourport);
1179 ourport->rx_claimed = 0;
1180 ourport->rx_enabled = 0;
1181 }
1182
1183 if (ourport->dma)
1184 s3c24xx_serial_release_dma(ourport);
1185
1186 ourport->tx_in_progress = 0;
1187}
1188
1189static void s3c64xx_serial_shutdown(struct uart_port *port)
1190{
1191 struct s3c24xx_uart_port *ourport = to_ourport(port);
1192
1193 ourport->tx_enabled = 0;
1194 ourport->tx_mode = 0;
1195 ourport->rx_enabled = 0;
1196
1197 free_irq(port->irq, ourport);
1198
1199 wr_regl(port, S3C64XX_UINTP, 0xf);
1200 wr_regl(port, S3C64XX_UINTM, 0xf);
1201
1202 if (ourport->dma)
1203 s3c24xx_serial_release_dma(ourport);
1204
1205 ourport->tx_in_progress = 0;
1206}
1207
1208static void apple_s5l_serial_shutdown(struct uart_port *port)
1209{
1210 struct s3c24xx_uart_port *ourport = to_ourport(port);
1211
1212 unsigned int ucon;
1213
1214 ucon = rd_regl(port, S3C2410_UCON);
1215 ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
1216 APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
1217 APPLE_S5L_UCON_RXTO_ENA_MSK);
1218 wr_regl(port, S3C2410_UCON, ucon);
1219
1220 wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
1221
1222 free_irq(port->irq, ourport);
1223
1224 ourport->tx_enabled = 0;
1225 ourport->tx_mode = 0;
1226 ourport->rx_enabled = 0;
1227
1228 if (ourport->dma)
1229 s3c24xx_serial_release_dma(ourport);
1230
1231 ourport->tx_in_progress = 0;
1232}
1233
1234static int s3c24xx_serial_startup(struct uart_port *port)
1235{
1236 struct s3c24xx_uart_port *ourport = to_ourport(port);
1237 int ret;
1238
1239 ourport->rx_enabled = 1;
1240
1241 ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_irq, 0,
1242 s3c24xx_serial_portname(port), ourport);
1243
1244 if (ret != 0) {
1245 dev_err(port->dev, "cannot get irq %d\n", ourport->rx_irq);
1246 return ret;
1247 }
1248
1249 ourport->rx_claimed = 1;
1250
1251 dev_dbg(port->dev, "requesting tx irq...\n");
1252
1253 ourport->tx_enabled = 1;
1254
1255 ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_irq, 0,
1256 s3c24xx_serial_portname(port), ourport);
1257
1258 if (ret) {
1259 dev_err(port->dev, "cannot get irq %d\n", ourport->tx_irq);
1260 goto err;
1261 }
1262
1263 ourport->tx_claimed = 1;
1264
1265
1266
1267
1268
1269 return ret;
1270
1271err:
1272 s3c24xx_serial_shutdown(port);
1273 return ret;
1274}
1275
1276static int s3c64xx_serial_startup(struct uart_port *port)
1277{
1278 struct s3c24xx_uart_port *ourport = to_ourport(port);
1279 unsigned long flags;
1280 unsigned int ufcon;
1281 int ret;
1282
1283 wr_regl(port, S3C64XX_UINTM, 0xf);
1284 if (ourport->dma) {
1285 ret = s3c24xx_serial_request_dma(ourport);
1286 if (ret < 0) {
1287 devm_kfree(port->dev, ourport->dma);
1288 ourport->dma = NULL;
1289 }
1290 }
1291
1292 ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED,
1293 s3c24xx_serial_portname(port), ourport);
1294 if (ret) {
1295 dev_err(port->dev, "cannot get irq %d\n", port->irq);
1296 return ret;
1297 }
1298
1299
1300 ourport->rx_enabled = 1;
1301 ourport->tx_enabled = 0;
1302
1303 spin_lock_irqsave(&port->lock, flags);
1304
1305 ufcon = rd_regl(port, S3C2410_UFCON);
1306 ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
1307 if (!uart_console(port))
1308 ufcon |= S3C2410_UFCON_RESETTX;
1309 wr_regl(port, S3C2410_UFCON, ufcon);
1310
1311 enable_rx_pio(ourport);
1312
1313 spin_unlock_irqrestore(&port->lock, flags);
1314
1315
1316 s3c24xx_clear_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM);
1317
1318 return ret;
1319}
1320
1321static int apple_s5l_serial_startup(struct uart_port *port)
1322{
1323 struct s3c24xx_uart_port *ourport = to_ourport(port);
1324 unsigned long flags;
1325 unsigned int ufcon;
1326 int ret;
1327
1328 wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
1329
1330 ret = request_irq(port->irq, apple_serial_handle_irq, 0,
1331 s3c24xx_serial_portname(port), ourport);
1332 if (ret) {
1333 dev_err(port->dev, "cannot get irq %d\n", port->irq);
1334 return ret;
1335 }
1336
1337
1338 ourport->rx_enabled = 1;
1339 ourport->tx_enabled = 0;
1340
1341 spin_lock_irqsave(&port->lock, flags);
1342
1343 ufcon = rd_regl(port, S3C2410_UFCON);
1344 ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
1345 if (!uart_console(port))
1346 ufcon |= S3C2410_UFCON_RESETTX;
1347 wr_regl(port, S3C2410_UFCON, ufcon);
1348
1349 enable_rx_pio(ourport);
1350
1351 spin_unlock_irqrestore(&port->lock, flags);
1352
1353
1354 s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
1355 s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON);
1356
1357 return ret;
1358}
1359
1360static void exynos_usi_init(struct uart_port *port)
1361{
1362 struct s3c24xx_uart_port *ourport = to_ourport(port);
1363 struct s3c24xx_uart_info *info = ourport->info;
1364 unsigned int val;
1365
1366 if (!info->has_usi)
1367 return;
1368
1369
1370 val = rd_regl(port, USI_CON);
1371 val &= ~USI_CON_RESET_MASK;
1372 wr_regl(port, USI_CON, val);
1373 udelay(1);
1374
1375
1376 val = rd_regl(port, USI_OPTION);
1377 val &= ~USI_OPTION_HWACG_MASK;
1378 val |= USI_OPTION_HWACG_CLKREQ_ON;
1379 wr_regl(port, USI_OPTION, val);
1380}
1381
1382
1383
1384static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
1385 unsigned int old)
1386{
1387 struct s3c24xx_uart_port *ourport = to_ourport(port);
1388 int timeout = 10000;
1389
1390 ourport->pm_level = level;
1391
1392 switch (level) {
1393 case 3:
1394 while (--timeout && !s3c24xx_serial_txempty_nofifo(port))
1395 udelay(100);
1396
1397 if (!IS_ERR(ourport->baudclk))
1398 clk_disable_unprepare(ourport->baudclk);
1399
1400 clk_disable_unprepare(ourport->clk);
1401 break;
1402
1403 case 0:
1404 clk_prepare_enable(ourport->clk);
1405
1406 if (!IS_ERR(ourport->baudclk))
1407 clk_prepare_enable(ourport->baudclk);
1408
1409 exynos_usi_init(port);
1410 break;
1411 default:
1412 dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level);
1413 }
1414}
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429#define MAX_CLK_NAME_LENGTH 15
1430
1431static inline int s3c24xx_serial_getsource(struct uart_port *port)
1432{
1433 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1434 unsigned int ucon;
1435
1436 if (info->num_clks == 1)
1437 return 0;
1438
1439 ucon = rd_regl(port, S3C2410_UCON);
1440 ucon &= info->clksel_mask;
1441 return ucon >> info->clksel_shift;
1442}
1443
1444static void s3c24xx_serial_setsource(struct uart_port *port,
1445 unsigned int clk_sel)
1446{
1447 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1448 unsigned int ucon;
1449
1450 if (info->num_clks == 1)
1451 return;
1452
1453 ucon = rd_regl(port, S3C2410_UCON);
1454 if ((ucon & info->clksel_mask) >> info->clksel_shift == clk_sel)
1455 return;
1456
1457 ucon &= ~info->clksel_mask;
1458 ucon |= clk_sel << info->clksel_shift;
1459 wr_regl(port, S3C2410_UCON, ucon);
1460}
1461
1462static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
1463 unsigned int req_baud, struct clk **best_clk,
1464 unsigned int *clk_num)
1465{
1466 struct s3c24xx_uart_info *info = ourport->info;
1467 struct clk *clk;
1468 unsigned long rate;
1469 unsigned int cnt, baud, quot, best_quot = 0;
1470 char clkname[MAX_CLK_NAME_LENGTH];
1471 int calc_deviation, deviation = (1 << 30) - 1;
1472
1473 for (cnt = 0; cnt < info->num_clks; cnt++) {
1474
1475 if (ourport->cfg->clk_sel &&
1476 !(ourport->cfg->clk_sel & (1 << cnt)))
1477 continue;
1478
1479 sprintf(clkname, "clk_uart_baud%d", cnt);
1480 clk = clk_get(ourport->port.dev, clkname);
1481 if (IS_ERR(clk))
1482 continue;
1483
1484 rate = clk_get_rate(clk);
1485 if (!rate)
1486 continue;
1487
1488 if (ourport->info->has_divslot) {
1489 unsigned long div = rate / req_baud;
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499 quot = div / 16;
1500 baud = rate / div;
1501 } else {
1502 quot = (rate + (8 * req_baud)) / (16 * req_baud);
1503 baud = rate / (quot * 16);
1504 }
1505 quot--;
1506
1507 calc_deviation = req_baud - baud;
1508 if (calc_deviation < 0)
1509 calc_deviation = -calc_deviation;
1510
1511 if (calc_deviation < deviation) {
1512 *best_clk = clk;
1513 best_quot = quot;
1514 *clk_num = cnt;
1515 deviation = calc_deviation;
1516 }
1517 }
1518
1519 return best_quot;
1520}
1521
1522
1523
1524
1525
1526
1527static u16 udivslot_table[16] = {
1528 [0] = 0x0000,
1529 [1] = 0x0080,
1530 [2] = 0x0808,
1531 [3] = 0x0888,
1532 [4] = 0x2222,
1533 [5] = 0x4924,
1534 [6] = 0x4A52,
1535 [7] = 0x54AA,
1536 [8] = 0x5555,
1537 [9] = 0xD555,
1538 [10] = 0xD5D5,
1539 [11] = 0xDDD5,
1540 [12] = 0xDDDD,
1541 [13] = 0xDFDD,
1542 [14] = 0xDFDF,
1543 [15] = 0xFFDF,
1544};
1545
1546static void s3c24xx_serial_set_termios(struct uart_port *port,
1547 struct ktermios *termios,
1548 struct ktermios *old)
1549{
1550 struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
1551 struct s3c24xx_uart_port *ourport = to_ourport(port);
1552 struct clk *clk = ERR_PTR(-EINVAL);
1553 unsigned long flags;
1554 unsigned int baud, quot, clk_sel = 0;
1555 unsigned int ulcon;
1556 unsigned int umcon;
1557 unsigned int udivslot = 0;
1558
1559
1560
1561
1562 termios->c_cflag &= ~(HUPCL | CMSPAR);
1563 termios->c_cflag |= CLOCAL;
1564
1565
1566
1567
1568
1569 baud = uart_get_baud_rate(port, termios, old, 0, 3000000);
1570 quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel);
1571 if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
1572 quot = port->custom_divisor;
1573 if (IS_ERR(clk))
1574 return;
1575
1576
1577
1578 if (ourport->baudclk != clk) {
1579 clk_prepare_enable(clk);
1580
1581 s3c24xx_serial_setsource(port, clk_sel);
1582
1583 if (!IS_ERR(ourport->baudclk)) {
1584 clk_disable_unprepare(ourport->baudclk);
1585 ourport->baudclk = ERR_PTR(-EINVAL);
1586 }
1587
1588 ourport->baudclk = clk;
1589 ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
1590 }
1591
1592 if (ourport->info->has_divslot) {
1593 unsigned int div = ourport->baudclk_rate / baud;
1594
1595 if (cfg->has_fracval) {
1596 udivslot = (div & 15);
1597 dev_dbg(port->dev, "fracval = %04x\n", udivslot);
1598 } else {
1599 udivslot = udivslot_table[div & 15];
1600 dev_dbg(port->dev, "udivslot = %04x (div %d)\n",
1601 udivslot, div & 15);
1602 }
1603 }
1604
1605 switch (termios->c_cflag & CSIZE) {
1606 case CS5:
1607 dev_dbg(port->dev, "config: 5bits/char\n");
1608 ulcon = S3C2410_LCON_CS5;
1609 break;
1610 case CS6:
1611 dev_dbg(port->dev, "config: 6bits/char\n");
1612 ulcon = S3C2410_LCON_CS6;
1613 break;
1614 case CS7:
1615 dev_dbg(port->dev, "config: 7bits/char\n");
1616 ulcon = S3C2410_LCON_CS7;
1617 break;
1618 case CS8:
1619 default:
1620 dev_dbg(port->dev, "config: 8bits/char\n");
1621 ulcon = S3C2410_LCON_CS8;
1622 break;
1623 }
1624
1625
1626 ulcon |= (cfg->ulcon & S3C2410_LCON_IRM);
1627
1628 if (termios->c_cflag & CSTOPB)
1629 ulcon |= S3C2410_LCON_STOPB;
1630
1631 if (termios->c_cflag & PARENB) {
1632 if (termios->c_cflag & PARODD)
1633 ulcon |= S3C2410_LCON_PODD;
1634 else
1635 ulcon |= S3C2410_LCON_PEVEN;
1636 } else {
1637 ulcon |= S3C2410_LCON_PNONE;
1638 }
1639
1640 spin_lock_irqsave(&port->lock, flags);
1641
1642 dev_dbg(port->dev,
1643 "setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
1644 ulcon, quot, udivslot);
1645
1646 wr_regl(port, S3C2410_ULCON, ulcon);
1647 wr_regl(port, S3C2410_UBRDIV, quot);
1648
1649 port->status &= ~UPSTAT_AUTOCTS;
1650
1651 umcon = rd_regl(port, S3C2410_UMCON);
1652 if (termios->c_cflag & CRTSCTS) {
1653 umcon |= S3C2410_UMCOM_AFC;
1654
1655 umcon &= ~S3C2412_UMCON_AFC_8;
1656 port->status = UPSTAT_AUTOCTS;
1657 } else {
1658 umcon &= ~S3C2410_UMCOM_AFC;
1659 }
1660 wr_regl(port, S3C2410_UMCON, umcon);
1661
1662 if (ourport->info->has_divslot)
1663 wr_regl(port, S3C2443_DIVSLOT, udivslot);
1664
1665 dev_dbg(port->dev,
1666 "uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
1667 rd_regl(port, S3C2410_ULCON),
1668 rd_regl(port, S3C2410_UCON),
1669 rd_regl(port, S3C2410_UFCON));
1670
1671
1672
1673
1674 uart_update_timeout(port, termios->c_cflag, baud);
1675
1676
1677
1678
1679 port->read_status_mask = S3C2410_UERSTAT_OVERRUN;
1680 if (termios->c_iflag & INPCK)
1681 port->read_status_mask |= S3C2410_UERSTAT_FRAME |
1682 S3C2410_UERSTAT_PARITY;
1683
1684
1685
1686 port->ignore_status_mask = 0;
1687 if (termios->c_iflag & IGNPAR)
1688 port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN;
1689 if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
1690 port->ignore_status_mask |= S3C2410_UERSTAT_FRAME;
1691
1692
1693
1694
1695 if ((termios->c_cflag & CREAD) == 0)
1696 port->ignore_status_mask |= RXSTAT_DUMMY_READ;
1697
1698 spin_unlock_irqrestore(&port->lock, flags);
1699}
1700
1701static const char *s3c24xx_serial_type(struct uart_port *port)
1702{
1703 struct s3c24xx_uart_port *ourport = to_ourport(port);
1704
1705 switch (ourport->info->type) {
1706 case TYPE_S3C24XX:
1707 return "S3C24XX";
1708 case TYPE_S3C6400:
1709 return "S3C6400/10";
1710 case TYPE_APPLE_S5L:
1711 return "APPLE S5L";
1712 default:
1713 return NULL;
1714 }
1715}
1716
1717static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
1718{
1719 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1720
1721 if (flags & UART_CONFIG_TYPE)
1722 port->type = info->port_type;
1723}
1724
1725
1726
1727
1728static int
1729s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
1730{
1731 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1732
1733 if (ser->type != PORT_UNKNOWN && ser->type != info->port_type)
1734 return -EINVAL;
1735
1736 return 0;
1737}
1738
1739#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
1740
1741static struct console s3c24xx_serial_console;
1742
1743static int __init s3c24xx_serial_console_init(void)
1744{
1745 register_console(&s3c24xx_serial_console);
1746 return 0;
1747}
1748console_initcall(s3c24xx_serial_console_init);
1749
1750#define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
1751#else
1752#define S3C24XX_SERIAL_CONSOLE NULL
1753#endif
1754
1755#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
1756static int s3c24xx_serial_get_poll_char(struct uart_port *port);
1757static void s3c24xx_serial_put_poll_char(struct uart_port *port,
1758 unsigned char c);
1759#endif
1760
1761static const struct uart_ops s3c24xx_serial_ops = {
1762 .pm = s3c24xx_serial_pm,
1763 .tx_empty = s3c24xx_serial_tx_empty,
1764 .get_mctrl = s3c24xx_serial_get_mctrl,
1765 .set_mctrl = s3c24xx_serial_set_mctrl,
1766 .stop_tx = s3c24xx_serial_stop_tx,
1767 .start_tx = s3c24xx_serial_start_tx,
1768 .stop_rx = s3c24xx_serial_stop_rx,
1769 .break_ctl = s3c24xx_serial_break_ctl,
1770 .startup = s3c24xx_serial_startup,
1771 .shutdown = s3c24xx_serial_shutdown,
1772 .set_termios = s3c24xx_serial_set_termios,
1773 .type = s3c24xx_serial_type,
1774 .config_port = s3c24xx_serial_config_port,
1775 .verify_port = s3c24xx_serial_verify_port,
1776#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
1777 .poll_get_char = s3c24xx_serial_get_poll_char,
1778 .poll_put_char = s3c24xx_serial_put_poll_char,
1779#endif
1780};
1781
1782static const struct uart_ops s3c64xx_serial_ops = {
1783 .pm = s3c24xx_serial_pm,
1784 .tx_empty = s3c24xx_serial_tx_empty,
1785 .get_mctrl = s3c24xx_serial_get_mctrl,
1786 .set_mctrl = s3c24xx_serial_set_mctrl,
1787 .stop_tx = s3c24xx_serial_stop_tx,
1788 .start_tx = s3c24xx_serial_start_tx,
1789 .stop_rx = s3c24xx_serial_stop_rx,
1790 .break_ctl = s3c24xx_serial_break_ctl,
1791 .startup = s3c64xx_serial_startup,
1792 .shutdown = s3c64xx_serial_shutdown,
1793 .set_termios = s3c24xx_serial_set_termios,
1794 .type = s3c24xx_serial_type,
1795 .config_port = s3c24xx_serial_config_port,
1796 .verify_port = s3c24xx_serial_verify_port,
1797#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
1798 .poll_get_char = s3c24xx_serial_get_poll_char,
1799 .poll_put_char = s3c24xx_serial_put_poll_char,
1800#endif
1801};
1802
1803static const struct uart_ops apple_s5l_serial_ops = {
1804 .pm = s3c24xx_serial_pm,
1805 .tx_empty = s3c24xx_serial_tx_empty,
1806 .get_mctrl = s3c24xx_serial_get_mctrl,
1807 .set_mctrl = s3c24xx_serial_set_mctrl,
1808 .stop_tx = s3c24xx_serial_stop_tx,
1809 .start_tx = s3c24xx_serial_start_tx,
1810 .stop_rx = s3c24xx_serial_stop_rx,
1811 .break_ctl = s3c24xx_serial_break_ctl,
1812 .startup = apple_s5l_serial_startup,
1813 .shutdown = apple_s5l_serial_shutdown,
1814 .set_termios = s3c24xx_serial_set_termios,
1815 .type = s3c24xx_serial_type,
1816 .config_port = s3c24xx_serial_config_port,
1817 .verify_port = s3c24xx_serial_verify_port,
1818#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
1819 .poll_get_char = s3c24xx_serial_get_poll_char,
1820 .poll_put_char = s3c24xx_serial_put_poll_char,
1821#endif
1822};
1823
1824static struct uart_driver s3c24xx_uart_drv = {
1825 .owner = THIS_MODULE,
1826 .driver_name = "s3c2410_serial",
1827 .nr = CONFIG_SERIAL_SAMSUNG_UARTS,
1828 .cons = S3C24XX_SERIAL_CONSOLE,
1829 .dev_name = S3C24XX_SERIAL_NAME,
1830 .major = S3C24XX_SERIAL_MAJOR,
1831 .minor = S3C24XX_SERIAL_MINOR,
1832};
1833
1834#define __PORT_LOCK_UNLOCKED(i) \
1835 __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[i].port.lock)
1836static struct s3c24xx_uart_port
1837s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
1838 [0] = {
1839 .port = {
1840 .lock = __PORT_LOCK_UNLOCKED(0),
1841 .iotype = UPIO_MEM,
1842 .uartclk = 0,
1843 .fifosize = 16,
1844 .ops = &s3c24xx_serial_ops,
1845 .flags = UPF_BOOT_AUTOCONF,
1846 .line = 0,
1847 }
1848 },
1849 [1] = {
1850 .port = {
1851 .lock = __PORT_LOCK_UNLOCKED(1),
1852 .iotype = UPIO_MEM,
1853 .uartclk = 0,
1854 .fifosize = 16,
1855 .ops = &s3c24xx_serial_ops,
1856 .flags = UPF_BOOT_AUTOCONF,
1857 .line = 1,
1858 }
1859 },
1860#if CONFIG_SERIAL_SAMSUNG_UARTS > 2
1861 [2] = {
1862 .port = {
1863 .lock = __PORT_LOCK_UNLOCKED(2),
1864 .iotype = UPIO_MEM,
1865 .uartclk = 0,
1866 .fifosize = 16,
1867 .ops = &s3c24xx_serial_ops,
1868 .flags = UPF_BOOT_AUTOCONF,
1869 .line = 2,
1870 }
1871 },
1872#endif
1873#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
1874 [3] = {
1875 .port = {
1876 .lock = __PORT_LOCK_UNLOCKED(3),
1877 .iotype = UPIO_MEM,
1878 .uartclk = 0,
1879 .fifosize = 16,
1880 .ops = &s3c24xx_serial_ops,
1881 .flags = UPF_BOOT_AUTOCONF,
1882 .line = 3,
1883 }
1884 }
1885#endif
1886};
1887#undef __PORT_LOCK_UNLOCKED
1888
1889
1890
1891
1892
1893
1894static void s3c24xx_serial_resetport(struct uart_port *port,
1895 struct s3c2410_uartcfg *cfg)
1896{
1897 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1898 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1899
1900 ucon &= (info->clksel_mask | info->ucon_mask);
1901 wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
1902
1903
1904 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
1905 wr_regl(port, S3C2410_UFCON, cfg->ufcon);
1906
1907
1908 udelay(1);
1909}
1910
1911#ifdef CONFIG_ARM_S3C24XX_CPUFREQ
1912
1913static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
1914 unsigned long val, void *data)
1915{
1916 struct s3c24xx_uart_port *port;
1917 struct uart_port *uport;
1918
1919 port = container_of(nb, struct s3c24xx_uart_port, freq_transition);
1920 uport = &port->port;
1921
1922
1923
1924 if (port->pm_level != 0)
1925 return 0;
1926
1927
1928
1929
1930
1931
1932 if (IS_ERR(port->baudclk))
1933 goto exit;
1934
1935 if (port->baudclk_rate == clk_get_rate(port->baudclk))
1936 goto exit;
1937
1938 if (val == CPUFREQ_PRECHANGE) {
1939
1940
1941
1942
1943 } else if (val == CPUFREQ_POSTCHANGE) {
1944 struct ktermios *termios;
1945 struct tty_struct *tty;
1946
1947 if (uport->state == NULL)
1948 goto exit;
1949
1950 tty = uport->state->port.tty;
1951
1952 if (tty == NULL)
1953 goto exit;
1954
1955 termios = &tty->termios;
1956
1957 if (termios == NULL) {
1958 dev_warn(uport->dev, "%s: no termios?\n", __func__);
1959 goto exit;
1960 }
1961
1962 s3c24xx_serial_set_termios(uport, termios, NULL);
1963 }
1964
1965exit:
1966 return 0;
1967}
1968
1969static inline int
1970s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
1971{
1972 port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition;
1973
1974 return cpufreq_register_notifier(&port->freq_transition,
1975 CPUFREQ_TRANSITION_NOTIFIER);
1976}
1977
1978static inline void
1979s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
1980{
1981 cpufreq_unregister_notifier(&port->freq_transition,
1982 CPUFREQ_TRANSITION_NOTIFIER);
1983}
1984
1985#else
1986static inline int
1987s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
1988{
1989 return 0;
1990}
1991
1992static inline void
1993s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
1994{
1995}
1996#endif
1997
1998static int s3c24xx_serial_enable_baudclk(struct s3c24xx_uart_port *ourport)
1999{
2000 struct device *dev = ourport->port.dev;
2001 struct s3c24xx_uart_info *info = ourport->info;
2002 char clk_name[MAX_CLK_NAME_LENGTH];
2003 unsigned int clk_sel;
2004 struct clk *clk;
2005 int clk_num;
2006 int ret;
2007
2008 clk_sel = ourport->cfg->clk_sel ? : info->def_clk_sel;
2009 for (clk_num = 0; clk_num < info->num_clks; clk_num++) {
2010 if (!(clk_sel & (1 << clk_num)))
2011 continue;
2012
2013 sprintf(clk_name, "clk_uart_baud%d", clk_num);
2014 clk = clk_get(dev, clk_name);
2015 if (IS_ERR(clk))
2016 continue;
2017
2018 ret = clk_prepare_enable(clk);
2019 if (ret) {
2020 clk_put(clk);
2021 continue;
2022 }
2023
2024 ourport->baudclk = clk;
2025 ourport->baudclk_rate = clk_get_rate(clk);
2026 s3c24xx_serial_setsource(&ourport->port, clk_num);
2027
2028 return 0;
2029 }
2030
2031 return -EINVAL;
2032}
2033
2034
2035
2036
2037
2038
2039static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
2040 struct platform_device *platdev)
2041{
2042 struct uart_port *port = &ourport->port;
2043 struct s3c2410_uartcfg *cfg = ourport->cfg;
2044 struct resource *res;
2045 int ret;
2046
2047 if (platdev == NULL)
2048 return -ENODEV;
2049
2050 if (port->mapbase != 0)
2051 return -EINVAL;
2052
2053
2054 port->dev = &platdev->dev;
2055
2056 port->uartclk = 1;
2057
2058 if (cfg->uart_flags & UPF_CONS_FLOW) {
2059 dev_dbg(port->dev, "enabling flow control\n");
2060 port->flags |= UPF_CONS_FLOW;
2061 }
2062
2063
2064
2065 res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
2066 if (res == NULL) {
2067 dev_err(port->dev, "failed to find memory resource for uart\n");
2068 return -EINVAL;
2069 }
2070
2071 dev_dbg(port->dev, "resource %pR)\n", res);
2072
2073 port->membase = devm_ioremap_resource(port->dev, res);
2074 if (IS_ERR(port->membase)) {
2075 dev_err(port->dev, "failed to remap controller address\n");
2076 return -EBUSY;
2077 }
2078
2079 port->mapbase = res->start;
2080 ret = platform_get_irq(platdev, 0);
2081 if (ret < 0) {
2082 port->irq = 0;
2083 } else {
2084 port->irq = ret;
2085 ourport->rx_irq = ret;
2086 ourport->tx_irq = ret + 1;
2087 }
2088
2089 switch (ourport->info->type) {
2090 case TYPE_S3C24XX:
2091 ret = platform_get_irq(platdev, 1);
2092 if (ret > 0)
2093 ourport->tx_irq = ret;
2094 break;
2095 default:
2096 break;
2097 }
2098
2099
2100
2101
2102
2103 if (platdev->dev.of_node && of_find_property(platdev->dev.of_node,
2104 "dmas", NULL)) {
2105 ourport->dma = devm_kzalloc(port->dev,
2106 sizeof(*ourport->dma),
2107 GFP_KERNEL);
2108 if (!ourport->dma) {
2109 ret = -ENOMEM;
2110 goto err;
2111 }
2112 }
2113
2114 ourport->clk = clk_get(&platdev->dev, "uart");
2115 if (IS_ERR(ourport->clk)) {
2116 pr_err("%s: Controller clock not found\n",
2117 dev_name(&platdev->dev));
2118 ret = PTR_ERR(ourport->clk);
2119 goto err;
2120 }
2121
2122 ret = clk_prepare_enable(ourport->clk);
2123 if (ret) {
2124 pr_err("uart: clock failed to prepare+enable: %d\n", ret);
2125 clk_put(ourport->clk);
2126 goto err;
2127 }
2128
2129 ret = s3c24xx_serial_enable_baudclk(ourport);
2130 if (ret)
2131 pr_warn("uart: failed to enable baudclk\n");
2132
2133 exynos_usi_init(port);
2134
2135
2136 switch (ourport->info->type) {
2137 case TYPE_S3C6400:
2138 wr_regl(port, S3C64XX_UINTM, 0xf);
2139 wr_regl(port, S3C64XX_UINTP, 0xf);
2140 wr_regl(port, S3C64XX_UINTSP, 0xf);
2141 break;
2142 case TYPE_APPLE_S5L: {
2143 unsigned int ucon;
2144
2145 ucon = rd_regl(port, S3C2410_UCON);
2146 ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
2147 APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
2148 APPLE_S5L_UCON_RXTO_ENA_MSK);
2149 wr_regl(port, S3C2410_UCON, ucon);
2150
2151 wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
2152 break;
2153 }
2154 default:
2155 break;
2156 }
2157
2158 dev_dbg(port->dev, "port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n",
2159 &port->mapbase, port->membase, port->irq,
2160 ourport->rx_irq, ourport->tx_irq, port->uartclk);
2161
2162
2163 s3c24xx_serial_resetport(port, cfg);
2164
2165 return 0;
2166
2167err:
2168 port->mapbase = 0;
2169 return ret;
2170}
2171
2172
2173
2174#ifdef CONFIG_OF
2175static const struct of_device_id s3c24xx_uart_dt_match[];
2176#endif
2177
2178static int probe_index;
2179
2180static inline struct s3c24xx_serial_drv_data *
2181s3c24xx_get_driver_data(struct platform_device *pdev)
2182{
2183#ifdef CONFIG_OF
2184 if (pdev->dev.of_node) {
2185 const struct of_device_id *match;
2186
2187 match = of_match_node(s3c24xx_uart_dt_match, pdev->dev.of_node);
2188 return (struct s3c24xx_serial_drv_data *)match->data;
2189 }
2190#endif
2191 return (struct s3c24xx_serial_drv_data *)
2192 platform_get_device_id(pdev)->driver_data;
2193}
2194
2195static int s3c24xx_serial_probe(struct platform_device *pdev)
2196{
2197 struct device_node *np = pdev->dev.of_node;
2198 struct s3c24xx_uart_port *ourport;
2199 int index = probe_index;
2200 int ret, prop = 0;
2201
2202 if (np) {
2203 ret = of_alias_get_id(np, "serial");
2204 if (ret >= 0)
2205 index = ret;
2206 }
2207
2208 if (index >= ARRAY_SIZE(s3c24xx_serial_ports)) {
2209 dev_err(&pdev->dev, "serial%d out of range\n", index);
2210 return -EINVAL;
2211 }
2212 ourport = &s3c24xx_serial_ports[index];
2213
2214 ourport->drv_data = s3c24xx_get_driver_data(pdev);
2215 if (!ourport->drv_data) {
2216 dev_err(&pdev->dev, "could not find driver data\n");
2217 return -ENODEV;
2218 }
2219
2220 ourport->baudclk = ERR_PTR(-EINVAL);
2221 ourport->info = ourport->drv_data->info;
2222 ourport->cfg = (dev_get_platdata(&pdev->dev)) ?
2223 dev_get_platdata(&pdev->dev) :
2224 ourport->drv_data->def_cfg;
2225
2226 switch (ourport->info->type) {
2227 case TYPE_S3C24XX:
2228 ourport->port.ops = &s3c24xx_serial_ops;
2229 break;
2230 case TYPE_S3C6400:
2231 ourport->port.ops = &s3c64xx_serial_ops;
2232 break;
2233 case TYPE_APPLE_S5L:
2234 ourport->port.ops = &apple_s5l_serial_ops;
2235 break;
2236 }
2237
2238 if (np) {
2239 of_property_read_u32(np,
2240 "samsung,uart-fifosize", &ourport->port.fifosize);
2241
2242 if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
2243 switch (prop) {
2244 case 1:
2245 ourport->port.iotype = UPIO_MEM;
2246 break;
2247 case 4:
2248 ourport->port.iotype = UPIO_MEM32;
2249 break;
2250 default:
2251 dev_warn(&pdev->dev, "unsupported reg-io-width (%d)\n",
2252 prop);
2253 return -EINVAL;
2254 }
2255 }
2256 }
2257
2258 if (ourport->drv_data->fifosize[index])
2259 ourport->port.fifosize = ourport->drv_data->fifosize[index];
2260 else if (ourport->info->fifosize)
2261 ourport->port.fifosize = ourport->info->fifosize;
2262 ourport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SAMSUNG_CONSOLE);
2263
2264
2265
2266
2267
2268 ourport->min_dma_size = max_t(int, ourport->port.fifosize,
2269 dma_get_cache_alignment());
2270
2271 dev_dbg(&pdev->dev, "%s: initialising port %p...\n", __func__, ourport);
2272
2273 ret = s3c24xx_serial_init_port(ourport, pdev);
2274 if (ret < 0)
2275 return ret;
2276
2277 if (!s3c24xx_uart_drv.state) {
2278 ret = uart_register_driver(&s3c24xx_uart_drv);
2279 if (ret < 0) {
2280 pr_err("Failed to register Samsung UART driver\n");
2281 return ret;
2282 }
2283 }
2284
2285 dev_dbg(&pdev->dev, "%s: adding port\n", __func__);
2286 uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
2287 platform_set_drvdata(pdev, &ourport->port);
2288
2289
2290
2291
2292
2293
2294 clk_disable_unprepare(ourport->clk);
2295 if (!IS_ERR(ourport->baudclk))
2296 clk_disable_unprepare(ourport->baudclk);
2297
2298 ret = s3c24xx_serial_cpufreq_register(ourport);
2299 if (ret < 0)
2300 dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
2301
2302 probe_index++;
2303
2304 return 0;
2305}
2306
2307static int s3c24xx_serial_remove(struct platform_device *dev)
2308{
2309 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
2310
2311 if (port) {
2312 s3c24xx_serial_cpufreq_deregister(to_ourport(port));
2313 uart_remove_one_port(&s3c24xx_uart_drv, port);
2314 }
2315
2316 uart_unregister_driver(&s3c24xx_uart_drv);
2317
2318 return 0;
2319}
2320
2321
2322#ifdef CONFIG_PM_SLEEP
2323static int s3c24xx_serial_suspend(struct device *dev)
2324{
2325 struct uart_port *port = s3c24xx_dev_to_port(dev);
2326
2327 if (port)
2328 uart_suspend_port(&s3c24xx_uart_drv, port);
2329
2330 return 0;
2331}
2332
2333static int s3c24xx_serial_resume(struct device *dev)
2334{
2335 struct uart_port *port = s3c24xx_dev_to_port(dev);
2336 struct s3c24xx_uart_port *ourport = to_ourport(port);
2337
2338 if (port) {
2339 clk_prepare_enable(ourport->clk);
2340 if (!IS_ERR(ourport->baudclk))
2341 clk_prepare_enable(ourport->baudclk);
2342 s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
2343 if (!IS_ERR(ourport->baudclk))
2344 clk_disable_unprepare(ourport->baudclk);
2345 clk_disable_unprepare(ourport->clk);
2346
2347 uart_resume_port(&s3c24xx_uart_drv, port);
2348 }
2349
2350 return 0;
2351}
2352
2353static int s3c24xx_serial_resume_noirq(struct device *dev)
2354{
2355 struct uart_port *port = s3c24xx_dev_to_port(dev);
2356 struct s3c24xx_uart_port *ourport = to_ourport(port);
2357
2358 if (port) {
2359
2360 switch (ourport->info->type) {
2361 case TYPE_S3C6400: {
2362 unsigned int uintm = 0xf;
2363
2364 if (ourport->tx_enabled)
2365 uintm &= ~S3C64XX_UINTM_TXD_MSK;
2366 if (ourport->rx_enabled)
2367 uintm &= ~S3C64XX_UINTM_RXD_MSK;
2368 clk_prepare_enable(ourport->clk);
2369 if (!IS_ERR(ourport->baudclk))
2370 clk_prepare_enable(ourport->baudclk);
2371 wr_regl(port, S3C64XX_UINTM, uintm);
2372 if (!IS_ERR(ourport->baudclk))
2373 clk_disable_unprepare(ourport->baudclk);
2374 clk_disable_unprepare(ourport->clk);
2375 break;
2376 }
2377 case TYPE_APPLE_S5L: {
2378 unsigned int ucon;
2379 int ret;
2380
2381 ret = clk_prepare_enable(ourport->clk);
2382 if (ret) {
2383 dev_err(dev, "clk_enable clk failed: %d\n", ret);
2384 return ret;
2385 }
2386 if (!IS_ERR(ourport->baudclk)) {
2387 ret = clk_prepare_enable(ourport->baudclk);
2388 if (ret) {
2389 dev_err(dev, "clk_enable baudclk failed: %d\n", ret);
2390 clk_disable_unprepare(ourport->clk);
2391 return ret;
2392 }
2393 }
2394
2395 ucon = rd_regl(port, S3C2410_UCON);
2396
2397 ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
2398 APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
2399 APPLE_S5L_UCON_RXTO_ENA_MSK);
2400
2401 if (ourport->tx_enabled)
2402 ucon |= APPLE_S5L_UCON_TXTHRESH_ENA_MSK;
2403 if (ourport->rx_enabled)
2404 ucon |= APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
2405 APPLE_S5L_UCON_RXTO_ENA_MSK;
2406
2407 wr_regl(port, S3C2410_UCON, ucon);
2408
2409 if (!IS_ERR(ourport->baudclk))
2410 clk_disable_unprepare(ourport->baudclk);
2411 clk_disable_unprepare(ourport->clk);
2412 break;
2413 }
2414 default:
2415 break;
2416 }
2417 }
2418
2419 return 0;
2420}
2421
2422static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
2423 .suspend = s3c24xx_serial_suspend,
2424 .resume = s3c24xx_serial_resume,
2425 .resume_noirq = s3c24xx_serial_resume_noirq,
2426};
2427#define SERIAL_SAMSUNG_PM_OPS (&s3c24xx_serial_pm_ops)
2428
2429#else
2430
2431#define SERIAL_SAMSUNG_PM_OPS NULL
2432#endif
2433
2434
2435
2436#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
2437
2438static struct uart_port *cons_uart;
2439
2440static int
2441s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
2442{
2443 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
2444 unsigned long ufstat, utrstat;
2445
2446 if (ufcon & S3C2410_UFCON_FIFOMODE) {
2447
2448
2449 ufstat = rd_regl(port, S3C2410_UFSTAT);
2450 return (ufstat & info->tx_fifofull) ? 0 : 1;
2451 }
2452
2453
2454
2455 utrstat = rd_regl(port, S3C2410_UTRSTAT);
2456 return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
2457}
2458
2459static bool
2460s3c24xx_port_configured(unsigned int ucon)
2461{
2462
2463 return (ucon & 0xf) != 0;
2464}
2465
2466#ifdef CONFIG_CONSOLE_POLL
2467
2468
2469
2470
2471
2472static int s3c24xx_serial_get_poll_char(struct uart_port *port)
2473{
2474 struct s3c24xx_uart_port *ourport = to_ourport(port);
2475 unsigned int ufstat;
2476
2477 ufstat = rd_regl(port, S3C2410_UFSTAT);
2478 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
2479 return NO_POLL_CHAR;
2480
2481 return rd_reg(port, S3C2410_URXH);
2482}
2483
2484static void s3c24xx_serial_put_poll_char(struct uart_port *port,
2485 unsigned char c)
2486{
2487 unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
2488 unsigned int ucon = rd_regl(port, S3C2410_UCON);
2489
2490
2491 if (!s3c24xx_port_configured(ucon))
2492 return;
2493
2494 while (!s3c24xx_serial_console_txrdy(port, ufcon))
2495 cpu_relax();
2496 wr_reg(port, S3C2410_UTXH, c);
2497}
2498
2499#endif
2500
2501static void
2502s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
2503{
2504 unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
2505
2506 while (!s3c24xx_serial_console_txrdy(port, ufcon))
2507 cpu_relax();
2508 wr_reg(port, S3C2410_UTXH, ch);
2509}
2510
2511static void
2512s3c24xx_serial_console_write(struct console *co, const char *s,
2513 unsigned int count)
2514{
2515 unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
2516
2517
2518 if (!s3c24xx_port_configured(ucon))
2519 return;
2520
2521 uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
2522}
2523
2524static void __init
2525s3c24xx_serial_get_options(struct uart_port *port, int *baud,
2526 int *parity, int *bits)
2527{
2528 struct clk *clk;
2529 unsigned int ulcon;
2530 unsigned int ucon;
2531 unsigned int ubrdiv;
2532 unsigned long rate;
2533 unsigned int clk_sel;
2534 char clk_name[MAX_CLK_NAME_LENGTH];
2535
2536 ulcon = rd_regl(port, S3C2410_ULCON);
2537 ucon = rd_regl(port, S3C2410_UCON);
2538 ubrdiv = rd_regl(port, S3C2410_UBRDIV);
2539
2540 if (s3c24xx_port_configured(ucon)) {
2541 switch (ulcon & S3C2410_LCON_CSMASK) {
2542 case S3C2410_LCON_CS5:
2543 *bits = 5;
2544 break;
2545 case S3C2410_LCON_CS6:
2546 *bits = 6;
2547 break;
2548 case S3C2410_LCON_CS7:
2549 *bits = 7;
2550 break;
2551 case S3C2410_LCON_CS8:
2552 default:
2553 *bits = 8;
2554 break;
2555 }
2556
2557 switch (ulcon & S3C2410_LCON_PMASK) {
2558 case S3C2410_LCON_PEVEN:
2559 *parity = 'e';
2560 break;
2561
2562 case S3C2410_LCON_PODD:
2563 *parity = 'o';
2564 break;
2565
2566 case S3C2410_LCON_PNONE:
2567 default:
2568 *parity = 'n';
2569 }
2570
2571
2572
2573 clk_sel = s3c24xx_serial_getsource(port);
2574 sprintf(clk_name, "clk_uart_baud%d", clk_sel);
2575
2576 clk = clk_get(port->dev, clk_name);
2577 if (!IS_ERR(clk))
2578 rate = clk_get_rate(clk);
2579 else
2580 rate = 1;
2581
2582 *baud = rate / (16 * (ubrdiv + 1));
2583 dev_dbg(port->dev, "calculated baud %d\n", *baud);
2584 }
2585}
2586
2587static int __init
2588s3c24xx_serial_console_setup(struct console *co, char *options)
2589{
2590 struct uart_port *port;
2591 int baud = 9600;
2592 int bits = 8;
2593 int parity = 'n';
2594 int flow = 'n';
2595
2596
2597
2598 if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS)
2599 co->index = 0;
2600
2601 port = &s3c24xx_serial_ports[co->index].port;
2602
2603
2604
2605 if (port->mapbase == 0x0)
2606 return -ENODEV;
2607
2608 cons_uart = port;
2609
2610
2611
2612
2613
2614
2615 if (options)
2616 uart_parse_options(options, &baud, &parity, &bits, &flow);
2617 else
2618 s3c24xx_serial_get_options(port, &baud, &parity, &bits);
2619
2620 dev_dbg(port->dev, "baud %d\n", baud);
2621
2622 return uart_set_options(port, co, baud, parity, bits, flow);
2623}
2624
2625static struct console s3c24xx_serial_console = {
2626 .name = S3C24XX_SERIAL_NAME,
2627 .device = uart_console_device,
2628 .flags = CON_PRINTBUFFER,
2629 .index = -1,
2630 .write = s3c24xx_serial_console_write,
2631 .setup = s3c24xx_serial_console_setup,
2632 .data = &s3c24xx_uart_drv,
2633};
2634#endif
2635
2636#ifdef CONFIG_CPU_S3C2410
2637static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = {
2638 .info = &(struct s3c24xx_uart_info) {
2639 .name = "Samsung S3C2410 UART",
2640 .type = TYPE_S3C24XX,
2641 .port_type = PORT_S3C2410,
2642 .fifosize = 16,
2643 .rx_fifomask = S3C2410_UFSTAT_RXMASK,
2644 .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
2645 .rx_fifofull = S3C2410_UFSTAT_RXFULL,
2646 .tx_fifofull = S3C2410_UFSTAT_TXFULL,
2647 .tx_fifomask = S3C2410_UFSTAT_TXMASK,
2648 .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
2649 .def_clk_sel = S3C2410_UCON_CLKSEL0,
2650 .num_clks = 2,
2651 .clksel_mask = S3C2410_UCON_CLKMASK,
2652 .clksel_shift = S3C2410_UCON_CLKSHIFT,
2653 },
2654 .def_cfg = &(struct s3c2410_uartcfg) {
2655 .ucon = S3C2410_UCON_DEFAULT,
2656 .ufcon = S3C2410_UFCON_DEFAULT,
2657 },
2658};
2659#define S3C2410_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2410_serial_drv_data)
2660#else
2661#define S3C2410_SERIAL_DRV_DATA (kernel_ulong_t)NULL
2662#endif
2663
2664#ifdef CONFIG_CPU_S3C2412
2665static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
2666 .info = &(struct s3c24xx_uart_info) {
2667 .name = "Samsung S3C2412 UART",
2668 .type = TYPE_S3C24XX,
2669 .port_type = PORT_S3C2412,
2670 .fifosize = 64,
2671 .has_divslot = 1,
2672 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
2673 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
2674 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
2675 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
2676 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
2677 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
2678 .def_clk_sel = S3C2410_UCON_CLKSEL2,
2679 .num_clks = 4,
2680 .clksel_mask = S3C2412_UCON_CLKMASK,
2681 .clksel_shift = S3C2412_UCON_CLKSHIFT,
2682 },
2683 .def_cfg = &(struct s3c2410_uartcfg) {
2684 .ucon = S3C2410_UCON_DEFAULT,
2685 .ufcon = S3C2410_UFCON_DEFAULT,
2686 },
2687};
2688#define S3C2412_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2412_serial_drv_data)
2689#else
2690#define S3C2412_SERIAL_DRV_DATA (kernel_ulong_t)NULL
2691#endif
2692
2693#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \
2694 defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2442)
2695static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
2696 .info = &(struct s3c24xx_uart_info) {
2697 .name = "Samsung S3C2440 UART",
2698 .type = TYPE_S3C24XX,
2699 .port_type = PORT_S3C2440,
2700 .fifosize = 64,
2701 .has_divslot = 1,
2702 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
2703 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
2704 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
2705 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
2706 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
2707 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
2708 .def_clk_sel = S3C2410_UCON_CLKSEL2,
2709 .num_clks = 4,
2710 .clksel_mask = S3C2412_UCON_CLKMASK,
2711 .clksel_shift = S3C2412_UCON_CLKSHIFT,
2712 .ucon_mask = S3C2440_UCON0_DIVMASK,
2713 },
2714 .def_cfg = &(struct s3c2410_uartcfg) {
2715 .ucon = S3C2410_UCON_DEFAULT,
2716 .ufcon = S3C2410_UFCON_DEFAULT,
2717 },
2718};
2719#define S3C2440_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2440_serial_drv_data)
2720#else
2721#define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
2722#endif
2723
2724#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
2725static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
2726 .info = &(struct s3c24xx_uart_info) {
2727 .name = "Samsung S3C6400 UART",
2728 .type = TYPE_S3C6400,
2729 .port_type = PORT_S3C6400,
2730 .fifosize = 64,
2731 .has_divslot = 1,
2732 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
2733 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
2734 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
2735 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
2736 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
2737 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
2738 .def_clk_sel = S3C2410_UCON_CLKSEL2,
2739 .num_clks = 4,
2740 .clksel_mask = S3C6400_UCON_CLKMASK,
2741 .clksel_shift = S3C6400_UCON_CLKSHIFT,
2742 },
2743 .def_cfg = &(struct s3c2410_uartcfg) {
2744 .ucon = S3C2410_UCON_DEFAULT,
2745 .ufcon = S3C2410_UFCON_DEFAULT,
2746 },
2747};
2748#define S3C6400_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c6400_serial_drv_data)
2749#else
2750#define S3C6400_SERIAL_DRV_DATA (kernel_ulong_t)NULL
2751#endif
2752
2753#ifdef CONFIG_CPU_S5PV210
2754static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
2755 .info = &(struct s3c24xx_uart_info) {
2756 .name = "Samsung S5PV210 UART",
2757 .type = TYPE_S3C6400,
2758 .port_type = PORT_S3C6400,
2759 .has_divslot = 1,
2760 .rx_fifomask = S5PV210_UFSTAT_RXMASK,
2761 .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
2762 .rx_fifofull = S5PV210_UFSTAT_RXFULL,
2763 .tx_fifofull = S5PV210_UFSTAT_TXFULL,
2764 .tx_fifomask = S5PV210_UFSTAT_TXMASK,
2765 .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
2766 .def_clk_sel = S3C2410_UCON_CLKSEL0,
2767 .num_clks = 2,
2768 .clksel_mask = S5PV210_UCON_CLKMASK,
2769 .clksel_shift = S5PV210_UCON_CLKSHIFT,
2770 },
2771 .def_cfg = &(struct s3c2410_uartcfg) {
2772 .ucon = S5PV210_UCON_DEFAULT,
2773 .ufcon = S5PV210_UFCON_DEFAULT,
2774 },
2775 .fifosize = { 256, 64, 16, 16 },
2776};
2777#define S5PV210_SERIAL_DRV_DATA ((kernel_ulong_t)&s5pv210_serial_drv_data)
2778#else
2779#define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
2780#endif
2781
2782#if defined(CONFIG_ARCH_EXYNOS)
2783#define EXYNOS_COMMON_SERIAL_DRV_DATA_USI(_has_usi) \
2784 .info = &(struct s3c24xx_uart_info) { \
2785 .name = "Samsung Exynos UART", \
2786 .type = TYPE_S3C6400, \
2787 .has_usi = _has_usi, \
2788 .port_type = PORT_S3C6400, \
2789 .has_divslot = 1, \
2790 .rx_fifomask = S5PV210_UFSTAT_RXMASK, \
2791 .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \
2792 .rx_fifofull = S5PV210_UFSTAT_RXFULL, \
2793 .tx_fifofull = S5PV210_UFSTAT_TXFULL, \
2794 .tx_fifomask = S5PV210_UFSTAT_TXMASK, \
2795 .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, \
2796 .def_clk_sel = S3C2410_UCON_CLKSEL0, \
2797 .num_clks = 1, \
2798 .clksel_mask = 0, \
2799 .clksel_shift = 0, \
2800 }, \
2801 .def_cfg = &(struct s3c2410_uartcfg) { \
2802 .ucon = S5PV210_UCON_DEFAULT, \
2803 .ufcon = S5PV210_UFCON_DEFAULT, \
2804 .has_fracval = 1, \
2805 } \
2806
2807#define EXYNOS_COMMON_SERIAL_DRV_DATA \
2808 EXYNOS_COMMON_SERIAL_DRV_DATA_USI(0)
2809
2810static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
2811 EXYNOS_COMMON_SERIAL_DRV_DATA,
2812 .fifosize = { 256, 64, 16, 16 },
2813};
2814
2815static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
2816 EXYNOS_COMMON_SERIAL_DRV_DATA,
2817 .fifosize = { 64, 256, 16, 256 },
2818};
2819
2820static struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
2821 EXYNOS_COMMON_SERIAL_DRV_DATA_USI(1),
2822 .fifosize = { 256, 64, 64, 64 },
2823};
2824
2825#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data)
2826#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos5433_serial_drv_data)
2827#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos850_serial_drv_data)
2828
2829#else
2830#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
2831#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
2832#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
2833#endif
2834
2835#ifdef CONFIG_ARCH_APPLE
2836static struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
2837 .info = &(struct s3c24xx_uart_info) {
2838 .name = "Apple S5L UART",
2839 .type = TYPE_APPLE_S5L,
2840 .port_type = PORT_8250,
2841 .fifosize = 16,
2842 .rx_fifomask = S3C2410_UFSTAT_RXMASK,
2843 .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
2844 .rx_fifofull = S3C2410_UFSTAT_RXFULL,
2845 .tx_fifofull = S3C2410_UFSTAT_TXFULL,
2846 .tx_fifomask = S3C2410_UFSTAT_TXMASK,
2847 .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
2848 .def_clk_sel = S3C2410_UCON_CLKSEL0,
2849 .num_clks = 1,
2850 .clksel_mask = 0,
2851 .clksel_shift = 0,
2852 },
2853 .def_cfg = &(struct s3c2410_uartcfg) {
2854 .ucon = APPLE_S5L_UCON_DEFAULT,
2855 .ufcon = S3C2410_UFCON_DEFAULT,
2856 },
2857};
2858#define S5L_SERIAL_DRV_DATA ((kernel_ulong_t)&s5l_serial_drv_data)
2859#else
2860#define S5L_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
2861#endif
2862
2863static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
2864 {
2865 .name = "s3c2410-uart",
2866 .driver_data = S3C2410_SERIAL_DRV_DATA,
2867 }, {
2868 .name = "s3c2412-uart",
2869 .driver_data = S3C2412_SERIAL_DRV_DATA,
2870 }, {
2871 .name = "s3c2440-uart",
2872 .driver_data = S3C2440_SERIAL_DRV_DATA,
2873 }, {
2874 .name = "s3c6400-uart",
2875 .driver_data = S3C6400_SERIAL_DRV_DATA,
2876 }, {
2877 .name = "s5pv210-uart",
2878 .driver_data = S5PV210_SERIAL_DRV_DATA,
2879 }, {
2880 .name = "exynos4210-uart",
2881 .driver_data = EXYNOS4210_SERIAL_DRV_DATA,
2882 }, {
2883 .name = "exynos5433-uart",
2884 .driver_data = EXYNOS5433_SERIAL_DRV_DATA,
2885 }, {
2886 .name = "s5l-uart",
2887 .driver_data = S5L_SERIAL_DRV_DATA,
2888 }, {
2889 .name = "exynos850-uart",
2890 .driver_data = EXYNOS850_SERIAL_DRV_DATA,
2891 },
2892 { },
2893};
2894MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids);
2895
2896#ifdef CONFIG_OF
2897static const struct of_device_id s3c24xx_uart_dt_match[] = {
2898 { .compatible = "samsung,s3c2410-uart",
2899 .data = (void *)S3C2410_SERIAL_DRV_DATA },
2900 { .compatible = "samsung,s3c2412-uart",
2901 .data = (void *)S3C2412_SERIAL_DRV_DATA },
2902 { .compatible = "samsung,s3c2440-uart",
2903 .data = (void *)S3C2440_SERIAL_DRV_DATA },
2904 { .compatible = "samsung,s3c6400-uart",
2905 .data = (void *)S3C6400_SERIAL_DRV_DATA },
2906 { .compatible = "samsung,s5pv210-uart",
2907 .data = (void *)S5PV210_SERIAL_DRV_DATA },
2908 { .compatible = "samsung,exynos4210-uart",
2909 .data = (void *)EXYNOS4210_SERIAL_DRV_DATA },
2910 { .compatible = "samsung,exynos5433-uart",
2911 .data = (void *)EXYNOS5433_SERIAL_DRV_DATA },
2912 { .compatible = "apple,s5l-uart",
2913 .data = (void *)S5L_SERIAL_DRV_DATA },
2914 { .compatible = "samsung,exynos850-uart",
2915 .data = (void *)EXYNOS850_SERIAL_DRV_DATA },
2916 {},
2917};
2918MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
2919#endif
2920
2921static struct platform_driver samsung_serial_driver = {
2922 .probe = s3c24xx_serial_probe,
2923 .remove = s3c24xx_serial_remove,
2924 .id_table = s3c24xx_serial_driver_ids,
2925 .driver = {
2926 .name = "samsung-uart",
2927 .pm = SERIAL_SAMSUNG_PM_OPS,
2928 .of_match_table = of_match_ptr(s3c24xx_uart_dt_match),
2929 },
2930};
2931
2932module_platform_driver(samsung_serial_driver);
2933
2934#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
2935
2936
2937
2938
2939static void wr_reg_barrier(struct uart_port *port, u32 reg, u32 val)
2940{
2941 switch (port->iotype) {
2942 case UPIO_MEM:
2943 writeb(val, portaddr(port, reg));
2944 break;
2945 case UPIO_MEM32:
2946 writel(val, portaddr(port, reg));
2947 break;
2948 }
2949}
2950
2951struct samsung_early_console_data {
2952 u32 txfull_mask;
2953};
2954
2955static void samsung_early_busyuart(struct uart_port *port)
2956{
2957 while (!(readl(port->membase + S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXFE))
2958 ;
2959}
2960
2961static void samsung_early_busyuart_fifo(struct uart_port *port)
2962{
2963 struct samsung_early_console_data *data = port->private_data;
2964
2965 while (readl(port->membase + S3C2410_UFSTAT) & data->txfull_mask)
2966 ;
2967}
2968
2969static void samsung_early_putc(struct uart_port *port, int c)
2970{
2971 if (readl(port->membase + S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE)
2972 samsung_early_busyuart_fifo(port);
2973 else
2974 samsung_early_busyuart(port);
2975
2976 wr_reg_barrier(port, S3C2410_UTXH, c);
2977}
2978
2979static void samsung_early_write(struct console *con, const char *s,
2980 unsigned int n)
2981{
2982 struct earlycon_device *dev = con->data;
2983
2984 uart_console_write(&dev->port, s, n, samsung_early_putc);
2985}
2986
2987static int __init samsung_early_console_setup(struct earlycon_device *device,
2988 const char *opt)
2989{
2990 if (!device->port.membase)
2991 return -ENODEV;
2992
2993 device->con->write = samsung_early_write;
2994 return 0;
2995}
2996
2997
2998static struct samsung_early_console_data s3c2410_early_console_data = {
2999 .txfull_mask = S3C2410_UFSTAT_TXFULL,
3000};
3001
3002static int __init s3c2410_early_console_setup(struct earlycon_device *device,
3003 const char *opt)
3004{
3005 device->port.private_data = &s3c2410_early_console_data;
3006 return samsung_early_console_setup(device, opt);
3007}
3008
3009OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart",
3010 s3c2410_early_console_setup);
3011
3012
3013static struct samsung_early_console_data s3c2440_early_console_data = {
3014 .txfull_mask = S3C2440_UFSTAT_TXFULL,
3015};
3016
3017static int __init s3c2440_early_console_setup(struct earlycon_device *device,
3018 const char *opt)
3019{
3020 device->port.private_data = &s3c2440_early_console_data;
3021 return samsung_early_console_setup(device, opt);
3022}
3023
3024OF_EARLYCON_DECLARE(s3c2412, "samsung,s3c2412-uart",
3025 s3c2440_early_console_setup);
3026OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart",
3027 s3c2440_early_console_setup);
3028OF_EARLYCON_DECLARE(s3c6400, "samsung,s3c6400-uart",
3029 s3c2440_early_console_setup);
3030
3031
3032static struct samsung_early_console_data s5pv210_early_console_data = {
3033 .txfull_mask = S5PV210_UFSTAT_TXFULL,
3034};
3035
3036static int __init s5pv210_early_console_setup(struct earlycon_device *device,
3037 const char *opt)
3038{
3039 device->port.private_data = &s5pv210_early_console_data;
3040 return samsung_early_console_setup(device, opt);
3041}
3042
3043OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",
3044 s5pv210_early_console_setup);
3045OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
3046 s5pv210_early_console_setup);
3047
3048
3049static int __init apple_s5l_early_console_setup(struct earlycon_device *device,
3050 const char *opt)
3051{
3052
3053 device->port.private_data = &s3c2410_early_console_data;
3054
3055#ifdef CONFIG_ARM64
3056
3057 __set_fixmap(FIX_EARLYCON_MEM_BASE, device->port.mapbase,
3058 __pgprot(PROT_DEVICE_nGnRnE));
3059#endif
3060 return samsung_early_console_setup(device, opt);
3061}
3062
3063OF_EARLYCON_DECLARE(s5l, "apple,s5l-uart", apple_s5l_early_console_setup);
3064#endif
3065
3066MODULE_ALIAS("platform:samsung-uart");
3067MODULE_DESCRIPTION("Samsung SoC Serial port driver");
3068MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
3069MODULE_LICENSE("GPL v2");
3070