Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.35-rc1 570 lines 16 kB view raw
1/* 2 * altera_uart.c -- Altera UART driver 3 * 4 * Based on mcf.c -- Freescale ColdFire UART driver 5 * 6 * (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com> 7 * (C) Copyright 2008, Thomas Chou <thomas@wytron.com.tw> 8 * (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 */ 15 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/platform_device.h> 26#include <linux/io.h> 27#include <linux/altera_uart.h> 28 29#define DRV_NAME "altera_uart" 30 31/* 32 * Altera UART register definitions according to the Nios UART datasheet: 33 * http://www.altera.com/literature/ds/ds_nios_uart.pdf 34 */ 35 36#define ALTERA_UART_SIZE 32 37 38#define ALTERA_UART_RXDATA_REG 0 39#define ALTERA_UART_TXDATA_REG 4 40#define ALTERA_UART_STATUS_REG 8 41#define ALTERA_UART_CONTROL_REG 12 42#define ALTERA_UART_DIVISOR_REG 16 43#define ALTERA_UART_EOP_REG 20 44 45#define ALTERA_UART_STATUS_PE_MSK 0x0001 /* parity error */ 46#define ALTERA_UART_STATUS_FE_MSK 0x0002 /* framing error */ 47#define ALTERA_UART_STATUS_BRK_MSK 0x0004 /* break */ 48#define ALTERA_UART_STATUS_ROE_MSK 0x0008 /* RX overrun error */ 49#define ALTERA_UART_STATUS_TOE_MSK 0x0010 /* TX overrun error */ 50#define ALTERA_UART_STATUS_TMT_MSK 0x0020 /* TX shift register state */ 51#define ALTERA_UART_STATUS_TRDY_MSK 0x0040 /* TX ready */ 52#define ALTERA_UART_STATUS_RRDY_MSK 0x0080 /* RX ready */ 53#define ALTERA_UART_STATUS_E_MSK 0x0100 /* exception condition */ 54#define ALTERA_UART_STATUS_DCTS_MSK 0x0400 /* CTS logic-level change */ 55#define ALTERA_UART_STATUS_CTS_MSK 0x0800 /* CTS logic state */ 56#define ALTERA_UART_STATUS_EOP_MSK 0x1000 /* EOP written/read */ 57 58 /* Enable interrupt on... */ 59#define ALTERA_UART_CONTROL_PE_MSK 0x0001 /* ...parity error */ 60#define ALTERA_UART_CONTROL_FE_MSK 0x0002 /* ...framing error */ 61#define ALTERA_UART_CONTROL_BRK_MSK 0x0004 /* ...break */ 62#define ALTERA_UART_CONTROL_ROE_MSK 0x0008 /* ...RX overrun */ 63#define ALTERA_UART_CONTROL_TOE_MSK 0x0010 /* ...TX overrun */ 64#define ALTERA_UART_CONTROL_TMT_MSK 0x0020 /* ...TX shift register empty */ 65#define ALTERA_UART_CONTROL_TRDY_MSK 0x0040 /* ...TX ready */ 66#define ALTERA_UART_CONTROL_RRDY_MSK 0x0080 /* ...RX ready */ 67#define ALTERA_UART_CONTROL_E_MSK 0x0100 /* ...exception*/ 68 69#define ALTERA_UART_CONTROL_TRBK_MSK 0x0200 /* TX break */ 70#define ALTERA_UART_CONTROL_DCTS_MSK 0x0400 /* Interrupt on CTS change */ 71#define ALTERA_UART_CONTROL_RTS_MSK 0x0800 /* RTS signal */ 72#define ALTERA_UART_CONTROL_EOP_MSK 0x1000 /* Interrupt on EOP */ 73 74/* 75 * Local per-uart structure. 76 */ 77struct altera_uart { 78 struct uart_port port; 79 unsigned int sigs; /* Local copy of line sigs */ 80 unsigned short imr; /* Local IMR mirror */ 81}; 82 83static unsigned int altera_uart_tx_empty(struct uart_port *port) 84{ 85 return (readl(port->membase + ALTERA_UART_STATUS_REG) & 86 ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0; 87} 88 89static unsigned int altera_uart_get_mctrl(struct uart_port *port) 90{ 91 struct altera_uart *pp = container_of(port, struct altera_uart, port); 92 unsigned long flags; 93 unsigned int sigs; 94 95 spin_lock_irqsave(&port->lock, flags); 96 sigs = 97 (readl(port->membase + ALTERA_UART_STATUS_REG) & 98 ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0; 99 sigs |= (pp->sigs & TIOCM_RTS); 100 spin_unlock_irqrestore(&port->lock, flags); 101 102 return sigs; 103} 104 105static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs) 106{ 107 struct altera_uart *pp = container_of(port, struct altera_uart, port); 108 unsigned long flags; 109 110 spin_lock_irqsave(&port->lock, flags); 111 pp->sigs = sigs; 112 if (sigs & TIOCM_RTS) 113 pp->imr |= ALTERA_UART_CONTROL_RTS_MSK; 114 else 115 pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK; 116 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 117 spin_unlock_irqrestore(&port->lock, flags); 118} 119 120static void altera_uart_start_tx(struct uart_port *port) 121{ 122 struct altera_uart *pp = container_of(port, struct altera_uart, port); 123 unsigned long flags; 124 125 spin_lock_irqsave(&port->lock, flags); 126 pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK; 127 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 128 spin_unlock_irqrestore(&port->lock, flags); 129} 130 131static void altera_uart_stop_tx(struct uart_port *port) 132{ 133 struct altera_uart *pp = container_of(port, struct altera_uart, port); 134 unsigned long flags; 135 136 spin_lock_irqsave(&port->lock, flags); 137 pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; 138 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 139 spin_unlock_irqrestore(&port->lock, flags); 140} 141 142static void altera_uart_stop_rx(struct uart_port *port) 143{ 144 struct altera_uart *pp = container_of(port, struct altera_uart, port); 145 unsigned long flags; 146 147 spin_lock_irqsave(&port->lock, flags); 148 pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK; 149 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 150 spin_unlock_irqrestore(&port->lock, flags); 151} 152 153static void altera_uart_break_ctl(struct uart_port *port, int break_state) 154{ 155 struct altera_uart *pp = container_of(port, struct altera_uart, port); 156 unsigned long flags; 157 158 spin_lock_irqsave(&port->lock, flags); 159 if (break_state == -1) 160 pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK; 161 else 162 pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK; 163 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 164 spin_unlock_irqrestore(&port->lock, flags); 165} 166 167static void altera_uart_enable_ms(struct uart_port *port) 168{ 169} 170 171static void altera_uart_set_termios(struct uart_port *port, 172 struct ktermios *termios, 173 struct ktermios *old) 174{ 175 unsigned long flags; 176 unsigned int baud, baudclk; 177 178 baud = uart_get_baud_rate(port, termios, old, 0, 4000000); 179 baudclk = port->uartclk / baud; 180 181 if (old) 182 tty_termios_copy_hw(termios, old); 183 tty_termios_encode_baud_rate(termios, baud, baud); 184 185 spin_lock_irqsave(&port->lock, flags); 186 writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG); 187 spin_unlock_irqrestore(&port->lock, flags); 188} 189 190static void altera_uart_rx_chars(struct altera_uart *pp) 191{ 192 struct uart_port *port = &pp->port; 193 unsigned char ch, flag; 194 unsigned short status; 195 196 while ((status = readl(port->membase + ALTERA_UART_STATUS_REG)) & 197 ALTERA_UART_STATUS_RRDY_MSK) { 198 ch = readl(port->membase + ALTERA_UART_RXDATA_REG); 199 flag = TTY_NORMAL; 200 port->icount.rx++; 201 202 if (status & ALTERA_UART_STATUS_E_MSK) { 203 writel(status, port->membase + ALTERA_UART_STATUS_REG); 204 205 if (status & ALTERA_UART_STATUS_BRK_MSK) { 206 port->icount.brk++; 207 if (uart_handle_break(port)) 208 continue; 209 } else if (status & ALTERA_UART_STATUS_PE_MSK) { 210 port->icount.parity++; 211 } else if (status & ALTERA_UART_STATUS_ROE_MSK) { 212 port->icount.overrun++; 213 } else if (status & ALTERA_UART_STATUS_FE_MSK) { 214 port->icount.frame++; 215 } 216 217 status &= port->read_status_mask; 218 219 if (status & ALTERA_UART_STATUS_BRK_MSK) 220 flag = TTY_BREAK; 221 else if (status & ALTERA_UART_STATUS_PE_MSK) 222 flag = TTY_PARITY; 223 else if (status & ALTERA_UART_STATUS_FE_MSK) 224 flag = TTY_FRAME; 225 } 226 227 if (uart_handle_sysrq_char(port, ch)) 228 continue; 229 uart_insert_char(port, status, ALTERA_UART_STATUS_ROE_MSK, ch, 230 flag); 231 } 232 233 tty_flip_buffer_push(port->state->port.tty); 234} 235 236static void altera_uart_tx_chars(struct altera_uart *pp) 237{ 238 struct uart_port *port = &pp->port; 239 struct circ_buf *xmit = &port->state->xmit; 240 241 if (port->x_char) { 242 /* Send special char - probably flow control */ 243 writel(port->x_char, port->membase + ALTERA_UART_TXDATA_REG); 244 port->x_char = 0; 245 port->icount.tx++; 246 return; 247 } 248 249 while (readl(port->membase + ALTERA_UART_STATUS_REG) & 250 ALTERA_UART_STATUS_TRDY_MSK) { 251 if (xmit->head == xmit->tail) 252 break; 253 writel(xmit->buf[xmit->tail], 254 port->membase + ALTERA_UART_TXDATA_REG); 255 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 256 port->icount.tx++; 257 } 258 259 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 260 uart_write_wakeup(port); 261 262 if (xmit->head == xmit->tail) { 263 pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; 264 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 265 } 266} 267 268static irqreturn_t altera_uart_interrupt(int irq, void *data) 269{ 270 struct uart_port *port = data; 271 struct altera_uart *pp = container_of(port, struct altera_uart, port); 272 unsigned int isr; 273 274 isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr; 275 if (isr & ALTERA_UART_STATUS_RRDY_MSK) 276 altera_uart_rx_chars(pp); 277 if (isr & ALTERA_UART_STATUS_TRDY_MSK) 278 altera_uart_tx_chars(pp); 279 return IRQ_RETVAL(isr); 280} 281 282static void altera_uart_config_port(struct uart_port *port, int flags) 283{ 284 port->type = PORT_ALTERA_UART; 285 286 /* Clear mask, so no surprise interrupts. */ 287 writel(0, port->membase + ALTERA_UART_CONTROL_REG); 288 /* Clear status register */ 289 writel(0, port->membase + ALTERA_UART_STATUS_REG); 290} 291 292static int altera_uart_startup(struct uart_port *port) 293{ 294 struct altera_uart *pp = container_of(port, struct altera_uart, port); 295 unsigned long flags; 296 int ret; 297 298 ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED, 299 DRV_NAME, port); 300 if (ret) { 301 pr_err(DRV_NAME ": unable to attach Altera UART %d " 302 "interrupt vector=%d\n", port->line, port->irq); 303 return ret; 304 } 305 306 spin_lock_irqsave(&port->lock, flags); 307 308 /* Enable RX interrupts now */ 309 pp->imr = ALTERA_UART_CONTROL_RRDY_MSK; 310 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 311 312 spin_unlock_irqrestore(&port->lock, flags); 313 314 return 0; 315} 316 317static void altera_uart_shutdown(struct uart_port *port) 318{ 319 struct altera_uart *pp = container_of(port, struct altera_uart, port); 320 unsigned long flags; 321 322 spin_lock_irqsave(&port->lock, flags); 323 324 /* Disable all interrupts now */ 325 pp->imr = 0; 326 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 327 328 spin_unlock_irqrestore(&port->lock, flags); 329 330 free_irq(port->irq, port); 331} 332 333static const char *altera_uart_type(struct uart_port *port) 334{ 335 return (port->type == PORT_ALTERA_UART) ? "Altera UART" : NULL; 336} 337 338static int altera_uart_request_port(struct uart_port *port) 339{ 340 /* UARTs always present */ 341 return 0; 342} 343 344static void altera_uart_release_port(struct uart_port *port) 345{ 346 /* Nothing to release... */ 347} 348 349static int altera_uart_verify_port(struct uart_port *port, 350 struct serial_struct *ser) 351{ 352 if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_ALTERA_UART)) 353 return -EINVAL; 354 return 0; 355} 356 357/* 358 * Define the basic serial functions we support. 359 */ 360static struct uart_ops altera_uart_ops = { 361 .tx_empty = altera_uart_tx_empty, 362 .get_mctrl = altera_uart_get_mctrl, 363 .set_mctrl = altera_uart_set_mctrl, 364 .start_tx = altera_uart_start_tx, 365 .stop_tx = altera_uart_stop_tx, 366 .stop_rx = altera_uart_stop_rx, 367 .enable_ms = altera_uart_enable_ms, 368 .break_ctl = altera_uart_break_ctl, 369 .startup = altera_uart_startup, 370 .shutdown = altera_uart_shutdown, 371 .set_termios = altera_uart_set_termios, 372 .type = altera_uart_type, 373 .request_port = altera_uart_request_port, 374 .release_port = altera_uart_release_port, 375 .config_port = altera_uart_config_port, 376 .verify_port = altera_uart_verify_port, 377}; 378 379static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS]; 380 381#if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) 382 383int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) 384{ 385 struct uart_port *port; 386 int i; 387 388 for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) { 389 port = &altera_uart_ports[i].port; 390 391 port->line = i; 392 port->type = PORT_ALTERA_UART; 393 port->mapbase = platp[i].mapbase; 394 port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); 395 port->iotype = SERIAL_IO_MEM; 396 port->irq = platp[i].irq; 397 port->uartclk = platp[i].uartclk; 398 port->flags = ASYNC_BOOT_AUTOCONF; 399 port->ops = &altera_uart_ops; 400 } 401 402 return 0; 403} 404 405static void altera_uart_console_putc(struct console *co, const char c) 406{ 407 struct uart_port *port = &(altera_uart_ports + co->index)->port; 408 int i; 409 410 for (i = 0; i < 0x10000; i++) { 411 if (readl(port->membase + ALTERA_UART_STATUS_REG) & 412 ALTERA_UART_STATUS_TRDY_MSK) 413 break; 414 } 415 writel(c, port->membase + ALTERA_UART_TXDATA_REG); 416 for (i = 0; i < 0x10000; i++) { 417 if (readl(port->membase + ALTERA_UART_STATUS_REG) & 418 ALTERA_UART_STATUS_TRDY_MSK) 419 break; 420 } 421} 422 423static void altera_uart_console_write(struct console *co, const char *s, 424 unsigned int count) 425{ 426 for (; count; count--, s++) { 427 altera_uart_console_putc(co, *s); 428 if (*s == '\n') 429 altera_uart_console_putc(co, '\r'); 430 } 431} 432 433static int __init altera_uart_console_setup(struct console *co, char *options) 434{ 435 struct uart_port *port; 436 int baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE; 437 int bits = 8; 438 int parity = 'n'; 439 int flow = 'n'; 440 441 if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) 442 return -EINVAL; 443 port = &altera_uart_ports[co->index].port; 444 if (port->membase == 0) 445 return -ENODEV; 446 447 if (options) 448 uart_parse_options(options, &baud, &parity, &bits, &flow); 449 450 return uart_set_options(port, co, baud, parity, bits, flow); 451} 452 453static struct uart_driver altera_uart_driver; 454 455static struct console altera_uart_console = { 456 .name = "ttyS", 457 .write = altera_uart_console_write, 458 .device = uart_console_device, 459 .setup = altera_uart_console_setup, 460 .flags = CON_PRINTBUFFER, 461 .index = -1, 462 .data = &altera_uart_driver, 463}; 464 465static int __init altera_uart_console_init(void) 466{ 467 register_console(&altera_uart_console); 468 return 0; 469} 470 471console_initcall(altera_uart_console_init); 472 473#define ALTERA_UART_CONSOLE (&altera_uart_console) 474 475#else 476 477#define ALTERA_UART_CONSOLE NULL 478 479#endif /* CONFIG_ALTERA_UART_CONSOLE */ 480 481/* 482 * Define the altera_uart UART driver structure. 483 */ 484static struct uart_driver altera_uart_driver = { 485 .owner = THIS_MODULE, 486 .driver_name = DRV_NAME, 487 .dev_name = "ttyS", 488 .major = TTY_MAJOR, 489 .minor = 64, 490 .nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS, 491 .cons = ALTERA_UART_CONSOLE, 492}; 493 494static int __devinit altera_uart_probe(struct platform_device *pdev) 495{ 496 struct altera_uart_platform_uart *platp = pdev->dev.platform_data; 497 struct uart_port *port; 498 int i; 499 500 for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) { 501 port = &altera_uart_ports[i].port; 502 503 port->line = i; 504 port->type = PORT_ALTERA_UART; 505 port->mapbase = platp[i].mapbase; 506 port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); 507 port->iotype = SERIAL_IO_MEM; 508 port->irq = platp[i].irq; 509 port->uartclk = platp[i].uartclk; 510 port->ops = &altera_uart_ops; 511 port->flags = ASYNC_BOOT_AUTOCONF; 512 513 uart_add_one_port(&altera_uart_driver, port); 514 } 515 516 return 0; 517} 518 519static int altera_uart_remove(struct platform_device *pdev) 520{ 521 struct uart_port *port; 522 int i; 523 524 for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) { 525 port = &altera_uart_ports[i].port; 526 if (port) 527 uart_remove_one_port(&altera_uart_driver, port); 528 } 529 530 return 0; 531} 532 533static struct platform_driver altera_uart_platform_driver = { 534 .probe = altera_uart_probe, 535 .remove = __devexit_p(altera_uart_remove), 536 .driver = { 537 .name = DRV_NAME, 538 .owner = THIS_MODULE, 539 .pm = NULL, 540 }, 541}; 542 543static int __init altera_uart_init(void) 544{ 545 int rc; 546 547 rc = uart_register_driver(&altera_uart_driver); 548 if (rc) 549 return rc; 550 rc = platform_driver_register(&altera_uart_platform_driver); 551 if (rc) { 552 uart_unregister_driver(&altera_uart_driver); 553 return rc; 554 } 555 return 0; 556} 557 558static void __exit altera_uart_exit(void) 559{ 560 platform_driver_unregister(&altera_uart_platform_driver); 561 uart_unregister_driver(&altera_uart_driver); 562} 563 564module_init(altera_uart_init); 565module_exit(altera_uart_exit); 566 567MODULE_DESCRIPTION("Altera UART driver"); 568MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); 569MODULE_LICENSE("GPL"); 570MODULE_ALIAS("platform:" DRV_NAME);