MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / serial / serial_s3c24a0.c
blobd167a266a7543d7e29bb474c8b864c2bc3e6cd79
1 /*
2 * drivser/serial/serial_s3c24a0.c
4 * device for S3C24A0
6 * $Id: serial_s3c24a0.c,v 1.1 2004/12/12 12:11:10 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/config.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/slab.h>
17 #include <linux/tty.h>
18 #include <linux/serial.h>
19 #include <linux/console.h>
20 #include <linux/serial_core.h>
22 #include <asm/irq.h>
23 #include <asm/hardware.h>
24 #include <asm/arch/clocks.h>
26 #define CONFIG_USE_ERR_IRQ 0
28 #define __DRIVER_NAME "Samsung S3C24A0 Internal UART"
31 #ifdef CONFIG_BOARD_S3C24A0_SMDK
32 #define UART_NR 1
33 #else
34 #define UART_NR 2
35 #endif
37 #define UART_ULCON(port) __REG((port)->iobase + oULCON)
38 #define UART_UCON(port) __REG((port)->iobase + oUCON)
39 #define UART_UFCON(port) __REG((port)->iobase + oUFCON)
40 #define UART_UTRSTAT(port) __REG((port)->iobase + oUTRSTAT)
41 #define UART_UERSTAT(port) __REG((port)->iobase + oUERSTAT)
42 #define UART_UTXH(port) __REG((port)->iobase + oUTXH)
43 #define UART_URXH(port) __REG((port)->iobase + oURXH)
44 #define UART_UBRDIV(port) __REG((port)->iobase + oUBRDIV)
46 #define ERR_IRQ(port) ((port)->irq + 2)
47 #define TX_IRQ(port) ((port)->irq + 1)
48 #define RX_IRQ(port) ((port)->irq)
50 #define INT_DISABLE(port) disable_irq(port);
51 #define INT_ENABLE(port) enable_irq(port);
53 * Internal helper function
55 static void __xmit_char(struct uart_port *port, const char ch)
57 while (!(UART_UTRSTAT(port) & UTRSTAT_TX_EMP));
58 UART_UTXH(port) = ch;
59 if (ch == '\n') {
60 while (!(UART_UTRSTAT(port) & UTRSTAT_TX_EMP));
61 UART_UTXH(port) = '\r';
65 static void __xmit_string(struct uart_port *port, const char *p, int len)
67 while( len-- > 0) {
68 __xmit_char( port, *p++);
74 static void elfinuart_stop_tx(struct uart_port *port, u_int from_tty)
78 static void elfinuart_start_tx(struct uart_port *port, u_int from_tty)
80 struct uart_info *info = port->info;
81 struct circ_buf *xmit = &port->info->xmit;
83 int count;
85 if (port->x_char) {
86 __xmit_char(port, port->x_char);
87 port->icount.tx++;
88 port->x_char = 0;
89 return;
92 if (uart_circ_empty( xmit) || uart_tx_stopped( port)) {
93 elfinuart_stop_tx(port, 0);
94 return;
97 count = port->fifosize >> 1;
98 do {
99 __xmit_char( port, xmit->buf[xmit->tail]);
100 info->xmit.tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
101 port->icount.tx++;
102 if (uart_circ_empty(xmit))
103 break;
104 } while (--count > 0);
106 if (uart_circ_chars_pending( xmit) < WAKEUP_CHARS)
107 uart_write_wakeup( port);
109 if (uart_circ_empty(xmit))
110 elfinuart_stop_tx( port, 0);
113 static void elfinuart_stop_rx(struct uart_port *port)
117 static void elfinuart_enable_ms(struct uart_port *port)
121 static void elfinuart_rx_char(struct uart_port *port)
123 unsigned int status, ch, max_count = 256;
124 struct tty_struct *tty = port->info->tty;
126 status = UART_UTRSTAT(port);
127 while ((status & UTRSTAT_RX_RDY) && max_count--) {
128 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
129 tty->flip.work.func((void *) tty);
130 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
131 printk(KERN_WARNING "TTY_DONT_FLIP set\n");
132 return;
136 ch = UART_URXH(port);
138 *tty->flip.char_buf_ptr = ch;
139 *tty->flip.flag_buf_ptr = TTY_NORMAL;
140 port->icount.rx++;
141 tty->flip.flag_buf_ptr++;
142 tty->flip.char_buf_ptr++;
143 tty->flip.count++;
144 /* No error handling just yet.
145 * On the MX1 these are seperate
146 * IRQs, so we need to deal with
147 * the sanity of 5 IRQs for one
148 * serial port before we deal
149 * with the error path properly.
151 status = UART_UTRSTAT(port);
153 tty_flip_buffer_push(tty);
156 static u_int elfinuart_tx_empty(struct uart_port *port)
158 return (UART_UTRSTAT(port) & UTRSTAT_TR_EMP ? 0 : TIOCSER_TEMT);
161 static u_int elfinuart_get_mctrl(struct uart_port *port)
163 return (TIOCM_CTS | TIOCM_DSR | TIOCM_CAR);
166 static void elfinuart_set_mctrl(struct uart_port *port, u_int mctrl)
170 static void elfinuart_break_ctl(struct uart_port *port, int break_state)
172 u_int ucon;
174 ucon = UART_UCON(port);
176 if (break_state == -1)
177 ucon |= UCON_BRK_SIG;
178 else
179 ucon &= ~UCON_BRK_SIG;
181 UART_UCON(port) = ucon;
184 static irqreturn_t elfinuart_rx_int(int irq, void *dev_id, struct pt_regs *regs)
186 struct uart_port *port = dev_id;
187 elfinuart_rx_char(port);
189 return IRQ_HANDLED;
192 static irqreturn_t elfinuart_tx_int(int irq, void *dev_id, struct pt_regs *regs)
194 struct uart_port *port = dev_id;
195 elfinuart_start_tx(port, 0);
196 return IRQ_HANDLED;
199 #ifdef CONFIG_USE_ERR_IRQ
200 static irqreturn_t elfinuart_err_int(int irq, void *dev_id,
201 struct pt_regs *reg)
203 struct uart_port *port = dev_id;
204 struct uart_info *info = port->info;
205 struct tty_struct *tty = info->tty;
206 unsigned char err = UART_UERSTAT(port) & UERSTAT_ERR_MASK;
207 unsigned int ch, flg = TTY_NORMAL;
209 ch = UART_URXH(port);
210 if (!err)
211 return IRQ_HANDLED;
213 if (err & UERSTAT_OVERRUN)
214 port->icount.overrun++;
216 err &= port->read_status_mask;
218 if (err & UERSTAT_OVERRUN) {
219 *tty->flip.char_buf_ptr = ch;
220 *tty->flip.flag_buf_ptr = flg;
221 tty->flip.flag_buf_ptr++;
222 tty->flip.char_buf_ptr++;
223 tty->flip.count++;
224 if (tty->flip.count < TTY_FLIPBUF_SIZE) {
225 ch = 0;
226 flg = TTY_OVERRUN;
230 *tty->flip.flag_buf_ptr++ = flg;
231 *tty->flip.char_buf_ptr++ = ch;
232 tty->flip.count++;
233 return IRQ_HANDLED;
235 #endif
237 static struct irqaction __rx_irqaction[UART_NR] = {
239 name: "serial0_rx",
240 flags: SA_INTERRUPT,
241 handler: elfinuart_rx_int,
244 name: "serial1_rx",
245 flags: SA_INTERRUPT,
246 handler: elfinuart_rx_int,
250 static struct irqaction __tx_irqaction[UART_NR] = {
252 name: "serial0_tx",
253 flags: SA_INTERRUPT,
254 handler: elfinuart_tx_int,
257 name: "serial1_tx",
258 flags: SA_INTERRUPT,
259 handler: elfinuart_tx_int,
263 static struct irqaction __err_irqaction[UART_NR] = {
265 name: "serial0_err",
266 flags: SA_INTERRUPT,
267 handler: elfinuart_err_int,
270 name: "serial1_err",
271 flags: SA_INTERRUPT,
272 handler: elfinuart_err_int,
276 static int elfinuart_startup(struct uart_port *port)
278 int ret;
279 u_int ucon;
282 * Allocate the IRQs for TX and RX
284 __tx_irqaction[port->line].dev_id = (void *)port;
285 __rx_irqaction[port->line].dev_id = (void *)port;
286 __err_irqaction[port->line].dev_id = (void *)port;
288 ret = setup_irq( RX_IRQ(port), &__rx_irqaction[port->line]);
289 if (ret) goto rx_failed;
291 #if 0
292 ret = setup_irq( TX_IRQ(port), &__tx_irqaction[port->line]);
293 if (ret) goto tx_failed;
294 #endif
296 #ifdef CONFIG_USE_ERR_IRQ
297 ret = setup_irq( ERR_IRQ(port), &__err_irqaction[port->line]);
298 if (ret) goto err_failed;
299 #endif
301 ucon = (UCON_TX_INT_LVL | UCON_RX_INT_LVL |
302 UCON_TX_INT | UCON_RX_INT | UCON_RX_TIMEOUT);
305 spin_lock_irq( &port->lock);
307 UART_UCON(port) = ucon;
309 spin_unlock_irq( &port->lock);
311 return 0;
313 #ifdef CONFIG_USE_ERR_IRQ
314 err_failed:
315 printk(KERN_ERR "%s: err failed\n", __FUNCTION__);
316 INT_DISABLE( ERR_IRQ(port));
317 #endif
318 tx_failed:
319 printk(KERN_ERR "%s: tx failed\n", __FUNCTION__);
320 INT_DISABLE( TX_IRQ(port));
321 rx_failed:
322 printk(KERN_ERR "%s: rx failed\n", __FUNCTION__);
323 INT_DISABLE( RX_IRQ(port));
324 return ret;
327 static void elfinuart_shutdown(struct uart_port *port)
329 #ifdef CONFIG_USE_ERR_IRQ
330 INT_DISABLE( ERR_IRQ(port));
331 #endif
332 INT_DISABLE( TX_IRQ(port));
333 INT_DISABLE( RX_IRQ(port));
335 UART_UCON(port) = 0x0;
338 #if 0
339 static void elfinuart_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
341 u_int ulcon, ufcon;
342 int flags;
344 ufcon = UART_UFCON(port);
346 switch (cflag & CSIZE) {
347 case CS5:
348 ulcon = ULCON_WL5;
349 break;
350 case CS6:
351 ulcon = ULCON_WL6;
352 break;
353 case CS7:
354 ulcon = ULCON_WL7;
355 break;
356 default:
357 ulcon = ULCON_WL8;
358 break;
361 if (cflag & CSTOPB)
362 ulcon |= ULCON_STOP;
363 if (cflag & PARENB) {
364 if (!(cflag & PARODD))
365 ulcon |= ULCON_PAR_EVEN;
368 if (port->fifosize > 1)
369 ufcon |= UFCON_FIFO_EN;
371 port->read_status_mask = UERSTAT_OVERRUN;
373 port->ignore_status_mask = 0;
374 if (iflag & IGNBRK) {
375 if (iflag & IGNPAR)
376 port->ignore_status_mask |= UERSTAT_OVERRUN;
379 quot -= 1;
381 spin_lock_irqsave( &port->lock, flags );
383 UART_UFCON(port) = ufcon;
384 UART_ULCON(port) = ulcon;
385 UART_UBRDIV(port) = quot;
387 spin_unlock_irqrestore(&port->lock, flags);
390 #endif
392 static void elfinuart_set_termios(struct uart_port *port, struct termios *termios, struct termios *old)
394 int quot;
396 uart_update_timeout(port, termios->c_cflag, 115200);
397 #if 0
398 quot = uart_get_divisor(port, 115200);
399 elfinuart_change_speed(port, termios->c_cflag, 0, quot);
400 #endif
403 static void elfinuart_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
407 static int elfinuart_set_wake(struct uart_port *port, unsigned int state)
409 return 0;
415 static const char *elfinuart_type(struct uart_port *port)
417 return __DRIVER_NAME;
420 static void elfinuart_config_port(struct uart_port *port, int flags)
422 if (flags & UART_CONFIG_TYPE)
423 port->type = PORT_S3C24A0;
426 static void elfinuart_release_port(struct uart_port *port)
430 static int elfinuart_request_port(struct uart_port *port)
432 return 0;
435 static int elfinuart_verify_port(struct uart_port *port, struct serial_struct *serial)
437 return 0;
440 static struct uart_ops elfin_pops = {
441 tx_empty : elfinuart_tx_empty,
442 set_mctrl : elfinuart_set_mctrl,
443 get_mctrl : elfinuart_get_mctrl,
444 stop_tx : elfinuart_stop_tx,
445 start_tx : elfinuart_start_tx,
446 stop_rx : elfinuart_stop_rx,
447 enable_ms : elfinuart_enable_ms,
448 break_ctl : elfinuart_break_ctl,
449 startup : elfinuart_startup,
450 shutdown : elfinuart_shutdown,
451 set_termios: elfinuart_set_termios,
452 pm: elfinuart_pm,
453 set_wake: elfinuart_set_wake,
454 type : elfinuart_type,
455 config_port : elfinuart_config_port,
456 release_port : elfinuart_release_port,
457 request_port : elfinuart_request_port,
458 verify_port: elfinuart_verify_port,
461 static struct uart_port elfin_ports[UART_NR] = {
463 iobase : (unsigned long)(UART0_CTL_BASE),
464 irq : IRQ_RXD0,
465 uartclk : 130252800,
466 fifosize : 64,
467 ops : &elfin_pops,
468 type : PORT_S3C24A0,
469 flags : ASYNC_BOOT_AUTOCONF,
471 #ifndef CONFIG_BOARD_S3C24A0_SMDK
473 iobase : (unsigned long)(UART1_CTL_BASE),
474 irq : IRQ_RXD1,
475 uartclk : 130252800,
476 fifosize : 64,
477 ops : &elfin_pops,
478 type : PORT_S3C24A0,
479 flags : ASYNC_BOOT_AUTOCONF,
481 #endif /* !CONFIG_BOARD_S3C24A0_SMDK */
484 void __init elfin_register_uart(int idx, int port)
486 if (idx >= UART_NR) {
487 printk(KERN_ERR "%s: bad index number %d\n"
488 , __FUNCTION__, idx);
489 return;
491 elfin_ports[idx].uartclk = elfin_get_bus_clk(GET_PCLK);
493 switch (port) {
494 case 0:
495 elfin_ports[idx].iobase = (unsigned long)(UART0_CTL_BASE);
496 elfin_ports[idx].irq = IRQ_RXD0;
497 break;
498 case 1:
499 elfin_ports[idx].iobase = (unsigned long)(UART1_CTL_BASE);
500 elfin_ports[idx].irq = IRQ_RXD1;
501 break;
502 default:
503 printk(KERN_ERR "%s : bad port number %d\n", __FUNCTION__, port);
509 #ifdef CONFIG_SERIAL_S3C24A0_CONSOLE
511 static void elfin_console_write(struct console *co, const char *s, u_int count)
513 struct uart_port *port = elfin_ports + co->index;
514 __xmit_string( port, s, count);
517 static int __init elfin_console_setup(struct console *co, char *options)
519 struct uart_port *port;
520 int baud = 115200;
521 int bits = 8;
522 int parity = 'n';
523 int flow = 0;
525 port = uart_get_console(elfin_ports, UART_NR, co);
527 if (options)
528 uart_parse_options(options, &baud, &parity, &bits, &flow);
530 return uart_set_options(port, co, baud, parity, bits, flow);
533 extern struct uart_driver elfin_reg;
534 static struct console elfin_cons = {
535 name : "ttyS",
536 write : elfin_console_write,
537 device : uart_console_device,
538 setup : elfin_console_setup,
539 flags : CON_PRINTBUFFER,
540 index : -1,
541 data : &elfin_reg,
544 static int __init elfin_console_init(void)
546 register_console(&elfin_cons);
547 return 0;
550 console_initcall(elfin_console_init);
552 #define S3C24A0_CONSOLE &elfin_cons
553 #else /* CONFIG_SERIAL_S3C24A0_CONSOLE */
554 #define S3C24A0_CONSOLE NULL
555 #endif /* CONFIG_SERIAL_S3C24A0_CONSOLE */
558 static struct uart_driver elfin_reg = {
559 owner : THIS_MODULE,
560 driver_name : "ttyS",
561 dev_name : "ttyS",
562 major : TTY_MAJOR,
563 minor : 64,
564 nr : UART_NR,
565 cons : S3C24A0_CONSOLE,
568 static int __init elfinuart_init(void)
570 int ret;
572 printk("Initializing %s\n", __DRIVER_NAME);
573 ret = uart_register_driver(&elfin_reg);
574 if (ret == 0) {
575 int i;
577 for (i = 0; i < UART_NR; i++)
578 uart_add_one_port(&elfin_reg, &elfin_ports[i]);
580 return ret;
584 static void __exit elfinuart_exit(void)
586 uart_unregister_driver(&elfin_reg);
589 module_init(elfinuart_init);
590 module_exit(elfinuart_exit);
593 MODULE_AUTHOR("Samsung");
594 MODULE_DESCRIPTION("S3C24A0 generic serial port driver");
595 MODULE_SUPPORTED_DEVICE("ttyS");
596 MODULE_LICENSE("GPL");