x86: memtest bootparam
[linux-2.6/linux-2.6-openrd.git] / drivers / serial / mcf.c
blob7e164e0cd2116d05fef1d1e131cc859b0bcc1d15
1 /****************************************************************************/
3 /*
4 * mcf.c -- Freescale ColdFire UART driver
6 * (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
14 /****************************************************************************/
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/module.h>
20 #include <linux/console.h>
21 #include <linux/tty.h>
22 #include <linux/tty_flip.h>
23 #include <linux/serial.h>
24 #include <linux/serial_core.h>
25 #include <linux/io.h>
26 #include <asm/coldfire.h>
27 #include <asm/mcfsim.h>
28 #include <asm/mcfuart.h>
29 #include <asm/nettel.h>
31 /****************************************************************************/
34 * Some boards implement the DTR/DCD lines using GPIO lines, most
35 * don't. Dummy out the access macros for those that don't. Those
36 * that do should define these macros somewhere in there board
37 * specific inlude files.
39 #if !defined(mcf_getppdcd)
40 #define mcf_getppdcd(p) (1)
41 #endif
42 #if !defined(mcf_getppdtr)
43 #define mcf_getppdtr(p) (1)
44 #endif
45 #if !defined(mcf_setppdtr)
46 #define mcf_setppdtr(p, v) do { } while (0)
47 #endif
49 /****************************************************************************/
52 * Local per-uart structure.
54 struct mcf_uart {
55 struct uart_port port;
56 unsigned int sigs; /* Local copy of line sigs */
57 unsigned char imr; /* Local IMR mirror */
60 /****************************************************************************/
62 static unsigned int mcf_tx_empty(struct uart_port *port)
64 return (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXEMPTY) ?
65 TIOCSER_TEMT : 0;
68 /****************************************************************************/
70 static unsigned int mcf_get_mctrl(struct uart_port *port)
72 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
73 unsigned long flags;
74 unsigned int sigs;
76 spin_lock_irqsave(&port->lock, flags);
77 sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ?
78 0 : TIOCM_CTS;
79 sigs |= (pp->sigs & TIOCM_RTS);
80 sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0);
81 sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0);
82 spin_unlock_irqrestore(&port->lock, flags);
83 return sigs;
86 /****************************************************************************/
88 static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs)
90 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
91 unsigned long flags;
93 spin_lock_irqsave(&port->lock, flags);
94 pp->sigs = sigs;
95 mcf_setppdtr(port->line, (sigs & TIOCM_DTR));
96 if (sigs & TIOCM_RTS)
97 writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1);
98 else
99 writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0);
100 spin_unlock_irqrestore(&port->lock, flags);
103 /****************************************************************************/
105 static void mcf_start_tx(struct uart_port *port)
107 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
108 unsigned long flags;
110 spin_lock_irqsave(&port->lock, flags);
111 pp->imr |= MCFUART_UIR_TXREADY;
112 writeb(pp->imr, port->membase + MCFUART_UIMR);
113 spin_unlock_irqrestore(&port->lock, flags);
116 /****************************************************************************/
118 static void mcf_stop_tx(struct uart_port *port)
120 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
121 unsigned long flags;
123 spin_lock_irqsave(&port->lock, flags);
124 pp->imr &= ~MCFUART_UIR_TXREADY;
125 writeb(pp->imr, port->membase + MCFUART_UIMR);
126 spin_unlock_irqrestore(&port->lock, flags);
129 /****************************************************************************/
131 static void mcf_stop_rx(struct uart_port *port)
133 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
134 unsigned long flags;
136 spin_lock_irqsave(&port->lock, flags);
137 pp->imr &= ~MCFUART_UIR_RXREADY;
138 writeb(pp->imr, port->membase + MCFUART_UIMR);
139 spin_unlock_irqrestore(&port->lock, flags);
142 /****************************************************************************/
144 static void mcf_break_ctl(struct uart_port *port, int break_state)
146 unsigned long flags;
148 spin_lock_irqsave(&port->lock, flags);
149 if (break_state == -1)
150 writeb(MCFUART_UCR_CMDBREAKSTART, port->membase + MCFUART_UCR);
151 else
152 writeb(MCFUART_UCR_CMDBREAKSTOP, port->membase + MCFUART_UCR);
153 spin_unlock_irqrestore(&port->lock, flags);
156 /****************************************************************************/
158 static void mcf_enable_ms(struct uart_port *port)
162 /****************************************************************************/
164 static int mcf_startup(struct uart_port *port)
166 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
167 unsigned long flags;
169 spin_lock_irqsave(&port->lock, flags);
171 /* Reset UART, get it into known state... */
172 writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
173 writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
175 /* Enable the UART transmitter and receiver */
176 writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
177 port->membase + MCFUART_UCR);
179 /* Enable RX interrupts now */
180 pp->imr = MCFUART_UIR_RXREADY;
181 writeb(pp->imr, port->membase + MCFUART_UIMR);
183 spin_unlock_irqrestore(&port->lock, flags);
185 return 0;
188 /****************************************************************************/
190 static void mcf_shutdown(struct uart_port *port)
192 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
193 unsigned long flags;
195 spin_lock_irqsave(&port->lock, flags);
197 /* Disable all interrupts now */
198 pp->imr = 0;
199 writeb(pp->imr, port->membase + MCFUART_UIMR);
201 /* Disable UART transmitter and receiver */
202 writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
203 writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
205 spin_unlock_irqrestore(&port->lock, flags);
208 /****************************************************************************/
210 static void mcf_set_termios(struct uart_port *port, struct ktermios *termios,
211 struct ktermios *old)
213 unsigned long flags;
214 unsigned int baud, baudclk;
215 unsigned char mr1, mr2;
217 baud = uart_get_baud_rate(port, termios, old, 0, 230400);
218 baudclk = ((MCF_BUSCLK / baud) + 16) / 32;
220 mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR;
221 mr2 = 0;
223 switch (termios->c_cflag & CSIZE) {
224 case CS5: mr1 |= MCFUART_MR1_CS5; break;
225 case CS6: mr1 |= MCFUART_MR1_CS6; break;
226 case CS7: mr1 |= MCFUART_MR1_CS7; break;
227 case CS8:
228 default: mr1 |= MCFUART_MR1_CS8; break;
231 if (termios->c_cflag & PARENB) {
232 if (termios->c_cflag & CMSPAR) {
233 if (termios->c_cflag & PARODD)
234 mr1 |= MCFUART_MR1_PARITYMARK;
235 else
236 mr1 |= MCFUART_MR1_PARITYSPACE;
237 } else {
238 if (termios->c_cflag & PARODD)
239 mr1 |= MCFUART_MR1_PARITYODD;
240 else
241 mr1 |= MCFUART_MR1_PARITYEVEN;
243 } else {
244 mr1 |= MCFUART_MR1_PARITYNONE;
247 if (termios->c_cflag & CSTOPB)
248 mr2 |= MCFUART_MR2_STOP2;
249 else
250 mr2 |= MCFUART_MR2_STOP1;
252 if (termios->c_cflag & CRTSCTS) {
253 mr1 |= MCFUART_MR1_RXRTS;
254 mr2 |= MCFUART_MR2_TXCTS;
257 spin_lock_irqsave(&port->lock, flags);
258 writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
259 writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
260 writeb(MCFUART_UCR_CMDRESETMRPTR, port->membase + MCFUART_UCR);
261 writeb(mr1, port->membase + MCFUART_UMR);
262 writeb(mr2, port->membase + MCFUART_UMR);
263 writeb((baudclk & 0xff00) >> 8, port->membase + MCFUART_UBG1);
264 writeb((baudclk & 0xff), port->membase + MCFUART_UBG2);
265 writeb(MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER,
266 port->membase + MCFUART_UCSR);
267 writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
268 port->membase + MCFUART_UCR);
269 spin_unlock_irqrestore(&port->lock, flags);
272 /****************************************************************************/
274 static void mcf_rx_chars(struct mcf_uart *pp)
276 struct uart_port *port = &pp->port;
277 unsigned char status, ch, flag;
279 while ((status = readb(port->membase + MCFUART_USR)) & MCFUART_USR_RXREADY) {
280 ch = readb(port->membase + MCFUART_URB);
281 flag = TTY_NORMAL;
282 port->icount.rx++;
284 if (status & MCFUART_USR_RXERR) {
285 writeb(MCFUART_UCR_CMDRESETERR,
286 port->membase + MCFUART_UCR);
288 if (status & MCFUART_USR_RXBREAK) {
289 port->icount.brk++;
290 if (uart_handle_break(port))
291 continue;
292 } else if (status & MCFUART_USR_RXPARITY) {
293 port->icount.parity++;
294 } else if (status & MCFUART_USR_RXOVERRUN) {
295 port->icount.overrun++;
296 } else if (status & MCFUART_USR_RXFRAMING) {
297 port->icount.frame++;
300 status &= port->read_status_mask;
302 if (status & MCFUART_USR_RXBREAK)
303 flag = TTY_BREAK;
304 else if (status & MCFUART_USR_RXPARITY)
305 flag = TTY_PARITY;
306 else if (status & MCFUART_USR_RXFRAMING)
307 flag = TTY_FRAME;
310 if (uart_handle_sysrq_char(port, ch))
311 continue;
312 uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag);
315 tty_flip_buffer_push(port->info->tty);
318 /****************************************************************************/
320 static void mcf_tx_chars(struct mcf_uart *pp)
322 struct uart_port *port = &pp->port;
323 struct circ_buf *xmit = &port->info->xmit;
325 if (port->x_char) {
326 /* Send special char - probably flow control */
327 writeb(port->x_char, port->membase + MCFUART_UTB);
328 port->x_char = 0;
329 port->icount.tx++;
330 return;
333 while (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) {
334 if (xmit->head == xmit->tail)
335 break;
336 writeb(xmit->buf[xmit->tail], port->membase + MCFUART_UTB);
337 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1);
338 port->icount.tx++;
341 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
342 uart_write_wakeup(port);
344 if (xmit->head == xmit->tail) {
345 pp->imr &= ~MCFUART_UIR_TXREADY;
346 writeb(pp->imr, port->membase + MCFUART_UIMR);
350 /****************************************************************************/
352 static irqreturn_t mcf_interrupt(int irq, void *data)
354 struct uart_port *port = data;
355 struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
356 unsigned int isr;
358 isr = readb(port->membase + MCFUART_UISR) & pp->imr;
359 if (isr & MCFUART_UIR_RXREADY)
360 mcf_rx_chars(pp);
361 if (isr & MCFUART_UIR_TXREADY)
362 mcf_tx_chars(pp);
363 return IRQ_HANDLED;
366 /****************************************************************************/
368 static void mcf_config_port(struct uart_port *port, int flags)
370 port->type = PORT_MCF;
372 /* Clear mask, so no surprise interrupts. */
373 writeb(0, port->membase + MCFUART_UIMR);
375 if (request_irq(port->irq, mcf_interrupt, IRQF_DISABLED, "UART", port))
376 printk(KERN_ERR "MCF: unable to attach ColdFire UART %d "
377 "interrupt vector=%d\n", port->line, port->irq);
380 /****************************************************************************/
382 static const char *mcf_type(struct uart_port *port)
384 return (port->type == PORT_MCF) ? "ColdFire UART" : NULL;
387 /****************************************************************************/
389 static int mcf_request_port(struct uart_port *port)
391 /* UARTs always present */
392 return 0;
395 /****************************************************************************/
397 static void mcf_release_port(struct uart_port *port)
399 /* Nothing to release... */
402 /****************************************************************************/
404 static int mcf_verify_port(struct uart_port *port, struct serial_struct *ser)
406 if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_MCF))
407 return -EINVAL;
408 return 0;
411 /****************************************************************************/
414 * Define the basic serial functions we support.
416 static struct uart_ops mcf_uart_ops = {
417 .tx_empty = mcf_tx_empty,
418 .get_mctrl = mcf_get_mctrl,
419 .set_mctrl = mcf_set_mctrl,
420 .start_tx = mcf_start_tx,
421 .stop_tx = mcf_stop_tx,
422 .stop_rx = mcf_stop_rx,
423 .enable_ms = mcf_enable_ms,
424 .break_ctl = mcf_break_ctl,
425 .startup = mcf_startup,
426 .shutdown = mcf_shutdown,
427 .set_termios = mcf_set_termios,
428 .type = mcf_type,
429 .request_port = mcf_request_port,
430 .release_port = mcf_release_port,
431 .config_port = mcf_config_port,
432 .verify_port = mcf_verify_port,
435 static struct mcf_uart mcf_ports[3];
437 #define MCF_MAXPORTS ARRAY_SIZE(mcf_ports)
439 /****************************************************************************/
440 #if defined(CONFIG_SERIAL_MCF_CONSOLE)
441 /****************************************************************************/
443 int __init early_mcf_setup(struct mcf_platform_uart *platp)
445 struct uart_port *port;
446 int i;
448 for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
449 port = &mcf_ports[i].port;
451 port->line = i;
452 port->type = PORT_MCF;
453 port->mapbase = platp[i].mapbase;
454 port->membase = (platp[i].membase) ? platp[i].membase :
455 (unsigned char __iomem *) port->mapbase;
456 port->iotype = SERIAL_IO_MEM;
457 port->irq = platp[i].irq;
458 port->uartclk = MCF_BUSCLK;
459 port->flags = ASYNC_BOOT_AUTOCONF;
460 port->ops = &mcf_uart_ops;
463 return 0;
466 /****************************************************************************/
468 static void mcf_console_putc(struct console *co, const char c)
470 struct uart_port *port = &(mcf_ports + co->index)->port;
471 int i;
473 for (i = 0; (i < 0x10000); i++) {
474 if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
475 break;
477 writeb(c, port->membase + MCFUART_UTB);
478 for (i = 0; (i < 0x10000); i++) {
479 if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
480 break;
484 /****************************************************************************/
486 static void mcf_console_write(struct console *co, const char *s, unsigned int count)
488 for (; (count); count--, s++) {
489 mcf_console_putc(co, *s);
490 if (*s == '\n')
491 mcf_console_putc(co, '\r');
495 /****************************************************************************/
497 static int __init mcf_console_setup(struct console *co, char *options)
499 struct uart_port *port;
500 int baud = CONFIG_SERIAL_MCF_BAUDRATE;
501 int bits = 8;
502 int parity = 'n';
503 int flow = 'n';
505 if ((co->index >= 0) && (co->index <= MCF_MAXPORTS))
506 co->index = 0;
507 port = &mcf_ports[co->index].port;
508 if (port->membase == 0)
509 return -ENODEV;
511 if (options)
512 uart_parse_options(options, &baud, &parity, &bits, &flow);
514 return uart_set_options(port, co, baud, parity, bits, flow);
517 /****************************************************************************/
519 static struct uart_driver mcf_driver;
521 static struct console mcf_console = {
522 .name = "ttyS",
523 .write = mcf_console_write,
524 .device = uart_console_device,
525 .setup = mcf_console_setup,
526 .flags = CON_PRINTBUFFER,
527 .index = -1,
528 .data = &mcf_driver,
531 static int __init mcf_console_init(void)
533 register_console(&mcf_console);
534 return 0;
537 console_initcall(mcf_console_init);
539 #define MCF_CONSOLE &mcf_console
541 /****************************************************************************/
542 #else
543 /****************************************************************************/
545 #define MCF_CONSOLE NULL
547 /****************************************************************************/
548 #endif /* CONFIG_MCF_CONSOLE */
549 /****************************************************************************/
552 * Define the mcf UART driver structure.
554 static struct uart_driver mcf_driver = {
555 .owner = THIS_MODULE,
556 .driver_name = "mcf",
557 .dev_name = "ttyS",
558 .major = TTY_MAJOR,
559 .minor = 64,
560 .nr = MCF_MAXPORTS,
561 .cons = MCF_CONSOLE,
564 /****************************************************************************/
566 static int __devinit mcf_probe(struct platform_device *pdev)
568 struct mcf_platform_uart *platp = pdev->dev.platform_data;
569 struct uart_port *port;
570 int i;
572 for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
573 port = &mcf_ports[i].port;
575 port->line = i;
576 port->type = PORT_MCF;
577 port->mapbase = platp[i].mapbase;
578 port->membase = (platp[i].membase) ? platp[i].membase :
579 (unsigned char __iomem *) platp[i].mapbase;
580 port->iotype = SERIAL_IO_MEM;
581 port->irq = platp[i].irq;
582 port->uartclk = MCF_BUSCLK;
583 port->ops = &mcf_uart_ops;
584 port->flags = ASYNC_BOOT_AUTOCONF;
586 uart_add_one_port(&mcf_driver, port);
589 return 0;
592 /****************************************************************************/
594 static int mcf_remove(struct platform_device *pdev)
596 struct uart_port *port;
597 int i;
599 for (i = 0; (i < MCF_MAXPORTS); i++) {
600 port = &mcf_ports[i].port;
601 if (port)
602 uart_remove_one_port(&mcf_driver, port);
605 return 0;
608 /****************************************************************************/
610 static struct platform_driver mcf_platform_driver = {
611 .probe = mcf_probe,
612 .remove = __devexit_p(mcf_remove),
613 .driver = {
614 .name = "mcfuart",
615 .owner = THIS_MODULE,
619 /****************************************************************************/
621 static int __init mcf_init(void)
623 int rc;
625 printk("ColdFire internal UART serial driver\n");
627 rc = uart_register_driver(&mcf_driver);
628 if (rc)
629 return rc;
630 rc = platform_driver_register(&mcf_platform_driver);
631 if (rc)
632 return rc;
633 return 0;
636 /****************************************************************************/
638 static void __exit mcf_exit(void)
640 platform_driver_unregister(&mcf_platform_driver);
641 uart_unregister_driver(&mcf_driver);
644 /****************************************************************************/
646 module_init(mcf_init);
647 module_exit(mcf_exit);
649 MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
650 MODULE_DESCRIPTION("Freescale ColdFire UART driver");
651 MODULE_LICENSE("GPL");
652 MODULE_ALIAS("platform:mcfuart");
654 /****************************************************************************/