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.

[ARM] 3242/2: AT91RM9200 support for 2.6 (Serial)

Patch from Andrew Victor

This patch adds support to the 2.6 kernel series for the Atmel
AT91RM9200 processor.

This patch is the Serial driver.

This version uses the newly re-written GPL'ed hardware headers.

Signed-off-by: Andrew Victor <andrew@sanpeople.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Andrew Victor and committed by
Russell King
1e6c9c28 97712717

+1127
+34
drivers/serial/Kconfig
··· 280 280 your boot loader (lilo or loadlin) about how to pass options to the 281 281 kernel at boot time.) 282 282 283 + config SERIAL_AT91 284 + bool "AT91RM9200 serial port support" 285 + depends on ARM && ARCH_AT91RM9200 286 + select SERIAL_CORE 287 + help 288 + This enables the driver for the on-chip UARTs of the AT91RM9200 289 + processor. 290 + 291 + config SERIAL_AT91_CONSOLE 292 + bool "Support for console on AT91RM9200 serial port" 293 + depends on SERIAL_AT91=y 294 + select SERIAL_CORE_CONSOLE 295 + help 296 + Say Y here if you wish to use a UART on the AT91RM9200 as the system 297 + console (the system console is the device which receives all kernel 298 + messages and warnings and which allows logins in single user mode). 299 + 300 + config SERIAL_AT91_TTYAT 301 + bool "Install as device ttyAT0-4 instead of ttyS0-4" 302 + depends on SERIAL_AT91=y 303 + help 304 + Say Y here if you wish to have the five internal AT91RM9200 UARTs 305 + appear as /dev/ttyAT0-4 (major 240, minor 0-4) instead of the 306 + normal /dev/ttyS0-4 (major 4, minor 64-68). This is necessary if 307 + you also want other UARTs, such as external 8250/16C550 compatible 308 + UARTs. 309 + The ttySn nodes are legally reserved for the 8250 serial driver 310 + but are often misused by other serial drivers. 311 + 312 + To use this, you should create suitable ttyATn device nodes in 313 + /dev/, and pass "console=ttyATn" to the kernel. 314 + 315 + Say Y if you have an external 8250/16C550 UART. If unsure, say N. 316 + 283 317 config SERIAL_CLPS711X 284 318 tristate "CLPS711X serial port support" 285 319 depends on ARM && ARCH_CLPS711X
+1
drivers/serial/Makefile
··· 56 56 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o 57 57 obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o 58 58 obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o 59 + obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
+894
drivers/serial/at91_serial.c
··· 1 + /* 2 + * linux/drivers/char/at91_serial.c 3 + * 4 + * Driver for Atmel AT91RM9200 Serial ports 5 + * 6 + * Copyright (C) 2003 Rick Bronson 7 + * 8 + * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd. 9 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. 10 + * 11 + * This program is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * This program is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this program; if not, write to the Free Software 23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 + * 25 + */ 26 + #include <linux/config.h> 27 + #include <linux/module.h> 28 + #include <linux/tty.h> 29 + #include <linux/ioport.h> 30 + #include <linux/slab.h> 31 + #include <linux/init.h> 32 + #include <linux/serial.h> 33 + #include <linux/console.h> 34 + #include <linux/sysrq.h> 35 + #include <linux/tty_flip.h> 36 + 37 + #include <asm/io.h> 38 + 39 + #include <asm/arch/at91rm9200_usart.h> 40 + #include <asm/mach/serial_at91rm9200.h> 41 + #include <asm/arch/board.h> 42 + #include <asm/arch/pio.h> 43 + 44 + 45 + #if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) 46 + #define SUPPORT_SYSRQ 47 + #endif 48 + 49 + #include <linux/serial_core.h> 50 + 51 + #ifdef CONFIG_SERIAL_AT91_TTYAT 52 + 53 + /* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we 54 + * should coexist with the 8250 driver, such as if we have an external 16C550 55 + * UART. */ 56 + #define SERIAL_AT91_MAJOR 204 57 + #define MINOR_START 154 58 + #define AT91_DEVICENAME "ttyAT" 59 + 60 + #else 61 + 62 + /* Use device name ttyS, major 4, minor 64-68. This is the usual serial port 63 + * name, but it is legally reserved for the 8250 driver. */ 64 + #define SERIAL_AT91_MAJOR TTY_MAJOR 65 + #define MINOR_START 64 66 + #define AT91_DEVICENAME "ttyS" 67 + 68 + #endif 69 + 70 + #define AT91_VA_BASE_DBGU ((unsigned long) AT91_VA_BASE_SYS + AT91_DBGU) 71 + #define AT91_ISR_PASS_LIMIT 256 72 + 73 + #define UART_PUT_CR(port,v) writel(v, (port)->membase + AT91_US_CR) 74 + #define UART_GET_MR(port) readl((port)->membase + AT91_US_MR) 75 + #define UART_PUT_MR(port,v) writel(v, (port)->membase + AT91_US_MR) 76 + #define UART_PUT_IER(port,v) writel(v, (port)->membase + AT91_US_IER) 77 + #define UART_PUT_IDR(port,v) writel(v, (port)->membase + AT91_US_IDR) 78 + #define UART_GET_IMR(port) readl((port)->membase + AT91_US_IMR) 79 + #define UART_GET_CSR(port) readl((port)->membase + AT91_US_CSR) 80 + #define UART_GET_CHAR(port) readl((port)->membase + AT91_US_RHR) 81 + #define UART_PUT_CHAR(port,v) writel(v, (port)->membase + AT91_US_THR) 82 + #define UART_GET_BRGR(port) readl((port)->membase + AT91_US_BRGR) 83 + #define UART_PUT_BRGR(port,v) writel(v, (port)->membase + AT91_US_BRGR) 84 + #define UART_PUT_RTOR(port,v) writel(v, (port)->membase + AT91_US_RTOR) 85 + 86 + // #define UART_GET_CR(port) readl((port)->membase + AT91_US_CR) // is write-only 87 + 88 + /* PDC registers */ 89 + #define UART_PUT_PTCR(port,v) writel(v, (port)->membase + AT91_PDC_PTCR) 90 + #define UART_PUT_RPR(port,v) writel(v, (port)->membase + AT91_PDC_RPR) 91 + #define UART_PUT_RCR(port,v) writel(v, (port)->membase + AT91_PDC_RCR) 92 + #define UART_GET_RCR(port) readl((port)->membase + AT91_PDC_RCR) 93 + #define UART_PUT_RNPR(port,v) writel(v, (port)->membase + AT91_PDC_RNPR) 94 + #define UART_PUT_RNCR(port,v) writel(v, (port)->membase + AT91_PDC_RNCR) 95 + 96 + 97 + static int (*at91_open)(struct uart_port *); 98 + static void (*at91_close)(struct uart_port *); 99 + 100 + #ifdef SUPPORT_SYSRQ 101 + static struct console at91_console; 102 + #endif 103 + 104 + /* 105 + * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty. 106 + */ 107 + static u_int at91_tx_empty(struct uart_port *port) 108 + { 109 + return (UART_GET_CSR(port) & AT91_US_TXEMPTY) ? TIOCSER_TEMT : 0; 110 + } 111 + 112 + /* 113 + * Set state of the modem control output lines 114 + */ 115 + static void at91_set_mctrl(struct uart_port *port, u_int mctrl) 116 + { 117 + unsigned int control = 0; 118 + 119 + /* 120 + * Errata #39: RTS0 is not internally connected to PA21. We need to drive 121 + * the pin manually. 122 + */ 123 + if (port->mapbase == AT91_VA_BASE_US0) { 124 + if (mctrl & TIOCM_RTS) 125 + at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0); 126 + else 127 + at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0); 128 + } 129 + 130 + if (mctrl & TIOCM_RTS) 131 + control |= AT91_US_RTSEN; 132 + else 133 + control |= AT91_US_RTSDIS; 134 + 135 + if (mctrl & TIOCM_DTR) 136 + control |= AT91_US_DTREN; 137 + else 138 + control |= AT91_US_DTRDIS; 139 + 140 + UART_PUT_CR(port,control); 141 + } 142 + 143 + /* 144 + * Get state of the modem control input lines 145 + */ 146 + static u_int at91_get_mctrl(struct uart_port *port) 147 + { 148 + unsigned int status, ret = 0; 149 + 150 + status = UART_GET_CSR(port); 151 + 152 + /* 153 + * The control signals are active low. 154 + */ 155 + if (!(status & AT91_US_DCD)) 156 + ret |= TIOCM_CD; 157 + if (!(status & AT91_US_CTS)) 158 + ret |= TIOCM_CTS; 159 + if (!(status & AT91_US_DSR)) 160 + ret |= TIOCM_DSR; 161 + if (!(status & AT91_US_RI)) 162 + ret |= TIOCM_RI; 163 + 164 + return ret; 165 + } 166 + 167 + /* 168 + * Stop transmitting. 169 + */ 170 + static void at91_stop_tx(struct uart_port *port) 171 + { 172 + UART_PUT_IDR(port, AT91_US_TXRDY); 173 + port->read_status_mask &= ~AT91_US_TXRDY; 174 + } 175 + 176 + /* 177 + * Start transmitting. 178 + */ 179 + static void at91_start_tx(struct uart_port *port) 180 + { 181 + port->read_status_mask |= AT91_US_TXRDY; 182 + UART_PUT_IER(port, AT91_US_TXRDY); 183 + } 184 + 185 + /* 186 + * Stop receiving - port is in process of being closed. 187 + */ 188 + static void at91_stop_rx(struct uart_port *port) 189 + { 190 + UART_PUT_IDR(port, AT91_US_RXRDY); 191 + } 192 + 193 + /* 194 + * Enable modem status interrupts 195 + */ 196 + static void at91_enable_ms(struct uart_port *port) 197 + { 198 + port->read_status_mask |= (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC); 199 + UART_PUT_IER(port, AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC); 200 + } 201 + 202 + /* 203 + * Control the transmission of a break signal 204 + */ 205 + static void at91_break_ctl(struct uart_port *port, int break_state) 206 + { 207 + if (break_state != 0) 208 + UART_PUT_CR(port, AT91_US_STTBRK); /* start break */ 209 + else 210 + UART_PUT_CR(port, AT91_US_STPBRK); /* stop break */ 211 + } 212 + 213 + /* 214 + * Characters received (called from interrupt handler) 215 + */ 216 + static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs) 217 + { 218 + struct tty_struct *tty = port->info->tty; 219 + unsigned int status, ch, flg; 220 + 221 + status = UART_GET_CSR(port) & port->read_status_mask; 222 + while (status & (AT91_US_RXRDY)) { 223 + ch = UART_GET_CHAR(port); 224 + 225 + if (tty->flip.count >= TTY_FLIPBUF_SIZE) 226 + goto ignore_char; 227 + port->icount.rx++; 228 + 229 + flg = TTY_NORMAL; 230 + 231 + /* 232 + * note that the error handling code is 233 + * out of the main execution path 234 + */ 235 + if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE))) { 236 + UART_PUT_CR(port, AT91_US_RSTSTA); /* clear error */ 237 + if (status & (AT91_US_PARE)) 238 + port->icount.parity++; 239 + if (status & (AT91_US_FRAME)) 240 + port->icount.frame++; 241 + if (status & (AT91_US_OVRE)) 242 + port->icount.overrun++; 243 + 244 + if (status & AT91_US_PARE) 245 + flg = TTY_PARITY; 246 + else if (status & AT91_US_FRAME) 247 + flg = TTY_FRAME; 248 + if (status & AT91_US_OVRE) { 249 + /* 250 + * overrun does *not* affect the character 251 + * we read from the FIFO 252 + */ 253 + tty_insert_flip_char(tty, ch, flg); 254 + ch = 0; 255 + flg = TTY_OVERRUN; 256 + } 257 + #ifdef SUPPORT_SYSRQ 258 + port->sysrq = 0; 259 + #endif 260 + } 261 + 262 + if (uart_handle_sysrq_char(port, ch, regs)) 263 + goto ignore_char; 264 + 265 + tty_insert_flip_char(tty, ch, flg); 266 + 267 + ignore_char: 268 + status = UART_GET_CSR(port) & port->read_status_mask; 269 + } 270 + 271 + tty_flip_buffer_push(tty); 272 + } 273 + 274 + /* 275 + * Transmit characters (called from interrupt handler) 276 + */ 277 + static void at91_tx_chars(struct uart_port *port) 278 + { 279 + struct circ_buf *xmit = &port->info->xmit; 280 + 281 + if (port->x_char) { 282 + UART_PUT_CHAR(port, port->x_char); 283 + port->icount.tx++; 284 + port->x_char = 0; 285 + return; 286 + } 287 + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { 288 + at91_stop_tx(port); 289 + return; 290 + } 291 + 292 + while (UART_GET_CSR(port) & AT91_US_TXRDY) { 293 + UART_PUT_CHAR(port, xmit->buf[xmit->tail]); 294 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 295 + port->icount.tx++; 296 + if (uart_circ_empty(xmit)) 297 + break; 298 + } 299 + 300 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 301 + uart_write_wakeup(port); 302 + 303 + if (uart_circ_empty(xmit)) 304 + at91_stop_tx(port); 305 + } 306 + 307 + /* 308 + * Interrupt handler 309 + */ 310 + static irqreturn_t at91_interrupt(int irq, void *dev_id, struct pt_regs *regs) 311 + { 312 + struct uart_port *port = dev_id; 313 + unsigned int status, pending, pass_counter = 0; 314 + 315 + status = UART_GET_CSR(port); 316 + pending = status & port->read_status_mask; 317 + if (pending) { 318 + do { 319 + if (pending & AT91_US_RXRDY) 320 + at91_rx_chars(port, regs); 321 + 322 + /* Clear the relevent break bits */ 323 + if (pending & AT91_US_RXBRK) { 324 + UART_PUT_CR(port, AT91_US_RSTSTA); 325 + port->icount.brk++; 326 + uart_handle_break(port); 327 + } 328 + 329 + // TODO: All reads to CSR will clear these interrupts! 330 + if (pending & AT91_US_RIIC) port->icount.rng++; 331 + if (pending & AT91_US_DSRIC) port->icount.dsr++; 332 + if (pending & AT91_US_DCDIC) 333 + uart_handle_dcd_change(port, !(status & AT91_US_DCD)); 334 + if (pending & AT91_US_CTSIC) 335 + uart_handle_cts_change(port, !(status & AT91_US_CTS)); 336 + if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC)) 337 + wake_up_interruptible(&port->info->delta_msr_wait); 338 + 339 + if (pending & AT91_US_TXRDY) 340 + at91_tx_chars(port); 341 + if (pass_counter++ > AT91_ISR_PASS_LIMIT) 342 + break; 343 + 344 + status = UART_GET_CSR(port); 345 + pending = status & port->read_status_mask; 346 + } while (pending); 347 + } 348 + return IRQ_HANDLED; 349 + } 350 + 351 + /* 352 + * Perform initialization and enable port for reception 353 + */ 354 + static int at91_startup(struct uart_port *port) 355 + { 356 + int retval; 357 + 358 + /* 359 + * Ensure that no interrupts are enabled otherwise when 360 + * request_irq() is called we could get stuck trying to 361 + * handle an unexpected interrupt 362 + */ 363 + UART_PUT_IDR(port, -1); 364 + 365 + /* 366 + * Allocate the IRQ 367 + */ 368 + retval = request_irq(port->irq, at91_interrupt, SA_SHIRQ, "at91_serial", port); 369 + if (retval) { 370 + printk("at91_serial: at91_startup - Can't get irq\n"); 371 + return retval; 372 + } 373 + 374 + /* 375 + * If there is a specific "open" function (to register 376 + * control line interrupts) 377 + */ 378 + if (at91_open) { 379 + retval = at91_open(port); 380 + if (retval) { 381 + free_irq(port->irq, port); 382 + return retval; 383 + } 384 + } 385 + 386 + port->read_status_mask = AT91_US_RXRDY | AT91_US_TXRDY | AT91_US_OVRE 387 + | AT91_US_FRAME | AT91_US_PARE | AT91_US_RXBRK; 388 + /* 389 + * Finally, enable the serial port 390 + */ 391 + UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); 392 + UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); /* enable xmit & rcvr */ 393 + UART_PUT_IER(port, AT91_US_RXRDY); /* do receive only */ 394 + return 0; 395 + } 396 + 397 + /* 398 + * Disable the port 399 + */ 400 + static void at91_shutdown(struct uart_port *port) 401 + { 402 + /* 403 + * Disable all interrupts, port and break condition. 404 + */ 405 + UART_PUT_CR(port, AT91_US_RSTSTA); 406 + UART_PUT_IDR(port, -1); 407 + 408 + /* 409 + * Free the interrupt 410 + */ 411 + free_irq(port->irq, port); 412 + 413 + /* 414 + * If there is a specific "close" function (to unregister 415 + * control line interrupts) 416 + */ 417 + if (at91_close) 418 + at91_close(port); 419 + } 420 + 421 + /* 422 + * Power / Clock management. 423 + */ 424 + static void at91_serial_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) 425 + { 426 + switch (state) { 427 + case 0: 428 + /* 429 + * Enable the peripheral clock for this serial port. 430 + * This is called on uart_open() or a resume event. 431 + */ 432 + at91_sys_write(AT91_PMC_PCER, 1 << port->irq); 433 + break; 434 + case 3: 435 + /* 436 + * Disable the peripheral clock for this serial port. 437 + * This is called on uart_close() or a suspend event. 438 + */ 439 + if (port->irq != AT91_ID_SYS) /* is this a shared clock? */ 440 + at91_sys_write(AT91_PMC_PCDR, 1 << port->irq); 441 + break; 442 + default: 443 + printk(KERN_ERR "at91_serial: unknown pm %d\n", state); 444 + } 445 + } 446 + 447 + /* 448 + * Change the port parameters 449 + */ 450 + static void at91_set_termios(struct uart_port *port, struct termios * termios, struct termios * old) 451 + { 452 + unsigned long flags; 453 + unsigned int mode, imr, quot, baud; 454 + 455 + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 456 + quot = uart_get_divisor(port, baud); 457 + 458 + /* Get current mode register */ 459 + mode = UART_GET_MR(port) & ~(AT91_US_CHRL | AT91_US_NBSTOP | AT91_US_PAR); 460 + 461 + /* byte size */ 462 + switch (termios->c_cflag & CSIZE) { 463 + case CS5: 464 + mode |= AT91_US_CHRL_5; 465 + break; 466 + case CS6: 467 + mode |= AT91_US_CHRL_6; 468 + break; 469 + case CS7: 470 + mode |= AT91_US_CHRL_7; 471 + break; 472 + default: 473 + mode |= AT91_US_CHRL_8; 474 + break; 475 + } 476 + 477 + /* stop bits */ 478 + if (termios->c_cflag & CSTOPB) 479 + mode |= AT91_US_NBSTOP_2; 480 + 481 + /* parity */ 482 + if (termios->c_cflag & PARENB) { 483 + if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */ 484 + if (termios->c_cflag & PARODD) 485 + mode |= AT91_US_PAR_MARK; 486 + else 487 + mode |= AT91_US_PAR_SPACE; 488 + } 489 + else if (termios->c_cflag & PARODD) 490 + mode |= AT91_US_PAR_ODD; 491 + else 492 + mode |= AT91_US_PAR_EVEN; 493 + } 494 + else 495 + mode |= AT91_US_PAR_NONE; 496 + 497 + spin_lock_irqsave(&port->lock, flags); 498 + 499 + port->read_status_mask |= AT91_US_OVRE; 500 + if (termios->c_iflag & INPCK) 501 + port->read_status_mask |= AT91_US_FRAME | AT91_US_PARE; 502 + if (termios->c_iflag & (BRKINT | PARMRK)) 503 + port->read_status_mask |= AT91_US_RXBRK; 504 + 505 + /* 506 + * Characters to ignore 507 + */ 508 + port->ignore_status_mask = 0; 509 + if (termios->c_iflag & IGNPAR) 510 + port->ignore_status_mask |= (AT91_US_FRAME | AT91_US_PARE); 511 + if (termios->c_iflag & IGNBRK) { 512 + port->ignore_status_mask |= AT91_US_RXBRK; 513 + /* 514 + * If we're ignoring parity and break indicators, 515 + * ignore overruns too (for real raw support). 516 + */ 517 + if (termios->c_iflag & IGNPAR) 518 + port->ignore_status_mask |= AT91_US_OVRE; 519 + } 520 + 521 + // TODO: Ignore all characters if CREAD is set. 522 + 523 + /* update the per-port timeout */ 524 + uart_update_timeout(port, termios->c_cflag, baud); 525 + 526 + /* disable interrupts and drain transmitter */ 527 + imr = UART_GET_IMR(port); /* get interrupt mask */ 528 + UART_PUT_IDR(port, -1); /* disable all interrupts */ 529 + while (!(UART_GET_CSR(port) & AT91_US_TXEMPTY)) { barrier(); } 530 + 531 + /* disable receiver and transmitter */ 532 + UART_PUT_CR(port, AT91_US_TXDIS | AT91_US_RXDIS); 533 + 534 + /* set the parity, stop bits and data size */ 535 + UART_PUT_MR(port, mode); 536 + 537 + /* set the baud rate */ 538 + UART_PUT_BRGR(port, quot); 539 + UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); 540 + UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); 541 + 542 + /* restore interrupts */ 543 + UART_PUT_IER(port, imr); 544 + 545 + /* CTS flow-control and modem-status interrupts */ 546 + if (UART_ENABLE_MS(port, termios->c_cflag)) 547 + port->ops->enable_ms(port); 548 + 549 + spin_unlock_irqrestore(&port->lock, flags); 550 + } 551 + 552 + /* 553 + * Return string describing the specified port 554 + */ 555 + static const char *at91_type(struct uart_port *port) 556 + { 557 + return (port->type == PORT_AT91RM9200) ? "AT91_SERIAL" : NULL; 558 + } 559 + 560 + /* 561 + * Release the memory region(s) being used by 'port'. 562 + */ 563 + static void at91_release_port(struct uart_port *port) 564 + { 565 + release_mem_region(port->mapbase, 566 + (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K); 567 + } 568 + 569 + /* 570 + * Request the memory region(s) being used by 'port'. 571 + */ 572 + static int at91_request_port(struct uart_port *port) 573 + { 574 + return request_mem_region(port->mapbase, 575 + (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K, 576 + "at91_serial") != NULL ? 0 : -EBUSY; 577 + 578 + } 579 + 580 + /* 581 + * Configure/autoconfigure the port. 582 + */ 583 + static void at91_config_port(struct uart_port *port, int flags) 584 + { 585 + if (flags & UART_CONFIG_TYPE) { 586 + port->type = PORT_AT91RM9200; 587 + at91_request_port(port); 588 + } 589 + } 590 + 591 + /* 592 + * Verify the new serial_struct (for TIOCSSERIAL). 593 + */ 594 + static int at91_verify_port(struct uart_port *port, struct serial_struct *ser) 595 + { 596 + int ret = 0; 597 + if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200) 598 + ret = -EINVAL; 599 + if (port->irq != ser->irq) 600 + ret = -EINVAL; 601 + if (ser->io_type != SERIAL_IO_MEM) 602 + ret = -EINVAL; 603 + if (port->uartclk / 16 != ser->baud_base) 604 + ret = -EINVAL; 605 + if ((void *)port->mapbase != ser->iomem_base) 606 + ret = -EINVAL; 607 + if (port->iobase != ser->port) 608 + ret = -EINVAL; 609 + if (ser->hub6 != 0) 610 + ret = -EINVAL; 611 + return ret; 612 + } 613 + 614 + static struct uart_ops at91_pops = { 615 + .tx_empty = at91_tx_empty, 616 + .set_mctrl = at91_set_mctrl, 617 + .get_mctrl = at91_get_mctrl, 618 + .stop_tx = at91_stop_tx, 619 + .start_tx = at91_start_tx, 620 + .stop_rx = at91_stop_rx, 621 + .enable_ms = at91_enable_ms, 622 + .break_ctl = at91_break_ctl, 623 + .startup = at91_startup, 624 + .shutdown = at91_shutdown, 625 + .set_termios = at91_set_termios, 626 + .type = at91_type, 627 + .release_port = at91_release_port, 628 + .request_port = at91_request_port, 629 + .config_port = at91_config_port, 630 + .verify_port = at91_verify_port, 631 + .pm = at91_serial_pm, 632 + }; 633 + 634 + static struct uart_port at91_ports[AT91_NR_UART]; 635 + 636 + void __init at91_init_ports(void) 637 + { 638 + static int first = 1; 639 + int i; 640 + 641 + if (!first) 642 + return; 643 + first = 0; 644 + 645 + for (i = 0; i < AT91_NR_UART; i++) { 646 + at91_ports[i].iotype = UPIO_MEM; 647 + at91_ports[i].flags = UPF_BOOT_AUTOCONF; 648 + at91_ports[i].uartclk = at91_master_clock; 649 + at91_ports[i].ops = &at91_pops; 650 + at91_ports[i].fifosize = 1; 651 + at91_ports[i].line = i; 652 + } 653 + } 654 + 655 + void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns) 656 + { 657 + if (fns->enable_ms) 658 + at91_pops.enable_ms = fns->enable_ms; 659 + if (fns->get_mctrl) 660 + at91_pops.get_mctrl = fns->get_mctrl; 661 + if (fns->set_mctrl) 662 + at91_pops.set_mctrl = fns->set_mctrl; 663 + at91_open = fns->open; 664 + at91_close = fns->close; 665 + at91_pops.pm = fns->pm; 666 + at91_pops.set_wake = fns->set_wake; 667 + } 668 + 669 + /* 670 + * Setup ports. 671 + */ 672 + void __init at91_register_uart(int idx, int port) 673 + { 674 + if ((idx < 0) || (idx >= AT91_NR_UART)) { 675 + printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx); 676 + return; 677 + } 678 + 679 + switch (port) { 680 + case 0: 681 + at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US0; 682 + at91_ports[idx].mapbase = AT91_VA_BASE_US0; 683 + at91_ports[idx].irq = AT91_ID_US0; 684 + AT91_CfgPIO_USART0(); 685 + break; 686 + case 1: 687 + at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US1; 688 + at91_ports[idx].mapbase = AT91_VA_BASE_US1; 689 + at91_ports[idx].irq = AT91_ID_US1; 690 + AT91_CfgPIO_USART1(); 691 + break; 692 + case 2: 693 + at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US2; 694 + at91_ports[idx].mapbase = AT91_VA_BASE_US2; 695 + at91_ports[idx].irq = AT91_ID_US2; 696 + AT91_CfgPIO_USART2(); 697 + break; 698 + case 3: 699 + at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US3; 700 + at91_ports[idx].mapbase = AT91_VA_BASE_US3; 701 + at91_ports[idx].irq = AT91_ID_US3; 702 + AT91_CfgPIO_USART3(); 703 + break; 704 + case 4: 705 + at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_DBGU; 706 + at91_ports[idx].mapbase = AT91_VA_BASE_DBGU; 707 + at91_ports[idx].irq = AT91_ID_SYS; 708 + AT91_CfgPIO_DBGU(); 709 + break; 710 + default: 711 + printk(KERN_ERR "%s : bad port number %d\n", __FUNCTION__, port); 712 + } 713 + } 714 + 715 + #ifdef CONFIG_SERIAL_AT91_CONSOLE 716 + 717 + /* 718 + * Interrupts are disabled on entering 719 + */ 720 + static void at91_console_write(struct console *co, const char *s, u_int count) 721 + { 722 + struct uart_port *port = at91_ports + co->index; 723 + unsigned int status, i, imr; 724 + 725 + /* 726 + * First, save IMR and then disable interrupts 727 + */ 728 + imr = UART_GET_IMR(port); /* get interrupt mask */ 729 + UART_PUT_IDR(port, AT91_US_RXRDY | AT91_US_TXRDY); 730 + 731 + /* 732 + * Now, do each character 733 + */ 734 + for (i = 0; i < count; i++) { 735 + do { 736 + status = UART_GET_CSR(port); 737 + } while (!(status & AT91_US_TXRDY)); 738 + UART_PUT_CHAR(port, s[i]); 739 + if (s[i] == '\n') { 740 + do { 741 + status = UART_GET_CSR(port); 742 + } while (!(status & AT91_US_TXRDY)); 743 + UART_PUT_CHAR(port, '\r'); 744 + } 745 + } 746 + 747 + /* 748 + * Finally, wait for transmitter to become empty 749 + * and restore IMR 750 + */ 751 + do { 752 + status = UART_GET_CSR(port); 753 + } while (!(status & AT91_US_TXRDY)); 754 + UART_PUT_IER(port, imr); /* set interrupts back the way they were */ 755 + } 756 + 757 + /* 758 + * If the port was already initialised (eg, by a boot loader), try to determine 759 + * the current setup. 760 + */ 761 + static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) 762 + { 763 + unsigned int mr, quot; 764 + 765 + // TODO: CR is a write-only register 766 + // unsigned int cr; 767 + // 768 + // cr = UART_GET_CR(port) & (AT91_US_RXEN | AT91_US_TXEN); 769 + // if (cr == (AT91_US_RXEN | AT91_US_TXEN)) { 770 + // /* ok, the port was enabled */ 771 + // } 772 + 773 + mr = UART_GET_MR(port) & AT91_US_CHRL; 774 + if (mr == AT91_US_CHRL_8) 775 + *bits = 8; 776 + else 777 + *bits = 7; 778 + 779 + mr = UART_GET_MR(port) & AT91_US_PAR; 780 + if (mr == AT91_US_PAR_EVEN) 781 + *parity = 'e'; 782 + else if (mr == AT91_US_PAR_ODD) 783 + *parity = 'o'; 784 + 785 + quot = UART_GET_BRGR(port); 786 + *baud = port->uartclk / (16 * (quot)); 787 + } 788 + 789 + static int __init at91_console_setup(struct console *co, char *options) 790 + { 791 + struct uart_port *port; 792 + int baud = 115200; 793 + int bits = 8; 794 + int parity = 'n'; 795 + int flow = 'n'; 796 + 797 + /* 798 + * Check whether an invalid uart number has been specified, and 799 + * if so, search for the first available port that does have 800 + * console support. 801 + */ 802 + port = uart_get_console(at91_ports, AT91_NR_UART, co); 803 + 804 + /* 805 + * Enable the serial console, in-case bootloader did not do it. 806 + */ 807 + at91_sys_write(AT91_PMC_PCER, 1 << port->irq); /* enable clock */ 808 + UART_PUT_IDR(port, -1); /* disable interrupts */ 809 + UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); 810 + UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); 811 + 812 + if (options) 813 + uart_parse_options(options, &baud, &parity, &bits, &flow); 814 + else 815 + at91_console_get_options(port, &baud, &parity, &bits); 816 + 817 + return uart_set_options(port, co, baud, parity, bits, flow); 818 + } 819 + 820 + static struct uart_driver at91_uart; 821 + 822 + static struct console at91_console = { 823 + .name = AT91_DEVICENAME, 824 + .write = at91_console_write, 825 + .device = uart_console_device, 826 + .setup = at91_console_setup, 827 + .flags = CON_PRINTBUFFER, 828 + .index = -1, 829 + .data = &at91_uart, 830 + }; 831 + 832 + #define AT91_CONSOLE_DEVICE &at91_console 833 + 834 + static int __init at91_console_init(void) 835 + { 836 + at91_init_ports(); 837 + 838 + at91_console.index = at91_console_port; 839 + register_console(&at91_console); 840 + return 0; 841 + } 842 + console_initcall(at91_console_init); 843 + 844 + #else 845 + #define AT91_CONSOLE_DEVICE NULL 846 + #endif 847 + 848 + static struct uart_driver at91_uart = { 849 + .owner = THIS_MODULE, 850 + .driver_name = AT91_DEVICENAME, 851 + .dev_name = AT91_DEVICENAME, 852 + .devfs_name = AT91_DEVICENAME, 853 + .major = SERIAL_AT91_MAJOR, 854 + .minor = MINOR_START, 855 + .nr = AT91_NR_UART, 856 + .cons = AT91_CONSOLE_DEVICE, 857 + }; 858 + 859 + static int __init at91_serial_init(void) 860 + { 861 + int ret, i; 862 + 863 + at91_init_ports(); 864 + 865 + ret = uart_register_driver(&at91_uart); 866 + if (ret) 867 + return ret; 868 + 869 + for (i = 0; i < AT91_NR_UART; i++) { 870 + if (at91_serial_map[i] >= 0) 871 + uart_add_one_port(&at91_uart, &at91_ports[i]); 872 + } 873 + 874 + return 0; 875 + } 876 + 877 + static void __exit at91_serial_exit(void) 878 + { 879 + int i; 880 + 881 + for (i = 0; i < AT91_NR_UART; i++) { 882 + if (at91_serial_map[i] >= 0) 883 + uart_remove_one_port(&at91_uart, &at91_ports[i]); 884 + } 885 + 886 + uart_unregister_driver(&at91_uart); 887 + } 888 + 889 + module_init(at91_serial_init); 890 + module_exit(at91_serial_exit); 891 + 892 + MODULE_AUTHOR("Rick Bronson"); 893 + MODULE_DESCRIPTION("AT91 generic serial port driver"); 894 + MODULE_LICENSE("GPL");
+36
include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h
··· 1 + /* 2 + * include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h 3 + * 4 + * Copyright (C) 2005 Ivan Kokshaysky 5 + * Copyright (C) SAN People 6 + * 7 + * Peripheral Data Controller (PDC) registers. 8 + * Based on AT91RM9200 datasheet revision E. 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 + #ifndef AT91RM9200_PDC_H 17 + #define AT91RM9200_PDC_H 18 + 19 + #define AT91_PDC_RPR 0x100 /* Receive Pointer Register */ 20 + #define AT91_PDC_RCR 0x104 /* Receive Counter Register */ 21 + #define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */ 22 + #define AT91_PDC_TCR 0x10c /* Transmit Counter Register */ 23 + #define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */ 24 + #define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */ 25 + #define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */ 26 + #define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */ 27 + 28 + #define AT91_PDC_PTCR 0x120 /* Transfer Control Register */ 29 + #define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */ 30 + #define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */ 31 + #define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */ 32 + #define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */ 33 + 34 + #define AT91_PDC_PTSR 0x124 /* Transfer Status Register */ 35 + 36 + #endif
+123
include/asm-arm/arch-at91rm9200/at91rm9200_usart.h
··· 1 + /* 2 + * include/asm-arm/arch-at91rm9200/at91rm9200_usart.h 3 + * 4 + * Copyright (C) 2005 Ivan Kokshaysky 5 + * Copyright (C) SAN People 6 + * 7 + * USART registers. 8 + * Based on AT91RM9200 datasheet revision E. 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 + #ifndef AT91RM9200_USART_H 17 + #define AT91RM9200_USART_H 18 + 19 + #define AT91_US_CR 0x00 /* Control Register */ 20 + #define AT91_US_RSTRX (1 << 2) /* Reset Receiver */ 21 + #define AT91_US_RSTTX (1 << 3) /* Reset Transmitter */ 22 + #define AT91_US_RXEN (1 << 4) /* Receiver Enable */ 23 + #define AT91_US_RXDIS (1 << 5) /* Receiver Disable */ 24 + #define AT91_US_TXEN (1 << 6) /* Transmitter Enable */ 25 + #define AT91_US_TXDIS (1 << 7) /* Transmitter Disable */ 26 + #define AT91_US_RSTSTA (1 << 8) /* Reset Status Bits */ 27 + #define AT91_US_STTBRK (1 << 9) /* Start Break */ 28 + #define AT91_US_STPBRK (1 << 10) /* Stop Break */ 29 + #define AT91_US_STTTO (1 << 11) /* Start Time-out */ 30 + #define AT91_US_SENDA (1 << 12) /* Send Address */ 31 + #define AT91_US_RSTIT (1 << 13) /* Reset Iterations */ 32 + #define AT91_US_RSTNACK (1 << 14) /* Reset Non Acknowledge */ 33 + #define AT91_US_RETTO (1 << 15) /* Rearm Time-out */ 34 + #define AT91_US_DTREN (1 << 16) /* Data Terminal Ready Enable */ 35 + #define AT91_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable */ 36 + #define AT91_US_RTSEN (1 << 18) /* Request To Send Enable */ 37 + #define AT91_US_RTSDIS (1 << 19) /* Request To Send Disable */ 38 + 39 + #define AT91_US_MR 0x04 /* Mode Register */ 40 + #define AT91_US_USMODE (0xf << 0) /* Mode of the USART */ 41 + #define AT91_US_USMODE_NORMAL 0 42 + #define AT91_US_USMODE_RS485 1 43 + #define AT91_US_USMODE_HWHS 2 44 + #define AT91_US_USMODE_MODEM 3 45 + #define AT91_US_USMODE_ISO7816_T0 4 46 + #define AT91_US_USMODE_ISO7816_T1 6 47 + #define AT91_US_USMODE_IRDA 8 48 + #define AT91_US_USCLKS (3 << 4) /* Clock Selection */ 49 + #define AT91_US_CHRL (3 << 6) /* Character Length */ 50 + #define AT91_US_CHRL_5 (0 << 6) 51 + #define AT91_US_CHRL_6 (1 << 6) 52 + #define AT91_US_CHRL_7 (2 << 6) 53 + #define AT91_US_CHRL_8 (3 << 6) 54 + #define AT91_US_SYNC (1 << 8) /* Synchronous Mode Select */ 55 + #define AT91_US_PAR (7 << 9) /* Parity Type */ 56 + #define AT91_US_PAR_EVEN (0 << 9) 57 + #define AT91_US_PAR_ODD (1 << 9) 58 + #define AT91_US_PAR_SPACE (2 << 9) 59 + #define AT91_US_PAR_MARK (3 << 9) 60 + #define AT91_US_PAR_NONE (4 << 9) 61 + #define AT91_US_PAR_MULTI_DROP (6 << 9) 62 + #define AT91_US_NBSTOP (3 << 12) /* Number of Stop Bits */ 63 + #define AT91_US_NBSTOP_1 (0 << 12) 64 + #define AT91_US_NBSTOP_1_5 (1 << 12) 65 + #define AT91_US_NBSTOP_2 (2 << 12) 66 + #define AT91_US_CHMODE (3 << 14) /* Channel Mode */ 67 + #define AT91_US_CHMODE_NORMAL (0 << 14) 68 + #define AT91_US_CHMODE_ECHO (1 << 14) 69 + #define AT91_US_CHMODE_LOC_LOOP (2 << 14) 70 + #define AT91_US_CHMODE_REM_LOOP (3 << 14) 71 + #define AT91_US_MSBF (1 << 16) /* Bit Order */ 72 + #define AT91_US_MODE9 (1 << 17) /* 9-bit Character Length */ 73 + #define AT91_US_CLKO (1 << 18) /* Clock Output Select */ 74 + #define AT91_US_OVER (1 << 19) /* Oversampling Mode */ 75 + #define AT91_US_INACK (1 << 20) /* Inhibit Non Acknowledge */ 76 + #define AT91_US_DSNACK (1 << 21) /* Disable Successive NACK */ 77 + #define AT91_US_MAX_ITER (7 << 24) /* Max Iterations */ 78 + #define AT91_US_FILTER (1 << 28) /* Infrared Receive Line Filter */ 79 + 80 + #define AT91_US_IER 0x08 /* Interrupt Enable Register */ 81 + #define AT91_US_RXRDY (1 << 0) /* Receiver Ready */ 82 + #define AT91_US_TXRDY (1 << 1) /* Transmitter Ready */ 83 + #define AT91_US_RXBRK (1 << 2) /* Break Received / End of Break */ 84 + #define AT91_US_ENDRX (1 << 3) /* End of Receiver Transfer */ 85 + #define AT91_US_ENDTX (1 << 4) /* End of Transmitter Transfer */ 86 + #define AT91_US_OVRE (1 << 5) /* Overrun Error */ 87 + #define AT91_US_FRAME (1 << 6) /* Framing Error */ 88 + #define AT91_US_PARE (1 << 7) /* Parity Error */ 89 + #define AT91_US_TIMEOUT (1 << 8) /* Receiver Time-out */ 90 + #define AT91_US_TXEMPTY (1 << 9) /* Transmitter Empty */ 91 + #define AT91_US_ITERATION (1 << 10) /* Max number of Repetitions Reached */ 92 + #define AT91_US_TXBUFE (1 << 11) /* Transmission Buffer Empty */ 93 + #define AT91_US_RXBUFF (1 << 12) /* Reception Buffer Full */ 94 + #define AT91_US_NACK (1 << 13) /* Non Acknowledge */ 95 + #define AT91_US_RIIC (1 << 16) /* Ring Indicator Input Change */ 96 + #define AT91_US_DSRIC (1 << 17) /* Data Set Ready Input Change */ 97 + #define AT91_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change */ 98 + #define AT91_US_CTSIC (1 << 19) /* Clear to Send Input Change */ 99 + #define AT91_US_RI (1 << 20) /* RI */ 100 + #define AT91_US_DSR (1 << 21) /* DSR */ 101 + #define AT91_US_DCD (1 << 22) /* DCD */ 102 + #define AT91_US_CTS (1 << 23) /* CTS */ 103 + 104 + #define AT91_US_IDR 0x0c /* Interrupt Disable Register */ 105 + #define AT91_US_IMR 0x10 /* Interrupt Mask Register */ 106 + #define AT91_US_CSR 0x14 /* Channel Status Register */ 107 + #define AT91_US_RHR 0x18 /* Receiver Holding Register */ 108 + #define AT91_US_THR 0x1c /* Transmitter Holding Register */ 109 + 110 + #define AT91_US_BRGR 0x20 /* Baud Rate Generator Register */ 111 + #define AT91_US_CD (0xffff << 0) /* Clock Divider */ 112 + 113 + #define AT91_US_RTOR 0x24 /* Receiver Time-out Register */ 114 + #define AT91_US_TO (0xffff << 0) /* Time-out Value */ 115 + 116 + #define AT91_US_TTGR 0x28 /* Transmitter Timeguard Register */ 117 + #define AT91_US_TG (0xff << 0) /* Timeguard Value */ 118 + 119 + #define AT91_US_FIDI 0x40 /* FI DI Ratio Register */ 120 + #define AT91_US_NER 0x44 /* Number of Errors Register */ 121 + #define AT91_US_IF 0x4c /* IrDA Filter Register */ 122 + 123 + #endif
+36
include/asm-arm/mach/serial_at91rm9200.h
··· 1 + /* 2 + * linux/include/asm-arm/mach/serial_at91rm9200.h 3 + * 4 + * Based on serial_sa1100.h by Nicolas Pitre 5 + * 6 + * Copyright (C) 2002 ATMEL Rousset 7 + * 8 + * Low level machine dependent UART functions. 9 + */ 10 + #include <linux/config.h> 11 + 12 + struct uart_port; 13 + 14 + /* 15 + * This is a temporary structure for registering these 16 + * functions; it is intended to be discarded after boot. 17 + */ 18 + struct at91rm9200_port_fns { 19 + void (*set_mctrl)(struct uart_port *, u_int); 20 + u_int (*get_mctrl)(struct uart_port *); 21 + void (*enable_ms)(struct uart_port *); 22 + void (*pm)(struct uart_port *, u_int, u_int); 23 + int (*set_wake)(struct uart_port *, u_int); 24 + int (*open)(struct uart_port *); 25 + void (*close)(struct uart_port *); 26 + }; 27 + 28 + #if defined(CONFIG_SERIAL_AT91) 29 + void at91_register_uart_fns(struct at91rm9200_port_fns *fns); 30 + void at91_register_uart(int idx, int port); 31 + #else 32 + #define at91_register_uart_fns(fns) do { } while (0) 33 + #define at91_register_uart(idx,port) do { } while (0) 34 + #endif 35 + 36 +
+3
include/linux/serial_core.h
··· 67 67 /* Parisc type numbers. */ 68 68 #define PORT_MUX 48 69 69 70 + /* Atmel AT91RM9200 SoC */ 71 + #define PORT_AT91RM9200 49 72 + 70 73 /* Macintosh Zilog type numbers */ 71 74 #define PORT_MAC_ZILOG 50 /* m68k : not yet implemented */ 72 75 #define PORT_PMAC_ZILOG 51