MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / serial / serial_s3c24a0.c
blobbf43a1befb4cecf46d5a27826d73ad0afeba92f0
1 /*
2 * drivser/serial/serial_s3c24a0.c
4 * device for S3C24A0
6 * $Id: serial_s3c24a0.c,v 1.3 2006/12/12 13:38:51 gerg Exp $
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive
10 * for more details.
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/slab.h>
16 #include <linux/tty.h>
17 #include <linux/serial.h>
18 #include <linux/console.h>
19 #include <linux/serial_core.h>
21 #include <asm/irq.h>
22 #include <asm/hardware.h>
23 #include <asm/arch/clocks.h>
25 #define CONFIG_USE_ERR_IRQ 0
27 #define __DRIVER_NAME "Samsung S3C24A0 Internal UART"
30 #ifdef CONFIG_BOARD_S3C24A0_SMDK
31 #define UART_NR 1
32 #else
33 #define UART_NR 2
34 #endif
36 #define UART_ULCON(port) __REG((port)->iobase + oULCON)
37 #define UART_UCON(port) __REG((port)->iobase + oUCON)
38 #define UART_UFCON(port) __REG((port)->iobase + oUFCON)
39 #define UART_UTRSTAT(port) __REG((port)->iobase + oUTRSTAT)
40 #define UART_UERSTAT(port) __REG((port)->iobase + oUERSTAT)
41 #define UART_UTXH(port) __REG((port)->iobase + oUTXH)
42 #define UART_URXH(port) __REG((port)->iobase + oURXH)
43 #define UART_UBRDIV(port) __REG((port)->iobase + oUBRDIV)
45 #define ERR_IRQ(port) ((port)->irq + 2)
46 #define TX_IRQ(port) ((port)->irq + 1)
47 #define RX_IRQ(port) ((port)->irq)
49 #define INT_DISABLE(port) disable_irq(port);
50 #define INT_ENABLE(port) enable_irq(port);
52 * Internal helper function
54 static void __xmit_char(struct uart_port *port, const char ch)
56 while (!(UART_UTRSTAT(port) & UTRSTAT_TX_EMP));
57 UART_UTXH(port) = ch;
58 if (ch == '\n') {
59 while (!(UART_UTRSTAT(port) & UTRSTAT_TX_EMP));
60 UART_UTXH(port) = '\r';
64 static void __xmit_string(struct uart_port *port, const char *p, int len)
66 while( len-- > 0) {
67 __xmit_char( port, *p++);
73 static void elfinuart_stop_tx(struct uart_port *port)
77 static void elfinuart_start_tx(struct uart_port *port)
79 struct uart_info *info = port->info;
80 struct circ_buf *xmit = &port->info->xmit;
82 int count;
84 if (port->x_char) {
85 __xmit_char(port, port->x_char);
86 port->icount.tx++;
87 port->x_char = 0;
88 return;
91 if (uart_circ_empty( xmit) || uart_tx_stopped( port)) {
92 elfinuart_stop_tx(port);
93 return;
96 count = port->fifosize >> 1;
97 do {
98 __xmit_char( port, xmit->buf[xmit->tail]);
99 info->xmit.tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
100 port->icount.tx++;
101 if (uart_circ_empty(xmit))
102 break;
103 } while (--count > 0);
105 if (uart_circ_chars_pending( xmit) < WAKEUP_CHARS)
106 uart_write_wakeup( port);
108 if (uart_circ_empty(xmit))
109 elfinuart_stop_tx( port);
112 static void elfinuart_stop_rx(struct uart_port *port)
116 static void elfinuart_enable_ms(struct uart_port *port)
120 static void elfinuart_rx_char(struct uart_port *port)
122 unsigned int status, ch, max_count = 256;
123 struct tty_struct *tty = port->info->tty;
125 status = UART_UTRSTAT(port);
126 while ((status & UTRSTAT_RX_RDY) && max_count--) {
127 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
128 tty->flip.work.func((void *) tty);
129 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
130 printk(KERN_WARNING "TTY_DONT_FLIP set\n");
131 return;
135 ch = UART_URXH(port);
137 *tty->flip.char_buf_ptr = ch;
138 *tty->flip.flag_buf_ptr = TTY_NORMAL;
139 port->icount.rx++;
140 tty->flip.flag_buf_ptr++;
141 tty->flip.char_buf_ptr++;
142 tty->flip.count++;
143 /* No error handling just yet.
144 * On the MX1 these are seperate
145 * IRQs, so we need to deal with
146 * the sanity of 5 IRQs for one
147 * serial port before we deal
148 * with the error path properly.
150 status = UART_UTRSTAT(port);
152 tty_flip_buffer_push(tty);
155 static u_int elfinuart_tx_empty(struct uart_port *port)
157 return (UART_UTRSTAT(port) & UTRSTAT_TR_EMP ? 0 : TIOCSER_TEMT);
160 static u_int elfinuart_get_mctrl(struct uart_port *port)
162 return (TIOCM_CTS | TIOCM_DSR | TIOCM_CAR);
165 static void elfinuart_set_mctrl(struct uart_port *port, u_int mctrl)
169 static void elfinuart_break_ctl(struct uart_port *port, int break_state)
171 u_int ucon;
173 ucon = UART_UCON(port);
175 if (break_state == -1)
176 ucon |= UCON_BRK_SIG;
177 else
178 ucon &= ~UCON_BRK_SIG;
180 UART_UCON(port) = ucon;
183 static irqreturn_t elfinuart_rx_int(int irq, void *dev_id, struct pt_regs *regs)
185 struct uart_port *port = dev_id;
186 elfinuart_rx_char(port);
188 return IRQ_HANDLED;
191 static irqreturn_t elfinuart_tx_int(int irq, void *dev_id, struct pt_regs *regs)
193 struct uart_port *port = dev_id;
194 elfinuart_start_tx(port);
195 return IRQ_HANDLED;
198 #ifdef CONFIG_USE_ERR_IRQ
199 static irqreturn_t elfinuart_err_int(int irq, void *dev_id,
200 struct pt_regs *reg)
202 struct uart_port *port = dev_id;
203 struct uart_info *info = port->info;
204 struct tty_struct *tty = info->tty;
205 unsigned char err = UART_UERSTAT(port) & UERSTAT_ERR_MASK;
206 unsigned int ch, flg = TTY_NORMAL;
208 ch = UART_URXH(port);
209 if (!err)
210 return IRQ_HANDLED;
212 if (err & UERSTAT_OVERRUN)
213 port->icount.overrun++;
215 err &= port->read_status_mask;
217 if (err & UERSTAT_OVERRUN) {
218 *tty->flip.char_buf_ptr = ch;
219 *tty->flip.flag_buf_ptr = flg;
220 tty->flip.flag_buf_ptr++;
221 tty->flip.char_buf_ptr++;
222 tty->flip.count++;
223 if (tty->flip.count < TTY_FLIPBUF_SIZE) {
224 ch = 0;
225 flg = TTY_OVERRUN;
229 *tty->flip.flag_buf_ptr++ = flg;
230 *tty->flip.char_buf_ptr++ = ch;
231 tty->flip.count++;
232 return IRQ_HANDLED;
234 #endif
236 static struct irqaction __rx_irqaction[UART_NR] = {
238 name: "serial0_rx",
239 flags: SA_INTERRUPT,
240 handler: elfinuart_rx_int,
243 name: "serial1_rx",
244 flags: SA_INTERRUPT,
245 handler: elfinuart_rx_int,
249 static struct irqaction __tx_irqaction[UART_NR] = {
251 name: "serial0_tx",
252 flags: SA_INTERRUPT,
253 handler: elfinuart_tx_int,
256 name: "serial1_tx",
257 flags: SA_INTERRUPT,
258 handler: elfinuart_tx_int,
262 static struct irqaction __err_irqaction[UART_NR] = {
264 name: "serial0_err",
265 flags: SA_INTERRUPT,
266 handler: elfinuart_err_int,
269 name: "serial1_err",
270 flags: SA_INTERRUPT,
271 handler: elfinuart_err_int,
275 static int elfinuart_startup(struct uart_port *port)
277 int ret;
278 u_int ucon;
281 * Allocate the IRQs for TX and RX
283 __tx_irqaction[port->line].dev_id = (void *)port;
284 __rx_irqaction[port->line].dev_id = (void *)port;
285 __err_irqaction[port->line].dev_id = (void *)port;
287 ret = setup_irq( RX_IRQ(port), &__rx_irqaction[port->line]);
288 if (ret) goto rx_failed;
290 #if 0
291 ret = setup_irq( TX_IRQ(port), &__tx_irqaction[port->line]);
292 if (ret) goto tx_failed;
293 #endif
295 #ifdef CONFIG_USE_ERR_IRQ
296 ret = setup_irq( ERR_IRQ(port), &__err_irqaction[port->line]);
297 if (ret) goto err_failed;
298 #endif
300 ucon = (UCON_TX_INT_LVL | UCON_RX_INT_LVL |
301 UCON_TX_INT | UCON_RX_INT | UCON_RX_TIMEOUT);
304 spin_lock_irq( &port->lock);
306 UART_UCON(port) = ucon;
308 spin_unlock_irq( &port->lock);
310 return 0;
312 #ifdef CONFIG_USE_ERR_IRQ
313 err_failed:
314 printk(KERN_ERR "%s: err failed\n", __FUNCTION__);
315 INT_DISABLE( ERR_IRQ(port));
316 #endif
317 tx_failed:
318 printk(KERN_ERR "%s: tx failed\n", __FUNCTION__);
319 INT_DISABLE( TX_IRQ(port));
320 rx_failed:
321 printk(KERN_ERR "%s: rx failed\n", __FUNCTION__);
322 INT_DISABLE( RX_IRQ(port));
323 return ret;
326 static void elfinuart_shutdown(struct uart_port *port)
328 #ifdef CONFIG_USE_ERR_IRQ
329 INT_DISABLE( ERR_IRQ(port));
330 #endif
331 INT_DISABLE( TX_IRQ(port));
332 INT_DISABLE( RX_IRQ(port));
334 UART_UCON(port) = 0x0;
337 #if 0
338 static void elfinuart_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
340 u_int ulcon, ufcon;
341 int flags;
343 ufcon = UART_UFCON(port);
345 switch (cflag & CSIZE) {
346 case CS5:
347 ulcon = ULCON_WL5;
348 break;
349 case CS6:
350 ulcon = ULCON_WL6;
351 break;
352 case CS7:
353 ulcon = ULCON_WL7;
354 break;
355 default:
356 ulcon = ULCON_WL8;
357 break;
360 if (cflag & CSTOPB)
361 ulcon |= ULCON_STOP;
362 if (cflag & PARENB) {
363 if (!(cflag & PARODD))
364 ulcon |= ULCON_PAR_EVEN;
367 if (port->fifosize > 1)
368 ufcon |= UFCON_FIFO_EN;
370 port->read_status_mask = UERSTAT_OVERRUN;
372 port->ignore_status_mask = 0;
373 if (iflag & IGNBRK) {
374 if (iflag & IGNPAR)
375 port->ignore_status_mask |= UERSTAT_OVERRUN;
378 quot -= 1;
380 spin_lock_irqsave( &port->lock, flags );
382 UART_UFCON(port) = ufcon;
383 UART_ULCON(port) = ulcon;
384 UART_UBRDIV(port) = quot;
386 spin_unlock_irqrestore(&port->lock, flags);
389 #endif
391 static void elfinuart_set_termios(struct uart_port *port, struct termios *termios, struct termios *old)
393 int quot;
395 uart_update_timeout(port, termios->c_cflag, 115200);
396 #if 0
397 quot = uart_get_divisor(port, 115200);
398 elfinuart_change_speed(port, termios->c_cflag, 0, quot);
399 #endif
402 static void elfinuart_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
406 static int elfinuart_set_wake(struct uart_port *port, unsigned int state)
408 return 0;
414 static const char *elfinuart_type(struct uart_port *port)
416 return __DRIVER_NAME;
419 static void elfinuart_config_port(struct uart_port *port, int flags)
421 if (flags & UART_CONFIG_TYPE)
422 port->type = PORT_S3C24A0;
425 static void elfinuart_release_port(struct uart_port *port)
429 static int elfinuart_request_port(struct uart_port *port)
431 return 0;
434 static int elfinuart_verify_port(struct uart_port *port, struct serial_struct *serial)
436 return 0;
439 static struct uart_ops elfin_pops = {
440 tx_empty : elfinuart_tx_empty,
441 set_mctrl : elfinuart_set_mctrl,
442 get_mctrl : elfinuart_get_mctrl,
443 stop_tx : elfinuart_stop_tx,
444 start_tx : elfinuart_start_tx,
445 stop_rx : elfinuart_stop_rx,
446 enable_ms : elfinuart_enable_ms,
447 break_ctl : elfinuart_break_ctl,
448 startup : elfinuart_startup,
449 shutdown : elfinuart_shutdown,
450 set_termios: elfinuart_set_termios,
451 pm: elfinuart_pm,
452 set_wake: elfinuart_set_wake,
453 type : elfinuart_type,
454 config_port : elfinuart_config_port,
455 release_port : elfinuart_release_port,
456 request_port : elfinuart_request_port,
457 verify_port: elfinuart_verify_port,
460 static struct uart_port elfin_ports[UART_NR] = {
462 iobase : (unsigned long)(UART0_CTL_BASE),
463 irq : IRQ_RXD0,
464 uartclk : 130252800,
465 fifosize : 64,
466 ops : &elfin_pops,
467 type : PORT_S3C24A0,
468 flags : ASYNC_BOOT_AUTOCONF,
470 #ifndef CONFIG_BOARD_S3C24A0_SMDK
472 iobase : (unsigned long)(UART1_CTL_BASE),
473 irq : IRQ_RXD1,
474 uartclk : 130252800,
475 fifosize : 64,
476 ops : &elfin_pops,
477 type : PORT_S3C24A0,
478 flags : ASYNC_BOOT_AUTOCONF,
480 #endif /* !CONFIG_BOARD_S3C24A0_SMDK */
483 void __init elfin_register_uart(int idx, int port)
485 if (idx >= UART_NR) {
486 printk(KERN_ERR "%s: bad index number %d\n"
487 , __FUNCTION__, idx);
488 return;
490 elfin_ports[idx].uartclk = elfin_get_bus_clk(GET_PCLK);
492 switch (port) {
493 case 0:
494 elfin_ports[idx].iobase = (unsigned long)(UART0_CTL_BASE);
495 elfin_ports[idx].irq = IRQ_RXD0;
496 break;
497 case 1:
498 elfin_ports[idx].iobase = (unsigned long)(UART1_CTL_BASE);
499 elfin_ports[idx].irq = IRQ_RXD1;
500 break;
501 default:
502 printk(KERN_ERR "%s : bad port number %d\n", __FUNCTION__, port);
508 #ifdef CONFIG_SERIAL_S3C24A0_CONSOLE
510 static void elfin_console_write(struct console *co, const char *s, u_int count)
512 struct uart_port *port = elfin_ports + co->index;
513 __xmit_string( port, s, count);
516 static int __init elfin_console_setup(struct console *co, char *options)
518 struct uart_port *port;
519 int baud = 115200;
520 int bits = 8;
521 int parity = 'n';
522 int flow = 0;
524 port = uart_get_console(elfin_ports, UART_NR, co);
526 if (options)
527 uart_parse_options(options, &baud, &parity, &bits, &flow);
529 return uart_set_options(port, co, baud, parity, bits, flow);
532 extern struct uart_driver elfin_reg;
533 static struct console elfin_cons = {
534 name : "ttyS",
535 write : elfin_console_write,
536 device : uart_console_device,
537 setup : elfin_console_setup,
538 flags : CON_PRINTBUFFER,
539 index : -1,
540 data : &elfin_reg,
543 static int __init elfin_console_init(void)
545 register_console(&elfin_cons);
546 return 0;
549 console_initcall(elfin_console_init);
551 #define S3C24A0_CONSOLE &elfin_cons
552 #else /* CONFIG_SERIAL_S3C24A0_CONSOLE */
553 #define S3C24A0_CONSOLE NULL
554 #endif /* CONFIG_SERIAL_S3C24A0_CONSOLE */
557 static struct uart_driver elfin_reg = {
558 owner : THIS_MODULE,
559 driver_name : "ttyS",
560 dev_name : "ttyS",
561 major : TTY_MAJOR,
562 minor : 64,
563 nr : UART_NR,
564 cons : S3C24A0_CONSOLE,
567 static int __init elfinuart_init(void)
569 int ret;
571 printk("Initializing %s\n", __DRIVER_NAME);
572 ret = uart_register_driver(&elfin_reg);
573 if (ret == 0) {
574 int i;
576 for (i = 0; i < UART_NR; i++)
577 uart_add_one_port(&elfin_reg, &elfin_ports[i]);
579 return ret;
583 static void __exit elfinuart_exit(void)
585 uart_unregister_driver(&elfin_reg);
588 module_init(elfinuart_init);
589 module_exit(elfinuart_exit);
592 MODULE_AUTHOR("Samsung");
593 MODULE_DESCRIPTION("S3C24A0 generic serial port driver");
594 MODULE_SUPPORTED_DEVICE("ttyS");
595 MODULE_LICENSE("GPL");