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 v3.18-rc3 1862 lines 47 kB view raw
1/* 2 * Driver core for Samsung SoC onboard UARTs. 3 * 4 * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics 5 * http://armlinux.simtec.co.uk/ 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10*/ 11 12/* Hote on 2410 error handling 13 * 14 * The s3c2410 manual has a love/hate affair with the contents of the 15 * UERSTAT register in the UART blocks, and keeps marking some of the 16 * error bits as reserved. Having checked with the s3c2410x01, 17 * it copes with BREAKs properly, so I am happy to ignore the RESERVED 18 * feature from the latter versions of the manual. 19 * 20 * If it becomes aparrent that latter versions of the 2410 remove these 21 * bits, then action will have to be taken to differentiate the versions 22 * and change the policy on BREAK 23 * 24 * BJD, 04-Nov-2004 25*/ 26 27#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) 28#define SUPPORT_SYSRQ 29#endif 30 31#include <linux/module.h> 32#include <linux/ioport.h> 33#include <linux/io.h> 34#include <linux/platform_device.h> 35#include <linux/init.h> 36#include <linux/sysrq.h> 37#include <linux/console.h> 38#include <linux/tty.h> 39#include <linux/tty_flip.h> 40#include <linux/serial_core.h> 41#include <linux/serial.h> 42#include <linux/serial_s3c.h> 43#include <linux/delay.h> 44#include <linux/clk.h> 45#include <linux/cpufreq.h> 46#include <linux/of.h> 47 48#include <asm/irq.h> 49 50#include "samsung.h" 51 52#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \ 53 defined(CONFIG_DEBUG_LL) && \ 54 !defined(MODULE) 55 56extern void printascii(const char *); 57 58__printf(1, 2) 59static void dbg(const char *fmt, ...) 60{ 61 va_list va; 62 char buff[256]; 63 64 va_start(va, fmt); 65 vscnprintf(buff, sizeof(buff), fmt, va); 66 va_end(va); 67 68 printascii(buff); 69} 70 71#else 72#define dbg(fmt, ...) do { if (0) no_printk(fmt, ##__VA_ARGS__); } while (0) 73#endif 74 75/* UART name and device definitions */ 76 77#define S3C24XX_SERIAL_NAME "ttySAC" 78#define S3C24XX_SERIAL_MAJOR 204 79#define S3C24XX_SERIAL_MINOR 64 80 81/* macros to change one thing to another */ 82 83#define tx_enabled(port) ((port)->unused[0]) 84#define rx_enabled(port) ((port)->unused[1]) 85 86/* flag to ignore all characters coming in */ 87#define RXSTAT_DUMMY_READ (0x10000000) 88 89static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port) 90{ 91 return container_of(port, struct s3c24xx_uart_port, port); 92} 93 94/* translate a port to the device name */ 95 96static inline const char *s3c24xx_serial_portname(struct uart_port *port) 97{ 98 return to_platform_device(port->dev)->name; 99} 100 101static int s3c24xx_serial_txempty_nofifo(struct uart_port *port) 102{ 103 return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE; 104} 105 106/* 107 * s3c64xx and later SoC's include the interrupt mask and status registers in 108 * the controller itself, unlike the s3c24xx SoC's which have these registers 109 * in the interrupt controller. Check if the port type is s3c64xx or higher. 110 */ 111static int s3c24xx_serial_has_interrupt_mask(struct uart_port *port) 112{ 113 return to_ourport(port)->info->type == PORT_S3C6400; 114} 115 116static void s3c24xx_serial_rx_enable(struct uart_port *port) 117{ 118 unsigned long flags; 119 unsigned int ucon, ufcon; 120 int count = 10000; 121 122 spin_lock_irqsave(&port->lock, flags); 123 124 while (--count && !s3c24xx_serial_txempty_nofifo(port)) 125 udelay(100); 126 127 ufcon = rd_regl(port, S3C2410_UFCON); 128 ufcon |= S3C2410_UFCON_RESETRX; 129 wr_regl(port, S3C2410_UFCON, ufcon); 130 131 ucon = rd_regl(port, S3C2410_UCON); 132 ucon |= S3C2410_UCON_RXIRQMODE; 133 wr_regl(port, S3C2410_UCON, ucon); 134 135 rx_enabled(port) = 1; 136 spin_unlock_irqrestore(&port->lock, flags); 137} 138 139static void s3c24xx_serial_rx_disable(struct uart_port *port) 140{ 141 unsigned long flags; 142 unsigned int ucon; 143 144 spin_lock_irqsave(&port->lock, flags); 145 146 ucon = rd_regl(port, S3C2410_UCON); 147 ucon &= ~S3C2410_UCON_RXIRQMODE; 148 wr_regl(port, S3C2410_UCON, ucon); 149 150 rx_enabled(port) = 0; 151 spin_unlock_irqrestore(&port->lock, flags); 152} 153 154static void s3c24xx_serial_stop_tx(struct uart_port *port) 155{ 156 struct s3c24xx_uart_port *ourport = to_ourport(port); 157 158 if (tx_enabled(port)) { 159 if (s3c24xx_serial_has_interrupt_mask(port)) 160 __set_bit(S3C64XX_UINTM_TXD, 161 portaddrl(port, S3C64XX_UINTM)); 162 else 163 disable_irq_nosync(ourport->tx_irq); 164 tx_enabled(port) = 0; 165 if (port->flags & UPF_CONS_FLOW) 166 s3c24xx_serial_rx_enable(port); 167 } 168} 169 170static void s3c24xx_serial_start_tx(struct uart_port *port) 171{ 172 struct s3c24xx_uart_port *ourport = to_ourport(port); 173 174 if (!tx_enabled(port)) { 175 if (port->flags & UPF_CONS_FLOW) 176 s3c24xx_serial_rx_disable(port); 177 178 if (s3c24xx_serial_has_interrupt_mask(port)) 179 __clear_bit(S3C64XX_UINTM_TXD, 180 portaddrl(port, S3C64XX_UINTM)); 181 else 182 enable_irq(ourport->tx_irq); 183 tx_enabled(port) = 1; 184 } 185} 186 187static void s3c24xx_serial_stop_rx(struct uart_port *port) 188{ 189 struct s3c24xx_uart_port *ourport = to_ourport(port); 190 191 if (rx_enabled(port)) { 192 dbg("s3c24xx_serial_stop_rx: port=%p\n", port); 193 if (s3c24xx_serial_has_interrupt_mask(port)) 194 __set_bit(S3C64XX_UINTM_RXD, 195 portaddrl(port, S3C64XX_UINTM)); 196 else 197 disable_irq_nosync(ourport->rx_irq); 198 rx_enabled(port) = 0; 199 } 200} 201 202static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port) 203{ 204 return to_ourport(port)->info; 205} 206 207static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port) 208{ 209 struct s3c24xx_uart_port *ourport; 210 211 if (port->dev == NULL) 212 return NULL; 213 214 ourport = container_of(port, struct s3c24xx_uart_port, port); 215 return ourport->cfg; 216} 217 218static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, 219 unsigned long ufstat) 220{ 221 struct s3c24xx_uart_info *info = ourport->info; 222 223 if (ufstat & info->rx_fifofull) 224 return ourport->port.fifosize; 225 226 return (ufstat & info->rx_fifomask) >> info->rx_fifoshift; 227} 228 229 230/* ? - where has parity gone?? */ 231#define S3C2410_UERSTAT_PARITY (0x1000) 232 233static irqreturn_t 234s3c24xx_serial_rx_chars(int irq, void *dev_id) 235{ 236 struct s3c24xx_uart_port *ourport = dev_id; 237 struct uart_port *port = &ourport->port; 238 unsigned int ufcon, ch, flag, ufstat, uerstat; 239 unsigned long flags; 240 int max_count = 64; 241 242 spin_lock_irqsave(&port->lock, flags); 243 244 while (max_count-- > 0) { 245 ufcon = rd_regl(port, S3C2410_UFCON); 246 ufstat = rd_regl(port, S3C2410_UFSTAT); 247 248 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) 249 break; 250 251 uerstat = rd_regl(port, S3C2410_UERSTAT); 252 ch = rd_regb(port, S3C2410_URXH); 253 254 if (port->flags & UPF_CONS_FLOW) { 255 int txe = s3c24xx_serial_txempty_nofifo(port); 256 257 if (rx_enabled(port)) { 258 if (!txe) { 259 rx_enabled(port) = 0; 260 continue; 261 } 262 } else { 263 if (txe) { 264 ufcon |= S3C2410_UFCON_RESETRX; 265 wr_regl(port, S3C2410_UFCON, ufcon); 266 rx_enabled(port) = 1; 267 spin_unlock_irqrestore(&port->lock, 268 flags); 269 goto out; 270 } 271 continue; 272 } 273 } 274 275 /* insert the character into the buffer */ 276 277 flag = TTY_NORMAL; 278 port->icount.rx++; 279 280 if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) { 281 dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n", 282 ch, uerstat); 283 284 /* check for break */ 285 if (uerstat & S3C2410_UERSTAT_BREAK) { 286 dbg("break!\n"); 287 port->icount.brk++; 288 if (uart_handle_break(port)) 289 goto ignore_char; 290 } 291 292 if (uerstat & S3C2410_UERSTAT_FRAME) 293 port->icount.frame++; 294 if (uerstat & S3C2410_UERSTAT_OVERRUN) 295 port->icount.overrun++; 296 297 uerstat &= port->read_status_mask; 298 299 if (uerstat & S3C2410_UERSTAT_BREAK) 300 flag = TTY_BREAK; 301 else if (uerstat & S3C2410_UERSTAT_PARITY) 302 flag = TTY_PARITY; 303 else if (uerstat & (S3C2410_UERSTAT_FRAME | 304 S3C2410_UERSTAT_OVERRUN)) 305 flag = TTY_FRAME; 306 } 307 308 if (uart_handle_sysrq_char(port, ch)) 309 goto ignore_char; 310 311 uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, 312 ch, flag); 313 314 ignore_char: 315 continue; 316 } 317 318 spin_unlock_irqrestore(&port->lock, flags); 319 tty_flip_buffer_push(&port->state->port); 320 321 out: 322 return IRQ_HANDLED; 323} 324 325static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) 326{ 327 struct s3c24xx_uart_port *ourport = id; 328 struct uart_port *port = &ourport->port; 329 struct circ_buf *xmit = &port->state->xmit; 330 unsigned long flags; 331 int count = 256; 332 333 spin_lock_irqsave(&port->lock, flags); 334 335 if (port->x_char) { 336 wr_regb(port, S3C2410_UTXH, port->x_char); 337 port->icount.tx++; 338 port->x_char = 0; 339 goto out; 340 } 341 342 /* if there isn't anything more to transmit, or the uart is now 343 * stopped, disable the uart and exit 344 */ 345 346 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { 347 s3c24xx_serial_stop_tx(port); 348 goto out; 349 } 350 351 /* try and drain the buffer... */ 352 353 while (!uart_circ_empty(xmit) && count-- > 0) { 354 if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull) 355 break; 356 357 wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]); 358 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 359 port->icount.tx++; 360 } 361 362 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { 363 spin_unlock(&port->lock); 364 uart_write_wakeup(port); 365 spin_lock(&port->lock); 366 } 367 368 if (uart_circ_empty(xmit)) 369 s3c24xx_serial_stop_tx(port); 370 371 out: 372 spin_unlock_irqrestore(&port->lock, flags); 373 return IRQ_HANDLED; 374} 375 376/* interrupt handler for s3c64xx and later SoC's.*/ 377static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) 378{ 379 struct s3c24xx_uart_port *ourport = id; 380 struct uart_port *port = &ourport->port; 381 unsigned int pend = rd_regl(port, S3C64XX_UINTP); 382 irqreturn_t ret = IRQ_HANDLED; 383 384 if (pend & S3C64XX_UINTM_RXD_MSK) { 385 ret = s3c24xx_serial_rx_chars(irq, id); 386 wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK); 387 } 388 if (pend & S3C64XX_UINTM_TXD_MSK) { 389 ret = s3c24xx_serial_tx_chars(irq, id); 390 wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK); 391 } 392 return ret; 393} 394 395static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) 396{ 397 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); 398 unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT); 399 unsigned long ufcon = rd_regl(port, S3C2410_UFCON); 400 401 if (ufcon & S3C2410_UFCON_FIFOMODE) { 402 if ((ufstat & info->tx_fifomask) != 0 || 403 (ufstat & info->tx_fifofull)) 404 return 0; 405 406 return 1; 407 } 408 409 return s3c24xx_serial_txempty_nofifo(port); 410} 411 412/* no modem control lines */ 413static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) 414{ 415 unsigned int umstat = rd_regb(port, S3C2410_UMSTAT); 416 417 if (umstat & S3C2410_UMSTAT_CTS) 418 return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; 419 else 420 return TIOCM_CAR | TIOCM_DSR; 421} 422 423static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) 424{ 425 unsigned int umcon = rd_regl(port, S3C2410_UMCON); 426 427 if (mctrl & TIOCM_RTS) 428 umcon |= S3C2410_UMCOM_RTS_LOW; 429 else 430 umcon &= ~S3C2410_UMCOM_RTS_LOW; 431 432 wr_regl(port, S3C2410_UMCON, umcon); 433} 434 435static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) 436{ 437 unsigned long flags; 438 unsigned int ucon; 439 440 spin_lock_irqsave(&port->lock, flags); 441 442 ucon = rd_regl(port, S3C2410_UCON); 443 444 if (break_state) 445 ucon |= S3C2410_UCON_SBREAK; 446 else 447 ucon &= ~S3C2410_UCON_SBREAK; 448 449 wr_regl(port, S3C2410_UCON, ucon); 450 451 spin_unlock_irqrestore(&port->lock, flags); 452} 453 454static void s3c24xx_serial_shutdown(struct uart_port *port) 455{ 456 struct s3c24xx_uart_port *ourport = to_ourport(port); 457 458 if (ourport->tx_claimed) { 459 if (!s3c24xx_serial_has_interrupt_mask(port)) 460 free_irq(ourport->tx_irq, ourport); 461 tx_enabled(port) = 0; 462 ourport->tx_claimed = 0; 463 } 464 465 if (ourport->rx_claimed) { 466 if (!s3c24xx_serial_has_interrupt_mask(port)) 467 free_irq(ourport->rx_irq, ourport); 468 ourport->rx_claimed = 0; 469 rx_enabled(port) = 0; 470 } 471 472 /* Clear pending interrupts and mask all interrupts */ 473 if (s3c24xx_serial_has_interrupt_mask(port)) { 474 free_irq(port->irq, ourport); 475 476 wr_regl(port, S3C64XX_UINTP, 0xf); 477 wr_regl(port, S3C64XX_UINTM, 0xf); 478 } 479} 480 481static int s3c24xx_serial_startup(struct uart_port *port) 482{ 483 struct s3c24xx_uart_port *ourport = to_ourport(port); 484 int ret; 485 486 dbg("s3c24xx_serial_startup: port=%p (%08llx,%p)\n", 487 port, (unsigned long long)port->mapbase, port->membase); 488 489 rx_enabled(port) = 1; 490 491 ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0, 492 s3c24xx_serial_portname(port), ourport); 493 494 if (ret != 0) { 495 dev_err(port->dev, "cannot get irq %d\n", ourport->rx_irq); 496 return ret; 497 } 498 499 ourport->rx_claimed = 1; 500 501 dbg("requesting tx irq...\n"); 502 503 tx_enabled(port) = 1; 504 505 ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0, 506 s3c24xx_serial_portname(port), ourport); 507 508 if (ret) { 509 dev_err(port->dev, "cannot get irq %d\n", ourport->tx_irq); 510 goto err; 511 } 512 513 ourport->tx_claimed = 1; 514 515 dbg("s3c24xx_serial_startup ok\n"); 516 517 /* the port reset code should have done the correct 518 * register setup for the port controls */ 519 520 return ret; 521 522 err: 523 s3c24xx_serial_shutdown(port); 524 return ret; 525} 526 527static int s3c64xx_serial_startup(struct uart_port *port) 528{ 529 struct s3c24xx_uart_port *ourport = to_ourport(port); 530 int ret; 531 532 dbg("s3c64xx_serial_startup: port=%p (%08llx,%p)\n", 533 port, (unsigned long long)port->mapbase, port->membase); 534 535 wr_regl(port, S3C64XX_UINTM, 0xf); 536 537 ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED, 538 s3c24xx_serial_portname(port), ourport); 539 if (ret) { 540 dev_err(port->dev, "cannot get irq %d\n", port->irq); 541 return ret; 542 } 543 544 /* For compatibility with s3c24xx Soc's */ 545 rx_enabled(port) = 1; 546 ourport->rx_claimed = 1; 547 tx_enabled(port) = 0; 548 ourport->tx_claimed = 1; 549 550 /* Enable Rx Interrupt */ 551 __clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM)); 552 dbg("s3c64xx_serial_startup ok\n"); 553 return ret; 554} 555 556/* power power management control */ 557 558static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, 559 unsigned int old) 560{ 561 struct s3c24xx_uart_port *ourport = to_ourport(port); 562 563 ourport->pm_level = level; 564 565 switch (level) { 566 case 3: 567 if (!IS_ERR(ourport->baudclk)) 568 clk_disable_unprepare(ourport->baudclk); 569 570 clk_disable_unprepare(ourport->clk); 571 break; 572 573 case 0: 574 clk_prepare_enable(ourport->clk); 575 576 if (!IS_ERR(ourport->baudclk)) 577 clk_prepare_enable(ourport->baudclk); 578 579 break; 580 default: 581 dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level); 582 } 583} 584 585/* baud rate calculation 586 * 587 * The UARTs on the S3C2410/S3C2440 can take their clocks from a number 588 * of different sources, including the peripheral clock ("pclk") and an 589 * external clock ("uclk"). The S3C2440 also adds the core clock ("fclk") 590 * with a programmable extra divisor. 591 * 592 * The following code goes through the clock sources, and calculates the 593 * baud clocks (and the resultant actual baud rates) and then tries to 594 * pick the closest one and select that. 595 * 596*/ 597 598#define MAX_CLK_NAME_LENGTH 15 599 600static inline int s3c24xx_serial_getsource(struct uart_port *port) 601{ 602 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); 603 unsigned int ucon; 604 605 if (info->num_clks == 1) 606 return 0; 607 608 ucon = rd_regl(port, S3C2410_UCON); 609 ucon &= info->clksel_mask; 610 return ucon >> info->clksel_shift; 611} 612 613static void s3c24xx_serial_setsource(struct uart_port *port, 614 unsigned int clk_sel) 615{ 616 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); 617 unsigned int ucon; 618 619 if (info->num_clks == 1) 620 return; 621 622 ucon = rd_regl(port, S3C2410_UCON); 623 if ((ucon & info->clksel_mask) >> info->clksel_shift == clk_sel) 624 return; 625 626 ucon &= ~info->clksel_mask; 627 ucon |= clk_sel << info->clksel_shift; 628 wr_regl(port, S3C2410_UCON, ucon); 629} 630 631static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, 632 unsigned int req_baud, struct clk **best_clk, 633 unsigned int *clk_num) 634{ 635 struct s3c24xx_uart_info *info = ourport->info; 636 struct clk *clk; 637 unsigned long rate; 638 unsigned int cnt, baud, quot, clk_sel, best_quot = 0; 639 char clkname[MAX_CLK_NAME_LENGTH]; 640 int calc_deviation, deviation = (1 << 30) - 1; 641 642 clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel : 643 ourport->info->def_clk_sel; 644 for (cnt = 0; cnt < info->num_clks; cnt++) { 645 if (!(clk_sel & (1 << cnt))) 646 continue; 647 648 sprintf(clkname, "clk_uart_baud%d", cnt); 649 clk = clk_get(ourport->port.dev, clkname); 650 if (IS_ERR(clk)) 651 continue; 652 653 rate = clk_get_rate(clk); 654 if (!rate) 655 continue; 656 657 if (ourport->info->has_divslot) { 658 unsigned long div = rate / req_baud; 659 660 /* The UDIVSLOT register on the newer UARTs allows us to 661 * get a divisor adjustment of 1/16th on the baud clock. 662 * 663 * We don't keep the UDIVSLOT value (the 16ths we 664 * calculated by not multiplying the baud by 16) as it 665 * is easy enough to recalculate. 666 */ 667 668 quot = div / 16; 669 baud = rate / div; 670 } else { 671 quot = (rate + (8 * req_baud)) / (16 * req_baud); 672 baud = rate / (quot * 16); 673 } 674 quot--; 675 676 calc_deviation = req_baud - baud; 677 if (calc_deviation < 0) 678 calc_deviation = -calc_deviation; 679 680 if (calc_deviation < deviation) { 681 *best_clk = clk; 682 best_quot = quot; 683 *clk_num = cnt; 684 deviation = calc_deviation; 685 } 686 } 687 688 return best_quot; 689} 690 691/* udivslot_table[] 692 * 693 * This table takes the fractional value of the baud divisor and gives 694 * the recommended setting for the UDIVSLOT register. 695 */ 696static u16 udivslot_table[16] = { 697 [0] = 0x0000, 698 [1] = 0x0080, 699 [2] = 0x0808, 700 [3] = 0x0888, 701 [4] = 0x2222, 702 [5] = 0x4924, 703 [6] = 0x4A52, 704 [7] = 0x54AA, 705 [8] = 0x5555, 706 [9] = 0xD555, 707 [10] = 0xD5D5, 708 [11] = 0xDDD5, 709 [12] = 0xDDDD, 710 [13] = 0xDFDD, 711 [14] = 0xDFDF, 712 [15] = 0xFFDF, 713}; 714 715static void s3c24xx_serial_set_termios(struct uart_port *port, 716 struct ktermios *termios, 717 struct ktermios *old) 718{ 719 struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); 720 struct s3c24xx_uart_port *ourport = to_ourport(port); 721 struct clk *clk = ERR_PTR(-EINVAL); 722 unsigned long flags; 723 unsigned int baud, quot, clk_sel = 0; 724 unsigned int ulcon; 725 unsigned int umcon; 726 unsigned int udivslot = 0; 727 728 /* 729 * We don't support modem control lines. 730 */ 731 termios->c_cflag &= ~(HUPCL | CMSPAR); 732 termios->c_cflag |= CLOCAL; 733 734 /* 735 * Ask the core to calculate the divisor for us. 736 */ 737 738 baud = uart_get_baud_rate(port, termios, old, 0, 115200*8); 739 quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel); 740 if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) 741 quot = port->custom_divisor; 742 if (IS_ERR(clk)) 743 return; 744 745 /* check to see if we need to change clock source */ 746 747 if (ourport->baudclk != clk) { 748 s3c24xx_serial_setsource(port, clk_sel); 749 750 if (!IS_ERR(ourport->baudclk)) { 751 clk_disable_unprepare(ourport->baudclk); 752 ourport->baudclk = ERR_PTR(-EINVAL); 753 } 754 755 clk_prepare_enable(clk); 756 757 ourport->baudclk = clk; 758 ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0; 759 } 760 761 if (ourport->info->has_divslot) { 762 unsigned int div = ourport->baudclk_rate / baud; 763 764 if (cfg->has_fracval) { 765 udivslot = (div & 15); 766 dbg("fracval = %04x\n", udivslot); 767 } else { 768 udivslot = udivslot_table[div & 15]; 769 dbg("udivslot = %04x (div %d)\n", udivslot, div & 15); 770 } 771 } 772 773 switch (termios->c_cflag & CSIZE) { 774 case CS5: 775 dbg("config: 5bits/char\n"); 776 ulcon = S3C2410_LCON_CS5; 777 break; 778 case CS6: 779 dbg("config: 6bits/char\n"); 780 ulcon = S3C2410_LCON_CS6; 781 break; 782 case CS7: 783 dbg("config: 7bits/char\n"); 784 ulcon = S3C2410_LCON_CS7; 785 break; 786 case CS8: 787 default: 788 dbg("config: 8bits/char\n"); 789 ulcon = S3C2410_LCON_CS8; 790 break; 791 } 792 793 /* preserve original lcon IR settings */ 794 ulcon |= (cfg->ulcon & S3C2410_LCON_IRM); 795 796 if (termios->c_cflag & CSTOPB) 797 ulcon |= S3C2410_LCON_STOPB; 798 799 if (termios->c_cflag & PARENB) { 800 if (termios->c_cflag & PARODD) 801 ulcon |= S3C2410_LCON_PODD; 802 else 803 ulcon |= S3C2410_LCON_PEVEN; 804 } else { 805 ulcon |= S3C2410_LCON_PNONE; 806 } 807 808 spin_lock_irqsave(&port->lock, flags); 809 810 dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n", 811 ulcon, quot, udivslot); 812 813 wr_regl(port, S3C2410_ULCON, ulcon); 814 wr_regl(port, S3C2410_UBRDIV, quot); 815 816 umcon = rd_regl(port, S3C2410_UMCON); 817 if (termios->c_cflag & CRTSCTS) { 818 umcon |= S3C2410_UMCOM_AFC; 819 /* Disable RTS when RX FIFO contains 63 bytes */ 820 umcon &= ~S3C2412_UMCON_AFC_8; 821 } else { 822 umcon &= ~S3C2410_UMCOM_AFC; 823 } 824 wr_regl(port, S3C2410_UMCON, umcon); 825 826 if (ourport->info->has_divslot) 827 wr_regl(port, S3C2443_DIVSLOT, udivslot); 828 829 dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n", 830 rd_regl(port, S3C2410_ULCON), 831 rd_regl(port, S3C2410_UCON), 832 rd_regl(port, S3C2410_UFCON)); 833 834 /* 835 * Update the per-port timeout. 836 */ 837 uart_update_timeout(port, termios->c_cflag, baud); 838 839 /* 840 * Which character status flags are we interested in? 841 */ 842 port->read_status_mask = S3C2410_UERSTAT_OVERRUN; 843 if (termios->c_iflag & INPCK) 844 port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY; 845 846 /* 847 * Which character status flags should we ignore? 848 */ 849 port->ignore_status_mask = 0; 850 if (termios->c_iflag & IGNPAR) 851 port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN; 852 if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR) 853 port->ignore_status_mask |= S3C2410_UERSTAT_FRAME; 854 855 /* 856 * Ignore all characters if CREAD is not set. 857 */ 858 if ((termios->c_cflag & CREAD) == 0) 859 port->ignore_status_mask |= RXSTAT_DUMMY_READ; 860 861 spin_unlock_irqrestore(&port->lock, flags); 862} 863 864static const char *s3c24xx_serial_type(struct uart_port *port) 865{ 866 switch (port->type) { 867 case PORT_S3C2410: 868 return "S3C2410"; 869 case PORT_S3C2440: 870 return "S3C2440"; 871 case PORT_S3C2412: 872 return "S3C2412"; 873 case PORT_S3C6400: 874 return "S3C6400/10"; 875 default: 876 return NULL; 877 } 878} 879 880#define MAP_SIZE (0x100) 881 882static void s3c24xx_serial_release_port(struct uart_port *port) 883{ 884 release_mem_region(port->mapbase, MAP_SIZE); 885} 886 887static int s3c24xx_serial_request_port(struct uart_port *port) 888{ 889 const char *name = s3c24xx_serial_portname(port); 890 return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY; 891} 892 893static void s3c24xx_serial_config_port(struct uart_port *port, int flags) 894{ 895 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); 896 897 if (flags & UART_CONFIG_TYPE && 898 s3c24xx_serial_request_port(port) == 0) 899 port->type = info->type; 900} 901 902/* 903 * verify the new serial_struct (for TIOCSSERIAL). 904 */ 905static int 906s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser) 907{ 908 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); 909 910 if (ser->type != PORT_UNKNOWN && ser->type != info->type) 911 return -EINVAL; 912 913 return 0; 914} 915 916 917#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE 918 919static struct console s3c24xx_serial_console; 920 921static int __init s3c24xx_serial_console_init(void) 922{ 923 register_console(&s3c24xx_serial_console); 924 return 0; 925} 926console_initcall(s3c24xx_serial_console_init); 927 928#define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console 929#else 930#define S3C24XX_SERIAL_CONSOLE NULL 931#endif 932 933#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL) 934static int s3c24xx_serial_get_poll_char(struct uart_port *port); 935static void s3c24xx_serial_put_poll_char(struct uart_port *port, 936 unsigned char c); 937#endif 938 939static struct uart_ops s3c24xx_serial_ops = { 940 .pm = s3c24xx_serial_pm, 941 .tx_empty = s3c24xx_serial_tx_empty, 942 .get_mctrl = s3c24xx_serial_get_mctrl, 943 .set_mctrl = s3c24xx_serial_set_mctrl, 944 .stop_tx = s3c24xx_serial_stop_tx, 945 .start_tx = s3c24xx_serial_start_tx, 946 .stop_rx = s3c24xx_serial_stop_rx, 947 .break_ctl = s3c24xx_serial_break_ctl, 948 .startup = s3c24xx_serial_startup, 949 .shutdown = s3c24xx_serial_shutdown, 950 .set_termios = s3c24xx_serial_set_termios, 951 .type = s3c24xx_serial_type, 952 .release_port = s3c24xx_serial_release_port, 953 .request_port = s3c24xx_serial_request_port, 954 .config_port = s3c24xx_serial_config_port, 955 .verify_port = s3c24xx_serial_verify_port, 956#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL) 957 .poll_get_char = s3c24xx_serial_get_poll_char, 958 .poll_put_char = s3c24xx_serial_put_poll_char, 959#endif 960}; 961 962static struct uart_driver s3c24xx_uart_drv = { 963 .owner = THIS_MODULE, 964 .driver_name = "s3c2410_serial", 965 .nr = CONFIG_SERIAL_SAMSUNG_UARTS, 966 .cons = S3C24XX_SERIAL_CONSOLE, 967 .dev_name = S3C24XX_SERIAL_NAME, 968 .major = S3C24XX_SERIAL_MAJOR, 969 .minor = S3C24XX_SERIAL_MINOR, 970}; 971 972static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = { 973 [0] = { 974 .port = { 975 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock), 976 .iotype = UPIO_MEM, 977 .uartclk = 0, 978 .fifosize = 16, 979 .ops = &s3c24xx_serial_ops, 980 .flags = UPF_BOOT_AUTOCONF, 981 .line = 0, 982 } 983 }, 984 [1] = { 985 .port = { 986 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock), 987 .iotype = UPIO_MEM, 988 .uartclk = 0, 989 .fifosize = 16, 990 .ops = &s3c24xx_serial_ops, 991 .flags = UPF_BOOT_AUTOCONF, 992 .line = 1, 993 } 994 }, 995#if CONFIG_SERIAL_SAMSUNG_UARTS > 2 996 997 [2] = { 998 .port = { 999 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock), 1000 .iotype = UPIO_MEM, 1001 .uartclk = 0, 1002 .fifosize = 16, 1003 .ops = &s3c24xx_serial_ops, 1004 .flags = UPF_BOOT_AUTOCONF, 1005 .line = 2, 1006 } 1007 }, 1008#endif 1009#if CONFIG_SERIAL_SAMSUNG_UARTS > 3 1010 [3] = { 1011 .port = { 1012 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock), 1013 .iotype = UPIO_MEM, 1014 .uartclk = 0, 1015 .fifosize = 16, 1016 .ops = &s3c24xx_serial_ops, 1017 .flags = UPF_BOOT_AUTOCONF, 1018 .line = 3, 1019 } 1020 } 1021#endif 1022}; 1023 1024/* s3c24xx_serial_resetport 1025 * 1026 * reset the fifos and other the settings. 1027*/ 1028 1029static void s3c24xx_serial_resetport(struct uart_port *port, 1030 struct s3c2410_uartcfg *cfg) 1031{ 1032 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); 1033 unsigned long ucon = rd_regl(port, S3C2410_UCON); 1034 unsigned int ucon_mask; 1035 1036 ucon_mask = info->clksel_mask; 1037 if (info->type == PORT_S3C2440) 1038 ucon_mask |= S3C2440_UCON0_DIVMASK; 1039 1040 ucon &= ucon_mask; 1041 wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); 1042 1043 /* reset both fifos */ 1044 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); 1045 wr_regl(port, S3C2410_UFCON, cfg->ufcon); 1046 1047 /* some delay is required after fifo reset */ 1048 udelay(1); 1049} 1050 1051 1052#ifdef CONFIG_CPU_FREQ 1053 1054static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb, 1055 unsigned long val, void *data) 1056{ 1057 struct s3c24xx_uart_port *port; 1058 struct uart_port *uport; 1059 1060 port = container_of(nb, struct s3c24xx_uart_port, freq_transition); 1061 uport = &port->port; 1062 1063 /* check to see if port is enabled */ 1064 1065 if (port->pm_level != 0) 1066 return 0; 1067 1068 /* try and work out if the baudrate is changing, we can detect 1069 * a change in rate, but we do not have support for detecting 1070 * a disturbance in the clock-rate over the change. 1071 */ 1072 1073 if (IS_ERR(port->baudclk)) 1074 goto exit; 1075 1076 if (port->baudclk_rate == clk_get_rate(port->baudclk)) 1077 goto exit; 1078 1079 if (val == CPUFREQ_PRECHANGE) { 1080 /* we should really shut the port down whilst the 1081 * frequency change is in progress. */ 1082 1083 } else if (val == CPUFREQ_POSTCHANGE) { 1084 struct ktermios *termios; 1085 struct tty_struct *tty; 1086 1087 if (uport->state == NULL) 1088 goto exit; 1089 1090 tty = uport->state->port.tty; 1091 1092 if (tty == NULL) 1093 goto exit; 1094 1095 termios = &tty->termios; 1096 1097 if (termios == NULL) { 1098 dev_warn(uport->dev, "%s: no termios?\n", __func__); 1099 goto exit; 1100 } 1101 1102 s3c24xx_serial_set_termios(uport, termios, NULL); 1103 } 1104 1105 exit: 1106 return 0; 1107} 1108 1109static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port) 1110{ 1111 port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition; 1112 1113 return cpufreq_register_notifier(&port->freq_transition, 1114 CPUFREQ_TRANSITION_NOTIFIER); 1115} 1116 1117static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port) 1118{ 1119 cpufreq_unregister_notifier(&port->freq_transition, 1120 CPUFREQ_TRANSITION_NOTIFIER); 1121} 1122 1123#else 1124static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port) 1125{ 1126 return 0; 1127} 1128 1129static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port) 1130{ 1131} 1132#endif 1133 1134/* s3c24xx_serial_init_port 1135 * 1136 * initialise a single serial port from the platform device given 1137 */ 1138 1139static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, 1140 struct platform_device *platdev) 1141{ 1142 struct uart_port *port = &ourport->port; 1143 struct s3c2410_uartcfg *cfg = ourport->cfg; 1144 struct resource *res; 1145 int ret; 1146 1147 dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev); 1148 1149 if (platdev == NULL) 1150 return -ENODEV; 1151 1152 if (port->mapbase != 0) 1153 return 0; 1154 1155 /* setup info for port */ 1156 port->dev = &platdev->dev; 1157 1158 /* Startup sequence is different for s3c64xx and higher SoC's */ 1159 if (s3c24xx_serial_has_interrupt_mask(port)) 1160 s3c24xx_serial_ops.startup = s3c64xx_serial_startup; 1161 1162 port->uartclk = 1; 1163 1164 if (cfg->uart_flags & UPF_CONS_FLOW) { 1165 dbg("s3c24xx_serial_init_port: enabling flow control\n"); 1166 port->flags |= UPF_CONS_FLOW; 1167 } 1168 1169 /* sort our the physical and virtual addresses for each UART */ 1170 1171 res = platform_get_resource(platdev, IORESOURCE_MEM, 0); 1172 if (res == NULL) { 1173 dev_err(port->dev, "failed to find memory resource for uart\n"); 1174 return -EINVAL; 1175 } 1176 1177 dbg("resource %pR)\n", res); 1178 1179 port->membase = devm_ioremap(port->dev, res->start, resource_size(res)); 1180 if (!port->membase) { 1181 dev_err(port->dev, "failed to remap controller address\n"); 1182 return -EBUSY; 1183 } 1184 1185 port->mapbase = res->start; 1186 ret = platform_get_irq(platdev, 0); 1187 if (ret < 0) 1188 port->irq = 0; 1189 else { 1190 port->irq = ret; 1191 ourport->rx_irq = ret; 1192 ourport->tx_irq = ret + 1; 1193 } 1194 1195 ret = platform_get_irq(platdev, 1); 1196 if (ret > 0) 1197 ourport->tx_irq = ret; 1198 1199 ourport->clk = clk_get(&platdev->dev, "uart"); 1200 if (IS_ERR(ourport->clk)) { 1201 pr_err("%s: Controller clock not found\n", 1202 dev_name(&platdev->dev)); 1203 return PTR_ERR(ourport->clk); 1204 } 1205 1206 ret = clk_prepare_enable(ourport->clk); 1207 if (ret) { 1208 pr_err("uart: clock failed to prepare+enable: %d\n", ret); 1209 clk_put(ourport->clk); 1210 return ret; 1211 } 1212 1213 /* Keep all interrupts masked and cleared */ 1214 if (s3c24xx_serial_has_interrupt_mask(port)) { 1215 wr_regl(port, S3C64XX_UINTM, 0xf); 1216 wr_regl(port, S3C64XX_UINTP, 0xf); 1217 wr_regl(port, S3C64XX_UINTSP, 0xf); 1218 } 1219 1220 dbg("port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n", 1221 &port->mapbase, port->membase, port->irq, 1222 ourport->rx_irq, ourport->tx_irq, port->uartclk); 1223 1224 /* reset the fifos (and setup the uart) */ 1225 s3c24xx_serial_resetport(port, cfg); 1226 return 0; 1227} 1228 1229#ifdef CONFIG_SAMSUNG_CLOCK 1230static ssize_t s3c24xx_serial_show_clksrc(struct device *dev, 1231 struct device_attribute *attr, 1232 char *buf) 1233{ 1234 struct uart_port *port = s3c24xx_dev_to_port(dev); 1235 struct s3c24xx_uart_port *ourport = to_ourport(port); 1236 1237 if (IS_ERR(ourport->baudclk)) 1238 return -EINVAL; 1239 1240 return snprintf(buf, PAGE_SIZE, "* %s\n", 1241 ourport->baudclk->name ?: "(null)"); 1242} 1243 1244static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL); 1245#endif 1246 1247/* Device driver serial port probe */ 1248 1249static const struct of_device_id s3c24xx_uart_dt_match[]; 1250static int probe_index; 1251 1252static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data( 1253 struct platform_device *pdev) 1254{ 1255#ifdef CONFIG_OF 1256 if (pdev->dev.of_node) { 1257 const struct of_device_id *match; 1258 match = of_match_node(s3c24xx_uart_dt_match, pdev->dev.of_node); 1259 return (struct s3c24xx_serial_drv_data *)match->data; 1260 } 1261#endif 1262 return (struct s3c24xx_serial_drv_data *) 1263 platform_get_device_id(pdev)->driver_data; 1264} 1265 1266static int s3c24xx_serial_probe(struct platform_device *pdev) 1267{ 1268 struct device_node *np = pdev->dev.of_node; 1269 struct s3c24xx_uart_port *ourport; 1270 int index = probe_index; 1271 int ret; 1272 1273 if (np) { 1274 ret = of_alias_get_id(np, "serial"); 1275 if (ret >= 0) 1276 index = ret; 1277 } 1278 1279 dbg("s3c24xx_serial_probe(%p) %d\n", pdev, index); 1280 1281 ourport = &s3c24xx_serial_ports[index]; 1282 1283 ourport->drv_data = s3c24xx_get_driver_data(pdev); 1284 if (!ourport->drv_data) { 1285 dev_err(&pdev->dev, "could not find driver data\n"); 1286 return -ENODEV; 1287 } 1288 1289 ourport->baudclk = ERR_PTR(-EINVAL); 1290 ourport->info = ourport->drv_data->info; 1291 ourport->cfg = (dev_get_platdata(&pdev->dev)) ? 1292 dev_get_platdata(&pdev->dev) : 1293 ourport->drv_data->def_cfg; 1294 1295 if (np) 1296 of_property_read_u32(np, 1297 "samsung,uart-fifosize", &ourport->port.fifosize); 1298 1299 if (!ourport->port.fifosize) { 1300 ourport->port.fifosize = (ourport->info->fifosize) ? 1301 ourport->info->fifosize : 1302 ourport->drv_data->fifosize[index]; 1303 } 1304 1305 probe_index++; 1306 1307 dbg("%s: initialising port %p...\n", __func__, ourport); 1308 1309 ret = s3c24xx_serial_init_port(ourport, pdev); 1310 if (ret < 0) 1311 return ret; 1312 1313 if (!s3c24xx_uart_drv.state) { 1314 ret = uart_register_driver(&s3c24xx_uart_drv); 1315 if (ret < 0) { 1316 pr_err("Failed to register Samsung UART driver\n"); 1317 return ret; 1318 } 1319 } 1320 1321 dbg("%s: adding port\n", __func__); 1322 uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); 1323 platform_set_drvdata(pdev, &ourport->port); 1324 1325 /* 1326 * Deactivate the clock enabled in s3c24xx_serial_init_port here, 1327 * so that a potential re-enablement through the pm-callback overlaps 1328 * and keeps the clock enabled in this case. 1329 */ 1330 clk_disable_unprepare(ourport->clk); 1331 1332#ifdef CONFIG_SAMSUNG_CLOCK 1333 ret = device_create_file(&pdev->dev, &dev_attr_clock_source); 1334 if (ret < 0) 1335 dev_err(&pdev->dev, "failed to add clock source attr.\n"); 1336#endif 1337 1338 ret = s3c24xx_serial_cpufreq_register(ourport); 1339 if (ret < 0) 1340 dev_err(&pdev->dev, "failed to add cpufreq notifier\n"); 1341 1342 return 0; 1343} 1344 1345static int s3c24xx_serial_remove(struct platform_device *dev) 1346{ 1347 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); 1348 1349 if (port) { 1350 s3c24xx_serial_cpufreq_deregister(to_ourport(port)); 1351#ifdef CONFIG_SAMSUNG_CLOCK 1352 device_remove_file(&dev->dev, &dev_attr_clock_source); 1353#endif 1354 uart_remove_one_port(&s3c24xx_uart_drv, port); 1355 } 1356 1357 uart_unregister_driver(&s3c24xx_uart_drv); 1358 1359 return 0; 1360} 1361 1362/* UART power management code */ 1363#ifdef CONFIG_PM_SLEEP 1364static int s3c24xx_serial_suspend(struct device *dev) 1365{ 1366 struct uart_port *port = s3c24xx_dev_to_port(dev); 1367 1368 if (port) 1369 uart_suspend_port(&s3c24xx_uart_drv, port); 1370 1371 return 0; 1372} 1373 1374static int s3c24xx_serial_resume(struct device *dev) 1375{ 1376 struct uart_port *port = s3c24xx_dev_to_port(dev); 1377 struct s3c24xx_uart_port *ourport = to_ourport(port); 1378 1379 if (port) { 1380 clk_prepare_enable(ourport->clk); 1381 s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port)); 1382 clk_disable_unprepare(ourport->clk); 1383 1384 uart_resume_port(&s3c24xx_uart_drv, port); 1385 } 1386 1387 return 0; 1388} 1389 1390static int s3c24xx_serial_resume_noirq(struct device *dev) 1391{ 1392 struct uart_port *port = s3c24xx_dev_to_port(dev); 1393 1394 if (port) { 1395 /* restore IRQ mask */ 1396 if (s3c24xx_serial_has_interrupt_mask(port)) { 1397 unsigned int uintm = 0xf; 1398 if (tx_enabled(port)) 1399 uintm &= ~S3C64XX_UINTM_TXD_MSK; 1400 if (rx_enabled(port)) 1401 uintm &= ~S3C64XX_UINTM_RXD_MSK; 1402 wr_regl(port, S3C64XX_UINTM, uintm); 1403 } 1404 } 1405 1406 return 0; 1407} 1408 1409static const struct dev_pm_ops s3c24xx_serial_pm_ops = { 1410 .suspend = s3c24xx_serial_suspend, 1411 .resume = s3c24xx_serial_resume, 1412 .resume_noirq = s3c24xx_serial_resume_noirq, 1413}; 1414#define SERIAL_SAMSUNG_PM_OPS (&s3c24xx_serial_pm_ops) 1415 1416#else /* !CONFIG_PM_SLEEP */ 1417 1418#define SERIAL_SAMSUNG_PM_OPS NULL 1419#endif /* CONFIG_PM_SLEEP */ 1420 1421/* Console code */ 1422 1423#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE 1424 1425static struct uart_port *cons_uart; 1426 1427static int 1428s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) 1429{ 1430 struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); 1431 unsigned long ufstat, utrstat; 1432 1433 if (ufcon & S3C2410_UFCON_FIFOMODE) { 1434 /* fifo mode - check amount of data in fifo registers... */ 1435 1436 ufstat = rd_regl(port, S3C2410_UFSTAT); 1437 return (ufstat & info->tx_fifofull) ? 0 : 1; 1438 } 1439 1440 /* in non-fifo mode, we go and use the tx buffer empty */ 1441 1442 utrstat = rd_regl(port, S3C2410_UTRSTAT); 1443 return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0; 1444} 1445 1446static bool 1447s3c24xx_port_configured(unsigned int ucon) 1448{ 1449 /* consider the serial port configured if the tx/rx mode set */ 1450 return (ucon & 0xf) != 0; 1451} 1452 1453#ifdef CONFIG_CONSOLE_POLL 1454/* 1455 * Console polling routines for writing and reading from the uart while 1456 * in an interrupt or debug context. 1457 */ 1458 1459static int s3c24xx_serial_get_poll_char(struct uart_port *port) 1460{ 1461 struct s3c24xx_uart_port *ourport = to_ourport(port); 1462 unsigned int ufstat; 1463 1464 ufstat = rd_regl(port, S3C2410_UFSTAT); 1465 if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) 1466 return NO_POLL_CHAR; 1467 1468 return rd_regb(port, S3C2410_URXH); 1469} 1470 1471static void s3c24xx_serial_put_poll_char(struct uart_port *port, 1472 unsigned char c) 1473{ 1474 unsigned int ufcon = rd_regl(port, S3C2410_UFCON); 1475 unsigned int ucon = rd_regl(port, S3C2410_UCON); 1476 1477 /* not possible to xmit on unconfigured port */ 1478 if (!s3c24xx_port_configured(ucon)) 1479 return; 1480 1481 while (!s3c24xx_serial_console_txrdy(port, ufcon)) 1482 cpu_relax(); 1483 wr_regb(port, S3C2410_UTXH, c); 1484} 1485 1486#endif /* CONFIG_CONSOLE_POLL */ 1487 1488static void 1489s3c24xx_serial_console_putchar(struct uart_port *port, int ch) 1490{ 1491 unsigned int ufcon = rd_regl(port, S3C2410_UFCON); 1492 1493 while (!s3c24xx_serial_console_txrdy(port, ufcon)) 1494 cpu_relax(); 1495 wr_regb(port, S3C2410_UTXH, ch); 1496} 1497 1498static void 1499s3c24xx_serial_console_write(struct console *co, const char *s, 1500 unsigned int count) 1501{ 1502 unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); 1503 1504 /* not possible to xmit on unconfigured port */ 1505 if (!s3c24xx_port_configured(ucon)) 1506 return; 1507 1508 uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar); 1509} 1510 1511static void __init 1512s3c24xx_serial_get_options(struct uart_port *port, int *baud, 1513 int *parity, int *bits) 1514{ 1515 struct clk *clk; 1516 unsigned int ulcon; 1517 unsigned int ucon; 1518 unsigned int ubrdiv; 1519 unsigned long rate; 1520 unsigned int clk_sel; 1521 char clk_name[MAX_CLK_NAME_LENGTH]; 1522 1523 ulcon = rd_regl(port, S3C2410_ULCON); 1524 ucon = rd_regl(port, S3C2410_UCON); 1525 ubrdiv = rd_regl(port, S3C2410_UBRDIV); 1526 1527 dbg("s3c24xx_serial_get_options: port=%p\n" 1528 "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n", 1529 port, ulcon, ucon, ubrdiv); 1530 1531 if (s3c24xx_port_configured(ucon)) { 1532 switch (ulcon & S3C2410_LCON_CSMASK) { 1533 case S3C2410_LCON_CS5: 1534 *bits = 5; 1535 break; 1536 case S3C2410_LCON_CS6: 1537 *bits = 6; 1538 break; 1539 case S3C2410_LCON_CS7: 1540 *bits = 7; 1541 break; 1542 case S3C2410_LCON_CS8: 1543 default: 1544 *bits = 8; 1545 break; 1546 } 1547 1548 switch (ulcon & S3C2410_LCON_PMASK) { 1549 case S3C2410_LCON_PEVEN: 1550 *parity = 'e'; 1551 break; 1552 1553 case S3C2410_LCON_PODD: 1554 *parity = 'o'; 1555 break; 1556 1557 case S3C2410_LCON_PNONE: 1558 default: 1559 *parity = 'n'; 1560 } 1561 1562 /* now calculate the baud rate */ 1563 1564 clk_sel = s3c24xx_serial_getsource(port); 1565 sprintf(clk_name, "clk_uart_baud%d", clk_sel); 1566 1567 clk = clk_get(port->dev, clk_name); 1568 if (!IS_ERR(clk)) 1569 rate = clk_get_rate(clk); 1570 else 1571 rate = 1; 1572 1573 *baud = rate / (16 * (ubrdiv + 1)); 1574 dbg("calculated baud %d\n", *baud); 1575 } 1576 1577} 1578 1579static int __init 1580s3c24xx_serial_console_setup(struct console *co, char *options) 1581{ 1582 struct uart_port *port; 1583 int baud = 9600; 1584 int bits = 8; 1585 int parity = 'n'; 1586 int flow = 'n'; 1587 1588 dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n", 1589 co, co->index, options); 1590 1591 /* is this a valid port */ 1592 1593 if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS) 1594 co->index = 0; 1595 1596 port = &s3c24xx_serial_ports[co->index].port; 1597 1598 /* is the port configured? */ 1599 1600 if (port->mapbase == 0x0) 1601 return -ENODEV; 1602 1603 cons_uart = port; 1604 1605 dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index); 1606 1607 /* 1608 * Check whether an invalid uart number has been specified, and 1609 * if so, search for the first available port that does have 1610 * console support. 1611 */ 1612 if (options) 1613 uart_parse_options(options, &baud, &parity, &bits, &flow); 1614 else 1615 s3c24xx_serial_get_options(port, &baud, &parity, &bits); 1616 1617 dbg("s3c24xx_serial_console_setup: baud %d\n", baud); 1618 1619 return uart_set_options(port, co, baud, parity, bits, flow); 1620} 1621 1622static struct console s3c24xx_serial_console = { 1623 .name = S3C24XX_SERIAL_NAME, 1624 .device = uart_console_device, 1625 .flags = CON_PRINTBUFFER, 1626 .index = -1, 1627 .write = s3c24xx_serial_console_write, 1628 .setup = s3c24xx_serial_console_setup, 1629 .data = &s3c24xx_uart_drv, 1630}; 1631#endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */ 1632 1633#ifdef CONFIG_CPU_S3C2410 1634static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = { 1635 .info = &(struct s3c24xx_uart_info) { 1636 .name = "Samsung S3C2410 UART", 1637 .type = PORT_S3C2410, 1638 .fifosize = 16, 1639 .rx_fifomask = S3C2410_UFSTAT_RXMASK, 1640 .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT, 1641 .rx_fifofull = S3C2410_UFSTAT_RXFULL, 1642 .tx_fifofull = S3C2410_UFSTAT_TXFULL, 1643 .tx_fifomask = S3C2410_UFSTAT_TXMASK, 1644 .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT, 1645 .def_clk_sel = S3C2410_UCON_CLKSEL0, 1646 .num_clks = 2, 1647 .clksel_mask = S3C2410_UCON_CLKMASK, 1648 .clksel_shift = S3C2410_UCON_CLKSHIFT, 1649 }, 1650 .def_cfg = &(struct s3c2410_uartcfg) { 1651 .ucon = S3C2410_UCON_DEFAULT, 1652 .ufcon = S3C2410_UFCON_DEFAULT, 1653 }, 1654}; 1655#define S3C2410_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2410_serial_drv_data) 1656#else 1657#define S3C2410_SERIAL_DRV_DATA (kernel_ulong_t)NULL 1658#endif 1659 1660#ifdef CONFIG_CPU_S3C2412 1661static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = { 1662 .info = &(struct s3c24xx_uart_info) { 1663 .name = "Samsung S3C2412 UART", 1664 .type = PORT_S3C2412, 1665 .fifosize = 64, 1666 .has_divslot = 1, 1667 .rx_fifomask = S3C2440_UFSTAT_RXMASK, 1668 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, 1669 .rx_fifofull = S3C2440_UFSTAT_RXFULL, 1670 .tx_fifofull = S3C2440_UFSTAT_TXFULL, 1671 .tx_fifomask = S3C2440_UFSTAT_TXMASK, 1672 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, 1673 .def_clk_sel = S3C2410_UCON_CLKSEL2, 1674 .num_clks = 4, 1675 .clksel_mask = S3C2412_UCON_CLKMASK, 1676 .clksel_shift = S3C2412_UCON_CLKSHIFT, 1677 }, 1678 .def_cfg = &(struct s3c2410_uartcfg) { 1679 .ucon = S3C2410_UCON_DEFAULT, 1680 .ufcon = S3C2410_UFCON_DEFAULT, 1681 }, 1682}; 1683#define S3C2412_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2412_serial_drv_data) 1684#else 1685#define S3C2412_SERIAL_DRV_DATA (kernel_ulong_t)NULL 1686#endif 1687 1688#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \ 1689 defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2442) 1690static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = { 1691 .info = &(struct s3c24xx_uart_info) { 1692 .name = "Samsung S3C2440 UART", 1693 .type = PORT_S3C2440, 1694 .fifosize = 64, 1695 .has_divslot = 1, 1696 .rx_fifomask = S3C2440_UFSTAT_RXMASK, 1697 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, 1698 .rx_fifofull = S3C2440_UFSTAT_RXFULL, 1699 .tx_fifofull = S3C2440_UFSTAT_TXFULL, 1700 .tx_fifomask = S3C2440_UFSTAT_TXMASK, 1701 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, 1702 .def_clk_sel = S3C2410_UCON_CLKSEL2, 1703 .num_clks = 4, 1704 .clksel_mask = S3C2412_UCON_CLKMASK, 1705 .clksel_shift = S3C2412_UCON_CLKSHIFT, 1706 }, 1707 .def_cfg = &(struct s3c2410_uartcfg) { 1708 .ucon = S3C2410_UCON_DEFAULT, 1709 .ufcon = S3C2410_UFCON_DEFAULT, 1710 }, 1711}; 1712#define S3C2440_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2440_serial_drv_data) 1713#else 1714#define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL 1715#endif 1716 1717#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410) 1718static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = { 1719 .info = &(struct s3c24xx_uart_info) { 1720 .name = "Samsung S3C6400 UART", 1721 .type = PORT_S3C6400, 1722 .fifosize = 64, 1723 .has_divslot = 1, 1724 .rx_fifomask = S3C2440_UFSTAT_RXMASK, 1725 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, 1726 .rx_fifofull = S3C2440_UFSTAT_RXFULL, 1727 .tx_fifofull = S3C2440_UFSTAT_TXFULL, 1728 .tx_fifomask = S3C2440_UFSTAT_TXMASK, 1729 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, 1730 .def_clk_sel = S3C2410_UCON_CLKSEL2, 1731 .num_clks = 4, 1732 .clksel_mask = S3C6400_UCON_CLKMASK, 1733 .clksel_shift = S3C6400_UCON_CLKSHIFT, 1734 }, 1735 .def_cfg = &(struct s3c2410_uartcfg) { 1736 .ucon = S3C2410_UCON_DEFAULT, 1737 .ufcon = S3C2410_UFCON_DEFAULT, 1738 }, 1739}; 1740#define S3C6400_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c6400_serial_drv_data) 1741#else 1742#define S3C6400_SERIAL_DRV_DATA (kernel_ulong_t)NULL 1743#endif 1744 1745#ifdef CONFIG_CPU_S5PV210 1746static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { 1747 .info = &(struct s3c24xx_uart_info) { 1748 .name = "Samsung S5PV210 UART", 1749 .type = PORT_S3C6400, 1750 .has_divslot = 1, 1751 .rx_fifomask = S5PV210_UFSTAT_RXMASK, 1752 .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, 1753 .rx_fifofull = S5PV210_UFSTAT_RXFULL, 1754 .tx_fifofull = S5PV210_UFSTAT_TXFULL, 1755 .tx_fifomask = S5PV210_UFSTAT_TXMASK, 1756 .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, 1757 .def_clk_sel = S3C2410_UCON_CLKSEL0, 1758 .num_clks = 2, 1759 .clksel_mask = S5PV210_UCON_CLKMASK, 1760 .clksel_shift = S5PV210_UCON_CLKSHIFT, 1761 }, 1762 .def_cfg = &(struct s3c2410_uartcfg) { 1763 .ucon = S5PV210_UCON_DEFAULT, 1764 .ufcon = S5PV210_UFCON_DEFAULT, 1765 }, 1766 .fifosize = { 256, 64, 16, 16 }, 1767}; 1768#define S5PV210_SERIAL_DRV_DATA ((kernel_ulong_t)&s5pv210_serial_drv_data) 1769#else 1770#define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL 1771#endif 1772 1773#if defined(CONFIG_ARCH_EXYNOS) 1774static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = { 1775 .info = &(struct s3c24xx_uart_info) { 1776 .name = "Samsung Exynos4 UART", 1777 .type = PORT_S3C6400, 1778 .has_divslot = 1, 1779 .rx_fifomask = S5PV210_UFSTAT_RXMASK, 1780 .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, 1781 .rx_fifofull = S5PV210_UFSTAT_RXFULL, 1782 .tx_fifofull = S5PV210_UFSTAT_TXFULL, 1783 .tx_fifomask = S5PV210_UFSTAT_TXMASK, 1784 .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, 1785 .def_clk_sel = S3C2410_UCON_CLKSEL0, 1786 .num_clks = 1, 1787 .clksel_mask = 0, 1788 .clksel_shift = 0, 1789 }, 1790 .def_cfg = &(struct s3c2410_uartcfg) { 1791 .ucon = S5PV210_UCON_DEFAULT, 1792 .ufcon = S5PV210_UFCON_DEFAULT, 1793 .has_fracval = 1, 1794 }, 1795 .fifosize = { 256, 64, 16, 16 }, 1796}; 1797#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data) 1798#else 1799#define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL 1800#endif 1801 1802static struct platform_device_id s3c24xx_serial_driver_ids[] = { 1803 { 1804 .name = "s3c2410-uart", 1805 .driver_data = S3C2410_SERIAL_DRV_DATA, 1806 }, { 1807 .name = "s3c2412-uart", 1808 .driver_data = S3C2412_SERIAL_DRV_DATA, 1809 }, { 1810 .name = "s3c2440-uart", 1811 .driver_data = S3C2440_SERIAL_DRV_DATA, 1812 }, { 1813 .name = "s3c6400-uart", 1814 .driver_data = S3C6400_SERIAL_DRV_DATA, 1815 }, { 1816 .name = "s5pv210-uart", 1817 .driver_data = S5PV210_SERIAL_DRV_DATA, 1818 }, { 1819 .name = "exynos4210-uart", 1820 .driver_data = EXYNOS4210_SERIAL_DRV_DATA, 1821 }, 1822 { }, 1823}; 1824MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids); 1825 1826#ifdef CONFIG_OF 1827static const struct of_device_id s3c24xx_uart_dt_match[] = { 1828 { .compatible = "samsung,s3c2410-uart", 1829 .data = (void *)S3C2410_SERIAL_DRV_DATA }, 1830 { .compatible = "samsung,s3c2412-uart", 1831 .data = (void *)S3C2412_SERIAL_DRV_DATA }, 1832 { .compatible = "samsung,s3c2440-uart", 1833 .data = (void *)S3C2440_SERIAL_DRV_DATA }, 1834 { .compatible = "samsung,s3c6400-uart", 1835 .data = (void *)S3C6400_SERIAL_DRV_DATA }, 1836 { .compatible = "samsung,s5pv210-uart", 1837 .data = (void *)S5PV210_SERIAL_DRV_DATA }, 1838 { .compatible = "samsung,exynos4210-uart", 1839 .data = (void *)EXYNOS4210_SERIAL_DRV_DATA }, 1840 {}, 1841}; 1842MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match); 1843#endif 1844 1845static struct platform_driver samsung_serial_driver = { 1846 .probe = s3c24xx_serial_probe, 1847 .remove = s3c24xx_serial_remove, 1848 .id_table = s3c24xx_serial_driver_ids, 1849 .driver = { 1850 .name = "samsung-uart", 1851 .owner = THIS_MODULE, 1852 .pm = SERIAL_SAMSUNG_PM_OPS, 1853 .of_match_table = of_match_ptr(s3c24xx_uart_dt_match), 1854 }, 1855}; 1856 1857module_platform_driver(samsung_serial_driver); 1858 1859MODULE_ALIAS("platform:samsung-uart"); 1860MODULE_DESCRIPTION("Samsung SoC Serial port driver"); 1861MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 1862MODULE_LICENSE("GPL v2");