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 int sigs; 93 94 sigs = 95 (readl(port->membase + ALTERA_UART_STATUS_REG) & 96 ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0; 97 sigs |= (pp->sigs & TIOCM_RTS); 98 99 return sigs; 100} 101 102static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs) 103{ 104 struct altera_uart *pp = container_of(port, struct altera_uart, port); 105 106 pp->sigs = sigs; 107 if (sigs & TIOCM_RTS) 108 pp->imr |= ALTERA_UART_CONTROL_RTS_MSK; 109 else 110 pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK; 111 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 112} 113 114static void altera_uart_start_tx(struct uart_port *port) 115{ 116 struct altera_uart *pp = container_of(port, struct altera_uart, port); 117 118 pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK; 119 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 120} 121 122static void altera_uart_stop_tx(struct uart_port *port) 123{ 124 struct altera_uart *pp = container_of(port, struct altera_uart, port); 125 126 pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; 127 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 128} 129 130static void altera_uart_stop_rx(struct uart_port *port) 131{ 132 struct altera_uart *pp = container_of(port, struct altera_uart, port); 133 134 pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK; 135 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 136} 137 138static void altera_uart_break_ctl(struct uart_port *port, int break_state) 139{ 140 struct altera_uart *pp = container_of(port, struct altera_uart, port); 141 unsigned long flags; 142 143 spin_lock_irqsave(&port->lock, flags); 144 if (break_state == -1) 145 pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK; 146 else 147 pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK; 148 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 149 spin_unlock_irqrestore(&port->lock, flags); 150} 151 152static void altera_uart_enable_ms(struct uart_port *port) 153{ 154} 155 156static void altera_uart_set_termios(struct uart_port *port, 157 struct ktermios *termios, 158 struct ktermios *old) 159{ 160 unsigned long flags; 161 unsigned int baud, baudclk; 162 163 baud = uart_get_baud_rate(port, termios, old, 0, 4000000); 164 baudclk = port->uartclk / baud; 165 166 if (old) 167 tty_termios_copy_hw(termios, old); 168 tty_termios_encode_baud_rate(termios, baud, baud); 169 170 spin_lock_irqsave(&port->lock, flags); 171 writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG); 172 spin_unlock_irqrestore(&port->lock, flags); 173} 174 175static void altera_uart_rx_chars(struct altera_uart *pp) 176{ 177 struct uart_port *port = &pp->port; 178 unsigned char ch, flag; 179 unsigned short status; 180 181 while ((status = readl(port->membase + ALTERA_UART_STATUS_REG)) & 182 ALTERA_UART_STATUS_RRDY_MSK) { 183 ch = readl(port->membase + ALTERA_UART_RXDATA_REG); 184 flag = TTY_NORMAL; 185 port->icount.rx++; 186 187 if (status & ALTERA_UART_STATUS_E_MSK) { 188 writel(status, port->membase + ALTERA_UART_STATUS_REG); 189 190 if (status & ALTERA_UART_STATUS_BRK_MSK) { 191 port->icount.brk++; 192 if (uart_handle_break(port)) 193 continue; 194 } else if (status & ALTERA_UART_STATUS_PE_MSK) { 195 port->icount.parity++; 196 } else if (status & ALTERA_UART_STATUS_ROE_MSK) { 197 port->icount.overrun++; 198 } else if (status & ALTERA_UART_STATUS_FE_MSK) { 199 port->icount.frame++; 200 } 201 202 status &= port->read_status_mask; 203 204 if (status & ALTERA_UART_STATUS_BRK_MSK) 205 flag = TTY_BREAK; 206 else if (status & ALTERA_UART_STATUS_PE_MSK) 207 flag = TTY_PARITY; 208 else if (status & ALTERA_UART_STATUS_FE_MSK) 209 flag = TTY_FRAME; 210 } 211 212 if (uart_handle_sysrq_char(port, ch)) 213 continue; 214 uart_insert_char(port, status, ALTERA_UART_STATUS_ROE_MSK, ch, 215 flag); 216 } 217 218 tty_flip_buffer_push(port->state->port.tty); 219} 220 221static void altera_uart_tx_chars(struct altera_uart *pp) 222{ 223 struct uart_port *port = &pp->port; 224 struct circ_buf *xmit = &port->state->xmit; 225 226 if (port->x_char) { 227 /* Send special char - probably flow control */ 228 writel(port->x_char, port->membase + ALTERA_UART_TXDATA_REG); 229 port->x_char = 0; 230 port->icount.tx++; 231 return; 232 } 233 234 while (readl(port->membase + ALTERA_UART_STATUS_REG) & 235 ALTERA_UART_STATUS_TRDY_MSK) { 236 if (xmit->head == xmit->tail) 237 break; 238 writel(xmit->buf[xmit->tail], 239 port->membase + ALTERA_UART_TXDATA_REG); 240 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 241 port->icount.tx++; 242 } 243 244 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 245 uart_write_wakeup(port); 246 247 if (xmit->head == xmit->tail) { 248 pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; 249 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 250 } 251} 252 253static irqreturn_t altera_uart_interrupt(int irq, void *data) 254{ 255 struct uart_port *port = data; 256 struct altera_uart *pp = container_of(port, struct altera_uart, port); 257 unsigned int isr; 258 259 isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr; 260 261 spin_lock(&port->lock); 262 if (isr & ALTERA_UART_STATUS_RRDY_MSK) 263 altera_uart_rx_chars(pp); 264 if (isr & ALTERA_UART_STATUS_TRDY_MSK) 265 altera_uart_tx_chars(pp); 266 spin_unlock(&port->lock); 267 268 return IRQ_RETVAL(isr); 269} 270 271static void altera_uart_config_port(struct uart_port *port, int flags) 272{ 273 port->type = PORT_ALTERA_UART; 274 275 /* Clear mask, so no surprise interrupts. */ 276 writel(0, port->membase + ALTERA_UART_CONTROL_REG); 277 /* Clear status register */ 278 writel(0, port->membase + ALTERA_UART_STATUS_REG); 279} 280 281static int altera_uart_startup(struct uart_port *port) 282{ 283 struct altera_uart *pp = container_of(port, struct altera_uart, port); 284 unsigned long flags; 285 int ret; 286 287 ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED, 288 DRV_NAME, port); 289 if (ret) { 290 pr_err(DRV_NAME ": unable to attach Altera UART %d " 291 "interrupt vector=%d\n", port->line, port->irq); 292 return ret; 293 } 294 295 spin_lock_irqsave(&port->lock, flags); 296 297 /* Enable RX interrupts now */ 298 pp->imr = ALTERA_UART_CONTROL_RRDY_MSK; 299 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 300 301 spin_unlock_irqrestore(&port->lock, flags); 302 303 return 0; 304} 305 306static void altera_uart_shutdown(struct uart_port *port) 307{ 308 struct altera_uart *pp = container_of(port, struct altera_uart, port); 309 unsigned long flags; 310 311 spin_lock_irqsave(&port->lock, flags); 312 313 /* Disable all interrupts now */ 314 pp->imr = 0; 315 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 316 317 spin_unlock_irqrestore(&port->lock, flags); 318 319 free_irq(port->irq, port); 320} 321 322static const char *altera_uart_type(struct uart_port *port) 323{ 324 return (port->type == PORT_ALTERA_UART) ? "Altera UART" : NULL; 325} 326 327static int altera_uart_request_port(struct uart_port *port) 328{ 329 /* UARTs always present */ 330 return 0; 331} 332 333static void altera_uart_release_port(struct uart_port *port) 334{ 335 /* Nothing to release... */ 336} 337 338static int altera_uart_verify_port(struct uart_port *port, 339 struct serial_struct *ser) 340{ 341 if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_ALTERA_UART)) 342 return -EINVAL; 343 return 0; 344} 345 346/* 347 * Define the basic serial functions we support. 348 */ 349static struct uart_ops altera_uart_ops = { 350 .tx_empty = altera_uart_tx_empty, 351 .get_mctrl = altera_uart_get_mctrl, 352 .set_mctrl = altera_uart_set_mctrl, 353 .start_tx = altera_uart_start_tx, 354 .stop_tx = altera_uart_stop_tx, 355 .stop_rx = altera_uart_stop_rx, 356 .enable_ms = altera_uart_enable_ms, 357 .break_ctl = altera_uart_break_ctl, 358 .startup = altera_uart_startup, 359 .shutdown = altera_uart_shutdown, 360 .set_termios = altera_uart_set_termios, 361 .type = altera_uart_type, 362 .request_port = altera_uart_request_port, 363 .release_port = altera_uart_release_port, 364 .config_port = altera_uart_config_port, 365 .verify_port = altera_uart_verify_port, 366}; 367 368static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS]; 369 370#if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) 371 372int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) 373{ 374 struct uart_port *port; 375 int i; 376 377 for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) { 378 port = &altera_uart_ports[i].port; 379 380 port->line = i; 381 port->type = PORT_ALTERA_UART; 382 port->mapbase = platp[i].mapbase; 383 port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); 384 port->iotype = SERIAL_IO_MEM; 385 port->irq = platp[i].irq; 386 port->uartclk = platp[i].uartclk; 387 port->flags = ASYNC_BOOT_AUTOCONF; 388 port->ops = &altera_uart_ops; 389 } 390 391 return 0; 392} 393 394static void altera_uart_console_putc(struct uart_port *port, const char c) 395{ 396 while (!(readl(port->membase + ALTERA_UART_STATUS_REG) & 397 ALTERA_UART_STATUS_TRDY_MSK)) 398 cpu_relax(); 399 400 writel(c, port->membase + ALTERA_UART_TXDATA_REG); 401} 402 403static void altera_uart_console_write(struct console *co, const char *s, 404 unsigned int count) 405{ 406 struct uart_port *port = &(altera_uart_ports + co->index)->port; 407 408 for (; count; count--, s++) { 409 altera_uart_console_putc(port, *s); 410 if (*s == '\n') 411 altera_uart_console_putc(port, '\r'); 412 } 413} 414 415static int __init altera_uart_console_setup(struct console *co, char *options) 416{ 417 struct uart_port *port; 418 int baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE; 419 int bits = 8; 420 int parity = 'n'; 421 int flow = 'n'; 422 423 if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) 424 return -EINVAL; 425 port = &altera_uart_ports[co->index].port; 426 if (port->membase == 0) 427 return -ENODEV; 428 429 if (options) 430 uart_parse_options(options, &baud, &parity, &bits, &flow); 431 432 return uart_set_options(port, co, baud, parity, bits, flow); 433} 434 435static struct uart_driver altera_uart_driver; 436 437static struct console altera_uart_console = { 438 .name = "ttyS", 439 .write = altera_uart_console_write, 440 .device = uart_console_device, 441 .setup = altera_uart_console_setup, 442 .flags = CON_PRINTBUFFER, 443 .index = -1, 444 .data = &altera_uart_driver, 445}; 446 447static int __init altera_uart_console_init(void) 448{ 449 register_console(&altera_uart_console); 450 return 0; 451} 452 453console_initcall(altera_uart_console_init); 454 455#define ALTERA_UART_CONSOLE (&altera_uart_console) 456 457#else 458 459#define ALTERA_UART_CONSOLE NULL 460 461#endif /* CONFIG_ALTERA_UART_CONSOLE */ 462 463/* 464 * Define the altera_uart UART driver structure. 465 */ 466static struct uart_driver altera_uart_driver = { 467 .owner = THIS_MODULE, 468 .driver_name = DRV_NAME, 469 .dev_name = "ttyS", 470 .major = TTY_MAJOR, 471 .minor = 64, 472 .nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS, 473 .cons = ALTERA_UART_CONSOLE, 474}; 475 476static int __devinit altera_uart_probe(struct platform_device *pdev) 477{ 478 struct altera_uart_platform_uart *platp = pdev->dev.platform_data; 479 struct uart_port *port; 480 int i; 481 482 for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) { 483 port = &altera_uart_ports[i].port; 484 485 port->line = i; 486 port->type = PORT_ALTERA_UART; 487 port->mapbase = platp[i].mapbase; 488 port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); 489 port->iotype = SERIAL_IO_MEM; 490 port->irq = platp[i].irq; 491 port->uartclk = platp[i].uartclk; 492 port->ops = &altera_uart_ops; 493 port->flags = ASYNC_BOOT_AUTOCONF; 494 495 uart_add_one_port(&altera_uart_driver, port); 496 } 497 498 return 0; 499} 500 501static int __devexit altera_uart_remove(struct platform_device *pdev) 502{ 503 struct uart_port *port; 504 int i; 505 506 for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) { 507 port = &altera_uart_ports[i].port; 508 if (port) 509 uart_remove_one_port(&altera_uart_driver, port); 510 } 511 512 return 0; 513} 514 515static struct platform_driver altera_uart_platform_driver = { 516 .probe = altera_uart_probe, 517 .remove = __devexit_p(altera_uart_remove), 518 .driver = { 519 .name = DRV_NAME, 520 .owner = THIS_MODULE, 521 .pm = NULL, 522 }, 523}; 524 525static int __init altera_uart_init(void) 526{ 527 int rc; 528 529 rc = uart_register_driver(&altera_uart_driver); 530 if (rc) 531 return rc; 532 rc = platform_driver_register(&altera_uart_platform_driver); 533 if (rc) { 534 uart_unregister_driver(&altera_uart_driver); 535 return rc; 536 } 537 return 0; 538} 539 540static void __exit altera_uart_exit(void) 541{ 542 platform_driver_unregister(&altera_uart_platform_driver); 543 uart_unregister_driver(&altera_uart_driver); 544} 545 546module_init(altera_uart_init); 547module_exit(altera_uart_exit); 548 549MODULE_DESCRIPTION("Altera UART driver"); 550MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); 551MODULE_LICENSE("GPL"); 552MODULE_ALIAS("platform:" DRV_NAME); 553