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