mxs-auart.c revision a481377013c1c07dac0421886db7a6b4c3081c49
1/* 2 * Freescale STMP37XX/STMP378X Application UART driver 3 * 4 * Author: dmitry pervushin <dimka@embeddedalley.com> 5 * 6 * Copyright 2008-2010 Freescale Semiconductor, Inc. 7 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. 8 * 9 * The code contained herein is licensed under the GNU General Public 10 * License. You may obtain a copy of the GNU General Public License 11 * Version 2 or later at the following locations: 12 * 13 * http://www.opensource.org/licenses/gpl-license.html 14 * http://www.gnu.org/copyleft/gpl.html 15 */ 16 17#include <linux/kernel.h> 18#include <linux/errno.h> 19#include <linux/init.h> 20#include <linux/console.h> 21#include <linux/interrupt.h> 22#include <linux/module.h> 23#include <linux/slab.h> 24#include <linux/wait.h> 25#include <linux/tty.h> 26#include <linux/tty_driver.h> 27#include <linux/tty_flip.h> 28#include <linux/serial.h> 29#include <linux/serial_core.h> 30#include <linux/platform_device.h> 31#include <linux/device.h> 32#include <linux/clk.h> 33#include <linux/delay.h> 34#include <linux/io.h> 35 36#include <asm/cacheflush.h> 37 38#define MXS_AUART_PORTS 5 39 40#define AUART_CTRL0 0x00000000 41#define AUART_CTRL0_SET 0x00000004 42#define AUART_CTRL0_CLR 0x00000008 43#define AUART_CTRL0_TOG 0x0000000c 44#define AUART_CTRL1 0x00000010 45#define AUART_CTRL1_SET 0x00000014 46#define AUART_CTRL1_CLR 0x00000018 47#define AUART_CTRL1_TOG 0x0000001c 48#define AUART_CTRL2 0x00000020 49#define AUART_CTRL2_SET 0x00000024 50#define AUART_CTRL2_CLR 0x00000028 51#define AUART_CTRL2_TOG 0x0000002c 52#define AUART_LINECTRL 0x00000030 53#define AUART_LINECTRL_SET 0x00000034 54#define AUART_LINECTRL_CLR 0x00000038 55#define AUART_LINECTRL_TOG 0x0000003c 56#define AUART_LINECTRL2 0x00000040 57#define AUART_LINECTRL2_SET 0x00000044 58#define AUART_LINECTRL2_CLR 0x00000048 59#define AUART_LINECTRL2_TOG 0x0000004c 60#define AUART_INTR 0x00000050 61#define AUART_INTR_SET 0x00000054 62#define AUART_INTR_CLR 0x00000058 63#define AUART_INTR_TOG 0x0000005c 64#define AUART_DATA 0x00000060 65#define AUART_STAT 0x00000070 66#define AUART_DEBUG 0x00000080 67#define AUART_VERSION 0x00000090 68#define AUART_AUTOBAUD 0x000000a0 69 70#define AUART_CTRL0_SFTRST (1 << 31) 71#define AUART_CTRL0_CLKGATE (1 << 30) 72 73#define AUART_CTRL2_CTSEN (1 << 15) 74#define AUART_CTRL2_RTS (1 << 11) 75#define AUART_CTRL2_RXE (1 << 9) 76#define AUART_CTRL2_TXE (1 << 8) 77#define AUART_CTRL2_UARTEN (1 << 0) 78 79#define AUART_LINECTRL_BAUD_DIVINT_SHIFT 16 80#define AUART_LINECTRL_BAUD_DIVINT_MASK 0xffff0000 81#define AUART_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16) 82#define AUART_LINECTRL_BAUD_DIVFRAC_SHIFT 8 83#define AUART_LINECTRL_BAUD_DIVFRAC_MASK 0x00003f00 84#define AUART_LINECTRL_BAUD_DIVFRAC(v) (((v) & 0x3f) << 8) 85#define AUART_LINECTRL_WLEN_MASK 0x00000060 86#define AUART_LINECTRL_WLEN(v) (((v) & 0x3) << 5) 87#define AUART_LINECTRL_FEN (1 << 4) 88#define AUART_LINECTRL_STP2 (1 << 3) 89#define AUART_LINECTRL_EPS (1 << 2) 90#define AUART_LINECTRL_PEN (1 << 1) 91#define AUART_LINECTRL_BRK (1 << 0) 92 93#define AUART_INTR_RTIEN (1 << 22) 94#define AUART_INTR_TXIEN (1 << 21) 95#define AUART_INTR_RXIEN (1 << 20) 96#define AUART_INTR_CTSMIEN (1 << 17) 97#define AUART_INTR_RTIS (1 << 6) 98#define AUART_INTR_TXIS (1 << 5) 99#define AUART_INTR_RXIS (1 << 4) 100#define AUART_INTR_CTSMIS (1 << 1) 101 102#define AUART_STAT_BUSY (1 << 29) 103#define AUART_STAT_CTS (1 << 28) 104#define AUART_STAT_TXFE (1 << 27) 105#define AUART_STAT_TXFF (1 << 25) 106#define AUART_STAT_RXFE (1 << 24) 107#define AUART_STAT_OERR (1 << 19) 108#define AUART_STAT_BERR (1 << 18) 109#define AUART_STAT_PERR (1 << 17) 110#define AUART_STAT_FERR (1 << 16) 111 112static struct uart_driver auart_driver; 113 114struct mxs_auart_port { 115 struct uart_port port; 116 117 unsigned int flags; 118 unsigned int ctrl; 119 120 unsigned int irq; 121 122 struct clk *clk; 123 struct device *dev; 124}; 125 126static void mxs_auart_stop_tx(struct uart_port *u); 127 128#define to_auart_port(u) container_of(u, struct mxs_auart_port, port) 129 130static inline void mxs_auart_tx_chars(struct mxs_auart_port *s) 131{ 132 struct circ_buf *xmit = &s->port.state->xmit; 133 134 while (!(readl(s->port.membase + AUART_STAT) & 135 AUART_STAT_TXFF)) { 136 if (s->port.x_char) { 137 s->port.icount.tx++; 138 writel(s->port.x_char, 139 s->port.membase + AUART_DATA); 140 s->port.x_char = 0; 141 continue; 142 } 143 if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) { 144 s->port.icount.tx++; 145 writel(xmit->buf[xmit->tail], 146 s->port.membase + AUART_DATA); 147 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 148 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 149 uart_write_wakeup(&s->port); 150 } else 151 break; 152 } 153 if (uart_circ_empty(&(s->port.state->xmit))) 154 writel(AUART_INTR_TXIEN, 155 s->port.membase + AUART_INTR_CLR); 156 else 157 writel(AUART_INTR_TXIEN, 158 s->port.membase + AUART_INTR_SET); 159 160 if (uart_tx_stopped(&s->port)) 161 mxs_auart_stop_tx(&s->port); 162} 163 164static void mxs_auart_rx_char(struct mxs_auart_port *s) 165{ 166 int flag; 167 u32 stat; 168 u8 c; 169 170 c = readl(s->port.membase + AUART_DATA); 171 stat = readl(s->port.membase + AUART_STAT); 172 173 flag = TTY_NORMAL; 174 s->port.icount.rx++; 175 176 if (stat & AUART_STAT_BERR) { 177 s->port.icount.brk++; 178 if (uart_handle_break(&s->port)) 179 goto out; 180 } else if (stat & AUART_STAT_PERR) { 181 s->port.icount.parity++; 182 } else if (stat & AUART_STAT_FERR) { 183 s->port.icount.frame++; 184 } 185 186 /* 187 * Mask off conditions which should be ingored. 188 */ 189 stat &= s->port.read_status_mask; 190 191 if (stat & AUART_STAT_BERR) { 192 flag = TTY_BREAK; 193 } else if (stat & AUART_STAT_PERR) 194 flag = TTY_PARITY; 195 else if (stat & AUART_STAT_FERR) 196 flag = TTY_FRAME; 197 198 if (stat & AUART_STAT_OERR) 199 s->port.icount.overrun++; 200 201 if (uart_handle_sysrq_char(&s->port, c)) 202 goto out; 203 204 uart_insert_char(&s->port, stat, AUART_STAT_OERR, c, flag); 205out: 206 writel(stat, s->port.membase + AUART_STAT); 207} 208 209static void mxs_auart_rx_chars(struct mxs_auart_port *s) 210{ 211 struct tty_struct *tty = s->port.state->port.tty; 212 u32 stat = 0; 213 214 for (;;) { 215 stat = readl(s->port.membase + AUART_STAT); 216 if (stat & AUART_STAT_RXFE) 217 break; 218 mxs_auart_rx_char(s); 219 } 220 221 writel(stat, s->port.membase + AUART_STAT); 222 tty_flip_buffer_push(tty); 223} 224 225static int mxs_auart_request_port(struct uart_port *u) 226{ 227 return 0; 228} 229 230static int mxs_auart_verify_port(struct uart_port *u, 231 struct serial_struct *ser) 232{ 233 if (u->type != PORT_UNKNOWN && u->type != PORT_IMX) 234 return -EINVAL; 235 return 0; 236} 237 238static void mxs_auart_config_port(struct uart_port *u, int flags) 239{ 240} 241 242static const char *mxs_auart_type(struct uart_port *u) 243{ 244 struct mxs_auart_port *s = to_auart_port(u); 245 246 return dev_name(s->dev); 247} 248 249static void mxs_auart_release_port(struct uart_port *u) 250{ 251} 252 253static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl) 254{ 255 struct mxs_auart_port *s = to_auart_port(u); 256 257 u32 ctrl = readl(u->membase + AUART_CTRL2); 258 259 ctrl &= ~AUART_CTRL2_RTS; 260 if (mctrl & TIOCM_RTS) 261 ctrl |= AUART_CTRL2_RTS; 262 s->ctrl = mctrl; 263 writel(ctrl, u->membase + AUART_CTRL2); 264} 265 266static u32 mxs_auart_get_mctrl(struct uart_port *u) 267{ 268 struct mxs_auart_port *s = to_auart_port(u); 269 u32 stat = readl(u->membase + AUART_STAT); 270 int ctrl2 = readl(u->membase + AUART_CTRL2); 271 u32 mctrl = s->ctrl; 272 273 mctrl &= ~TIOCM_CTS; 274 if (stat & AUART_STAT_CTS) 275 mctrl |= TIOCM_CTS; 276 277 if (ctrl2 & AUART_CTRL2_RTS) 278 mctrl |= TIOCM_RTS; 279 280 return mctrl; 281} 282 283static void mxs_auart_settermios(struct uart_port *u, 284 struct ktermios *termios, 285 struct ktermios *old) 286{ 287 u32 bm, ctrl, ctrl2, div; 288 unsigned int cflag, baud; 289 290 cflag = termios->c_cflag; 291 292 ctrl = AUART_LINECTRL_FEN; 293 ctrl2 = readl(u->membase + AUART_CTRL2); 294 295 /* byte size */ 296 switch (cflag & CSIZE) { 297 case CS5: 298 bm = 0; 299 break; 300 case CS6: 301 bm = 1; 302 break; 303 case CS7: 304 bm = 2; 305 break; 306 case CS8: 307 bm = 3; 308 break; 309 default: 310 return; 311 } 312 313 ctrl |= AUART_LINECTRL_WLEN(bm); 314 315 /* parity */ 316 if (cflag & PARENB) { 317 ctrl |= AUART_LINECTRL_PEN; 318 if ((cflag & PARODD) == 0) 319 ctrl |= AUART_LINECTRL_EPS; 320 } 321 322 u->read_status_mask = 0; 323 324 if (termios->c_iflag & INPCK) 325 u->read_status_mask |= AUART_STAT_PERR; 326 if (termios->c_iflag & (BRKINT | PARMRK)) 327 u->read_status_mask |= AUART_STAT_BERR; 328 329 /* 330 * Characters to ignore 331 */ 332 u->ignore_status_mask = 0; 333 if (termios->c_iflag & IGNPAR) 334 u->ignore_status_mask |= AUART_STAT_PERR; 335 if (termios->c_iflag & IGNBRK) { 336 u->ignore_status_mask |= AUART_STAT_BERR; 337 /* 338 * If we're ignoring parity and break indicators, 339 * ignore overruns too (for real raw support). 340 */ 341 if (termios->c_iflag & IGNPAR) 342 u->ignore_status_mask |= AUART_STAT_OERR; 343 } 344 345 /* 346 * ignore all characters if CREAD is not set 347 */ 348 if (cflag & CREAD) 349 ctrl2 |= AUART_CTRL2_RXE; 350 else 351 ctrl2 &= ~AUART_CTRL2_RXE; 352 353 /* figure out the stop bits requested */ 354 if (cflag & CSTOPB) 355 ctrl |= AUART_LINECTRL_STP2; 356 357 /* figure out the hardware flow control settings */ 358 if (cflag & CRTSCTS) 359 ctrl2 |= AUART_CTRL2_CTSEN; 360 else 361 ctrl2 &= ~AUART_CTRL2_CTSEN; 362 363 /* set baud rate */ 364 baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk); 365 div = u->uartclk * 32 / baud; 366 ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F); 367 ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6); 368 369 writel(ctrl, u->membase + AUART_LINECTRL); 370 writel(ctrl2, u->membase + AUART_CTRL2); 371} 372 373static irqreturn_t mxs_auart_irq_handle(int irq, void *context) 374{ 375 u32 istatus, istat; 376 struct mxs_auart_port *s = context; 377 u32 stat = readl(s->port.membase + AUART_STAT); 378 379 istatus = istat = readl(s->port.membase + AUART_INTR); 380 381 if (istat & AUART_INTR_CTSMIS) { 382 uart_handle_cts_change(&s->port, stat & AUART_STAT_CTS); 383 writel(AUART_INTR_CTSMIS, 384 s->port.membase + AUART_INTR_CLR); 385 istat &= ~AUART_INTR_CTSMIS; 386 } 387 388 if (istat & (AUART_INTR_RTIS | AUART_INTR_RXIS)) { 389 mxs_auart_rx_chars(s); 390 istat &= ~(AUART_INTR_RTIS | AUART_INTR_RXIS); 391 } 392 393 if (istat & AUART_INTR_TXIS) { 394 mxs_auart_tx_chars(s); 395 istat &= ~AUART_INTR_TXIS; 396 } 397 398 writel(istatus & (AUART_INTR_RTIS 399 | AUART_INTR_TXIS 400 | AUART_INTR_RXIS 401 | AUART_INTR_CTSMIS), 402 s->port.membase + AUART_INTR_CLR); 403 404 return IRQ_HANDLED; 405} 406 407static void mxs_auart_reset(struct uart_port *u) 408{ 409 int i; 410 unsigned int reg; 411 412 writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_CLR); 413 414 for (i = 0; i < 10000; i++) { 415 reg = readl(u->membase + AUART_CTRL0); 416 if (!(reg & AUART_CTRL0_SFTRST)) 417 break; 418 udelay(3); 419 } 420 writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); 421} 422 423static int mxs_auart_startup(struct uart_port *u) 424{ 425 struct mxs_auart_port *s = to_auart_port(u); 426 427 clk_prepare_enable(s->clk); 428 429 writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); 430 431 writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET); 432 433 writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, 434 u->membase + AUART_INTR); 435 436 /* 437 * Enable fifo so all four bytes of a DMA word are written to 438 * output (otherwise, only the LSB is written, ie. 1 in 4 bytes) 439 */ 440 writel(AUART_LINECTRL_FEN, u->membase + AUART_LINECTRL_SET); 441 442 return 0; 443} 444 445static void mxs_auart_shutdown(struct uart_port *u) 446{ 447 struct mxs_auart_port *s = to_auart_port(u); 448 449 writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR); 450 451 writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET); 452 453 writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, 454 u->membase + AUART_INTR_CLR); 455 456 clk_disable_unprepare(s->clk); 457} 458 459static unsigned int mxs_auart_tx_empty(struct uart_port *u) 460{ 461 if (readl(u->membase + AUART_STAT) & AUART_STAT_TXFE) 462 return TIOCSER_TEMT; 463 else 464 return 0; 465} 466 467static void mxs_auart_start_tx(struct uart_port *u) 468{ 469 struct mxs_auart_port *s = to_auart_port(u); 470 471 /* enable transmitter */ 472 writel(AUART_CTRL2_TXE, u->membase + AUART_CTRL2_SET); 473 474 mxs_auart_tx_chars(s); 475} 476 477static void mxs_auart_stop_tx(struct uart_port *u) 478{ 479 writel(AUART_CTRL2_TXE, u->membase + AUART_CTRL2_CLR); 480} 481 482static void mxs_auart_stop_rx(struct uart_port *u) 483{ 484 writel(AUART_CTRL2_RXE, u->membase + AUART_CTRL2_CLR); 485} 486 487static void mxs_auart_break_ctl(struct uart_port *u, int ctl) 488{ 489 if (ctl) 490 writel(AUART_LINECTRL_BRK, 491 u->membase + AUART_LINECTRL_SET); 492 else 493 writel(AUART_LINECTRL_BRK, 494 u->membase + AUART_LINECTRL_CLR); 495} 496 497static void mxs_auart_enable_ms(struct uart_port *port) 498{ 499 /* just empty */ 500} 501 502static struct uart_ops mxs_auart_ops = { 503 .tx_empty = mxs_auart_tx_empty, 504 .start_tx = mxs_auart_start_tx, 505 .stop_tx = mxs_auart_stop_tx, 506 .stop_rx = mxs_auart_stop_rx, 507 .enable_ms = mxs_auart_enable_ms, 508 .break_ctl = mxs_auart_break_ctl, 509 .set_mctrl = mxs_auart_set_mctrl, 510 .get_mctrl = mxs_auart_get_mctrl, 511 .startup = mxs_auart_startup, 512 .shutdown = mxs_auart_shutdown, 513 .set_termios = mxs_auart_settermios, 514 .type = mxs_auart_type, 515 .release_port = mxs_auart_release_port, 516 .request_port = mxs_auart_request_port, 517 .config_port = mxs_auart_config_port, 518 .verify_port = mxs_auart_verify_port, 519}; 520 521static struct mxs_auart_port *auart_port[MXS_AUART_PORTS]; 522 523#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE 524static void mxs_auart_console_putchar(struct uart_port *port, int ch) 525{ 526 unsigned int to = 1000; 527 528 while (readl(port->membase + AUART_STAT) & AUART_STAT_TXFF) { 529 if (!to--) 530 break; 531 udelay(1); 532 } 533 534 writel(ch, port->membase + AUART_DATA); 535} 536 537static void 538auart_console_write(struct console *co, const char *str, unsigned int count) 539{ 540 struct mxs_auart_port *s; 541 struct uart_port *port; 542 unsigned int old_ctrl0, old_ctrl2; 543 unsigned int to = 1000; 544 545 if (co->index > MXS_AUART_PORTS || co->index < 0) 546 return; 547 548 s = auart_port[co->index]; 549 port = &s->port; 550 551 clk_enable(s->clk); 552 553 /* First save the CR then disable the interrupts */ 554 old_ctrl2 = readl(port->membase + AUART_CTRL2); 555 old_ctrl0 = readl(port->membase + AUART_CTRL0); 556 557 writel(AUART_CTRL0_CLKGATE, 558 port->membase + AUART_CTRL0_CLR); 559 writel(AUART_CTRL2_UARTEN | AUART_CTRL2_TXE, 560 port->membase + AUART_CTRL2_SET); 561 562 uart_console_write(port, str, count, mxs_auart_console_putchar); 563 564 /* 565 * Finally, wait for transmitter to become empty 566 * and restore the TCR 567 */ 568 while (readl(port->membase + AUART_STAT) & AUART_STAT_BUSY) { 569 if (!to--) 570 break; 571 udelay(1); 572 } 573 574 writel(old_ctrl0, port->membase + AUART_CTRL0); 575 writel(old_ctrl2, port->membase + AUART_CTRL2); 576 577 clk_disable(s->clk); 578} 579 580static void __init 581auart_console_get_options(struct uart_port *port, int *baud, 582 int *parity, int *bits) 583{ 584 unsigned int lcr_h, quot; 585 586 if (!(readl(port->membase + AUART_CTRL2) & AUART_CTRL2_UARTEN)) 587 return; 588 589 lcr_h = readl(port->membase + AUART_LINECTRL); 590 591 *parity = 'n'; 592 if (lcr_h & AUART_LINECTRL_PEN) { 593 if (lcr_h & AUART_LINECTRL_EPS) 594 *parity = 'e'; 595 else 596 *parity = 'o'; 597 } 598 599 if ((lcr_h & AUART_LINECTRL_WLEN_MASK) == AUART_LINECTRL_WLEN(2)) 600 *bits = 7; 601 else 602 *bits = 8; 603 604 quot = ((readl(port->membase + AUART_LINECTRL) 605 & AUART_LINECTRL_BAUD_DIVINT_MASK)) 606 >> (AUART_LINECTRL_BAUD_DIVINT_SHIFT - 6); 607 quot |= ((readl(port->membase + AUART_LINECTRL) 608 & AUART_LINECTRL_BAUD_DIVFRAC_MASK)) 609 >> AUART_LINECTRL_BAUD_DIVFRAC_SHIFT; 610 if (quot == 0) 611 quot = 1; 612 613 *baud = (port->uartclk << 2) / quot; 614} 615 616static int __init 617auart_console_setup(struct console *co, char *options) 618{ 619 struct mxs_auart_port *s; 620 int baud = 9600; 621 int bits = 8; 622 int parity = 'n'; 623 int flow = 'n'; 624 int ret; 625 626 /* 627 * Check whether an invalid uart number has been specified, and 628 * if so, search for the first available port that does have 629 * console support. 630 */ 631 if (co->index == -1 || co->index >= ARRAY_SIZE(auart_port)) 632 co->index = 0; 633 s = auart_port[co->index]; 634 if (!s) 635 return -ENODEV; 636 637 clk_prepare_enable(s->clk); 638 639 if (options) 640 uart_parse_options(options, &baud, &parity, &bits, &flow); 641 else 642 auart_console_get_options(&s->port, &baud, &parity, &bits); 643 644 ret = uart_set_options(&s->port, co, baud, parity, bits, flow); 645 646 clk_disable_unprepare(s->clk); 647 648 return ret; 649} 650 651static struct console auart_console = { 652 .name = "ttyAPP", 653 .write = auart_console_write, 654 .device = uart_console_device, 655 .setup = auart_console_setup, 656 .flags = CON_PRINTBUFFER, 657 .index = -1, 658 .data = &auart_driver, 659}; 660#endif 661 662static struct uart_driver auart_driver = { 663 .owner = THIS_MODULE, 664 .driver_name = "ttyAPP", 665 .dev_name = "ttyAPP", 666 .major = 0, 667 .minor = 0, 668 .nr = MXS_AUART_PORTS, 669#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE 670 .cons = &auart_console, 671#endif 672}; 673 674static int __devinit mxs_auart_probe(struct platform_device *pdev) 675{ 676 struct mxs_auart_port *s; 677 u32 version; 678 int ret = 0; 679 struct resource *r; 680 681 s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL); 682 if (!s) { 683 ret = -ENOMEM; 684 goto out; 685 } 686 687 s->clk = clk_get(&pdev->dev, NULL); 688 if (IS_ERR(s->clk)) { 689 ret = PTR_ERR(s->clk); 690 goto out_free; 691 } 692 693 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 694 if (!r) { 695 ret = -ENXIO; 696 goto out_free_clk; 697 } 698 699 s->port.mapbase = r->start; 700 s->port.membase = ioremap(r->start, resource_size(r)); 701 s->port.ops = &mxs_auart_ops; 702 s->port.iotype = UPIO_MEM; 703 s->port.line = pdev->id < 0 ? 0 : pdev->id; 704 s->port.fifosize = 16; 705 s->port.uartclk = clk_get_rate(s->clk); 706 s->port.type = PORT_IMX; 707 s->port.dev = s->dev = get_device(&pdev->dev); 708 709 s->flags = 0; 710 s->ctrl = 0; 711 712 s->irq = platform_get_irq(pdev, 0); 713 s->port.irq = s->irq; 714 ret = request_irq(s->irq, mxs_auart_irq_handle, 0, dev_name(&pdev->dev), s); 715 if (ret) 716 goto out_free_clk; 717 718 platform_set_drvdata(pdev, s); 719 720 auart_port[pdev->id] = s; 721 722 mxs_auart_reset(&s->port); 723 724 ret = uart_add_one_port(&auart_driver, &s->port); 725 if (ret) 726 goto out_free_irq; 727 728 version = readl(s->port.membase + AUART_VERSION); 729 dev_info(&pdev->dev, "Found APPUART %d.%d.%d\n", 730 (version >> 24) & 0xff, 731 (version >> 16) & 0xff, version & 0xffff); 732 733 return 0; 734 735out_free_irq: 736 auart_port[pdev->id] = NULL; 737 free_irq(s->irq, s); 738out_free_clk: 739 clk_put(s->clk); 740out_free: 741 kfree(s); 742out: 743 return ret; 744} 745 746static int __devexit mxs_auart_remove(struct platform_device *pdev) 747{ 748 struct mxs_auart_port *s = platform_get_drvdata(pdev); 749 750 uart_remove_one_port(&auart_driver, &s->port); 751 752 auart_port[pdev->id] = NULL; 753 754 clk_put(s->clk); 755 free_irq(s->irq, s); 756 kfree(s); 757 758 return 0; 759} 760 761static struct platform_driver mxs_auart_driver = { 762 .probe = mxs_auart_probe, 763 .remove = __devexit_p(mxs_auart_remove), 764 .driver = { 765 .name = "mxs-auart", 766 .owner = THIS_MODULE, 767 }, 768}; 769 770static int __init mxs_auart_init(void) 771{ 772 int r; 773 774 r = uart_register_driver(&auart_driver); 775 if (r) 776 goto out; 777 778 r = platform_driver_register(&mxs_auart_driver); 779 if (r) 780 goto out_err; 781 782 return 0; 783out_err: 784 uart_unregister_driver(&auart_driver); 785out: 786 return r; 787} 788 789static void __exit mxs_auart_exit(void) 790{ 791 platform_driver_unregister(&mxs_auart_driver); 792 uart_unregister_driver(&auart_driver); 793} 794 795module_init(mxs_auart_init); 796module_exit(mxs_auart_exit); 797MODULE_LICENSE("GPL"); 798MODULE_DESCRIPTION("Freescale MXS application uart driver"); 799