diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-01-11 23:11:43 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-01-11 23:11:43 -0500 |
commit | b1bdd255661369cb6eb90b6e181169b5e6d0f9b6 (patch) | |
tree | 17d15f3a6dc5bdd6205070dbef0e339421b13d25 /drivers/tty | |
parent | 9d14070f656addddce3d63fd483de46930b51850 (diff) | |
parent | c1537b4863da620f12f5b42ece61bf65314148ed (diff) |
Merge branch 'sh/nommu' into sh-latest
Diffstat (limited to 'drivers/tty')
44 files changed, 2722 insertions, 1678 deletions
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index cea56033b34c..a09ce3ef5d74 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c | |||
@@ -417,7 +417,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) | |||
417 | __FILE__,__LINE__,tbuf,tbuf->count); | 417 | __FILE__,__LINE__,tbuf,tbuf->count); |
418 | 418 | ||
419 | /* Send the next block of data to device */ | 419 | /* Send the next block of data to device */ |
420 | tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); | 420 | set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); |
421 | actual = tty->ops->write(tty, tbuf->buf, tbuf->count); | 421 | actual = tty->ops->write(tty, tbuf->buf, tbuf->count); |
422 | 422 | ||
423 | /* rollback was possible and has been done */ | 423 | /* rollback was possible and has been done */ |
@@ -459,7 +459,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) | |||
459 | } | 459 | } |
460 | 460 | ||
461 | if (!tbuf) | 461 | if (!tbuf) |
462 | tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); | 462 | clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); |
463 | 463 | ||
464 | /* Clear the re-entry flag */ | 464 | /* Clear the re-entry flag */ |
465 | spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); | 465 | spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); |
@@ -491,7 +491,7 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty) | |||
491 | return; | 491 | return; |
492 | 492 | ||
493 | if (tty != n_hdlc->tty) { | 493 | if (tty != n_hdlc->tty) { |
494 | tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); | 494 | clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); |
495 | return; | 495 | return; |
496 | } | 496 | } |
497 | 497 | ||
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 39d6ab6551e0..d2256d08ee7e 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
@@ -61,7 +61,7 @@ | |||
61 | * controlling the space in the read buffer. | 61 | * controlling the space in the read buffer. |
62 | */ | 62 | */ |
63 | #define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */ | 63 | #define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */ |
64 | #define TTY_THRESHOLD_UNTHROTTLE 128 | 64 | #define TTY_THRESHOLD_UNTHROTTLE 128 |
65 | 65 | ||
66 | /* | 66 | /* |
67 | * Special byte codes used in the echo buffer to represent operations | 67 | * Special byte codes used in the echo buffer to represent operations |
@@ -405,7 +405,7 @@ static ssize_t process_output_block(struct tty_struct *tty, | |||
405 | const unsigned char *buf, unsigned int nr) | 405 | const unsigned char *buf, unsigned int nr) |
406 | { | 406 | { |
407 | int space; | 407 | int space; |
408 | int i; | 408 | int i; |
409 | const unsigned char *cp; | 409 | const unsigned char *cp; |
410 | 410 | ||
411 | mutex_lock(&tty->output_lock); | 411 | mutex_lock(&tty->output_lock); |
@@ -1607,7 +1607,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt) | |||
1607 | } | 1607 | } |
1608 | 1608 | ||
1609 | /** | 1609 | /** |
1610 | * copy_from_read_buf - copy read data directly | 1610 | * copy_from_read_buf - copy read data directly |
1611 | * @tty: terminal device | 1611 | * @tty: terminal device |
1612 | * @b: user data | 1612 | * @b: user data |
1613 | * @nr: size of data | 1613 | * @nr: size of data |
@@ -1909,7 +1909,7 @@ do_it_again: | |||
1909 | if (nr) | 1909 | if (nr) |
1910 | clear_bit(TTY_PUSH, &tty->flags); | 1910 | clear_bit(TTY_PUSH, &tty->flags); |
1911 | } else if (test_and_clear_bit(TTY_PUSH, &tty->flags)) | 1911 | } else if (test_and_clear_bit(TTY_PUSH, &tty->flags)) |
1912 | goto do_it_again; | 1912 | goto do_it_again; |
1913 | 1913 | ||
1914 | n_tty_set_room(tty); | 1914 | n_tty_set_room(tty); |
1915 | return retval; | 1915 | return retval; |
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index e18604b3fc7d..d8653ab6f498 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
@@ -446,19 +446,8 @@ static inline void legacy_pty_init(void) { } | |||
446 | int pty_limit = NR_UNIX98_PTY_DEFAULT; | 446 | int pty_limit = NR_UNIX98_PTY_DEFAULT; |
447 | static int pty_limit_min; | 447 | static int pty_limit_min; |
448 | static int pty_limit_max = NR_UNIX98_PTY_MAX; | 448 | static int pty_limit_max = NR_UNIX98_PTY_MAX; |
449 | static int tty_count; | ||
450 | static int pty_count; | 449 | static int pty_count; |
451 | 450 | ||
452 | static inline void pty_inc_count(void) | ||
453 | { | ||
454 | pty_count = (++tty_count) / 2; | ||
455 | } | ||
456 | |||
457 | static inline void pty_dec_count(void) | ||
458 | { | ||
459 | pty_count = (--tty_count) / 2; | ||
460 | } | ||
461 | |||
462 | static struct cdev ptmx_cdev; | 451 | static struct cdev ptmx_cdev; |
463 | 452 | ||
464 | static struct ctl_table pty_table[] = { | 453 | static struct ctl_table pty_table[] = { |
@@ -600,8 +589,7 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) | |||
600 | */ | 589 | */ |
601 | tty_driver_kref_get(driver); | 590 | tty_driver_kref_get(driver); |
602 | tty->count++; | 591 | tty->count++; |
603 | pty_inc_count(); /* tty */ | 592 | pty_count++; |
604 | pty_inc_count(); /* tty->link */ | ||
605 | return 0; | 593 | return 0; |
606 | err_free_mem: | 594 | err_free_mem: |
607 | deinitialize_tty_struct(o_tty); | 595 | deinitialize_tty_struct(o_tty); |
@@ -613,15 +601,19 @@ err_free_tty: | |||
613 | return -ENOMEM; | 601 | return -ENOMEM; |
614 | } | 602 | } |
615 | 603 | ||
616 | static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) | 604 | static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) |
605 | { | ||
606 | pty_count--; | ||
607 | } | ||
608 | |||
609 | static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) | ||
617 | { | 610 | { |
618 | pty_dec_count(); | ||
619 | } | 611 | } |
620 | 612 | ||
621 | static const struct tty_operations ptm_unix98_ops = { | 613 | static const struct tty_operations ptm_unix98_ops = { |
622 | .lookup = ptm_unix98_lookup, | 614 | .lookup = ptm_unix98_lookup, |
623 | .install = pty_unix98_install, | 615 | .install = pty_unix98_install, |
624 | .remove = pty_unix98_remove, | 616 | .remove = ptm_unix98_remove, |
625 | .open = pty_open, | 617 | .open = pty_open, |
626 | .close = pty_close, | 618 | .close = pty_close, |
627 | .write = pty_write, | 619 | .write = pty_write, |
@@ -638,7 +630,7 @@ static const struct tty_operations ptm_unix98_ops = { | |||
638 | static const struct tty_operations pty_unix98_ops = { | 630 | static const struct tty_operations pty_unix98_ops = { |
639 | .lookup = pts_unix98_lookup, | 631 | .lookup = pts_unix98_lookup, |
640 | .install = pty_unix98_install, | 632 | .install = pty_unix98_install, |
641 | .remove = pty_unix98_remove, | 633 | .remove = pts_unix98_remove, |
642 | .open = pty_open, | 634 | .open = pty_open, |
643 | .close = pty_close, | 635 | .close = pty_close, |
644 | .write = pty_write, | 636 | .write = pty_write, |
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index eeadf1b8e093..9f50c4e3c2be 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c | |||
@@ -129,32 +129,6 @@ static unsigned long probe_rsa[PORT_RSA_MAX]; | |||
129 | static unsigned int probe_rsa_count; | 129 | static unsigned int probe_rsa_count; |
130 | #endif /* CONFIG_SERIAL_8250_RSA */ | 130 | #endif /* CONFIG_SERIAL_8250_RSA */ |
131 | 131 | ||
132 | struct uart_8250_port { | ||
133 | struct uart_port port; | ||
134 | struct timer_list timer; /* "no irq" timer */ | ||
135 | struct list_head list; /* ports on this IRQ */ | ||
136 | unsigned short capabilities; /* port capabilities */ | ||
137 | unsigned short bugs; /* port bugs */ | ||
138 | unsigned int tx_loadsz; /* transmit fifo load size */ | ||
139 | unsigned char acr; | ||
140 | unsigned char ier; | ||
141 | unsigned char lcr; | ||
142 | unsigned char mcr; | ||
143 | unsigned char mcr_mask; /* mask of user bits */ | ||
144 | unsigned char mcr_force; /* mask of forced bits */ | ||
145 | unsigned char cur_iotype; /* Running I/O type */ | ||
146 | |||
147 | /* | ||
148 | * Some bits in registers are cleared on a read, so they must | ||
149 | * be saved whenever the register is read but the bits will not | ||
150 | * be immediately processed. | ||
151 | */ | ||
152 | #define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS | ||
153 | unsigned char lsr_saved_flags; | ||
154 | #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA | ||
155 | unsigned char msr_saved_flags; | ||
156 | }; | ||
157 | |||
158 | struct irq_info { | 132 | struct irq_info { |
159 | struct hlist_node node; | 133 | struct hlist_node node; |
160 | int irq; | 134 | int irq; |
@@ -1326,8 +1300,6 @@ static void serial8250_stop_tx(struct uart_port *port) | |||
1326 | } | 1300 | } |
1327 | } | 1301 | } |
1328 | 1302 | ||
1329 | static void transmit_chars(struct uart_8250_port *up); | ||
1330 | |||
1331 | static void serial8250_start_tx(struct uart_port *port) | 1303 | static void serial8250_start_tx(struct uart_port *port) |
1332 | { | 1304 | { |
1333 | struct uart_8250_port *up = | 1305 | struct uart_8250_port *up = |
@@ -1344,7 +1316,7 @@ static void serial8250_start_tx(struct uart_port *port) | |||
1344 | if ((up->port.type == PORT_RM9000) ? | 1316 | if ((up->port.type == PORT_RM9000) ? |
1345 | (lsr & UART_LSR_THRE) : | 1317 | (lsr & UART_LSR_THRE) : |
1346 | (lsr & UART_LSR_TEMT)) | 1318 | (lsr & UART_LSR_TEMT)) |
1347 | transmit_chars(up); | 1319 | serial8250_tx_chars(up); |
1348 | } | 1320 | } |
1349 | } | 1321 | } |
1350 | 1322 | ||
@@ -1401,11 +1373,16 @@ static void clear_rx_fifo(struct uart_8250_port *up) | |||
1401 | } while (1); | 1373 | } while (1); |
1402 | } | 1374 | } |
1403 | 1375 | ||
1404 | static void | 1376 | /* |
1405 | receive_chars(struct uart_8250_port *up, unsigned int *status) | 1377 | * serial8250_rx_chars: processes according to the passed in LSR |
1378 | * value, and returns the remaining LSR bits not handled | ||
1379 | * by this Rx routine. | ||
1380 | */ | ||
1381 | unsigned char | ||
1382 | serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) | ||
1406 | { | 1383 | { |
1407 | struct tty_struct *tty = up->port.state->port.tty; | 1384 | struct tty_struct *tty = up->port.state->port.tty; |
1408 | unsigned char ch, lsr = *status; | 1385 | unsigned char ch; |
1409 | int max_count = 256; | 1386 | int max_count = 256; |
1410 | char flag; | 1387 | char flag; |
1411 | 1388 | ||
@@ -1481,10 +1458,11 @@ ignore_char: | |||
1481 | spin_unlock(&up->port.lock); | 1458 | spin_unlock(&up->port.lock); |
1482 | tty_flip_buffer_push(tty); | 1459 | tty_flip_buffer_push(tty); |
1483 | spin_lock(&up->port.lock); | 1460 | spin_lock(&up->port.lock); |
1484 | *status = lsr; | 1461 | return lsr; |
1485 | } | 1462 | } |
1463 | EXPORT_SYMBOL_GPL(serial8250_rx_chars); | ||
1486 | 1464 | ||
1487 | static void transmit_chars(struct uart_8250_port *up) | 1465 | void serial8250_tx_chars(struct uart_8250_port *up) |
1488 | { | 1466 | { |
1489 | struct circ_buf *xmit = &up->port.state->xmit; | 1467 | struct circ_buf *xmit = &up->port.state->xmit; |
1490 | int count; | 1468 | int count; |
@@ -1521,8 +1499,9 @@ static void transmit_chars(struct uart_8250_port *up) | |||
1521 | if (uart_circ_empty(xmit)) | 1499 | if (uart_circ_empty(xmit)) |
1522 | __stop_tx(up); | 1500 | __stop_tx(up); |
1523 | } | 1501 | } |
1502 | EXPORT_SYMBOL_GPL(serial8250_tx_chars); | ||
1524 | 1503 | ||
1525 | static unsigned int check_modem_status(struct uart_8250_port *up) | 1504 | unsigned int serial8250_modem_status(struct uart_8250_port *up) |
1526 | { | 1505 | { |
1527 | unsigned int status = serial_in(up, UART_MSR); | 1506 | unsigned int status = serial_in(up, UART_MSR); |
1528 | 1507 | ||
@@ -1544,14 +1523,20 @@ static unsigned int check_modem_status(struct uart_8250_port *up) | |||
1544 | 1523 | ||
1545 | return status; | 1524 | return status; |
1546 | } | 1525 | } |
1526 | EXPORT_SYMBOL_GPL(serial8250_modem_status); | ||
1547 | 1527 | ||
1548 | /* | 1528 | /* |
1549 | * This handles the interrupt from one port. | 1529 | * This handles the interrupt from one port. |
1550 | */ | 1530 | */ |
1551 | static void serial8250_handle_port(struct uart_8250_port *up) | 1531 | int serial8250_handle_irq(struct uart_port *port, unsigned int iir) |
1552 | { | 1532 | { |
1553 | unsigned int status; | 1533 | unsigned char status; |
1554 | unsigned long flags; | 1534 | unsigned long flags; |
1535 | struct uart_8250_port *up = | ||
1536 | container_of(port, struct uart_8250_port, port); | ||
1537 | |||
1538 | if (iir & UART_IIR_NO_INT) | ||
1539 | return 0; | ||
1555 | 1540 | ||
1556 | spin_lock_irqsave(&up->port.lock, flags); | 1541 | spin_lock_irqsave(&up->port.lock, flags); |
1557 | 1542 | ||
@@ -1560,25 +1545,13 @@ static void serial8250_handle_port(struct uart_8250_port *up) | |||
1560 | DEBUG_INTR("status = %x...", status); | 1545 | DEBUG_INTR("status = %x...", status); |
1561 | 1546 | ||
1562 | if (status & (UART_LSR_DR | UART_LSR_BI)) | 1547 | if (status & (UART_LSR_DR | UART_LSR_BI)) |
1563 | receive_chars(up, &status); | 1548 | status = serial8250_rx_chars(up, status); |
1564 | check_modem_status(up); | 1549 | serial8250_modem_status(up); |
1565 | if (status & UART_LSR_THRE) | 1550 | if (status & UART_LSR_THRE) |
1566 | transmit_chars(up); | 1551 | serial8250_tx_chars(up); |
1567 | 1552 | ||
1568 | spin_unlock_irqrestore(&up->port.lock, flags); | 1553 | spin_unlock_irqrestore(&up->port.lock, flags); |
1569 | } | 1554 | return 1; |
1570 | |||
1571 | int serial8250_handle_irq(struct uart_port *port, unsigned int iir) | ||
1572 | { | ||
1573 | struct uart_8250_port *up = | ||
1574 | container_of(port, struct uart_8250_port, port); | ||
1575 | |||
1576 | if (!(iir & UART_IIR_NO_INT)) { | ||
1577 | serial8250_handle_port(up); | ||
1578 | return 1; | ||
1579 | } | ||
1580 | |||
1581 | return 0; | ||
1582 | } | 1555 | } |
1583 | EXPORT_SYMBOL_GPL(serial8250_handle_irq); | 1556 | EXPORT_SYMBOL_GPL(serial8250_handle_irq); |
1584 | 1557 | ||
@@ -1619,11 +1592,13 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) | |||
1619 | do { | 1592 | do { |
1620 | struct uart_8250_port *up; | 1593 | struct uart_8250_port *up; |
1621 | struct uart_port *port; | 1594 | struct uart_port *port; |
1595 | bool skip; | ||
1622 | 1596 | ||
1623 | up = list_entry(l, struct uart_8250_port, list); | 1597 | up = list_entry(l, struct uart_8250_port, list); |
1624 | port = &up->port; | 1598 | port = &up->port; |
1599 | skip = pass_counter && up->port.flags & UPF_IIR_ONCE; | ||
1625 | 1600 | ||
1626 | if (port->handle_irq(port)) { | 1601 | if (!skip && port->handle_irq(port)) { |
1627 | handled = 1; | 1602 | handled = 1; |
1628 | end = NULL; | 1603 | end = NULL; |
1629 | } else if (end == NULL) | 1604 | } else if (end == NULL) |
@@ -1758,11 +1733,8 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up) | |||
1758 | static void serial8250_timeout(unsigned long data) | 1733 | static void serial8250_timeout(unsigned long data) |
1759 | { | 1734 | { |
1760 | struct uart_8250_port *up = (struct uart_8250_port *)data; | 1735 | struct uart_8250_port *up = (struct uart_8250_port *)data; |
1761 | unsigned int iir; | ||
1762 | 1736 | ||
1763 | iir = serial_in(up, UART_IIR); | 1737 | up->port.handle_irq(&up->port); |
1764 | if (!(iir & UART_IIR_NO_INT)) | ||
1765 | serial8250_handle_port(up); | ||
1766 | mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port)); | 1738 | mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port)); |
1767 | } | 1739 | } |
1768 | 1740 | ||
@@ -1801,7 +1773,7 @@ static void serial8250_backup_timeout(unsigned long data) | |||
1801 | } | 1773 | } |
1802 | 1774 | ||
1803 | if (!(iir & UART_IIR_NO_INT)) | 1775 | if (!(iir & UART_IIR_NO_INT)) |
1804 | transmit_chars(up); | 1776 | serial8250_tx_chars(up); |
1805 | 1777 | ||
1806 | if (is_real_interrupt(up->port.irq)) | 1778 | if (is_real_interrupt(up->port.irq)) |
1807 | serial_out(up, UART_IER, ier); | 1779 | serial_out(up, UART_IER, ier); |
@@ -1835,7 +1807,7 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port) | |||
1835 | unsigned int status; | 1807 | unsigned int status; |
1836 | unsigned int ret; | 1808 | unsigned int ret; |
1837 | 1809 | ||
1838 | status = check_modem_status(up); | 1810 | status = serial8250_modem_status(up); |
1839 | 1811 | ||
1840 | ret = 0; | 1812 | ret = 0; |
1841 | if (status & UART_MSR_DCD) | 1813 | if (status & UART_MSR_DCD) |
@@ -2000,7 +1972,7 @@ static int serial8250_startup(struct uart_port *port) | |||
2000 | serial_outp(up, UART_IER, 0); | 1972 | serial_outp(up, UART_IER, 0); |
2001 | serial_outp(up, UART_LCR, 0); | 1973 | serial_outp(up, UART_LCR, 0); |
2002 | serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ | 1974 | serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ |
2003 | serial_outp(up, UART_LCR, 0xBF); | 1975 | serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); |
2004 | serial_outp(up, UART_EFR, UART_EFR_ECB); | 1976 | serial_outp(up, UART_EFR, UART_EFR_ECB); |
2005 | serial_outp(up, UART_LCR, 0); | 1977 | serial_outp(up, UART_LCR, 0); |
2006 | } | 1978 | } |
@@ -2848,7 +2820,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) | |||
2848 | 2820 | ||
2849 | local_irq_save(flags); | 2821 | local_irq_save(flags); |
2850 | if (up->port.sysrq) { | 2822 | if (up->port.sysrq) { |
2851 | /* serial8250_handle_port() already took the lock */ | 2823 | /* serial8250_handle_irq() already took the lock */ |
2852 | locked = 0; | 2824 | locked = 0; |
2853 | } else if (oops_in_progress) { | 2825 | } else if (oops_in_progress) { |
2854 | locked = spin_trylock(&up->port.lock); | 2826 | locked = spin_trylock(&up->port.lock); |
@@ -2882,7 +2854,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) | |||
2882 | * while processing with interrupts off. | 2854 | * while processing with interrupts off. |
2883 | */ | 2855 | */ |
2884 | if (up->msr_saved_flags) | 2856 | if (up->msr_saved_flags) |
2885 | check_modem_status(up); | 2857 | serial8250_modem_status(up); |
2886 | 2858 | ||
2887 | if (locked) | 2859 | if (locked) |
2888 | spin_unlock(&up->port.lock); | 2860 | spin_unlock(&up->port.lock); |
diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250.h index 6edf4a6a22d4..ae027be57e25 100644 --- a/drivers/tty/serial/8250.h +++ b/drivers/tty/serial/8250.h | |||
@@ -13,6 +13,32 @@ | |||
13 | 13 | ||
14 | #include <linux/serial_8250.h> | 14 | #include <linux/serial_8250.h> |
15 | 15 | ||
16 | struct uart_8250_port { | ||
17 | struct uart_port port; | ||
18 | struct timer_list timer; /* "no irq" timer */ | ||
19 | struct list_head list; /* ports on this IRQ */ | ||
20 | unsigned short capabilities; /* port capabilities */ | ||
21 | unsigned short bugs; /* port bugs */ | ||
22 | unsigned int tx_loadsz; /* transmit fifo load size */ | ||
23 | unsigned char acr; | ||
24 | unsigned char ier; | ||
25 | unsigned char lcr; | ||
26 | unsigned char mcr; | ||
27 | unsigned char mcr_mask; /* mask of user bits */ | ||
28 | unsigned char mcr_force; /* mask of forced bits */ | ||
29 | unsigned char cur_iotype; /* Running I/O type */ | ||
30 | |||
31 | /* | ||
32 | * Some bits in registers are cleared on a read, so they must | ||
33 | * be saved whenever the register is read but the bits will not | ||
34 | * be immediately processed. | ||
35 | */ | ||
36 | #define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS | ||
37 | unsigned char lsr_saved_flags; | ||
38 | #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA | ||
39 | unsigned char msr_saved_flags; | ||
40 | }; | ||
41 | |||
16 | struct old_serial_port { | 42 | struct old_serial_port { |
17 | unsigned int uart; | 43 | unsigned int uart; |
18 | unsigned int baud_base; | 44 | unsigned int baud_base; |
diff --git a/drivers/tty/serial/8250_dw.c b/drivers/tty/serial/8250_dw.c index bf1fba640c2d..f574eef3075f 100644 --- a/drivers/tty/serial/8250_dw.c +++ b/drivers/tty/serial/8250_dw.c | |||
@@ -177,17 +177,7 @@ static struct platform_driver dw8250_platform_driver = { | |||
177 | .remove = __devexit_p(dw8250_remove), | 177 | .remove = __devexit_p(dw8250_remove), |
178 | }; | 178 | }; |
179 | 179 | ||
180 | static int __init dw8250_init(void) | 180 | module_platform_driver(dw8250_platform_driver); |
181 | { | ||
182 | return platform_driver_register(&dw8250_platform_driver); | ||
183 | } | ||
184 | module_init(dw8250_init); | ||
185 | |||
186 | static void __exit dw8250_exit(void) | ||
187 | { | ||
188 | platform_driver_unregister(&dw8250_platform_driver); | ||
189 | } | ||
190 | module_exit(dw8250_exit); | ||
191 | 181 | ||
192 | MODULE_AUTHOR("Jamie Iles"); | 182 | MODULE_AUTHOR("Jamie Iles"); |
193 | MODULE_LICENSE("GPL"); | 183 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/tty/serial/8250_fsl.c b/drivers/tty/serial/8250_fsl.c new file mode 100644 index 000000000000..f4d3c47b88e8 --- /dev/null +++ b/drivers/tty/serial/8250_fsl.c | |||
@@ -0,0 +1,63 @@ | |||
1 | #include <linux/serial_reg.h> | ||
2 | #include <linux/serial_8250.h> | ||
3 | |||
4 | #include "8250.h" | ||
5 | |||
6 | /* | ||
7 | * Freescale 16550 UART "driver", Copyright (C) 2011 Paul Gortmaker. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This isn't a full driver; it just provides an alternate IRQ | ||
14 | * handler to deal with an errata. Everything else is just | ||
15 | * using the bog standard 8250 support. | ||
16 | * | ||
17 | * We follow code flow of serial8250_default_handle_irq() but add | ||
18 | * a check for a break and insert a dummy read on the Rx for the | ||
19 | * immediately following IRQ event. | ||
20 | * | ||
21 | * We re-use the already existing "bug handling" lsr_saved_flags | ||
22 | * field to carry the "what we just did" information from the one | ||
23 | * IRQ event to the next one. | ||
24 | */ | ||
25 | |||
26 | int fsl8250_handle_irq(struct uart_port *port) | ||
27 | { | ||
28 | unsigned char lsr, orig_lsr; | ||
29 | unsigned long flags; | ||
30 | unsigned int iir; | ||
31 | struct uart_8250_port *up = | ||
32 | container_of(port, struct uart_8250_port, port); | ||
33 | |||
34 | spin_lock_irqsave(&up->port.lock, flags); | ||
35 | |||
36 | iir = port->serial_in(port, UART_IIR); | ||
37 | if (iir & UART_IIR_NO_INT) { | ||
38 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | /* This is the WAR; if last event was BRK, then read and return */ | ||
43 | if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) { | ||
44 | up->lsr_saved_flags &= ~UART_LSR_BI; | ||
45 | port->serial_in(port, UART_RX); | ||
46 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
47 | return 1; | ||
48 | } | ||
49 | |||
50 | lsr = orig_lsr = up->port.serial_in(&up->port, UART_LSR); | ||
51 | |||
52 | if (lsr & (UART_LSR_DR | UART_LSR_BI)) | ||
53 | lsr = serial8250_rx_chars(up, lsr); | ||
54 | |||
55 | serial8250_modem_status(up); | ||
56 | |||
57 | if (lsr & UART_LSR_THRE) | ||
58 | serial8250_tx_chars(up); | ||
59 | |||
60 | up->lsr_saved_flags = orig_lsr; | ||
61 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
62 | return 1; | ||
63 | } | ||
diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c index 825937a5f210..da2b0b0a183f 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c | |||
@@ -1092,6 +1092,14 @@ static int skip_tx_en_setup(struct serial_private *priv, | |||
1092 | return pci_default_setup(priv, board, port, idx); | 1092 | return pci_default_setup(priv, board, port, idx); |
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | static int kt_serial_setup(struct serial_private *priv, | ||
1096 | const struct pciserial_board *board, | ||
1097 | struct uart_port *port, int idx) | ||
1098 | { | ||
1099 | port->flags |= UPF_IIR_ONCE; | ||
1100 | return skip_tx_en_setup(priv, board, port, idx); | ||
1101 | } | ||
1102 | |||
1095 | static int pci_eg20t_init(struct pci_dev *dev) | 1103 | static int pci_eg20t_init(struct pci_dev *dev) |
1096 | { | 1104 | { |
1097 | #if defined(CONFIG_SERIAL_PCH_UART) || defined(CONFIG_SERIAL_PCH_UART_MODULE) | 1105 | #if defined(CONFIG_SERIAL_PCH_UART) || defined(CONFIG_SERIAL_PCH_UART_MODULE) |
@@ -1110,7 +1118,18 @@ pci_xr17c154_setup(struct serial_private *priv, | |||
1110 | return pci_default_setup(priv, board, port, idx); | 1118 | return pci_default_setup(priv, board, port, idx); |
1111 | } | 1119 | } |
1112 | 1120 | ||
1113 | /* This should be in linux/pci_ids.h */ | 1121 | static int try_enable_msi(struct pci_dev *dev) |
1122 | { | ||
1123 | /* use msi if available, but fallback to legacy otherwise */ | ||
1124 | pci_enable_msi(dev); | ||
1125 | return 0; | ||
1126 | } | ||
1127 | |||
1128 | static void disable_msi(struct pci_dev *dev) | ||
1129 | { | ||
1130 | pci_disable_msi(dev); | ||
1131 | } | ||
1132 | |||
1114 | #define PCI_VENDOR_ID_SBSMODULARIO 0x124B | 1133 | #define PCI_VENDOR_ID_SBSMODULARIO 0x124B |
1115 | #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B | 1134 | #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B |
1116 | #define PCI_DEVICE_ID_OCTPRO 0x0001 | 1135 | #define PCI_DEVICE_ID_OCTPRO 0x0001 |
@@ -1133,9 +1152,14 @@ pci_xr17c154_setup(struct serial_private *priv, | |||
1133 | #define PCI_DEVICE_ID_TITAN_800E 0xA014 | 1152 | #define PCI_DEVICE_ID_TITAN_800E 0xA014 |
1134 | #define PCI_DEVICE_ID_TITAN_200EI 0xA016 | 1153 | #define PCI_DEVICE_ID_TITAN_200EI 0xA016 |
1135 | #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 | 1154 | #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 |
1155 | #define PCI_DEVICE_ID_TITAN_400V3 0xA310 | ||
1156 | #define PCI_DEVICE_ID_TITAN_410V3 0xA312 | ||
1157 | #define PCI_DEVICE_ID_TITAN_800V3 0xA314 | ||
1158 | #define PCI_DEVICE_ID_TITAN_800V3B 0xA315 | ||
1136 | #define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 | 1159 | #define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 |
1137 | #define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6 | 1160 | #define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6 |
1138 | #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001 | 1161 | #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001 |
1162 | #define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d | ||
1139 | 1163 | ||
1140 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ | 1164 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ |
1141 | #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 | 1165 | #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 |
@@ -1220,6 +1244,15 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
1220 | .subdevice = PCI_ANY_ID, | 1244 | .subdevice = PCI_ANY_ID, |
1221 | .setup = ce4100_serial_setup, | 1245 | .setup = ce4100_serial_setup, |
1222 | }, | 1246 | }, |
1247 | { | ||
1248 | .vendor = PCI_VENDOR_ID_INTEL, | ||
1249 | .device = PCI_DEVICE_ID_INTEL_PATSBURG_KT, | ||
1250 | .subvendor = PCI_ANY_ID, | ||
1251 | .subdevice = PCI_ANY_ID, | ||
1252 | .init = try_enable_msi, | ||
1253 | .setup = kt_serial_setup, | ||
1254 | .exit = disable_msi, | ||
1255 | }, | ||
1223 | /* | 1256 | /* |
1224 | * ITE | 1257 | * ITE |
1225 | */ | 1258 | */ |
@@ -3414,6 +3447,18 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
3414 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI, | 3447 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI, |
3415 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 3448 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
3416 | pbn_oxsemi_2_4000000 }, | 3449 | pbn_oxsemi_2_4000000 }, |
3450 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400V3, | ||
3451 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
3452 | pbn_b0_4_921600 }, | ||
3453 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_410V3, | ||
3454 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
3455 | pbn_b0_4_921600 }, | ||
3456 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3, | ||
3457 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
3458 | pbn_b0_4_921600 }, | ||
3459 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3B, | ||
3460 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
3461 | pbn_b0_4_921600 }, | ||
3417 | 3462 | ||
3418 | { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550, | 3463 | { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550, |
3419 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 3464 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 95b21a619900..f32a2ea70100 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
@@ -97,6 +97,11 @@ config SERIAL_8250_PNP | |||
97 | This builds standard PNP serial support. You may be able to | 97 | This builds standard PNP serial support. You may be able to |
98 | disable this feature if you only need legacy serial support. | 98 | disable this feature if you only need legacy serial support. |
99 | 99 | ||
100 | config SERIAL_8250_FSL | ||
101 | bool | ||
102 | depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550 | ||
103 | default PPC | ||
104 | |||
100 | config SERIAL_8250_HP300 | 105 | config SERIAL_8250_HP300 |
101 | tristate | 106 | tristate |
102 | depends on SERIAL_8250 && HP300 | 107 | depends on SERIAL_8250 && HP300 |
@@ -457,7 +462,7 @@ config SERIAL_SAMSUNG | |||
457 | config SERIAL_SAMSUNG_UARTS_4 | 462 | config SERIAL_SAMSUNG_UARTS_4 |
458 | bool | 463 | bool |
459 | depends on ARM && PLAT_SAMSUNG | 464 | depends on ARM && PLAT_SAMSUNG |
460 | default y if CPU_S3C2443 | 465 | default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442) |
461 | help | 466 | help |
462 | Internal node for the common case of 4 Samsung compatible UARTs | 467 | Internal node for the common case of 4 Samsung compatible UARTs |
463 | 468 | ||
@@ -465,7 +470,7 @@ config SERIAL_SAMSUNG_UARTS | |||
465 | int | 470 | int |
466 | depends on ARM && PLAT_SAMSUNG | 471 | depends on ARM && PLAT_SAMSUNG |
467 | default 6 if ARCH_S5P6450 | 472 | default 6 if ARCH_S5P6450 |
468 | default 4 if SERIAL_SAMSUNG_UARTS_4 | 473 | default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416 |
469 | default 3 | 474 | default 3 |
470 | help | 475 | help |
471 | Select the number of available UART ports for the Samsung S3C | 476 | Select the number of available UART ports for the Samsung S3C |
@@ -495,46 +500,27 @@ config SERIAL_SAMSUNG_CONSOLE | |||
495 | your boot loader about how to pass options to the kernel at | 500 | your boot loader about how to pass options to the kernel at |
496 | boot time.) | 501 | boot time.) |
497 | 502 | ||
498 | config SERIAL_S3C2410 | 503 | config SERIAL_SIRFSOC |
499 | tristate "Samsung S3C2410 Serial port support" | 504 | tristate "SiRF SoC Platform Serial port support" |
500 | depends on SERIAL_SAMSUNG && CPU_S3C2410 | 505 | depends on ARM && ARCH_PRIMA2 |
501 | default y if CPU_S3C2410 | 506 | select SERIAL_CORE |
502 | help | 507 | help |
503 | Serial port support for the Samsung S3C2410 SoC | 508 | Support for the on-chip UART on the CSR SiRFprimaII series, |
504 | 509 | providing /dev/ttySiRF0, 1 and 2 (note, some machines may not | |
505 | config SERIAL_S3C2412 | 510 | provide all of these ports, depending on how the serial port |
506 | tristate "Samsung S3C2412/S3C2413 Serial port support" | 511 | pins are configured). |
507 | depends on SERIAL_SAMSUNG && CPU_S3C2412 | 512 | |
508 | default y if CPU_S3C2412 | 513 | config SERIAL_SIRFSOC_CONSOLE |
509 | help | 514 | bool "Support for console on SiRF SoC serial port" |
510 | Serial port support for the Samsung S3C2412 and S3C2413 SoC | 515 | depends on SERIAL_SIRFSOC=y |
511 | 516 | select SERIAL_CORE_CONSOLE | |
512 | config SERIAL_S3C2440 | 517 | help |
513 | tristate "Samsung S3C2440/S3C2442/S3C2416 Serial port support" | 518 | Even if you say Y here, the currently visible virtual console |
514 | depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442 || CPU_S3C2416) | 519 | (/dev/tty0) will still be used as the system console by default, but |
515 | default y if CPU_S3C2440 | 520 | you can alter that using a kernel command line option such as |
516 | default y if CPU_S3C2442 | 521 | "console=ttySiRFx". (Try "man bootparam" or see the documentation of |
517 | select SERIAL_SAMSUNG_UARTS_4 if CPU_S3C2416 | 522 | your boot loader about how to pass options to the kernel at |
518 | help | 523 | boot time.) |
519 | Serial port support for the Samsung S3C2440, S3C2416 and S3C2442 SoC | ||
520 | |||
521 | config SERIAL_S3C6400 | ||
522 | tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support" | ||
523 | depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100) | ||
524 | select SERIAL_SAMSUNG_UARTS_4 | ||
525 | default y | ||
526 | help | ||
527 | Serial port support for the Samsung S3C6400, S3C6410, S5P6440, S5P6450 | ||
528 | and S5PC100 SoCs | ||
529 | |||
530 | config SERIAL_S5PV210 | ||
531 | tristate "Samsung S5PV210 Serial port support" | ||
532 | depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_EXYNOS4210 || SOC_EXYNOS4212) | ||
533 | select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210 || SOC_EXYNOS4212) | ||
534 | default y | ||
535 | help | ||
536 | Serial port support for Samsung's S5P Family of SoC's | ||
537 | |||
538 | 524 | ||
539 | config SERIAL_MAX3100 | 525 | config SERIAL_MAX3100 |
540 | tristate "MAX3100 support" | 526 | tristate "MAX3100 support" |
@@ -1324,7 +1310,7 @@ config SERIAL_OF_PLATFORM | |||
1324 | 1310 | ||
1325 | config SERIAL_OMAP | 1311 | config SERIAL_OMAP |
1326 | tristate "OMAP serial port support" | 1312 | tristate "OMAP serial port support" |
1327 | depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4 | 1313 | depends on ARCH_OMAP2PLUS |
1328 | select SERIAL_CORE | 1314 | select SERIAL_CORE |
1329 | help | 1315 | help |
1330 | If you have a machine based on an Texas Instruments OMAP CPU you | 1316 | If you have a machine based on an Texas Instruments OMAP CPU you |
@@ -1575,6 +1561,15 @@ config SERIAL_PCH_UART | |||
1575 | ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. | 1561 | ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. |
1576 | ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH. | 1562 | ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH. |
1577 | 1563 | ||
1564 | config SERIAL_PCH_UART_CONSOLE | ||
1565 | bool "Support for console on Intel EG20T PCH UART/OKI SEMICONDUCTOR ML7213 IOH" | ||
1566 | depends on SERIAL_PCH_UART=y | ||
1567 | select SERIAL_CORE_CONSOLE | ||
1568 | help | ||
1569 | Say Y here if you wish to use the PCH UART as the system console | ||
1570 | (the system console is the device which receives all kernel messages and | ||
1571 | warnings and which allows logins in single user mode). | ||
1572 | |||
1578 | config SERIAL_MSM_SMD | 1573 | config SERIAL_MSM_SMD |
1579 | bool "Enable tty device interface for some SMD ports" | 1574 | bool "Enable tty device interface for some SMD ports" |
1580 | default n | 1575 | default n |
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index e10cf5b54b6d..07e0494c6830 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile | |||
@@ -28,6 +28,7 @@ obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o | |||
28 | obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o | 28 | obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o |
29 | obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o | 29 | obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o |
30 | obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o | 30 | obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o |
31 | obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o | ||
31 | obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o | 32 | obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o |
32 | obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o | 33 | obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o |
33 | obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o | 34 | obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o |
@@ -39,11 +40,6 @@ obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o | |||
39 | obj-$(CONFIG_SERIAL_BFIN) += bfin_uart.o | 40 | obj-$(CONFIG_SERIAL_BFIN) += bfin_uart.o |
40 | obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o | 41 | obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o |
41 | obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o | 42 | obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o |
42 | obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o | ||
43 | obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o | ||
44 | obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o | ||
45 | obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o | ||
46 | obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o | ||
47 | obj-$(CONFIG_SERIAL_MAX3100) += max3100.o | 43 | obj-$(CONFIG_SERIAL_MAX3100) += max3100.o |
48 | obj-$(CONFIG_SERIAL_MAX3107) += max3107.o | 44 | obj-$(CONFIG_SERIAL_MAX3107) += max3107.o |
49 | obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o | 45 | obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o |
@@ -94,3 +90,4 @@ obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o | |||
94 | obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o | 90 | obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o |
95 | obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o | 91 | obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o |
96 | obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o | 92 | obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o |
93 | obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o | ||
diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c index 77554fd68d1f..7162f70d9260 100644 --- a/drivers/tty/serial/apbuart.c +++ b/drivers/tty/serial/apbuart.c | |||
@@ -577,7 +577,7 @@ static int __devinit apbuart_probe(struct platform_device *op) | |||
577 | return 0; | 577 | return 0; |
578 | } | 578 | } |
579 | 579 | ||
580 | static struct of_device_id __initdata apbuart_match[] = { | 580 | static struct of_device_id apbuart_match[] = { |
581 | { | 581 | { |
582 | .name = "GAISLER_APBUART", | 582 | .name = "GAISLER_APBUART", |
583 | }, | 583 | }, |
@@ -597,7 +597,7 @@ static struct platform_driver grlib_apbuart_of_driver = { | |||
597 | }; | 597 | }; |
598 | 598 | ||
599 | 599 | ||
600 | static int grlib_apbuart_configure(void) | 600 | static int __init grlib_apbuart_configure(void) |
601 | { | 601 | { |
602 | struct device_node *np; | 602 | struct device_node *np; |
603 | int line = 0; | 603 | int line = 0; |
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 4c823f341d98..10605ecc99ab 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
@@ -212,8 +212,9 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) | |||
212 | { | 212 | { |
213 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | 213 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
214 | unsigned int mode; | 214 | unsigned int mode; |
215 | unsigned long flags; | ||
215 | 216 | ||
216 | spin_lock(&port->lock); | 217 | spin_lock_irqsave(&port->lock, flags); |
217 | 218 | ||
218 | /* Disable interrupts */ | 219 | /* Disable interrupts */ |
219 | UART_PUT_IDR(port, atmel_port->tx_done_mask); | 220 | UART_PUT_IDR(port, atmel_port->tx_done_mask); |
@@ -244,7 +245,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) | |||
244 | /* Enable interrupts */ | 245 | /* Enable interrupts */ |
245 | UART_PUT_IER(port, atmel_port->tx_done_mask); | 246 | UART_PUT_IER(port, atmel_port->tx_done_mask); |
246 | 247 | ||
247 | spin_unlock(&port->lock); | 248 | spin_unlock_irqrestore(&port->lock, flags); |
248 | 249 | ||
249 | } | 250 | } |
250 | 251 | ||
@@ -1256,12 +1257,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1256 | 1257 | ||
1257 | static void atmel_set_ldisc(struct uart_port *port, int new) | 1258 | static void atmel_set_ldisc(struct uart_port *port, int new) |
1258 | { | 1259 | { |
1259 | int line = port->line; | 1260 | if (new == N_PPS) { |
1260 | |||
1261 | if (line >= port->state->port.tty->driver->num) | ||
1262 | return; | ||
1263 | |||
1264 | if (port->state->port.tty->ldisc->ops->num == N_PPS) { | ||
1265 | port->flags |= UPF_HARDPPS_CD; | 1261 | port->flags |= UPF_HARDPPS_CD; |
1266 | atmel_enable_ms(port); | 1262 | atmel_enable_ms(port); |
1267 | } else { | 1263 | } else { |
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c index ee101c0d358f..7fbc3a08f10d 100644 --- a/drivers/tty/serial/bfin_sport_uart.c +++ b/drivers/tty/serial/bfin_sport_uart.c | |||
@@ -299,8 +299,13 @@ static int sport_startup(struct uart_port *port) | |||
299 | dev_info(port->dev, "Unable to attach BlackFin UART over SPORT CTS interrupt. So, disable it.\n"); | 299 | dev_info(port->dev, "Unable to attach BlackFin UART over SPORT CTS interrupt. So, disable it.\n"); |
300 | } | 300 | } |
301 | } | 301 | } |
302 | if (up->rts_pin >= 0) | 302 | if (up->rts_pin >= 0) { |
303 | gpio_direction_output(up->rts_pin, 0); | 303 | if (gpio_request(up->rts_pin, DRV_NAME)) { |
304 | dev_info(port->dev, "fail to request RTS PIN at GPIO_%d\n", up->rts_pin); | ||
305 | up->rts_pin = -1; | ||
306 | } else | ||
307 | gpio_direction_output(up->rts_pin, 0); | ||
308 | } | ||
304 | #endif | 309 | #endif |
305 | 310 | ||
306 | return 0; | 311 | return 0; |
@@ -445,6 +450,8 @@ static void sport_shutdown(struct uart_port *port) | |||
445 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS | 450 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS |
446 | if (up->cts_pin >= 0) | 451 | if (up->cts_pin >= 0) |
447 | free_irq(gpio_to_irq(up->cts_pin), up); | 452 | free_irq(gpio_to_irq(up->cts_pin), up); |
453 | if (up->rts_pin >= 0) | ||
454 | gpio_free(up->rts_pin); | ||
448 | #endif | 455 | #endif |
449 | } | 456 | } |
450 | 457 | ||
@@ -803,17 +810,16 @@ static int __devinit sport_uart_probe(struct platform_device *pdev) | |||
803 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 810 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
804 | if (res == NULL) | 811 | if (res == NULL) |
805 | sport->cts_pin = -1; | 812 | sport->cts_pin = -1; |
806 | else | 813 | else { |
807 | sport->cts_pin = res->start; | 814 | sport->cts_pin = res->start; |
815 | sport->port.flags |= ASYNC_CTS_FLOW; | ||
816 | } | ||
808 | 817 | ||
809 | res = platform_get_resource(pdev, IORESOURCE_IO, 1); | 818 | res = platform_get_resource(pdev, IORESOURCE_IO, 1); |
810 | if (res == NULL) | 819 | if (res == NULL) |
811 | sport->rts_pin = -1; | 820 | sport->rts_pin = -1; |
812 | else | 821 | else |
813 | sport->rts_pin = res->start; | 822 | sport->rts_pin = res->start; |
814 | |||
815 | if (sport->rts_pin >= 0) | ||
816 | gpio_request(sport->rts_pin, DRV_NAME); | ||
817 | #endif | 823 | #endif |
818 | } | 824 | } |
819 | 825 | ||
@@ -853,10 +859,6 @@ static int __devexit sport_uart_remove(struct platform_device *pdev) | |||
853 | 859 | ||
854 | if (sport) { | 860 | if (sport) { |
855 | uart_remove_one_port(&sport_uart_reg, &sport->port); | 861 | uart_remove_one_port(&sport_uart_reg, &sport->port); |
856 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | ||
857 | if (sport->rts_pin >= 0) | ||
858 | gpio_free(sport->rts_pin); | ||
859 | #endif | ||
860 | iounmap(sport->port.membase); | 862 | iounmap(sport->port.membase); |
861 | peripheral_free_list( | 863 | peripheral_free_list( |
862 | (unsigned short *)pdev->dev.platform_data); | 864 | (unsigned short *)pdev->dev.platform_data); |
diff --git a/drivers/tty/serial/bfin_sport_uart.h b/drivers/tty/serial/bfin_sport_uart.h index 6d06ce1d5675..e4510ea135ce 100644 --- a/drivers/tty/serial/bfin_sport_uart.h +++ b/drivers/tty/serial/bfin_sport_uart.h | |||
@@ -45,11 +45,12 @@ | |||
45 | #define SPORT_GET_RX32(sport) \ | 45 | #define SPORT_GET_RX32(sport) \ |
46 | ({ \ | 46 | ({ \ |
47 | unsigned int __ret; \ | 47 | unsigned int __ret; \ |
48 | unsigned long flags; \ | ||
48 | if (ANOMALY_05000473) \ | 49 | if (ANOMALY_05000473) \ |
49 | local_irq_disable(); \ | 50 | local_irq_save(flags); \ |
50 | __ret = bfin_read32((sport)->port.membase + OFFSET_RX); \ | 51 | __ret = bfin_read32((sport)->port.membase + OFFSET_RX); \ |
51 | if (ANOMALY_05000473) \ | 52 | if (ANOMALY_05000473) \ |
52 | local_irq_enable(); \ | 53 | local_irq_restore(flags); \ |
53 | __ret; \ | 54 | __ret; \ |
54 | }) | 55 | }) |
55 | #define SPORT_GET_RCR1(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR1)) | 56 | #define SPORT_GET_RCR1(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR1)) |
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 66afb98b77b5..26953bfa6922 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c | |||
@@ -116,15 +116,22 @@ static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
116 | static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id) | 116 | static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id) |
117 | { | 117 | { |
118 | struct bfin_serial_port *uart = dev_id; | 118 | struct bfin_serial_port *uart = dev_id; |
119 | unsigned int status; | 119 | unsigned int status = bfin_serial_get_mctrl(&uart->port); |
120 | |||
121 | status = bfin_serial_get_mctrl(&uart->port); | ||
122 | uart_handle_cts_change(&uart->port, status & TIOCM_CTS); | ||
123 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS | 120 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS |
124 | uart->scts = 1; | 121 | struct tty_struct *tty = uart->port.state->port.tty; |
122 | |||
125 | UART_CLEAR_SCTS(uart); | 123 | UART_CLEAR_SCTS(uart); |
126 | UART_CLEAR_IER(uart, EDSSI); | 124 | if (tty->hw_stopped) { |
125 | if (status) { | ||
126 | tty->hw_stopped = 0; | ||
127 | uart_write_wakeup(&uart->port); | ||
128 | } | ||
129 | } else { | ||
130 | if (!status) | ||
131 | tty->hw_stopped = 1; | ||
132 | } | ||
127 | #endif | 133 | #endif |
134 | uart_handle_cts_change(&uart->port, status & TIOCM_CTS); | ||
128 | 135 | ||
129 | return IRQ_HANDLED; | 136 | return IRQ_HANDLED; |
130 | } | 137 | } |
@@ -175,13 +182,6 @@ static void bfin_serial_start_tx(struct uart_port *port) | |||
175 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | 182 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; |
176 | struct tty_struct *tty = uart->port.state->port.tty; | 183 | struct tty_struct *tty = uart->port.state->port.tty; |
177 | 184 | ||
178 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS | ||
179 | if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) { | ||
180 | uart->scts = 0; | ||
181 | uart_handle_cts_change(&uart->port, uart->scts); | ||
182 | } | ||
183 | #endif | ||
184 | |||
185 | /* | 185 | /* |
186 | * To avoid losting RX interrupt, we reset IR function | 186 | * To avoid losting RX interrupt, we reset IR function |
187 | * before sending data. | 187 | * before sending data. |
@@ -380,12 +380,6 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id) | |||
380 | { | 380 | { |
381 | struct bfin_serial_port *uart = dev_id; | 381 | struct bfin_serial_port *uart = dev_id; |
382 | 382 | ||
383 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS | ||
384 | if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) { | ||
385 | uart->scts = 0; | ||
386 | uart_handle_cts_change(&uart->port, uart->scts); | ||
387 | } | ||
388 | #endif | ||
389 | spin_lock(&uart->port.lock); | 383 | spin_lock(&uart->port.lock); |
390 | if (UART_GET_LSR(uart) & THRE) | 384 | if (UART_GET_LSR(uart) & THRE) |
391 | bfin_serial_tx_chars(uart); | 385 | bfin_serial_tx_chars(uart); |
@@ -531,13 +525,6 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id) | |||
531 | struct bfin_serial_port *uart = dev_id; | 525 | struct bfin_serial_port *uart = dev_id; |
532 | struct circ_buf *xmit = &uart->port.state->xmit; | 526 | struct circ_buf *xmit = &uart->port.state->xmit; |
533 | 527 | ||
534 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS | ||
535 | if (uart->scts && !(bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) { | ||
536 | uart->scts = 0; | ||
537 | uart_handle_cts_change(&uart->port, uart->scts); | ||
538 | } | ||
539 | #endif | ||
540 | |||
541 | spin_lock(&uart->port.lock); | 528 | spin_lock(&uart->port.lock); |
542 | if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) { | 529 | if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) { |
543 | disable_dma(uart->tx_dma_channel); | 530 | disable_dma(uart->tx_dma_channel); |
@@ -739,20 +726,26 @@ static int bfin_serial_startup(struct uart_port *port) | |||
739 | pr_info("Unable to attach BlackFin UART CTS interrupt. So, disable it.\n"); | 726 | pr_info("Unable to attach BlackFin UART CTS interrupt. So, disable it.\n"); |
740 | } | 727 | } |
741 | } | 728 | } |
742 | if (uart->rts_pin >= 0) | 729 | if (uart->rts_pin >= 0) { |
743 | gpio_direction_output(uart->rts_pin, 0); | 730 | if (gpio_request(uart->rts_pin, DRIVER_NAME)) { |
731 | pr_info("fail to request RTS PIN at GPIO_%d\n", uart->rts_pin); | ||
732 | uart->rts_pin = -1; | ||
733 | } else | ||
734 | gpio_direction_output(uart->rts_pin, 0); | ||
735 | } | ||
744 | #endif | 736 | #endif |
745 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS | 737 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS |
746 | if (uart->cts_pin >= 0 && request_irq(uart->status_irq, | 738 | if (uart->cts_pin >= 0) { |
747 | bfin_serial_mctrl_cts_int, | 739 | if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int, |
748 | 0, "BFIN_UART_MODEM_STATUS", uart)) { | 740 | IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) { |
749 | uart->cts_pin = -1; | 741 | uart->cts_pin = -1; |
750 | pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n"); | 742 | dev_info(port->dev, "Unable to attach BlackFin UART Modem Status interrupt.\n"); |
751 | } | 743 | } |
752 | 744 | ||
753 | /* CTS RTS PINs are negative assertive. */ | 745 | /* CTS RTS PINs are negative assertive. */ |
754 | UART_PUT_MCR(uart, ACTS); | 746 | UART_PUT_MCR(uart, ACTS); |
755 | UART_SET_IER(uart, EDSSI); | 747 | UART_SET_IER(uart, EDSSI); |
748 | } | ||
756 | #endif | 749 | #endif |
757 | 750 | ||
758 | UART_SET_IER(uart, ERBFI); | 751 | UART_SET_IER(uart, ERBFI); |
@@ -792,6 +785,8 @@ static void bfin_serial_shutdown(struct uart_port *port) | |||
792 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | 785 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS |
793 | if (uart->cts_pin >= 0) | 786 | if (uart->cts_pin >= 0) |
794 | free_irq(gpio_to_irq(uart->cts_pin), uart); | 787 | free_irq(gpio_to_irq(uart->cts_pin), uart); |
788 | if (uart->rts_pin >= 0) | ||
789 | gpio_free(uart->rts_pin); | ||
795 | #endif | 790 | #endif |
796 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS | 791 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS |
797 | if (uart->cts_pin >= 0) | 792 | if (uart->cts_pin >= 0) |
@@ -1370,18 +1365,18 @@ static int bfin_serial_probe(struct platform_device *pdev) | |||
1370 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1365 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
1371 | if (res == NULL) | 1366 | if (res == NULL) |
1372 | uart->cts_pin = -1; | 1367 | uart->cts_pin = -1; |
1373 | else | 1368 | else { |
1374 | uart->cts_pin = res->start; | 1369 | uart->cts_pin = res->start; |
1370 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | ||
1371 | uart->port.flags |= ASYNC_CTS_FLOW; | ||
1372 | #endif | ||
1373 | } | ||
1375 | 1374 | ||
1376 | res = platform_get_resource(pdev, IORESOURCE_IO, 1); | 1375 | res = platform_get_resource(pdev, IORESOURCE_IO, 1); |
1377 | if (res == NULL) | 1376 | if (res == NULL) |
1378 | uart->rts_pin = -1; | 1377 | uart->rts_pin = -1; |
1379 | else | 1378 | else |
1380 | uart->rts_pin = res->start; | 1379 | uart->rts_pin = res->start; |
1381 | # if defined(CONFIG_SERIAL_BFIN_CTSRTS) | ||
1382 | if (uart->rts_pin >= 0) | ||
1383 | gpio_request(uart->rts_pin, DRIVER_NAME); | ||
1384 | # endif | ||
1385 | #endif | 1380 | #endif |
1386 | } | 1381 | } |
1387 | 1382 | ||
@@ -1421,10 +1416,6 @@ static int __devexit bfin_serial_remove(struct platform_device *pdev) | |||
1421 | 1416 | ||
1422 | if (uart) { | 1417 | if (uart) { |
1423 | uart_remove_one_port(&bfin_serial_reg, &uart->port); | 1418 | uart_remove_one_port(&bfin_serial_reg, &uart->port); |
1424 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | ||
1425 | if (uart->rts_pin >= 0) | ||
1426 | gpio_free(uart->rts_pin); | ||
1427 | #endif | ||
1428 | iounmap(uart->port.membase); | 1419 | iounmap(uart->port.membase); |
1429 | peripheral_free_list( | 1420 | peripheral_free_list( |
1430 | (unsigned short *)pdev->dev.platform_data); | 1421 | (unsigned short *)pdev->dev.platform_data); |
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 426434e5eb7c..7e925e20cbaa 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c | |||
@@ -1334,7 +1334,6 @@ MODULE_DEVICE_TABLE(spi, ifx_id_table); | |||
1334 | static const struct spi_driver ifx_spi_driver = { | 1334 | static const struct spi_driver ifx_spi_driver = { |
1335 | .driver = { | 1335 | .driver = { |
1336 | .name = DRVNAME, | 1336 | .name = DRVNAME, |
1337 | .bus = &spi_bus_type, | ||
1338 | .pm = &ifx_spi_pm, | 1337 | .pm = &ifx_spi_pm, |
1339 | .owner = THIS_MODULE}, | 1338 | .owner = THIS_MODULE}, |
1340 | .probe = ifx_spi_spi_probe, | 1339 | .probe = ifx_spi_spi_probe, |
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 163fc9021f5a..0b7fed746b27 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c | |||
@@ -102,6 +102,7 @@ | |||
102 | #define UCR2_STPB (1<<6) /* Stop */ | 102 | #define UCR2_STPB (1<<6) /* Stop */ |
103 | #define UCR2_WS (1<<5) /* Word size */ | 103 | #define UCR2_WS (1<<5) /* Word size */ |
104 | #define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ | 104 | #define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ |
105 | #define UCR2_ATEN (1<<3) /* Aging Timer Enable */ | ||
105 | #define UCR2_TXEN (1<<2) /* Transmitter enabled */ | 106 | #define UCR2_TXEN (1<<2) /* Transmitter enabled */ |
106 | #define UCR2_RXEN (1<<1) /* Receiver enabled */ | 107 | #define UCR2_RXEN (1<<1) /* Receiver enabled */ |
107 | #define UCR2_SRST (1<<0) /* SW reset */ | 108 | #define UCR2_SRST (1<<0) /* SW reset */ |
@@ -207,6 +208,12 @@ struct imx_port { | |||
207 | struct imx_uart_data *devdata; | 208 | struct imx_uart_data *devdata; |
208 | }; | 209 | }; |
209 | 210 | ||
211 | struct imx_port_ucrs { | ||
212 | unsigned int ucr1; | ||
213 | unsigned int ucr2; | ||
214 | unsigned int ucr3; | ||
215 | }; | ||
216 | |||
210 | #ifdef CONFIG_IRDA | 217 | #ifdef CONFIG_IRDA |
211 | #define USE_IRDA(sport) ((sport)->use_irda) | 218 | #define USE_IRDA(sport) ((sport)->use_irda) |
212 | #else | 219 | #else |
@@ -260,6 +267,27 @@ static inline int is_imx21_uart(struct imx_port *sport) | |||
260 | } | 267 | } |
261 | 268 | ||
262 | /* | 269 | /* |
270 | * Save and restore functions for UCR1, UCR2 and UCR3 registers | ||
271 | */ | ||
272 | static void imx_port_ucrs_save(struct uart_port *port, | ||
273 | struct imx_port_ucrs *ucr) | ||
274 | { | ||
275 | /* save control registers */ | ||
276 | ucr->ucr1 = readl(port->membase + UCR1); | ||
277 | ucr->ucr2 = readl(port->membase + UCR2); | ||
278 | ucr->ucr3 = readl(port->membase + UCR3); | ||
279 | } | ||
280 | |||
281 | static void imx_port_ucrs_restore(struct uart_port *port, | ||
282 | struct imx_port_ucrs *ucr) | ||
283 | { | ||
284 | /* restore control registers */ | ||
285 | writel(ucr->ucr1, port->membase + UCR1); | ||
286 | writel(ucr->ucr2, port->membase + UCR2); | ||
287 | writel(ucr->ucr3, port->membase + UCR3); | ||
288 | } | ||
289 | |||
290 | /* | ||
263 | * Handle any change of modem status signal since we were last called. | 291 | * Handle any change of modem status signal since we were last called. |
264 | */ | 292 | */ |
265 | static void imx_mctrl_check(struct imx_port *sport) | 293 | static void imx_mctrl_check(struct imx_port *sport) |
@@ -566,6 +594,9 @@ static irqreturn_t imx_int(int irq, void *dev_id) | |||
566 | if (sts & USR1_RTSD) | 594 | if (sts & USR1_RTSD) |
567 | imx_rtsint(irq, dev_id); | 595 | imx_rtsint(irq, dev_id); |
568 | 596 | ||
597 | if (sts & USR1_AWAKE) | ||
598 | writel(USR1_AWAKE, sport->port.membase + USR1); | ||
599 | |||
569 | return IRQ_HANDLED; | 600 | return IRQ_HANDLED; |
570 | } | 601 | } |
571 | 602 | ||
@@ -901,6 +932,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, | |||
901 | ucr2 |= UCR2_PROE; | 932 | ucr2 |= UCR2_PROE; |
902 | } | 933 | } |
903 | 934 | ||
935 | del_timer_sync(&sport->timer); | ||
936 | |||
904 | /* | 937 | /* |
905 | * Ask the core to calculate the divisor for us. | 938 | * Ask the core to calculate the divisor for us. |
906 | */ | 939 | */ |
@@ -931,8 +964,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, | |||
931 | sport->port.ignore_status_mask |= URXD_OVRRUN; | 964 | sport->port.ignore_status_mask |= URXD_OVRRUN; |
932 | } | 965 | } |
933 | 966 | ||
934 | del_timer_sync(&sport->timer); | ||
935 | |||
936 | /* | 967 | /* |
937 | * Update the per-port timeout. | 968 | * Update the per-port timeout. |
938 | */ | 969 | */ |
@@ -1079,6 +1110,70 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
1079 | return ret; | 1110 | return ret; |
1080 | } | 1111 | } |
1081 | 1112 | ||
1113 | #if defined(CONFIG_CONSOLE_POLL) | ||
1114 | static int imx_poll_get_char(struct uart_port *port) | ||
1115 | { | ||
1116 | struct imx_port_ucrs old_ucr; | ||
1117 | unsigned int status; | ||
1118 | unsigned char c; | ||
1119 | |||
1120 | /* save control registers */ | ||
1121 | imx_port_ucrs_save(port, &old_ucr); | ||
1122 | |||
1123 | /* disable interrupts */ | ||
1124 | writel(UCR1_UARTEN, port->membase + UCR1); | ||
1125 | writel(old_ucr.ucr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI), | ||
1126 | port->membase + UCR2); | ||
1127 | writel(old_ucr.ucr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN), | ||
1128 | port->membase + UCR3); | ||
1129 | |||
1130 | /* poll */ | ||
1131 | do { | ||
1132 | status = readl(port->membase + USR2); | ||
1133 | } while (~status & USR2_RDR); | ||
1134 | |||
1135 | /* read */ | ||
1136 | c = readl(port->membase + URXD0); | ||
1137 | |||
1138 | /* restore control registers */ | ||
1139 | imx_port_ucrs_restore(port, &old_ucr); | ||
1140 | |||
1141 | return c; | ||
1142 | } | ||
1143 | |||
1144 | static void imx_poll_put_char(struct uart_port *port, unsigned char c) | ||
1145 | { | ||
1146 | struct imx_port_ucrs old_ucr; | ||
1147 | unsigned int status; | ||
1148 | |||
1149 | /* save control registers */ | ||
1150 | imx_port_ucrs_save(port, &old_ucr); | ||
1151 | |||
1152 | /* disable interrupts */ | ||
1153 | writel(UCR1_UARTEN, port->membase + UCR1); | ||
1154 | writel(old_ucr.ucr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI), | ||
1155 | port->membase + UCR2); | ||
1156 | writel(old_ucr.ucr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN), | ||
1157 | port->membase + UCR3); | ||
1158 | |||
1159 | /* drain */ | ||
1160 | do { | ||
1161 | status = readl(port->membase + USR1); | ||
1162 | } while (~status & USR1_TRDY); | ||
1163 | |||
1164 | /* write */ | ||
1165 | writel(c, port->membase + URTX0); | ||
1166 | |||
1167 | /* flush */ | ||
1168 | do { | ||
1169 | status = readl(port->membase + USR2); | ||
1170 | } while (~status & USR2_TXDC); | ||
1171 | |||
1172 | /* restore control registers */ | ||
1173 | imx_port_ucrs_restore(port, &old_ucr); | ||
1174 | } | ||
1175 | #endif | ||
1176 | |||
1082 | static struct uart_ops imx_pops = { | 1177 | static struct uart_ops imx_pops = { |
1083 | .tx_empty = imx_tx_empty, | 1178 | .tx_empty = imx_tx_empty, |
1084 | .set_mctrl = imx_set_mctrl, | 1179 | .set_mctrl = imx_set_mctrl, |
@@ -1096,6 +1191,10 @@ static struct uart_ops imx_pops = { | |||
1096 | .request_port = imx_request_port, | 1191 | .request_port = imx_request_port, |
1097 | .config_port = imx_config_port, | 1192 | .config_port = imx_config_port, |
1098 | .verify_port = imx_verify_port, | 1193 | .verify_port = imx_verify_port, |
1194 | #if defined(CONFIG_CONSOLE_POLL) | ||
1195 | .poll_get_char = imx_poll_get_char, | ||
1196 | .poll_put_char = imx_poll_put_char, | ||
1197 | #endif | ||
1099 | }; | 1198 | }; |
1100 | 1199 | ||
1101 | static struct imx_port *imx_ports[UART_NR]; | 1200 | static struct imx_port *imx_ports[UART_NR]; |
@@ -1118,13 +1217,14 @@ static void | |||
1118 | imx_console_write(struct console *co, const char *s, unsigned int count) | 1217 | imx_console_write(struct console *co, const char *s, unsigned int count) |
1119 | { | 1218 | { |
1120 | struct imx_port *sport = imx_ports[co->index]; | 1219 | struct imx_port *sport = imx_ports[co->index]; |
1121 | unsigned int old_ucr1, old_ucr2, ucr1; | 1220 | struct imx_port_ucrs old_ucr; |
1221 | unsigned int ucr1; | ||
1122 | 1222 | ||
1123 | /* | 1223 | /* |
1124 | * First, save UCR1/2 and then disable interrupts | 1224 | * First, save UCR1/2/3 and then disable interrupts |
1125 | */ | 1225 | */ |
1126 | ucr1 = old_ucr1 = readl(sport->port.membase + UCR1); | 1226 | imx_port_ucrs_save(&sport->port, &old_ucr); |
1127 | old_ucr2 = readl(sport->port.membase + UCR2); | 1227 | ucr1 = old_ucr.ucr1; |
1128 | 1228 | ||
1129 | if (is_imx1_uart(sport)) | 1229 | if (is_imx1_uart(sport)) |
1130 | ucr1 |= IMX1_UCR1_UARTCLKEN; | 1230 | ucr1 |= IMX1_UCR1_UARTCLKEN; |
@@ -1133,18 +1233,17 @@ imx_console_write(struct console *co, const char *s, unsigned int count) | |||
1133 | 1233 | ||
1134 | writel(ucr1, sport->port.membase + UCR1); | 1234 | writel(ucr1, sport->port.membase + UCR1); |
1135 | 1235 | ||
1136 | writel(old_ucr2 | UCR2_TXEN, sport->port.membase + UCR2); | 1236 | writel(old_ucr.ucr2 | UCR2_TXEN, sport->port.membase + UCR2); |
1137 | 1237 | ||
1138 | uart_console_write(&sport->port, s, count, imx_console_putchar); | 1238 | uart_console_write(&sport->port, s, count, imx_console_putchar); |
1139 | 1239 | ||
1140 | /* | 1240 | /* |
1141 | * Finally, wait for transmitter to become empty | 1241 | * Finally, wait for transmitter to become empty |
1142 | * and restore UCR1/2 | 1242 | * and restore UCR1/2/3 |
1143 | */ | 1243 | */ |
1144 | while (!(readl(sport->port.membase + USR2) & USR2_TXDC)); | 1244 | while (!(readl(sport->port.membase + USR2) & USR2_TXDC)); |
1145 | 1245 | ||
1146 | writel(old_ucr1, sport->port.membase + UCR1); | 1246 | imx_port_ucrs_restore(&sport->port, &old_ucr); |
1147 | writel(old_ucr2, sport->port.membase + UCR2); | ||
1148 | } | 1247 | } |
1149 | 1248 | ||
1150 | /* | 1249 | /* |
@@ -1269,6 +1368,12 @@ static struct uart_driver imx_reg = { | |||
1269 | static int serial_imx_suspend(struct platform_device *dev, pm_message_t state) | 1368 | static int serial_imx_suspend(struct platform_device *dev, pm_message_t state) |
1270 | { | 1369 | { |
1271 | struct imx_port *sport = platform_get_drvdata(dev); | 1370 | struct imx_port *sport = platform_get_drvdata(dev); |
1371 | unsigned int val; | ||
1372 | |||
1373 | /* enable wakeup from i.MX UART */ | ||
1374 | val = readl(sport->port.membase + UCR3); | ||
1375 | val |= UCR3_AWAKEN; | ||
1376 | writel(val, sport->port.membase + UCR3); | ||
1272 | 1377 | ||
1273 | if (sport) | 1378 | if (sport) |
1274 | uart_suspend_port(&imx_reg, &sport->port); | 1379 | uart_suspend_port(&imx_reg, &sport->port); |
@@ -1279,6 +1384,12 @@ static int serial_imx_suspend(struct platform_device *dev, pm_message_t state) | |||
1279 | static int serial_imx_resume(struct platform_device *dev) | 1384 | static int serial_imx_resume(struct platform_device *dev) |
1280 | { | 1385 | { |
1281 | struct imx_port *sport = platform_get_drvdata(dev); | 1386 | struct imx_port *sport = platform_get_drvdata(dev); |
1387 | unsigned int val; | ||
1388 | |||
1389 | /* disable wakeup from i.MX UART */ | ||
1390 | val = readl(sport->port.membase + UCR3); | ||
1391 | val &= ~UCR3_AWAKEN; | ||
1392 | writel(val, sport->port.membase + UCR3); | ||
1282 | 1393 | ||
1283 | if (sport) | 1394 | if (sport) |
1284 | uart_resume_port(&imx_reg, &sport->port); | 1395 | uart_resume_port(&imx_reg, &sport->port); |
@@ -1287,6 +1398,10 @@ static int serial_imx_resume(struct platform_device *dev) | |||
1287 | } | 1398 | } |
1288 | 1399 | ||
1289 | #ifdef CONFIG_OF | 1400 | #ifdef CONFIG_OF |
1401 | /* | ||
1402 | * This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it | ||
1403 | * could successfully get all information from dt or a negative errno. | ||
1404 | */ | ||
1290 | static int serial_imx_probe_dt(struct imx_port *sport, | 1405 | static int serial_imx_probe_dt(struct imx_port *sport, |
1291 | struct platform_device *pdev) | 1406 | struct platform_device *pdev) |
1292 | { | 1407 | { |
@@ -1296,12 +1411,13 @@ static int serial_imx_probe_dt(struct imx_port *sport, | |||
1296 | int ret; | 1411 | int ret; |
1297 | 1412 | ||
1298 | if (!np) | 1413 | if (!np) |
1299 | return -ENODEV; | 1414 | /* no device tree device */ |
1415 | return 1; | ||
1300 | 1416 | ||
1301 | ret = of_alias_get_id(np, "serial"); | 1417 | ret = of_alias_get_id(np, "serial"); |
1302 | if (ret < 0) { | 1418 | if (ret < 0) { |
1303 | dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret); | 1419 | dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret); |
1304 | return -ENODEV; | 1420 | return ret; |
1305 | } | 1421 | } |
1306 | sport->port.line = ret; | 1422 | sport->port.line = ret; |
1307 | 1423 | ||
@@ -1319,7 +1435,7 @@ static int serial_imx_probe_dt(struct imx_port *sport, | |||
1319 | static inline int serial_imx_probe_dt(struct imx_port *sport, | 1435 | static inline int serial_imx_probe_dt(struct imx_port *sport, |
1320 | struct platform_device *pdev) | 1436 | struct platform_device *pdev) |
1321 | { | 1437 | { |
1322 | return -ENODEV; | 1438 | return 1; |
1323 | } | 1439 | } |
1324 | #endif | 1440 | #endif |
1325 | 1441 | ||
@@ -1354,8 +1470,10 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
1354 | return -ENOMEM; | 1470 | return -ENOMEM; |
1355 | 1471 | ||
1356 | ret = serial_imx_probe_dt(sport, pdev); | 1472 | ret = serial_imx_probe_dt(sport, pdev); |
1357 | if (ret == -ENODEV) | 1473 | if (ret > 0) |
1358 | serial_imx_probe_pdata(sport, pdev); | 1474 | serial_imx_probe_pdata(sport, pdev); |
1475 | else if (ret < 0) | ||
1476 | goto free; | ||
1359 | 1477 | ||
1360 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1478 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1361 | if (!res) { | 1479 | if (!res) { |
@@ -1476,7 +1594,7 @@ static int __init imx_serial_init(void) | |||
1476 | if (ret != 0) | 1594 | if (ret != 0) |
1477 | uart_unregister_driver(&imx_reg); | 1595 | uart_unregister_driver(&imx_reg); |
1478 | 1596 | ||
1479 | return 0; | 1597 | return ret; |
1480 | } | 1598 | } |
1481 | 1599 | ||
1482 | static void __exit imx_serial_exit(void) | 1600 | static void __exit imx_serial_exit(void) |
diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 08018934e013..94a6792bf97b 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c | |||
@@ -1000,11 +1000,8 @@ static void __init m32r_sio_register_ports(struct uart_driver *drv) | |||
1000 | init_timer(&up->timer); | 1000 | init_timer(&up->timer); |
1001 | up->timer.function = m32r_sio_timeout; | 1001 | up->timer.function = m32r_sio_timeout; |
1002 | 1002 | ||
1003 | /* | 1003 | up->mcr_mask = ~0; |
1004 | * ALPHA_KLUDGE_MCR needs to be killed. | 1004 | up->mcr_force = 0; |
1005 | */ | ||
1006 | up->mcr_mask = ~ALPHA_KLUDGE_MCR; | ||
1007 | up->mcr_force = ALPHA_KLUDGE_MCR; | ||
1008 | 1005 | ||
1009 | uart_add_one_port(drv, &up->port); | 1006 | uart_add_one_port(drv, &up->port); |
1010 | } | 1007 | } |
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index 8a6cc8c30b5a..b4902b99cfd2 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c | |||
@@ -901,7 +901,6 @@ static int max3100_resume(struct spi_device *spi) | |||
901 | static struct spi_driver max3100_driver = { | 901 | static struct spi_driver max3100_driver = { |
902 | .driver = { | 902 | .driver = { |
903 | .name = "max3100", | 903 | .name = "max3100", |
904 | .bus = &spi_bus_type, | ||
905 | .owner = THIS_MODULE, | 904 | .owner = THIS_MODULE, |
906 | }, | 905 | }, |
907 | 906 | ||
diff --git a/drivers/tty/serial/max3107-aava.c b/drivers/tty/serial/max3107-aava.c index 90c40f22ec70..aae772a71de6 100644 --- a/drivers/tty/serial/max3107-aava.c +++ b/drivers/tty/serial/max3107-aava.c | |||
@@ -315,7 +315,6 @@ static int __devinit max3107_probe_aava(struct spi_device *spi) | |||
315 | static struct spi_driver max3107_driver = { | 315 | static struct spi_driver max3107_driver = { |
316 | .driver = { | 316 | .driver = { |
317 | .name = "aava-max3107", | 317 | .name = "aava-max3107", |
318 | .bus = &spi_bus_type, | ||
319 | .owner = THIS_MODULE, | 318 | .owner = THIS_MODULE, |
320 | }, | 319 | }, |
321 | .probe = max3107_probe_aava, | 320 | .probe = max3107_probe_aava, |
diff --git a/drivers/tty/serial/max3107.c b/drivers/tty/serial/max3107.c index 7827000db4f5..17c7ba805d98 100644 --- a/drivers/tty/serial/max3107.c +++ b/drivers/tty/serial/max3107.c | |||
@@ -1181,7 +1181,6 @@ static int max3107_probe_generic(struct spi_device *spi) | |||
1181 | static struct spi_driver max3107_driver = { | 1181 | static struct spi_driver max3107_driver = { |
1182 | .driver = { | 1182 | .driver = { |
1183 | .name = "max3107", | 1183 | .name = "max3107", |
1184 | .bus = &spi_bus_type, | ||
1185 | .owner = THIS_MODULE, | 1184 | .owner = THIS_MODULE, |
1186 | }, | 1185 | }, |
1187 | .probe = max3107_probe_generic, | 1186 | .probe = max3107_probe_generic, |
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index e272d3919c67..a9234ba8f8d5 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c | |||
@@ -1154,7 +1154,6 @@ serial_hsu_console_setup(struct console *co, char *options) | |||
1154 | int bits = 8; | 1154 | int bits = 8; |
1155 | int parity = 'n'; | 1155 | int parity = 'n'; |
1156 | int flow = 'n'; | 1156 | int flow = 'n'; |
1157 | int ret; | ||
1158 | 1157 | ||
1159 | if (co->index == -1 || co->index >= serial_hsu_reg.nr) | 1158 | if (co->index == -1 || co->index >= serial_hsu_reg.nr) |
1160 | co->index = 0; | 1159 | co->index = 0; |
@@ -1165,9 +1164,7 @@ serial_hsu_console_setup(struct console *co, char *options) | |||
1165 | if (options) | 1164 | if (options) |
1166 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 1165 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
1167 | 1166 | ||
1168 | ret = uart_set_options(&up->port, co, baud, parity, bits, flow); | 1167 | return uart_set_options(&up->port, co, baud, parity, bits, flow); |
1169 | |||
1170 | return ret; | ||
1171 | } | 1168 | } |
1172 | 1169 | ||
1173 | static struct console serial_hsu_console = { | 1170 | static struct console serial_hsu_console = { |
@@ -1176,9 +1173,13 @@ static struct console serial_hsu_console = { | |||
1176 | .device = uart_console_device, | 1173 | .device = uart_console_device, |
1177 | .setup = serial_hsu_console_setup, | 1174 | .setup = serial_hsu_console_setup, |
1178 | .flags = CON_PRINTBUFFER, | 1175 | .flags = CON_PRINTBUFFER, |
1179 | .index = 2, | 1176 | .index = -1, |
1180 | .data = &serial_hsu_reg, | 1177 | .data = &serial_hsu_reg, |
1181 | }; | 1178 | }; |
1179 | |||
1180 | #define SERIAL_HSU_CONSOLE (&serial_hsu_console) | ||
1181 | #else | ||
1182 | #define SERIAL_HSU_CONSOLE NULL | ||
1182 | #endif | 1183 | #endif |
1183 | 1184 | ||
1184 | struct uart_ops serial_hsu_pops = { | 1185 | struct uart_ops serial_hsu_pops = { |
@@ -1208,6 +1209,7 @@ static struct uart_driver serial_hsu_reg = { | |||
1208 | .major = TTY_MAJOR, | 1209 | .major = TTY_MAJOR, |
1209 | .minor = 128, | 1210 | .minor = 128, |
1210 | .nr = 3, | 1211 | .nr = 3, |
1212 | .cons = SERIAL_HSU_CONSOLE, | ||
1211 | }; | 1213 | }; |
1212 | 1214 | ||
1213 | #ifdef CONFIG_PM | 1215 | #ifdef CONFIG_PM |
@@ -1342,12 +1344,6 @@ static int serial_hsu_probe(struct pci_dev *pdev, | |||
1342 | } | 1344 | } |
1343 | uart_add_one_port(&serial_hsu_reg, &uport->port); | 1345 | uart_add_one_port(&serial_hsu_reg, &uport->port); |
1344 | 1346 | ||
1345 | #ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE | ||
1346 | if (index == 2) { | ||
1347 | register_console(&serial_hsu_console); | ||
1348 | uport->port.cons = &serial_hsu_console; | ||
1349 | } | ||
1350 | #endif | ||
1351 | pci_set_drvdata(pdev, uport); | 1347 | pci_set_drvdata(pdev, uport); |
1352 | } | 1348 | } |
1353 | 1349 | ||
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index 4c309e869903..df2a2240a3ae 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c | |||
@@ -876,7 +876,6 @@ static int __devexit serial_m3110_remove(struct spi_device *dev) | |||
876 | static struct spi_driver uart_max3110_driver = { | 876 | static struct spi_driver uart_max3110_driver = { |
877 | .driver = { | 877 | .driver = { |
878 | .name = "spi_max3111", | 878 | .name = "spi_max3111", |
879 | .bus = &spi_bus_type, | ||
880 | .owner = THIS_MODULE, | 879 | .owner = THIS_MODULE, |
881 | }, | 880 | }, |
882 | .probe = serial_m3110_probe, | 881 | .probe = serial_m3110_probe, |
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index 60c6eb850265..5e85e1e14c44 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c | |||
@@ -422,9 +422,9 @@ static int __devexit msm_hs_remove(struct platform_device *pdev) | |||
422 | msm_uport->rx.rbuffer); | 422 | msm_uport->rx.rbuffer); |
423 | dma_pool_destroy(msm_uport->rx.pool); | 423 | dma_pool_destroy(msm_uport->rx.pool); |
424 | 424 | ||
425 | dma_unmap_single(dev, msm_uport->rx.cmdptr_dmaaddr, sizeof(u32 *), | 425 | dma_unmap_single(dev, msm_uport->rx.cmdptr_dmaaddr, sizeof(u32), |
426 | DMA_TO_DEVICE); | 426 | DMA_TO_DEVICE); |
427 | dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr_ptr, sizeof(u32 *), | 427 | dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr_ptr, sizeof(u32), |
428 | DMA_TO_DEVICE); | 428 | DMA_TO_DEVICE); |
429 | dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr, sizeof(dmov_box), | 429 | dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr, sizeof(dmov_box), |
430 | DMA_TO_DEVICE); | 430 | DMA_TO_DEVICE); |
@@ -812,7 +812,7 @@ static void msm_hs_submit_tx_locked(struct uart_port *uport) | |||
812 | *tx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(tx->mapped_cmd_ptr); | 812 | *tx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(tx->mapped_cmd_ptr); |
813 | 813 | ||
814 | dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr_ptr, | 814 | dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr_ptr, |
815 | sizeof(u32 *), DMA_TO_DEVICE); | 815 | sizeof(u32), DMA_TO_DEVICE); |
816 | 816 | ||
817 | /* Save tx_count to use in Callback */ | 817 | /* Save tx_count to use in Callback */ |
818 | tx->tx_count = tx_count; | 818 | tx->tx_count = tx_count; |
@@ -1087,12 +1087,10 @@ static void msm_hs_config_port(struct uart_port *uport, int cfg_flags) | |||
1087 | } | 1087 | } |
1088 | 1088 | ||
1089 | /* Handle CTS changes (Called from interrupt handler) */ | 1089 | /* Handle CTS changes (Called from interrupt handler) */ |
1090 | static void msm_hs_handle_delta_cts(struct uart_port *uport) | 1090 | static void msm_hs_handle_delta_cts_locked(struct uart_port *uport) |
1091 | { | 1091 | { |
1092 | unsigned long flags; | ||
1093 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | 1092 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); |
1094 | 1093 | ||
1095 | spin_lock_irqsave(&uport->lock, flags); | ||
1096 | clk_enable(msm_uport->clk); | 1094 | clk_enable(msm_uport->clk); |
1097 | 1095 | ||
1098 | /* clear interrupt */ | 1096 | /* clear interrupt */ |
@@ -1100,7 +1098,6 @@ static void msm_hs_handle_delta_cts(struct uart_port *uport) | |||
1100 | uport->icount.cts++; | 1098 | uport->icount.cts++; |
1101 | 1099 | ||
1102 | clk_disable(msm_uport->clk); | 1100 | clk_disable(msm_uport->clk); |
1103 | spin_unlock_irqrestore(&uport->lock, flags); | ||
1104 | 1101 | ||
1105 | /* clear the IOCTL TIOCMIWAIT if called */ | 1102 | /* clear the IOCTL TIOCMIWAIT if called */ |
1106 | wake_up_interruptible(&uport->state->port.delta_msr_wait); | 1103 | wake_up_interruptible(&uport->state->port.delta_msr_wait); |
@@ -1248,7 +1245,7 @@ static irqreturn_t msm_hs_isr(int irq, void *dev) | |||
1248 | 1245 | ||
1249 | /* Change in CTS interrupt */ | 1246 | /* Change in CTS interrupt */ |
1250 | if (isr_status & UARTDM_ISR_DELTA_CTS_BMSK) | 1247 | if (isr_status & UARTDM_ISR_DELTA_CTS_BMSK) |
1251 | msm_hs_handle_delta_cts(uport); | 1248 | msm_hs_handle_delta_cts_locked(uport); |
1252 | 1249 | ||
1253 | spin_unlock_irqrestore(&uport->lock, flags); | 1250 | spin_unlock_irqrestore(&uport->lock, flags); |
1254 | 1251 | ||
@@ -1537,7 +1534,7 @@ static int __devinit uartdm_init_port(struct uart_port *uport) | |||
1537 | if (!tx->command_ptr) | 1534 | if (!tx->command_ptr) |
1538 | return -ENOMEM; | 1535 | return -ENOMEM; |
1539 | 1536 | ||
1540 | tx->command_ptr_ptr = kmalloc(sizeof(u32 *), GFP_KERNEL | __GFP_DMA); | 1537 | tx->command_ptr_ptr = kmalloc(sizeof(u32), GFP_KERNEL | __GFP_DMA); |
1541 | if (!tx->command_ptr_ptr) { | 1538 | if (!tx->command_ptr_ptr) { |
1542 | ret = -ENOMEM; | 1539 | ret = -ENOMEM; |
1543 | goto err_tx_command_ptr_ptr; | 1540 | goto err_tx_command_ptr_ptr; |
@@ -1547,7 +1544,7 @@ static int __devinit uartdm_init_port(struct uart_port *uport) | |||
1547 | sizeof(dmov_box), DMA_TO_DEVICE); | 1544 | sizeof(dmov_box), DMA_TO_DEVICE); |
1548 | tx->mapped_cmd_ptr_ptr = dma_map_single(uport->dev, | 1545 | tx->mapped_cmd_ptr_ptr = dma_map_single(uport->dev, |
1549 | tx->command_ptr_ptr, | 1546 | tx->command_ptr_ptr, |
1550 | sizeof(u32 *), DMA_TO_DEVICE); | 1547 | sizeof(u32), DMA_TO_DEVICE); |
1551 | tx->xfer.cmdptr = DMOV_CMD_ADDR(tx->mapped_cmd_ptr_ptr); | 1548 | tx->xfer.cmdptr = DMOV_CMD_ADDR(tx->mapped_cmd_ptr_ptr); |
1552 | 1549 | ||
1553 | init_waitqueue_head(&rx->wait); | 1550 | init_waitqueue_head(&rx->wait); |
@@ -1575,7 +1572,7 @@ static int __devinit uartdm_init_port(struct uart_port *uport) | |||
1575 | goto err_rx_command_ptr; | 1572 | goto err_rx_command_ptr; |
1576 | } | 1573 | } |
1577 | 1574 | ||
1578 | rx->command_ptr_ptr = kmalloc(sizeof(u32 *), GFP_KERNEL | __GFP_DMA); | 1575 | rx->command_ptr_ptr = kmalloc(sizeof(u32), GFP_KERNEL | __GFP_DMA); |
1579 | if (!rx->command_ptr_ptr) { | 1576 | if (!rx->command_ptr_ptr) { |
1580 | pr_err("%s(): cannot allocate rx->command_ptr_ptr", __func__); | 1577 | pr_err("%s(): cannot allocate rx->command_ptr_ptr", __func__); |
1581 | ret = -ENOMEM; | 1578 | ret = -ENOMEM; |
@@ -1593,7 +1590,7 @@ static int __devinit uartdm_init_port(struct uart_port *uport) | |||
1593 | *rx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(rx->mapped_cmd_ptr); | 1590 | *rx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(rx->mapped_cmd_ptr); |
1594 | 1591 | ||
1595 | rx->cmdptr_dmaaddr = dma_map_single(uport->dev, rx->command_ptr_ptr, | 1592 | rx->cmdptr_dmaaddr = dma_map_single(uport->dev, rx->command_ptr_ptr, |
1596 | sizeof(u32 *), DMA_TO_DEVICE); | 1593 | sizeof(u32), DMA_TO_DEVICE); |
1597 | rx->xfer.cmdptr = DMOV_CMD_ADDR(rx->cmdptr_dmaaddr); | 1594 | rx->xfer.cmdptr = DMOV_CMD_ADDR(rx->cmdptr_dmaaddr); |
1598 | 1595 | ||
1599 | INIT_WORK(&rx->tty_work, msm_hs_tty_flip_buffer_work); | 1596 | INIT_WORK(&rx->tty_work, msm_hs_tty_flip_buffer_work); |
@@ -1609,7 +1606,7 @@ err_dma_pool_alloc: | |||
1609 | dma_pool_destroy(msm_uport->rx.pool); | 1606 | dma_pool_destroy(msm_uport->rx.pool); |
1610 | err_dma_pool_create: | 1607 | err_dma_pool_create: |
1611 | dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr_ptr, | 1608 | dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr_ptr, |
1612 | sizeof(u32 *), DMA_TO_DEVICE); | 1609 | sizeof(u32), DMA_TO_DEVICE); |
1613 | dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr, | 1610 | dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr, |
1614 | sizeof(dmov_box), DMA_TO_DEVICE); | 1611 | sizeof(dmov_box), DMA_TO_DEVICE); |
1615 | kfree(msm_uport->tx.command_ptr_ptr); | 1612 | kfree(msm_uport->tx.command_ptr_ptr); |
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 7e02c9c344fe..55fd362b9879 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c | |||
@@ -145,11 +145,12 @@ static inline void mxs_auart_tx_chars(struct mxs_auart_port *s) | |||
145 | writel(xmit->buf[xmit->tail], | 145 | writel(xmit->buf[xmit->tail], |
146 | s->port.membase + AUART_DATA); | 146 | s->port.membase + AUART_DATA); |
147 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 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 | 148 | } else |
151 | break; | 149 | break; |
152 | } | 150 | } |
151 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
152 | uart_write_wakeup(&s->port); | ||
153 | |||
153 | if (uart_circ_empty(&(s->port.state->xmit))) | 154 | if (uart_circ_empty(&(s->port.state->xmit))) |
154 | writel(AUART_INTR_TXIEN, | 155 | writel(AUART_INTR_TXIEN, |
155 | s->port.membase + AUART_INTR_CLR); | 156 | s->port.membase + AUART_INTR_CLR); |
@@ -424,7 +425,7 @@ static int mxs_auart_startup(struct uart_port *u) | |||
424 | { | 425 | { |
425 | struct mxs_auart_port *s = to_auart_port(u); | 426 | struct mxs_auart_port *s = to_auart_port(u); |
426 | 427 | ||
427 | clk_enable(s->clk); | 428 | clk_prepare_enable(s->clk); |
428 | 429 | ||
429 | writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); | 430 | writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); |
430 | 431 | ||
@@ -453,7 +454,7 @@ static void mxs_auart_shutdown(struct uart_port *u) | |||
453 | writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, | 454 | writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, |
454 | u->membase + AUART_INTR_CLR); | 455 | u->membase + AUART_INTR_CLR); |
455 | 456 | ||
456 | clk_disable(s->clk); | 457 | clk_disable_unprepare(s->clk); |
457 | } | 458 | } |
458 | 459 | ||
459 | static unsigned int mxs_auart_tx_empty(struct uart_port *u) | 460 | static unsigned int mxs_auart_tx_empty(struct uart_port *u) |
@@ -634,7 +635,7 @@ auart_console_setup(struct console *co, char *options) | |||
634 | if (!s) | 635 | if (!s) |
635 | return -ENODEV; | 636 | return -ENODEV; |
636 | 637 | ||
637 | clk_enable(s->clk); | 638 | clk_prepare_enable(s->clk); |
638 | 639 | ||
639 | if (options) | 640 | if (options) |
640 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 641 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
@@ -643,7 +644,7 @@ auart_console_setup(struct console *co, char *options) | |||
643 | 644 | ||
644 | ret = uart_set_options(&s->port, co, baud, parity, bits, flow); | 645 | ret = uart_set_options(&s->port, co, baud, parity, bits, flow); |
645 | 646 | ||
646 | clk_disable(s->clk); | 647 | clk_disable_unprepare(s->clk); |
647 | 648 | ||
648 | return ret; | 649 | return ret; |
649 | } | 650 | } |
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 5e713d3ef1f4..d192dcbb82f5 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c | |||
@@ -37,17 +37,24 @@ | |||
37 | #include <linux/clk.h> | 37 | #include <linux/clk.h> |
38 | #include <linux/serial_core.h> | 38 | #include <linux/serial_core.h> |
39 | #include <linux/irq.h> | 39 | #include <linux/irq.h> |
40 | #include <linux/pm_runtime.h> | ||
41 | #include <linux/of.h> | ||
40 | 42 | ||
41 | #include <plat/dma.h> | 43 | #include <plat/dma.h> |
42 | #include <plat/dmtimer.h> | 44 | #include <plat/dmtimer.h> |
43 | #include <plat/omap-serial.h> | 45 | #include <plat/omap-serial.h> |
44 | 46 | ||
47 | #define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/ | ||
48 | |||
45 | static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; | 49 | static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; |
46 | 50 | ||
47 | /* Forward declaration of functions */ | 51 | /* Forward declaration of functions */ |
48 | static void uart_tx_dma_callback(int lch, u16 ch_status, void *data); | 52 | static void uart_tx_dma_callback(int lch, u16 ch_status, void *data); |
49 | static void serial_omap_rx_timeout(unsigned long uart_no); | 53 | static void serial_omap_rxdma_poll(unsigned long uart_no); |
50 | static int serial_omap_start_rxdma(struct uart_omap_port *up); | 54 | static int serial_omap_start_rxdma(struct uart_omap_port *up); |
55 | static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1); | ||
56 | |||
57 | static struct workqueue_struct *serial_omap_uart_wq; | ||
51 | 58 | ||
52 | static inline unsigned int serial_in(struct uart_omap_port *up, int offset) | 59 | static inline unsigned int serial_in(struct uart_omap_port *up, int offset) |
53 | { | 60 | { |
@@ -102,6 +109,8 @@ static void serial_omap_stop_rxdma(struct uart_omap_port *up) | |||
102 | omap_free_dma(up->uart_dma.rx_dma_channel); | 109 | omap_free_dma(up->uart_dma.rx_dma_channel); |
103 | up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; | 110 | up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; |
104 | up->uart_dma.rx_dma_used = false; | 111 | up->uart_dma.rx_dma_used = false; |
112 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
113 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
105 | } | 114 | } |
106 | } | 115 | } |
107 | 116 | ||
@@ -109,9 +118,12 @@ static void serial_omap_enable_ms(struct uart_port *port) | |||
109 | { | 118 | { |
110 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 119 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
111 | 120 | ||
112 | dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id); | 121 | dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->port.line); |
122 | |||
123 | pm_runtime_get_sync(&up->pdev->dev); | ||
113 | up->ier |= UART_IER_MSI; | 124 | up->ier |= UART_IER_MSI; |
114 | serial_out(up, UART_IER, up->ier); | 125 | serial_out(up, UART_IER, up->ier); |
126 | pm_runtime_put(&up->pdev->dev); | ||
115 | } | 127 | } |
116 | 128 | ||
117 | static void serial_omap_stop_tx(struct uart_port *port) | 129 | static void serial_omap_stop_tx(struct uart_port *port) |
@@ -129,30 +141,40 @@ static void serial_omap_stop_tx(struct uart_port *port) | |||
129 | omap_stop_dma(up->uart_dma.tx_dma_channel); | 141 | omap_stop_dma(up->uart_dma.tx_dma_channel); |
130 | omap_free_dma(up->uart_dma.tx_dma_channel); | 142 | omap_free_dma(up->uart_dma.tx_dma_channel); |
131 | up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; | 143 | up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; |
144 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
145 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
132 | } | 146 | } |
133 | 147 | ||
148 | pm_runtime_get_sync(&up->pdev->dev); | ||
134 | if (up->ier & UART_IER_THRI) { | 149 | if (up->ier & UART_IER_THRI) { |
135 | up->ier &= ~UART_IER_THRI; | 150 | up->ier &= ~UART_IER_THRI; |
136 | serial_out(up, UART_IER, up->ier); | 151 | serial_out(up, UART_IER, up->ier); |
137 | } | 152 | } |
153 | |||
154 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
155 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
138 | } | 156 | } |
139 | 157 | ||
140 | static void serial_omap_stop_rx(struct uart_port *port) | 158 | static void serial_omap_stop_rx(struct uart_port *port) |
141 | { | 159 | { |
142 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 160 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
143 | 161 | ||
162 | pm_runtime_get_sync(&up->pdev->dev); | ||
144 | if (up->use_dma) | 163 | if (up->use_dma) |
145 | serial_omap_stop_rxdma(up); | 164 | serial_omap_stop_rxdma(up); |
146 | up->ier &= ~UART_IER_RLSI; | 165 | up->ier &= ~UART_IER_RLSI; |
147 | up->port.read_status_mask &= ~UART_LSR_DR; | 166 | up->port.read_status_mask &= ~UART_LSR_DR; |
148 | serial_out(up, UART_IER, up->ier); | 167 | serial_out(up, UART_IER, up->ier); |
168 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
169 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
149 | } | 170 | } |
150 | 171 | ||
151 | static inline void receive_chars(struct uart_omap_port *up, int *status) | 172 | static inline void receive_chars(struct uart_omap_port *up, |
173 | unsigned int *status) | ||
152 | { | 174 | { |
153 | struct tty_struct *tty = up->port.state->port.tty; | 175 | struct tty_struct *tty = up->port.state->port.tty; |
154 | unsigned int flag; | 176 | unsigned int flag, lsr = *status; |
155 | unsigned char ch, lsr = *status; | 177 | unsigned char ch = 0; |
156 | int max_count = 256; | 178 | int max_count = 256; |
157 | 179 | ||
158 | do { | 180 | do { |
@@ -262,7 +284,10 @@ static void serial_omap_start_tx(struct uart_port *port) | |||
262 | int ret = 0; | 284 | int ret = 0; |
263 | 285 | ||
264 | if (!up->use_dma) { | 286 | if (!up->use_dma) { |
287 | pm_runtime_get_sync(&up->pdev->dev); | ||
265 | serial_omap_enable_ier_thri(up); | 288 | serial_omap_enable_ier_thri(up); |
289 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
290 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
266 | return; | 291 | return; |
267 | } | 292 | } |
268 | 293 | ||
@@ -272,6 +297,7 @@ static void serial_omap_start_tx(struct uart_port *port) | |||
272 | xmit = &up->port.state->xmit; | 297 | xmit = &up->port.state->xmit; |
273 | 298 | ||
274 | if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) { | 299 | if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) { |
300 | pm_runtime_get_sync(&up->pdev->dev); | ||
275 | ret = omap_request_dma(up->uart_dma.uart_dma_tx, | 301 | ret = omap_request_dma(up->uart_dma.uart_dma_tx, |
276 | "UART Tx DMA", | 302 | "UART Tx DMA", |
277 | (void *)uart_tx_dma_callback, up, | 303 | (void *)uart_tx_dma_callback, up, |
@@ -354,9 +380,13 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id) | |||
354 | unsigned int iir, lsr; | 380 | unsigned int iir, lsr; |
355 | unsigned long flags; | 381 | unsigned long flags; |
356 | 382 | ||
383 | pm_runtime_get_sync(&up->pdev->dev); | ||
357 | iir = serial_in(up, UART_IIR); | 384 | iir = serial_in(up, UART_IIR); |
358 | if (iir & UART_IIR_NO_INT) | 385 | if (iir & UART_IIR_NO_INT) { |
386 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
387 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
359 | return IRQ_NONE; | 388 | return IRQ_NONE; |
389 | } | ||
360 | 390 | ||
361 | spin_lock_irqsave(&up->port.lock, flags); | 391 | spin_lock_irqsave(&up->port.lock, flags); |
362 | lsr = serial_in(up, UART_LSR); | 392 | lsr = serial_in(up, UART_LSR); |
@@ -378,6 +408,9 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id) | |||
378 | transmit_chars(up); | 408 | transmit_chars(up); |
379 | 409 | ||
380 | spin_unlock_irqrestore(&up->port.lock, flags); | 410 | spin_unlock_irqrestore(&up->port.lock, flags); |
411 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
412 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
413 | |||
381 | up->port_activity = jiffies; | 414 | up->port_activity = jiffies; |
382 | return IRQ_HANDLED; | 415 | return IRQ_HANDLED; |
383 | } | 416 | } |
@@ -388,22 +421,26 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port) | |||
388 | unsigned long flags = 0; | 421 | unsigned long flags = 0; |
389 | unsigned int ret = 0; | 422 | unsigned int ret = 0; |
390 | 423 | ||
391 | dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id); | 424 | pm_runtime_get_sync(&up->pdev->dev); |
425 | dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line); | ||
392 | spin_lock_irqsave(&up->port.lock, flags); | 426 | spin_lock_irqsave(&up->port.lock, flags); |
393 | ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; | 427 | ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; |
394 | spin_unlock_irqrestore(&up->port.lock, flags); | 428 | spin_unlock_irqrestore(&up->port.lock, flags); |
395 | 429 | pm_runtime_put(&up->pdev->dev); | |
396 | return ret; | 430 | return ret; |
397 | } | 431 | } |
398 | 432 | ||
399 | static unsigned int serial_omap_get_mctrl(struct uart_port *port) | 433 | static unsigned int serial_omap_get_mctrl(struct uart_port *port) |
400 | { | 434 | { |
401 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 435 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
402 | unsigned char status; | 436 | unsigned int status; |
403 | unsigned int ret = 0; | 437 | unsigned int ret = 0; |
404 | 438 | ||
439 | pm_runtime_get_sync(&up->pdev->dev); | ||
405 | status = check_modem_status(up); | 440 | status = check_modem_status(up); |
406 | dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id); | 441 | pm_runtime_put(&up->pdev->dev); |
442 | |||
443 | dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->port.line); | ||
407 | 444 | ||
408 | if (status & UART_MSR_DCD) | 445 | if (status & UART_MSR_DCD) |
409 | ret |= TIOCM_CAR; | 446 | ret |= TIOCM_CAR; |
@@ -421,7 +458,7 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
421 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 458 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
422 | unsigned char mcr = 0; | 459 | unsigned char mcr = 0; |
423 | 460 | ||
424 | dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id); | 461 | dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line); |
425 | if (mctrl & TIOCM_RTS) | 462 | if (mctrl & TIOCM_RTS) |
426 | mcr |= UART_MCR_RTS; | 463 | mcr |= UART_MCR_RTS; |
427 | if (mctrl & TIOCM_DTR) | 464 | if (mctrl & TIOCM_DTR) |
@@ -433,8 +470,11 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
433 | if (mctrl & TIOCM_LOOP) | 470 | if (mctrl & TIOCM_LOOP) |
434 | mcr |= UART_MCR_LOOP; | 471 | mcr |= UART_MCR_LOOP; |
435 | 472 | ||
436 | mcr |= up->mcr; | 473 | pm_runtime_get_sync(&up->pdev->dev); |
437 | serial_out(up, UART_MCR, mcr); | 474 | up->mcr = serial_in(up, UART_MCR); |
475 | up->mcr |= mcr; | ||
476 | serial_out(up, UART_MCR, up->mcr); | ||
477 | pm_runtime_put(&up->pdev->dev); | ||
438 | } | 478 | } |
439 | 479 | ||
440 | static void serial_omap_break_ctl(struct uart_port *port, int break_state) | 480 | static void serial_omap_break_ctl(struct uart_port *port, int break_state) |
@@ -442,7 +482,8 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) | |||
442 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 482 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
443 | unsigned long flags = 0; | 483 | unsigned long flags = 0; |
444 | 484 | ||
445 | dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id); | 485 | dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line); |
486 | pm_runtime_get_sync(&up->pdev->dev); | ||
446 | spin_lock_irqsave(&up->port.lock, flags); | 487 | spin_lock_irqsave(&up->port.lock, flags); |
447 | if (break_state == -1) | 488 | if (break_state == -1) |
448 | up->lcr |= UART_LCR_SBC; | 489 | up->lcr |= UART_LCR_SBC; |
@@ -450,6 +491,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) | |||
450 | up->lcr &= ~UART_LCR_SBC; | 491 | up->lcr &= ~UART_LCR_SBC; |
451 | serial_out(up, UART_LCR, up->lcr); | 492 | serial_out(up, UART_LCR, up->lcr); |
452 | spin_unlock_irqrestore(&up->port.lock, flags); | 493 | spin_unlock_irqrestore(&up->port.lock, flags); |
494 | pm_runtime_put(&up->pdev->dev); | ||
453 | } | 495 | } |
454 | 496 | ||
455 | static int serial_omap_startup(struct uart_port *port) | 497 | static int serial_omap_startup(struct uart_port *port) |
@@ -466,8 +508,9 @@ static int serial_omap_startup(struct uart_port *port) | |||
466 | if (retval) | 508 | if (retval) |
467 | return retval; | 509 | return retval; |
468 | 510 | ||
469 | dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id); | 511 | dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line); |
470 | 512 | ||
513 | pm_runtime_get_sync(&up->pdev->dev); | ||
471 | /* | 514 | /* |
472 | * Clear the FIFO buffers and disable them. | 515 | * Clear the FIFO buffers and disable them. |
473 | * (they will be reenabled in set_termios()) | 516 | * (they will be reenabled in set_termios()) |
@@ -505,8 +548,8 @@ static int serial_omap_startup(struct uart_port *port) | |||
505 | (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys), | 548 | (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys), |
506 | 0); | 549 | 0); |
507 | init_timer(&(up->uart_dma.rx_timer)); | 550 | init_timer(&(up->uart_dma.rx_timer)); |
508 | up->uart_dma.rx_timer.function = serial_omap_rx_timeout; | 551 | up->uart_dma.rx_timer.function = serial_omap_rxdma_poll; |
509 | up->uart_dma.rx_timer.data = up->pdev->id; | 552 | up->uart_dma.rx_timer.data = up->port.line; |
510 | /* Currently the buffer size is 4KB. Can increase it */ | 553 | /* Currently the buffer size is 4KB. Can increase it */ |
511 | up->uart_dma.rx_buf = dma_alloc_coherent(NULL, | 554 | up->uart_dma.rx_buf = dma_alloc_coherent(NULL, |
512 | up->uart_dma.rx_buf_size, | 555 | up->uart_dma.rx_buf_size, |
@@ -523,6 +566,8 @@ static int serial_omap_startup(struct uart_port *port) | |||
523 | /* Enable module level wake up */ | 566 | /* Enable module level wake up */ |
524 | serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP); | 567 | serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP); |
525 | 568 | ||
569 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
570 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
526 | up->port_activity = jiffies; | 571 | up->port_activity = jiffies; |
527 | return 0; | 572 | return 0; |
528 | } | 573 | } |
@@ -532,7 +577,9 @@ static void serial_omap_shutdown(struct uart_port *port) | |||
532 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 577 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
533 | unsigned long flags = 0; | 578 | unsigned long flags = 0; |
534 | 579 | ||
535 | dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id); | 580 | dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line); |
581 | |||
582 | pm_runtime_get_sync(&up->pdev->dev); | ||
536 | /* | 583 | /* |
537 | * Disable interrupts from this port | 584 | * Disable interrupts from this port |
538 | */ | 585 | */ |
@@ -566,6 +613,8 @@ static void serial_omap_shutdown(struct uart_port *port) | |||
566 | up->uart_dma.rx_buf_dma_phys); | 613 | up->uart_dma.rx_buf_dma_phys); |
567 | up->uart_dma.rx_buf = NULL; | 614 | up->uart_dma.rx_buf = NULL; |
568 | } | 615 | } |
616 | |||
617 | pm_runtime_put(&up->pdev->dev); | ||
569 | free_irq(up->port.irq, up); | 618 | free_irq(up->port.irq, up); |
570 | } | 619 | } |
571 | 620 | ||
@@ -573,8 +622,6 @@ static inline void | |||
573 | serial_omap_configure_xonxoff | 622 | serial_omap_configure_xonxoff |
574 | (struct uart_omap_port *up, struct ktermios *termios) | 623 | (struct uart_omap_port *up, struct ktermios *termios) |
575 | { | 624 | { |
576 | unsigned char efr = 0; | ||
577 | |||
578 | up->lcr = serial_in(up, UART_LCR); | 625 | up->lcr = serial_in(up, UART_LCR); |
579 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | 626 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
580 | up->efr = serial_in(up, UART_EFR); | 627 | up->efr = serial_in(up, UART_EFR); |
@@ -584,8 +631,7 @@ serial_omap_configure_xonxoff | |||
584 | serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]); | 631 | serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]); |
585 | 632 | ||
586 | /* clear SW control mode bits */ | 633 | /* clear SW control mode bits */ |
587 | efr = up->efr; | 634 | up->efr &= OMAP_UART_SW_CLR; |
588 | efr &= OMAP_UART_SW_CLR; | ||
589 | 635 | ||
590 | /* | 636 | /* |
591 | * IXON Flag: | 637 | * IXON Flag: |
@@ -593,7 +639,7 @@ serial_omap_configure_xonxoff | |||
593 | * Transmit XON1, XOFF1 | 639 | * Transmit XON1, XOFF1 |
594 | */ | 640 | */ |
595 | if (termios->c_iflag & IXON) | 641 | if (termios->c_iflag & IXON) |
596 | efr |= OMAP_UART_SW_TX; | 642 | up->efr |= OMAP_UART_SW_TX; |
597 | 643 | ||
598 | /* | 644 | /* |
599 | * IXOFF Flag: | 645 | * IXOFF Flag: |
@@ -601,7 +647,7 @@ serial_omap_configure_xonxoff | |||
601 | * Receiver compares XON1, XOFF1. | 647 | * Receiver compares XON1, XOFF1. |
602 | */ | 648 | */ |
603 | if (termios->c_iflag & IXOFF) | 649 | if (termios->c_iflag & IXOFF) |
604 | efr |= OMAP_UART_SW_RX; | 650 | up->efr |= OMAP_UART_SW_RX; |
605 | 651 | ||
606 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); | 652 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); |
607 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | 653 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); |
@@ -624,13 +670,21 @@ serial_omap_configure_xonxoff | |||
624 | * load the new software flow control mode IXON or IXOFF | 670 | * load the new software flow control mode IXON or IXOFF |
625 | * and restore the UARTi.EFR_REG[4] ENHANCED_EN value. | 671 | * and restore the UARTi.EFR_REG[4] ENHANCED_EN value. |
626 | */ | 672 | */ |
627 | serial_out(up, UART_EFR, efr | UART_EFR_SCD); | 673 | serial_out(up, UART_EFR, up->efr | UART_EFR_SCD); |
628 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | 674 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); |
629 | 675 | ||
630 | serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR); | 676 | serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR); |
631 | serial_out(up, UART_LCR, up->lcr); | 677 | serial_out(up, UART_LCR, up->lcr); |
632 | } | 678 | } |
633 | 679 | ||
680 | static void serial_omap_uart_qos_work(struct work_struct *work) | ||
681 | { | ||
682 | struct uart_omap_port *up = container_of(work, struct uart_omap_port, | ||
683 | qos_work); | ||
684 | |||
685 | pm_qos_update_request(&up->pm_qos_request, up->latency); | ||
686 | } | ||
687 | |||
634 | static void | 688 | static void |
635 | serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | 689 | serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, |
636 | struct ktermios *old) | 690 | struct ktermios *old) |
@@ -671,6 +725,16 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
671 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13); | 725 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13); |
672 | quot = serial_omap_get_divisor(port, baud); | 726 | quot = serial_omap_get_divisor(port, baud); |
673 | 727 | ||
728 | /* calculate wakeup latency constraint */ | ||
729 | up->calc_latency = (1000000 * up->port.fifosize) / | ||
730 | (1000 * baud / 8); | ||
731 | up->latency = up->calc_latency; | ||
732 | schedule_work(&up->qos_work); | ||
733 | |||
734 | up->dll = quot & 0xff; | ||
735 | up->dlh = quot >> 8; | ||
736 | up->mdr1 = UART_OMAP_MDR1_DISABLE; | ||
737 | |||
674 | up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 | | 738 | up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 | |
675 | UART_FCR_ENABLE_FIFO; | 739 | UART_FCR_ENABLE_FIFO; |
676 | if (up->use_dma) | 740 | if (up->use_dma) |
@@ -680,6 +744,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
680 | * Ok, we're now changing the port state. Do it with | 744 | * Ok, we're now changing the port state. Do it with |
681 | * interrupts disabled. | 745 | * interrupts disabled. |
682 | */ | 746 | */ |
747 | pm_runtime_get_sync(&up->pdev->dev); | ||
683 | spin_lock_irqsave(&up->port.lock, flags); | 748 | spin_lock_irqsave(&up->port.lock, flags); |
684 | 749 | ||
685 | /* | 750 | /* |
@@ -723,6 +788,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
723 | up->ier |= UART_IER_MSI; | 788 | up->ier |= UART_IER_MSI; |
724 | serial_out(up, UART_IER, up->ier); | 789 | serial_out(up, UART_IER, up->ier); |
725 | serial_out(up, UART_LCR, cval); /* reset DLAB */ | 790 | serial_out(up, UART_LCR, cval); /* reset DLAB */ |
791 | up->lcr = cval; | ||
792 | up->scr = OMAP_UART_SCR_TX_EMPTY; | ||
726 | 793 | ||
727 | /* FIFOs and DMA Settings */ | 794 | /* FIFOs and DMA Settings */ |
728 | 795 | ||
@@ -749,17 +816,22 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
749 | 816 | ||
750 | if (up->use_dma) { | 817 | if (up->use_dma) { |
751 | serial_out(up, UART_TI752_TLR, 0); | 818 | serial_out(up, UART_TI752_TLR, 0); |
752 | serial_out(up, UART_OMAP_SCR, | 819 | up->scr |= (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8); |
753 | (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8)); | ||
754 | } | 820 | } |
755 | 821 | ||
822 | serial_out(up, UART_OMAP_SCR, up->scr); | ||
823 | |||
756 | serial_out(up, UART_EFR, up->efr); | 824 | serial_out(up, UART_EFR, up->efr); |
757 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | 825 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); |
758 | serial_out(up, UART_MCR, up->mcr); | 826 | serial_out(up, UART_MCR, up->mcr); |
759 | 827 | ||
760 | /* Protocol, Baud Rate, and Interrupt Settings */ | 828 | /* Protocol, Baud Rate, and Interrupt Settings */ |
761 | 829 | ||
762 | serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); | 830 | if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) |
831 | serial_omap_mdr1_errataset(up, up->mdr1); | ||
832 | else | ||
833 | serial_out(up, UART_OMAP_MDR1, up->mdr1); | ||
834 | |||
763 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | 835 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
764 | 836 | ||
765 | up->efr = serial_in(up, UART_EFR); | 837 | up->efr = serial_in(up, UART_EFR); |
@@ -769,8 +841,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
769 | serial_out(up, UART_IER, 0); | 841 | serial_out(up, UART_IER, 0); |
770 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | 842 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
771 | 843 | ||
772 | serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ | 844 | serial_out(up, UART_DLL, up->dll); /* LS of divisor */ |
773 | serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ | 845 | serial_out(up, UART_DLM, up->dlh); /* MS of divisor */ |
774 | 846 | ||
775 | serial_out(up, UART_LCR, 0); | 847 | serial_out(up, UART_LCR, 0); |
776 | serial_out(up, UART_IER, up->ier); | 848 | serial_out(up, UART_IER, up->ier); |
@@ -780,9 +852,14 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
780 | serial_out(up, UART_LCR, cval); | 852 | serial_out(up, UART_LCR, cval); |
781 | 853 | ||
782 | if (baud > 230400 && baud != 3000000) | 854 | if (baud > 230400 && baud != 3000000) |
783 | serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_13X_MODE); | 855 | up->mdr1 = UART_OMAP_MDR1_13X_MODE; |
784 | else | 856 | else |
785 | serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE); | 857 | up->mdr1 = UART_OMAP_MDR1_16X_MODE; |
858 | |||
859 | if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) | ||
860 | serial_omap_mdr1_errataset(up, up->mdr1); | ||
861 | else | ||
862 | serial_out(up, UART_OMAP_MDR1, up->mdr1); | ||
786 | 863 | ||
787 | /* Hardware Flow Control Configuration */ | 864 | /* Hardware Flow Control Configuration */ |
788 | 865 | ||
@@ -809,7 +886,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, | |||
809 | serial_omap_configure_xonxoff(up, termios); | 886 | serial_omap_configure_xonxoff(up, termios); |
810 | 887 | ||
811 | spin_unlock_irqrestore(&up->port.lock, flags); | 888 | spin_unlock_irqrestore(&up->port.lock, flags); |
812 | dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id); | 889 | pm_runtime_put(&up->pdev->dev); |
890 | dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line); | ||
813 | } | 891 | } |
814 | 892 | ||
815 | static void | 893 | static void |
@@ -819,7 +897,9 @@ serial_omap_pm(struct uart_port *port, unsigned int state, | |||
819 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 897 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
820 | unsigned char efr; | 898 | unsigned char efr; |
821 | 899 | ||
822 | dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id); | 900 | dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->port.line); |
901 | |||
902 | pm_runtime_get_sync(&up->pdev->dev); | ||
823 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | 903 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
824 | efr = serial_in(up, UART_EFR); | 904 | efr = serial_in(up, UART_EFR); |
825 | serial_out(up, UART_EFR, efr | UART_EFR_ECB); | 905 | serial_out(up, UART_EFR, efr | UART_EFR_ECB); |
@@ -829,6 +909,15 @@ serial_omap_pm(struct uart_port *port, unsigned int state, | |||
829 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | 909 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
830 | serial_out(up, UART_EFR, efr); | 910 | serial_out(up, UART_EFR, efr); |
831 | serial_out(up, UART_LCR, 0); | 911 | serial_out(up, UART_LCR, 0); |
912 | |||
913 | if (!device_may_wakeup(&up->pdev->dev)) { | ||
914 | if (!state) | ||
915 | pm_runtime_forbid(&up->pdev->dev); | ||
916 | else | ||
917 | pm_runtime_allow(&up->pdev->dev); | ||
918 | } | ||
919 | |||
920 | pm_runtime_put(&up->pdev->dev); | ||
832 | } | 921 | } |
833 | 922 | ||
834 | static void serial_omap_release_port(struct uart_port *port) | 923 | static void serial_omap_release_port(struct uart_port *port) |
@@ -847,7 +936,7 @@ static void serial_omap_config_port(struct uart_port *port, int flags) | |||
847 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 936 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
848 | 937 | ||
849 | dev_dbg(up->port.dev, "serial_omap_config_port+%d\n", | 938 | dev_dbg(up->port.dev, "serial_omap_config_port+%d\n", |
850 | up->pdev->id); | 939 | up->port.line); |
851 | up->port.type = PORT_OMAP; | 940 | up->port.type = PORT_OMAP; |
852 | } | 941 | } |
853 | 942 | ||
@@ -864,7 +953,7 @@ serial_omap_type(struct uart_port *port) | |||
864 | { | 953 | { |
865 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 954 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
866 | 955 | ||
867 | dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->pdev->id); | 956 | dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->port.line); |
868 | return up->name; | 957 | return up->name; |
869 | } | 958 | } |
870 | 959 | ||
@@ -906,19 +995,26 @@ static inline void wait_for_xmitr(struct uart_omap_port *up) | |||
906 | static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch) | 995 | static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch) |
907 | { | 996 | { |
908 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 997 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
998 | |||
999 | pm_runtime_get_sync(&up->pdev->dev); | ||
909 | wait_for_xmitr(up); | 1000 | wait_for_xmitr(up); |
910 | serial_out(up, UART_TX, ch); | 1001 | serial_out(up, UART_TX, ch); |
1002 | pm_runtime_put(&up->pdev->dev); | ||
911 | } | 1003 | } |
912 | 1004 | ||
913 | static int serial_omap_poll_get_char(struct uart_port *port) | 1005 | static int serial_omap_poll_get_char(struct uart_port *port) |
914 | { | 1006 | { |
915 | struct uart_omap_port *up = (struct uart_omap_port *)port; | 1007 | struct uart_omap_port *up = (struct uart_omap_port *)port; |
916 | unsigned int status = serial_in(up, UART_LSR); | 1008 | unsigned int status; |
917 | 1009 | ||
1010 | pm_runtime_get_sync(&up->pdev->dev); | ||
1011 | status = serial_in(up, UART_LSR); | ||
918 | if (!(status & UART_LSR_DR)) | 1012 | if (!(status & UART_LSR_DR)) |
919 | return NO_POLL_CHAR; | 1013 | return NO_POLL_CHAR; |
920 | 1014 | ||
921 | return serial_in(up, UART_RX); | 1015 | status = serial_in(up, UART_RX); |
1016 | pm_runtime_put(&up->pdev->dev); | ||
1017 | return status; | ||
922 | } | 1018 | } |
923 | 1019 | ||
924 | #endif /* CONFIG_CONSOLE_POLL */ | 1020 | #endif /* CONFIG_CONSOLE_POLL */ |
@@ -946,6 +1042,8 @@ serial_omap_console_write(struct console *co, const char *s, | |||
946 | unsigned int ier; | 1042 | unsigned int ier; |
947 | int locked = 1; | 1043 | int locked = 1; |
948 | 1044 | ||
1045 | pm_runtime_get_sync(&up->pdev->dev); | ||
1046 | |||
949 | local_irq_save(flags); | 1047 | local_irq_save(flags); |
950 | if (up->port.sysrq) | 1048 | if (up->port.sysrq) |
951 | locked = 0; | 1049 | locked = 0; |
@@ -978,6 +1076,8 @@ serial_omap_console_write(struct console *co, const char *s, | |||
978 | if (up->msr_saved_flags) | 1076 | if (up->msr_saved_flags) |
979 | check_modem_status(up); | 1077 | check_modem_status(up); |
980 | 1078 | ||
1079 | pm_runtime_mark_last_busy(&up->pdev->dev); | ||
1080 | pm_runtime_put_autosuspend(&up->pdev->dev); | ||
981 | if (locked) | 1081 | if (locked) |
982 | spin_unlock(&up->port.lock); | 1082 | spin_unlock(&up->port.lock); |
983 | local_irq_restore(flags); | 1083 | local_irq_restore(flags); |
@@ -1014,7 +1114,7 @@ static struct console serial_omap_console = { | |||
1014 | 1114 | ||
1015 | static void serial_omap_add_console_port(struct uart_omap_port *up) | 1115 | static void serial_omap_add_console_port(struct uart_omap_port *up) |
1016 | { | 1116 | { |
1017 | serial_omap_console_ports[up->pdev->id] = up; | 1117 | serial_omap_console_ports[up->port.line] = up; |
1018 | } | 1118 | } |
1019 | 1119 | ||
1020 | #define OMAP_CONSOLE (&serial_omap_console) | 1120 | #define OMAP_CONSOLE (&serial_omap_console) |
@@ -1060,26 +1160,30 @@ static struct uart_driver serial_omap_reg = { | |||
1060 | .cons = OMAP_CONSOLE, | 1160 | .cons = OMAP_CONSOLE, |
1061 | }; | 1161 | }; |
1062 | 1162 | ||
1063 | static int | 1163 | #ifdef CONFIG_SUSPEND |
1064 | serial_omap_suspend(struct platform_device *pdev, pm_message_t state) | 1164 | static int serial_omap_suspend(struct device *dev) |
1065 | { | 1165 | { |
1066 | struct uart_omap_port *up = platform_get_drvdata(pdev); | 1166 | struct uart_omap_port *up = dev_get_drvdata(dev); |
1067 | 1167 | ||
1068 | if (up) | 1168 | if (up) { |
1069 | uart_suspend_port(&serial_omap_reg, &up->port); | 1169 | uart_suspend_port(&serial_omap_reg, &up->port); |
1170 | flush_work_sync(&up->qos_work); | ||
1171 | } | ||
1172 | |||
1070 | return 0; | 1173 | return 0; |
1071 | } | 1174 | } |
1072 | 1175 | ||
1073 | static int serial_omap_resume(struct platform_device *dev) | 1176 | static int serial_omap_resume(struct device *dev) |
1074 | { | 1177 | { |
1075 | struct uart_omap_port *up = platform_get_drvdata(dev); | 1178 | struct uart_omap_port *up = dev_get_drvdata(dev); |
1076 | 1179 | ||
1077 | if (up) | 1180 | if (up) |
1078 | uart_resume_port(&serial_omap_reg, &up->port); | 1181 | uart_resume_port(&serial_omap_reg, &up->port); |
1079 | return 0; | 1182 | return 0; |
1080 | } | 1183 | } |
1184 | #endif | ||
1081 | 1185 | ||
1082 | static void serial_omap_rx_timeout(unsigned long uart_no) | 1186 | static void serial_omap_rxdma_poll(unsigned long uart_no) |
1083 | { | 1187 | { |
1084 | struct uart_omap_port *up = ui[uart_no]; | 1188 | struct uart_omap_port *up = ui[uart_no]; |
1085 | unsigned int curr_dma_pos, curr_transmitted_size; | 1189 | unsigned int curr_dma_pos, curr_transmitted_size; |
@@ -1089,9 +1193,9 @@ static void serial_omap_rx_timeout(unsigned long uart_no) | |||
1089 | if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) || | 1193 | if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) || |
1090 | (curr_dma_pos == 0)) { | 1194 | (curr_dma_pos == 0)) { |
1091 | if (jiffies_to_msecs(jiffies - up->port_activity) < | 1195 | if (jiffies_to_msecs(jiffies - up->port_activity) < |
1092 | RX_TIMEOUT) { | 1196 | up->uart_dma.rx_timeout) { |
1093 | mod_timer(&up->uart_dma.rx_timer, jiffies + | 1197 | mod_timer(&up->uart_dma.rx_timer, jiffies + |
1094 | usecs_to_jiffies(up->uart_dma.rx_timeout)); | 1198 | usecs_to_jiffies(up->uart_dma.rx_poll_rate)); |
1095 | } else { | 1199 | } else { |
1096 | serial_omap_stop_rxdma(up); | 1200 | serial_omap_stop_rxdma(up); |
1097 | up->ier |= (UART_IER_RDI | UART_IER_RLSI); | 1201 | up->ier |= (UART_IER_RDI | UART_IER_RLSI); |
@@ -1120,7 +1224,7 @@ static void serial_omap_rx_timeout(unsigned long uart_no) | |||
1120 | } | 1224 | } |
1121 | } else { | 1225 | } else { |
1122 | mod_timer(&up->uart_dma.rx_timer, jiffies + | 1226 | mod_timer(&up->uart_dma.rx_timer, jiffies + |
1123 | usecs_to_jiffies(up->uart_dma.rx_timeout)); | 1227 | usecs_to_jiffies(up->uart_dma.rx_poll_rate)); |
1124 | } | 1228 | } |
1125 | up->port_activity = jiffies; | 1229 | up->port_activity = jiffies; |
1126 | } | 1230 | } |
@@ -1135,6 +1239,7 @@ static int serial_omap_start_rxdma(struct uart_omap_port *up) | |||
1135 | int ret = 0; | 1239 | int ret = 0; |
1136 | 1240 | ||
1137 | if (up->uart_dma.rx_dma_channel == -1) { | 1241 | if (up->uart_dma.rx_dma_channel == -1) { |
1242 | pm_runtime_get_sync(&up->pdev->dev); | ||
1138 | ret = omap_request_dma(up->uart_dma.uart_dma_rx, | 1243 | ret = omap_request_dma(up->uart_dma.uart_dma_rx, |
1139 | "UART Rx DMA", | 1244 | "UART Rx DMA", |
1140 | (void *)uart_rx_dma_callback, up, | 1245 | (void *)uart_rx_dma_callback, up, |
@@ -1158,7 +1263,7 @@ static int serial_omap_start_rxdma(struct uart_omap_port *up) | |||
1158 | /* FIXME: Cache maintenance needed here? */ | 1263 | /* FIXME: Cache maintenance needed here? */ |
1159 | omap_start_dma(up->uart_dma.rx_dma_channel); | 1264 | omap_start_dma(up->uart_dma.rx_dma_channel); |
1160 | mod_timer(&up->uart_dma.rx_timer, jiffies + | 1265 | mod_timer(&up->uart_dma.rx_timer, jiffies + |
1161 | usecs_to_jiffies(up->uart_dma.rx_timeout)); | 1266 | usecs_to_jiffies(up->uart_dma.rx_poll_rate)); |
1162 | up->uart_dma.rx_dma_used = true; | 1267 | up->uart_dma.rx_dma_used = true; |
1163 | return ret; | 1268 | return ret; |
1164 | } | 1269 | } |
@@ -1221,6 +1326,19 @@ static void uart_tx_dma_callback(int lch, u16 ch_status, void *data) | |||
1221 | return; | 1326 | return; |
1222 | } | 1327 | } |
1223 | 1328 | ||
1329 | static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev) | ||
1330 | { | ||
1331 | struct omap_uart_port_info *omap_up_info; | ||
1332 | |||
1333 | omap_up_info = devm_kzalloc(dev, sizeof(*omap_up_info), GFP_KERNEL); | ||
1334 | if (!omap_up_info) | ||
1335 | return NULL; /* out of memory */ | ||
1336 | |||
1337 | of_property_read_u32(dev->of_node, "clock-frequency", | ||
1338 | &omap_up_info->uartclk); | ||
1339 | return omap_up_info; | ||
1340 | } | ||
1341 | |||
1224 | static int serial_omap_probe(struct platform_device *pdev) | 1342 | static int serial_omap_probe(struct platform_device *pdev) |
1225 | { | 1343 | { |
1226 | struct uart_omap_port *up; | 1344 | struct uart_omap_port *up; |
@@ -1228,6 +1346,9 @@ static int serial_omap_probe(struct platform_device *pdev) | |||
1228 | struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data; | 1346 | struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data; |
1229 | int ret = -ENOSPC; | 1347 | int ret = -ENOSPC; |
1230 | 1348 | ||
1349 | if (pdev->dev.of_node) | ||
1350 | omap_up_info = of_get_uart_port_info(&pdev->dev); | ||
1351 | |||
1231 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1352 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1232 | if (!mem) { | 1353 | if (!mem) { |
1233 | dev_err(&pdev->dev, "no mem resource?\n"); | 1354 | dev_err(&pdev->dev, "no mem resource?\n"); |
@@ -1263,7 +1384,6 @@ static int serial_omap_probe(struct platform_device *pdev) | |||
1263 | ret = -ENOMEM; | 1384 | ret = -ENOMEM; |
1264 | goto do_release_region; | 1385 | goto do_release_region; |
1265 | } | 1386 | } |
1266 | sprintf(up->name, "OMAP UART%d", pdev->id); | ||
1267 | up->pdev = pdev; | 1387 | up->pdev = pdev; |
1268 | up->port.dev = &pdev->dev; | 1388 | up->port.dev = &pdev->dev; |
1269 | up->port.type = PORT_OMAP; | 1389 | up->port.type = PORT_OMAP; |
@@ -1273,34 +1393,74 @@ static int serial_omap_probe(struct platform_device *pdev) | |||
1273 | up->port.regshift = 2; | 1393 | up->port.regshift = 2; |
1274 | up->port.fifosize = 64; | 1394 | up->port.fifosize = 64; |
1275 | up->port.ops = &serial_omap_pops; | 1395 | up->port.ops = &serial_omap_pops; |
1276 | up->port.line = pdev->id; | ||
1277 | 1396 | ||
1278 | up->port.membase = omap_up_info->membase; | 1397 | if (pdev->dev.of_node) |
1279 | up->port.mapbase = omap_up_info->mapbase; | 1398 | up->port.line = of_alias_get_id(pdev->dev.of_node, "serial"); |
1399 | else | ||
1400 | up->port.line = pdev->id; | ||
1401 | |||
1402 | if (up->port.line < 0) { | ||
1403 | dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", | ||
1404 | up->port.line); | ||
1405 | ret = -ENODEV; | ||
1406 | goto err; | ||
1407 | } | ||
1408 | |||
1409 | sprintf(up->name, "OMAP UART%d", up->port.line); | ||
1410 | up->port.mapbase = mem->start; | ||
1411 | up->port.membase = ioremap(mem->start, resource_size(mem)); | ||
1412 | if (!up->port.membase) { | ||
1413 | dev_err(&pdev->dev, "can't ioremap UART\n"); | ||
1414 | ret = -ENOMEM; | ||
1415 | goto err; | ||
1416 | } | ||
1417 | |||
1280 | up->port.flags = omap_up_info->flags; | 1418 | up->port.flags = omap_up_info->flags; |
1281 | up->port.irqflags = omap_up_info->irqflags; | ||
1282 | up->port.uartclk = omap_up_info->uartclk; | 1419 | up->port.uartclk = omap_up_info->uartclk; |
1420 | if (!up->port.uartclk) { | ||
1421 | up->port.uartclk = DEFAULT_CLK_SPEED; | ||
1422 | dev_warn(&pdev->dev, "No clock speed specified: using default:" | ||
1423 | "%d\n", DEFAULT_CLK_SPEED); | ||
1424 | } | ||
1283 | up->uart_dma.uart_base = mem->start; | 1425 | up->uart_dma.uart_base = mem->start; |
1426 | up->errata = omap_up_info->errata; | ||
1284 | 1427 | ||
1285 | if (omap_up_info->dma_enabled) { | 1428 | if (omap_up_info->dma_enabled) { |
1286 | up->uart_dma.uart_dma_tx = dma_tx->start; | 1429 | up->uart_dma.uart_dma_tx = dma_tx->start; |
1287 | up->uart_dma.uart_dma_rx = dma_rx->start; | 1430 | up->uart_dma.uart_dma_rx = dma_rx->start; |
1288 | up->use_dma = 1; | 1431 | up->use_dma = 1; |
1289 | up->uart_dma.rx_buf_size = 4096; | 1432 | up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size; |
1290 | up->uart_dma.rx_timeout = 2; | 1433 | up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout; |
1434 | up->uart_dma.rx_poll_rate = omap_up_info->dma_rx_poll_rate; | ||
1291 | spin_lock_init(&(up->uart_dma.tx_lock)); | 1435 | spin_lock_init(&(up->uart_dma.tx_lock)); |
1292 | spin_lock_init(&(up->uart_dma.rx_lock)); | 1436 | spin_lock_init(&(up->uart_dma.rx_lock)); |
1293 | up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; | 1437 | up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; |
1294 | up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; | 1438 | up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; |
1295 | } | 1439 | } |
1296 | 1440 | ||
1297 | ui[pdev->id] = up; | 1441 | up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; |
1442 | up->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; | ||
1443 | pm_qos_add_request(&up->pm_qos_request, | ||
1444 | PM_QOS_CPU_DMA_LATENCY, up->latency); | ||
1445 | serial_omap_uart_wq = create_singlethread_workqueue(up->name); | ||
1446 | INIT_WORK(&up->qos_work, serial_omap_uart_qos_work); | ||
1447 | |||
1448 | pm_runtime_use_autosuspend(&pdev->dev); | ||
1449 | pm_runtime_set_autosuspend_delay(&pdev->dev, | ||
1450 | omap_up_info->autosuspend_timeout); | ||
1451 | |||
1452 | pm_runtime_irq_safe(&pdev->dev); | ||
1453 | pm_runtime_enable(&pdev->dev); | ||
1454 | pm_runtime_get_sync(&pdev->dev); | ||
1455 | |||
1456 | ui[up->port.line] = up; | ||
1298 | serial_omap_add_console_port(up); | 1457 | serial_omap_add_console_port(up); |
1299 | 1458 | ||
1300 | ret = uart_add_one_port(&serial_omap_reg, &up->port); | 1459 | ret = uart_add_one_port(&serial_omap_reg, &up->port); |
1301 | if (ret != 0) | 1460 | if (ret != 0) |
1302 | goto do_release_region; | 1461 | goto do_release_region; |
1303 | 1462 | ||
1463 | pm_runtime_put(&pdev->dev); | ||
1304 | platform_set_drvdata(pdev, up); | 1464 | platform_set_drvdata(pdev, up); |
1305 | return 0; | 1465 | return 0; |
1306 | err: | 1466 | err: |
@@ -1315,22 +1475,168 @@ static int serial_omap_remove(struct platform_device *dev) | |||
1315 | { | 1475 | { |
1316 | struct uart_omap_port *up = platform_get_drvdata(dev); | 1476 | struct uart_omap_port *up = platform_get_drvdata(dev); |
1317 | 1477 | ||
1318 | platform_set_drvdata(dev, NULL); | ||
1319 | if (up) { | 1478 | if (up) { |
1479 | pm_runtime_disable(&up->pdev->dev); | ||
1320 | uart_remove_one_port(&serial_omap_reg, &up->port); | 1480 | uart_remove_one_port(&serial_omap_reg, &up->port); |
1481 | pm_qos_remove_request(&up->pm_qos_request); | ||
1482 | |||
1321 | kfree(up); | 1483 | kfree(up); |
1322 | } | 1484 | } |
1485 | |||
1486 | platform_set_drvdata(dev, NULL); | ||
1323 | return 0; | 1487 | return 0; |
1324 | } | 1488 | } |
1325 | 1489 | ||
1490 | /* | ||
1491 | * Work Around for Errata i202 (2430, 3430, 3630, 4430 and 4460) | ||
1492 | * The access to uart register after MDR1 Access | ||
1493 | * causes UART to corrupt data. | ||
1494 | * | ||
1495 | * Need a delay = | ||
1496 | * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS) | ||
1497 | * give 10 times as much | ||
1498 | */ | ||
1499 | static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1) | ||
1500 | { | ||
1501 | u8 timeout = 255; | ||
1502 | |||
1503 | serial_out(up, UART_OMAP_MDR1, mdr1); | ||
1504 | udelay(2); | ||
1505 | serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT | | ||
1506 | UART_FCR_CLEAR_RCVR); | ||
1507 | /* | ||
1508 | * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and | ||
1509 | * TX_FIFO_E bit is 1. | ||
1510 | */ | ||
1511 | while (UART_LSR_THRE != (serial_in(up, UART_LSR) & | ||
1512 | (UART_LSR_THRE | UART_LSR_DR))) { | ||
1513 | timeout--; | ||
1514 | if (!timeout) { | ||
1515 | /* Should *never* happen. we warn and carry on */ | ||
1516 | dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n", | ||
1517 | serial_in(up, UART_LSR)); | ||
1518 | break; | ||
1519 | } | ||
1520 | udelay(1); | ||
1521 | } | ||
1522 | } | ||
1523 | |||
1524 | static void serial_omap_restore_context(struct uart_omap_port *up) | ||
1525 | { | ||
1526 | if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) | ||
1527 | serial_omap_mdr1_errataset(up, UART_OMAP_MDR1_DISABLE); | ||
1528 | else | ||
1529 | serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); | ||
1530 | |||
1531 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */ | ||
1532 | serial_out(up, UART_EFR, UART_EFR_ECB); | ||
1533 | serial_out(up, UART_LCR, 0x0); /* Operational mode */ | ||
1534 | serial_out(up, UART_IER, 0x0); | ||
1535 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */ | ||
1536 | serial_out(up, UART_DLL, up->dll); | ||
1537 | serial_out(up, UART_DLM, up->dlh); | ||
1538 | serial_out(up, UART_LCR, 0x0); /* Operational mode */ | ||
1539 | serial_out(up, UART_IER, up->ier); | ||
1540 | serial_out(up, UART_FCR, up->fcr); | ||
1541 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); | ||
1542 | serial_out(up, UART_MCR, up->mcr); | ||
1543 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */ | ||
1544 | serial_out(up, UART_OMAP_SCR, up->scr); | ||
1545 | serial_out(up, UART_EFR, up->efr); | ||
1546 | serial_out(up, UART_LCR, up->lcr); | ||
1547 | if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) | ||
1548 | serial_omap_mdr1_errataset(up, up->mdr1); | ||
1549 | else | ||
1550 | serial_out(up, UART_OMAP_MDR1, up->mdr1); | ||
1551 | } | ||
1552 | |||
1553 | #ifdef CONFIG_PM_RUNTIME | ||
1554 | static int serial_omap_runtime_suspend(struct device *dev) | ||
1555 | { | ||
1556 | struct uart_omap_port *up = dev_get_drvdata(dev); | ||
1557 | struct omap_uart_port_info *pdata = dev->platform_data; | ||
1558 | |||
1559 | if (!up) | ||
1560 | return -EINVAL; | ||
1561 | |||
1562 | if (!pdata || !pdata->enable_wakeup) | ||
1563 | return 0; | ||
1564 | |||
1565 | if (pdata->get_context_loss_count) | ||
1566 | up->context_loss_cnt = pdata->get_context_loss_count(dev); | ||
1567 | |||
1568 | if (device_may_wakeup(dev)) { | ||
1569 | if (!up->wakeups_enabled) { | ||
1570 | pdata->enable_wakeup(up->pdev, true); | ||
1571 | up->wakeups_enabled = true; | ||
1572 | } | ||
1573 | } else { | ||
1574 | if (up->wakeups_enabled) { | ||
1575 | pdata->enable_wakeup(up->pdev, false); | ||
1576 | up->wakeups_enabled = false; | ||
1577 | } | ||
1578 | } | ||
1579 | |||
1580 | /* Errata i291 */ | ||
1581 | if (up->use_dma && pdata->set_forceidle && | ||
1582 | (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE)) | ||
1583 | pdata->set_forceidle(up->pdev); | ||
1584 | |||
1585 | up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; | ||
1586 | schedule_work(&up->qos_work); | ||
1587 | |||
1588 | return 0; | ||
1589 | } | ||
1590 | |||
1591 | static int serial_omap_runtime_resume(struct device *dev) | ||
1592 | { | ||
1593 | struct uart_omap_port *up = dev_get_drvdata(dev); | ||
1594 | struct omap_uart_port_info *pdata = dev->platform_data; | ||
1595 | |||
1596 | if (up) { | ||
1597 | if (pdata->get_context_loss_count) { | ||
1598 | u32 loss_cnt = pdata->get_context_loss_count(dev); | ||
1599 | |||
1600 | if (up->context_loss_cnt != loss_cnt) | ||
1601 | serial_omap_restore_context(up); | ||
1602 | } | ||
1603 | |||
1604 | /* Errata i291 */ | ||
1605 | if (up->use_dma && pdata->set_noidle && | ||
1606 | (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE)) | ||
1607 | pdata->set_noidle(up->pdev); | ||
1608 | |||
1609 | up->latency = up->calc_latency; | ||
1610 | schedule_work(&up->qos_work); | ||
1611 | } | ||
1612 | |||
1613 | return 0; | ||
1614 | } | ||
1615 | #endif | ||
1616 | |||
1617 | static const struct dev_pm_ops serial_omap_dev_pm_ops = { | ||
1618 | SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume) | ||
1619 | SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend, | ||
1620 | serial_omap_runtime_resume, NULL) | ||
1621 | }; | ||
1622 | |||
1623 | #if defined(CONFIG_OF) | ||
1624 | static const struct of_device_id omap_serial_of_match[] = { | ||
1625 | { .compatible = "ti,omap2-uart" }, | ||
1626 | { .compatible = "ti,omap3-uart" }, | ||
1627 | { .compatible = "ti,omap4-uart" }, | ||
1628 | {}, | ||
1629 | }; | ||
1630 | MODULE_DEVICE_TABLE(of, omap_serial_of_match); | ||
1631 | #endif | ||
1632 | |||
1326 | static struct platform_driver serial_omap_driver = { | 1633 | static struct platform_driver serial_omap_driver = { |
1327 | .probe = serial_omap_probe, | 1634 | .probe = serial_omap_probe, |
1328 | .remove = serial_omap_remove, | 1635 | .remove = serial_omap_remove, |
1329 | |||
1330 | .suspend = serial_omap_suspend, | ||
1331 | .resume = serial_omap_resume, | ||
1332 | .driver = { | 1636 | .driver = { |
1333 | .name = DRIVER_NAME, | 1637 | .name = DRIVER_NAME, |
1638 | .pm = &serial_omap_dev_pm_ops, | ||
1639 | .of_match_table = of_match_ptr(omap_serial_of_match), | ||
1334 | }, | 1640 | }, |
1335 | }; | 1641 | }; |
1336 | 1642 | ||
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index d6aba8c087e4..de0f613ed6f5 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c | |||
@@ -25,6 +25,9 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/dmi.h> | 27 | #include <linux/dmi.h> |
28 | #include <linux/console.h> | ||
29 | #include <linux/nmi.h> | ||
30 | #include <linux/delay.h> | ||
28 | 31 | ||
29 | #include <linux/dmaengine.h> | 32 | #include <linux/dmaengine.h> |
30 | #include <linux/pch_dma.h> | 33 | #include <linux/pch_dma.h> |
@@ -198,6 +201,10 @@ enum { | |||
198 | 201 | ||
199 | #define PCI_VENDOR_ID_ROHM 0x10DB | 202 | #define PCI_VENDOR_ID_ROHM 0x10DB |
200 | 203 | ||
204 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) | ||
205 | |||
206 | #define DEFAULT_BAUD_RATE 1843200 /* 1.8432MHz */ | ||
207 | |||
201 | struct pch_uart_buffer { | 208 | struct pch_uart_buffer { |
202 | unsigned char *buf; | 209 | unsigned char *buf; |
203 | int size; | 210 | int size; |
@@ -276,6 +283,9 @@ static struct pch_uart_driver_data drv_dat[] = { | |||
276 | [pch_ml7831_uart1] = {PCH_UART_2LINE, 1}, | 283 | [pch_ml7831_uart1] = {PCH_UART_2LINE, 1}, |
277 | }; | 284 | }; |
278 | 285 | ||
286 | #ifdef CONFIG_SERIAL_PCH_UART_CONSOLE | ||
287 | static struct eg20t_port *pch_uart_ports[PCH_UART_NR]; | ||
288 | #endif | ||
279 | static unsigned int default_baud = 9600; | 289 | static unsigned int default_baud = 9600; |
280 | static const int trigger_level_256[4] = { 1, 64, 128, 224 }; | 290 | static const int trigger_level_256[4] = { 1, 64, 128, 224 }; |
281 | static const int trigger_level_64[4] = { 1, 16, 32, 56 }; | 291 | static const int trigger_level_64[4] = { 1, 16, 32, 56 }; |
@@ -1385,6 +1395,143 @@ static struct uart_ops pch_uart_ops = { | |||
1385 | .verify_port = pch_uart_verify_port | 1395 | .verify_port = pch_uart_verify_port |
1386 | }; | 1396 | }; |
1387 | 1397 | ||
1398 | #ifdef CONFIG_SERIAL_PCH_UART_CONSOLE | ||
1399 | |||
1400 | /* | ||
1401 | * Wait for transmitter & holding register to empty | ||
1402 | */ | ||
1403 | static void wait_for_xmitr(struct eg20t_port *up, int bits) | ||
1404 | { | ||
1405 | unsigned int status, tmout = 10000; | ||
1406 | |||
1407 | /* Wait up to 10ms for the character(s) to be sent. */ | ||
1408 | for (;;) { | ||
1409 | status = ioread8(up->membase + UART_LSR); | ||
1410 | |||
1411 | if ((status & bits) == bits) | ||
1412 | break; | ||
1413 | if (--tmout == 0) | ||
1414 | break; | ||
1415 | udelay(1); | ||
1416 | } | ||
1417 | |||
1418 | /* Wait up to 1s for flow control if necessary */ | ||
1419 | if (up->port.flags & UPF_CONS_FLOW) { | ||
1420 | unsigned int tmout; | ||
1421 | for (tmout = 1000000; tmout; tmout--) { | ||
1422 | unsigned int msr = ioread8(up->membase + UART_MSR); | ||
1423 | if (msr & UART_MSR_CTS) | ||
1424 | break; | ||
1425 | udelay(1); | ||
1426 | touch_nmi_watchdog(); | ||
1427 | } | ||
1428 | } | ||
1429 | } | ||
1430 | |||
1431 | static void pch_console_putchar(struct uart_port *port, int ch) | ||
1432 | { | ||
1433 | struct eg20t_port *priv = | ||
1434 | container_of(port, struct eg20t_port, port); | ||
1435 | |||
1436 | wait_for_xmitr(priv, UART_LSR_THRE); | ||
1437 | iowrite8(ch, priv->membase + PCH_UART_THR); | ||
1438 | } | ||
1439 | |||
1440 | /* | ||
1441 | * Print a string to the serial port trying not to disturb | ||
1442 | * any possible real use of the port... | ||
1443 | * | ||
1444 | * The console_lock must be held when we get here. | ||
1445 | */ | ||
1446 | static void | ||
1447 | pch_console_write(struct console *co, const char *s, unsigned int count) | ||
1448 | { | ||
1449 | struct eg20t_port *priv; | ||
1450 | |||
1451 | unsigned long flags; | ||
1452 | u8 ier; | ||
1453 | int locked = 1; | ||
1454 | |||
1455 | priv = pch_uart_ports[co->index]; | ||
1456 | |||
1457 | touch_nmi_watchdog(); | ||
1458 | |||
1459 | local_irq_save(flags); | ||
1460 | if (priv->port.sysrq) { | ||
1461 | /* serial8250_handle_port() already took the lock */ | ||
1462 | locked = 0; | ||
1463 | } else if (oops_in_progress) { | ||
1464 | locked = spin_trylock(&priv->port.lock); | ||
1465 | } else | ||
1466 | spin_lock(&priv->port.lock); | ||
1467 | |||
1468 | /* | ||
1469 | * First save the IER then disable the interrupts | ||
1470 | */ | ||
1471 | ier = ioread8(priv->membase + UART_IER); | ||
1472 | |||
1473 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT); | ||
1474 | |||
1475 | uart_console_write(&priv->port, s, count, pch_console_putchar); | ||
1476 | |||
1477 | /* | ||
1478 | * Finally, wait for transmitter to become empty | ||
1479 | * and restore the IER | ||
1480 | */ | ||
1481 | wait_for_xmitr(priv, BOTH_EMPTY); | ||
1482 | iowrite8(ier, priv->membase + UART_IER); | ||
1483 | |||
1484 | if (locked) | ||
1485 | spin_unlock(&priv->port.lock); | ||
1486 | local_irq_restore(flags); | ||
1487 | } | ||
1488 | |||
1489 | static int __init pch_console_setup(struct console *co, char *options) | ||
1490 | { | ||
1491 | struct uart_port *port; | ||
1492 | int baud = 9600; | ||
1493 | int bits = 8; | ||
1494 | int parity = 'n'; | ||
1495 | int flow = 'n'; | ||
1496 | |||
1497 | /* | ||
1498 | * Check whether an invalid uart number has been specified, and | ||
1499 | * if so, search for the first available port that does have | ||
1500 | * console support. | ||
1501 | */ | ||
1502 | if (co->index >= PCH_UART_NR) | ||
1503 | co->index = 0; | ||
1504 | port = &pch_uart_ports[co->index]->port; | ||
1505 | |||
1506 | if (!port || (!port->iobase && !port->membase)) | ||
1507 | return -ENODEV; | ||
1508 | |||
1509 | /* setup uartclock */ | ||
1510 | port->uartclk = DEFAULT_BAUD_RATE; | ||
1511 | |||
1512 | if (options) | ||
1513 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
1514 | |||
1515 | return uart_set_options(port, co, baud, parity, bits, flow); | ||
1516 | } | ||
1517 | |||
1518 | static struct uart_driver pch_uart_driver; | ||
1519 | |||
1520 | static struct console pch_console = { | ||
1521 | .name = PCH_UART_DRIVER_DEVICE, | ||
1522 | .write = pch_console_write, | ||
1523 | .device = uart_console_device, | ||
1524 | .setup = pch_console_setup, | ||
1525 | .flags = CON_PRINTBUFFER | CON_ANYTIME, | ||
1526 | .index = -1, | ||
1527 | .data = &pch_uart_driver, | ||
1528 | }; | ||
1529 | |||
1530 | #define PCH_CONSOLE (&pch_console) | ||
1531 | #else | ||
1532 | #define PCH_CONSOLE NULL | ||
1533 | #endif | ||
1534 | |||
1388 | static struct uart_driver pch_uart_driver = { | 1535 | static struct uart_driver pch_uart_driver = { |
1389 | .owner = THIS_MODULE, | 1536 | .owner = THIS_MODULE, |
1390 | .driver_name = KBUILD_MODNAME, | 1537 | .driver_name = KBUILD_MODNAME, |
@@ -1392,6 +1539,7 @@ static struct uart_driver pch_uart_driver = { | |||
1392 | .major = 0, | 1539 | .major = 0, |
1393 | .minor = 0, | 1540 | .minor = 0, |
1394 | .nr = PCH_UART_NR, | 1541 | .nr = PCH_UART_NR, |
1542 | .cons = PCH_CONSOLE, | ||
1395 | }; | 1543 | }; |
1396 | 1544 | ||
1397 | static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | 1545 | static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, |
@@ -1418,7 +1566,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | |||
1418 | if (!rxbuf) | 1566 | if (!rxbuf) |
1419 | goto init_port_free_txbuf; | 1567 | goto init_port_free_txbuf; |
1420 | 1568 | ||
1421 | base_baud = 1843200; /* 1.8432MHz */ | 1569 | base_baud = DEFAULT_BAUD_RATE; |
1422 | 1570 | ||
1423 | /* quirk for CM-iTC board */ | 1571 | /* quirk for CM-iTC board */ |
1424 | board_name = dmi_get_system_info(DMI_BOARD_NAME); | 1572 | board_name = dmi_get_system_info(DMI_BOARD_NAME); |
@@ -1468,6 +1616,9 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | |||
1468 | pci_set_drvdata(pdev, priv); | 1616 | pci_set_drvdata(pdev, priv); |
1469 | pch_uart_hal_request(pdev, fifosize, base_baud); | 1617 | pch_uart_hal_request(pdev, fifosize, base_baud); |
1470 | 1618 | ||
1619 | #ifdef CONFIG_SERIAL_PCH_UART_CONSOLE | ||
1620 | pch_uart_ports[board->line_no] = priv; | ||
1621 | #endif | ||
1471 | ret = uart_add_one_port(&pch_uart_driver, &priv->port); | 1622 | ret = uart_add_one_port(&pch_uart_driver, &priv->port); |
1472 | if (ret < 0) | 1623 | if (ret < 0) |
1473 | goto init_port_hal_free; | 1624 | goto init_port_hal_free; |
@@ -1475,6 +1626,9 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | |||
1475 | return priv; | 1626 | return priv; |
1476 | 1627 | ||
1477 | init_port_hal_free: | 1628 | init_port_hal_free: |
1629 | #ifdef CONFIG_SERIAL_PCH_UART_CONSOLE | ||
1630 | pch_uart_ports[board->line_no] = NULL; | ||
1631 | #endif | ||
1478 | free_page((unsigned long)rxbuf); | 1632 | free_page((unsigned long)rxbuf); |
1479 | init_port_free_txbuf: | 1633 | init_port_free_txbuf: |
1480 | kfree(priv); | 1634 | kfree(priv); |
@@ -1497,6 +1651,10 @@ static void pch_uart_pci_remove(struct pci_dev *pdev) | |||
1497 | priv = (struct eg20t_port *)pci_get_drvdata(pdev); | 1651 | priv = (struct eg20t_port *)pci_get_drvdata(pdev); |
1498 | 1652 | ||
1499 | pci_disable_msi(pdev); | 1653 | pci_disable_msi(pdev); |
1654 | |||
1655 | #ifdef CONFIG_SERIAL_PCH_UART_CONSOLE | ||
1656 | pch_uart_ports[priv->port.line] = NULL; | ||
1657 | #endif | ||
1500 | pch_uart_exit_port(priv); | 1658 | pch_uart_exit_port(priv); |
1501 | pci_disable_device(pdev); | 1659 | pci_disable_device(pdev); |
1502 | kfree(priv); | 1660 | kfree(priv); |
diff --git a/drivers/tty/serial/s3c2410.c b/drivers/tty/serial/s3c2410.c deleted file mode 100644 index b1d7e7c1849d..000000000000 --- a/drivers/tty/serial/s3c2410.c +++ /dev/null | |||
@@ -1,115 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for Samsung S3C2410 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 | #include <linux/module.h> | ||
13 | #include <linux/ioport.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/serial_core.h> | ||
18 | #include <linux/serial.h> | ||
19 | |||
20 | #include <asm/irq.h> | ||
21 | #include <mach/hardware.h> | ||
22 | |||
23 | #include <plat/regs-serial.h> | ||
24 | #include <mach/regs-gpio.h> | ||
25 | |||
26 | #include "samsung.h" | ||
27 | |||
28 | static int s3c2410_serial_setsource(struct uart_port *port, | ||
29 | struct s3c24xx_uart_clksrc *clk) | ||
30 | { | ||
31 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
32 | |||
33 | if (strcmp(clk->name, "uclk") == 0) | ||
34 | ucon |= S3C2410_UCON_UCLK; | ||
35 | else | ||
36 | ucon &= ~S3C2410_UCON_UCLK; | ||
37 | |||
38 | wr_regl(port, S3C2410_UCON, ucon); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static int s3c2410_serial_getsource(struct uart_port *port, | ||
43 | struct s3c24xx_uart_clksrc *clk) | ||
44 | { | ||
45 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
46 | |||
47 | clk->divisor = 1; | ||
48 | clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk"; | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static int s3c2410_serial_resetport(struct uart_port *port, | ||
54 | struct s3c2410_uartcfg *cfg) | ||
55 | { | ||
56 | dbg("s3c2410_serial_resetport: port=%p (%08lx), cfg=%p\n", | ||
57 | port, port->mapbase, cfg); | ||
58 | |||
59 | wr_regl(port, S3C2410_UCON, cfg->ucon); | ||
60 | wr_regl(port, S3C2410_ULCON, cfg->ulcon); | ||
61 | |||
62 | /* reset both fifos */ | ||
63 | |||
64 | wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); | ||
65 | wr_regl(port, S3C2410_UFCON, cfg->ufcon); | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static struct s3c24xx_uart_info s3c2410_uart_inf = { | ||
71 | .name = "Samsung S3C2410 UART", | ||
72 | .type = PORT_S3C2410, | ||
73 | .fifosize = 16, | ||
74 | .rx_fifomask = S3C2410_UFSTAT_RXMASK, | ||
75 | .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT, | ||
76 | .rx_fifofull = S3C2410_UFSTAT_RXFULL, | ||
77 | .tx_fifofull = S3C2410_UFSTAT_TXFULL, | ||
78 | .tx_fifomask = S3C2410_UFSTAT_TXMASK, | ||
79 | .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT, | ||
80 | .get_clksrc = s3c2410_serial_getsource, | ||
81 | .set_clksrc = s3c2410_serial_setsource, | ||
82 | .reset_port = s3c2410_serial_resetport, | ||
83 | }; | ||
84 | |||
85 | static int s3c2410_serial_probe(struct platform_device *dev) | ||
86 | { | ||
87 | return s3c24xx_serial_probe(dev, &s3c2410_uart_inf); | ||
88 | } | ||
89 | |||
90 | static struct platform_driver s3c2410_serial_driver = { | ||
91 | .probe = s3c2410_serial_probe, | ||
92 | .remove = __devexit_p(s3c24xx_serial_remove), | ||
93 | .driver = { | ||
94 | .name = "s3c2410-uart", | ||
95 | .owner = THIS_MODULE, | ||
96 | }, | ||
97 | }; | ||
98 | |||
99 | static int __init s3c2410_serial_init(void) | ||
100 | { | ||
101 | return s3c24xx_serial_init(&s3c2410_serial_driver, &s3c2410_uart_inf); | ||
102 | } | ||
103 | |||
104 | static void __exit s3c2410_serial_exit(void) | ||
105 | { | ||
106 | platform_driver_unregister(&s3c2410_serial_driver); | ||
107 | } | ||
108 | |||
109 | module_init(s3c2410_serial_init); | ||
110 | module_exit(s3c2410_serial_exit); | ||
111 | |||
112 | MODULE_LICENSE("GPL v2"); | ||
113 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
114 | MODULE_DESCRIPTION("Samsung S3C2410 SoC Serial port driver"); | ||
115 | MODULE_ALIAS("platform:s3c2410-uart"); | ||
diff --git a/drivers/tty/serial/s3c2412.c b/drivers/tty/serial/s3c2412.c deleted file mode 100644 index 2234bf9ced45..000000000000 --- a/drivers/tty/serial/s3c2412.c +++ /dev/null | |||
@@ -1,149 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for Samsung S3C2412 and S3C2413 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 | #include <linux/module.h> | ||
13 | #include <linux/ioport.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/serial_core.h> | ||
18 | #include <linux/serial.h> | ||
19 | |||
20 | #include <asm/irq.h> | ||
21 | #include <mach/hardware.h> | ||
22 | |||
23 | #include <plat/regs-serial.h> | ||
24 | #include <mach/regs-gpio.h> | ||
25 | |||
26 | #include "samsung.h" | ||
27 | |||
28 | static int s3c2412_serial_setsource(struct uart_port *port, | ||
29 | struct s3c24xx_uart_clksrc *clk) | ||
30 | { | ||
31 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
32 | |||
33 | ucon &= ~S3C2412_UCON_CLKMASK; | ||
34 | |||
35 | if (strcmp(clk->name, "uclk") == 0) | ||
36 | ucon |= S3C2440_UCON_UCLK; | ||
37 | else if (strcmp(clk->name, "pclk") == 0) | ||
38 | ucon |= S3C2440_UCON_PCLK; | ||
39 | else if (strcmp(clk->name, "usysclk") == 0) | ||
40 | ucon |= S3C2412_UCON_USYSCLK; | ||
41 | else { | ||
42 | printk(KERN_ERR "unknown clock source %s\n", clk->name); | ||
43 | return -EINVAL; | ||
44 | } | ||
45 | |||
46 | wr_regl(port, S3C2410_UCON, ucon); | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | |||
51 | static int s3c2412_serial_getsource(struct uart_port *port, | ||
52 | struct s3c24xx_uart_clksrc *clk) | ||
53 | { | ||
54 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
55 | |||
56 | switch (ucon & S3C2412_UCON_CLKMASK) { | ||
57 | case S3C2412_UCON_UCLK: | ||
58 | clk->divisor = 1; | ||
59 | clk->name = "uclk"; | ||
60 | break; | ||
61 | |||
62 | case S3C2412_UCON_PCLK: | ||
63 | case S3C2412_UCON_PCLK2: | ||
64 | clk->divisor = 1; | ||
65 | clk->name = "pclk"; | ||
66 | break; | ||
67 | |||
68 | case S3C2412_UCON_USYSCLK: | ||
69 | clk->divisor = 1; | ||
70 | clk->name = "usysclk"; | ||
71 | break; | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int s3c2412_serial_resetport(struct uart_port *port, | ||
78 | struct s3c2410_uartcfg *cfg) | ||
79 | { | ||
80 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
81 | |||
82 | dbg("%s: port=%p (%08lx), cfg=%p\n", | ||
83 | __func__, port, port->mapbase, cfg); | ||
84 | |||
85 | /* ensure we don't change the clock settings... */ | ||
86 | |||
87 | ucon &= S3C2412_UCON_CLKMASK; | ||
88 | |||
89 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); | ||
90 | wr_regl(port, S3C2410_ULCON, cfg->ulcon); | ||
91 | |||
92 | /* reset both fifos */ | ||
93 | |||
94 | wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); | ||
95 | wr_regl(port, S3C2410_UFCON, cfg->ufcon); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static struct s3c24xx_uart_info s3c2412_uart_inf = { | ||
101 | .name = "Samsung S3C2412 UART", | ||
102 | .type = PORT_S3C2412, | ||
103 | .fifosize = 64, | ||
104 | .has_divslot = 1, | ||
105 | .rx_fifomask = S3C2440_UFSTAT_RXMASK, | ||
106 | .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, | ||
107 | .rx_fifofull = S3C2440_UFSTAT_RXFULL, | ||
108 | .tx_fifofull = S3C2440_UFSTAT_TXFULL, | ||
109 | .tx_fifomask = S3C2440_UFSTAT_TXMASK, | ||
110 | .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, | ||
111 | .get_clksrc = s3c2412_serial_getsource, | ||
112 | .set_clksrc = s3c2412_serial_setsource, | ||
113 | .reset_port = s3c2412_serial_resetport, | ||
114 | }; | ||
115 | |||
116 | /* device management */ | ||
117 | |||
118 | static int s3c2412_serial_probe(struct platform_device *dev) | ||
119 | { | ||
120 | dbg("s3c2440_serial_probe: dev=%p\n", dev); | ||
121 | return s3c24xx_serial_probe(dev, &s3c2412_uart_inf); | ||
122 | } | ||
123 | |||
124 | static struct platform_driver s3c2412_serial_driver = { | ||
125 | .probe = s3c2412_serial_probe, | ||
126 | .remove = __devexit_p(s3c24xx_serial_remove), | ||
127 | .driver = { | ||
128 | .name = "s3c2412-uart", | ||
129 | .owner = THIS_MODULE, | ||
130 | }, | ||
131 | }; | ||
132 | |||
133 | static inline int s3c2412_serial_init(void) | ||
134 | { | ||
135 | return s3c24xx_serial_init(&s3c2412_serial_driver, &s3c2412_uart_inf); | ||
136 | } | ||
137 | |||
138 | static inline void s3c2412_serial_exit(void) | ||
139 | { | ||
140 | platform_driver_unregister(&s3c2412_serial_driver); | ||
141 | } | ||
142 | |||
143 | module_init(s3c2412_serial_init); | ||
144 | module_exit(s3c2412_serial_exit); | ||
145 | |||
146 | MODULE_DESCRIPTION("Samsung S3C2412,S3C2413 SoC Serial port driver"); | ||
147 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
148 | MODULE_LICENSE("GPL v2"); | ||
149 | MODULE_ALIAS("platform:s3c2412-uart"); | ||
diff --git a/drivers/tty/serial/s3c2440.c b/drivers/tty/serial/s3c2440.c deleted file mode 100644 index 1d0c324b813f..000000000000 --- a/drivers/tty/serial/s3c2440.c +++ /dev/null | |||
@@ -1,178 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for Samsung S3C2440 and S3C2442 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 | #include <linux/module.h> | ||
13 | #include <linux/ioport.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/serial_core.h> | ||
18 | #include <linux/serial.h> | ||
19 | |||
20 | #include <asm/irq.h> | ||
21 | #include <mach/hardware.h> | ||
22 | |||
23 | #include <plat/regs-serial.h> | ||
24 | #include <mach/regs-gpio.h> | ||
25 | |||
26 | #include "samsung.h" | ||
27 | |||
28 | |||
29 | static int s3c2440_serial_setsource(struct uart_port *port, | ||
30 | struct s3c24xx_uart_clksrc *clk) | ||
31 | { | ||
32 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
33 | |||
34 | /* todo - proper fclk<>nonfclk switch. */ | ||
35 | |||
36 | ucon &= ~S3C2440_UCON_CLKMASK; | ||
37 | |||
38 | if (strcmp(clk->name, "uclk") == 0) | ||
39 | ucon |= S3C2440_UCON_UCLK; | ||
40 | else if (strcmp(clk->name, "pclk") == 0) | ||
41 | ucon |= S3C2440_UCON_PCLK; | ||
42 | else if (strcmp(clk->name, "fclk") == 0) | ||
43 | ucon |= S3C2440_UCON_FCLK; | ||
44 | else { | ||
45 | printk(KERN_ERR "unknown clock source %s\n", clk->name); | ||
46 | return -EINVAL; | ||
47 | } | ||
48 | |||
49 | wr_regl(port, S3C2410_UCON, ucon); | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | |||
54 | static int s3c2440_serial_getsource(struct uart_port *port, | ||
55 | struct s3c24xx_uart_clksrc *clk) | ||
56 | { | ||
57 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
58 | unsigned long ucon0, ucon1, ucon2; | ||
59 | |||
60 | switch (ucon & S3C2440_UCON_CLKMASK) { | ||
61 | case S3C2440_UCON_UCLK: | ||
62 | clk->divisor = 1; | ||
63 | clk->name = "uclk"; | ||
64 | break; | ||
65 | |||
66 | case S3C2440_UCON_PCLK: | ||
67 | case S3C2440_UCON_PCLK2: | ||
68 | clk->divisor = 1; | ||
69 | clk->name = "pclk"; | ||
70 | break; | ||
71 | |||
72 | case S3C2440_UCON_FCLK: | ||
73 | /* the fun of calculating the uart divisors on | ||
74 | * the s3c2440 */ | ||
75 | |||
76 | ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON); | ||
77 | ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON); | ||
78 | ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON); | ||
79 | |||
80 | printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2); | ||
81 | |||
82 | ucon0 &= S3C2440_UCON0_DIVMASK; | ||
83 | ucon1 &= S3C2440_UCON1_DIVMASK; | ||
84 | ucon2 &= S3C2440_UCON2_DIVMASK; | ||
85 | |||
86 | if (ucon0 != 0) { | ||
87 | clk->divisor = ucon0 >> S3C2440_UCON_DIVSHIFT; | ||
88 | clk->divisor += 6; | ||
89 | } else if (ucon1 != 0) { | ||
90 | clk->divisor = ucon1 >> S3C2440_UCON_DIVSHIFT; | ||
91 | clk->divisor += 21; | ||
92 | } else if (ucon2 != 0) { | ||
93 | clk->divisor = ucon2 >> S3C2440_UCON_DIVSHIFT; | ||
94 | clk->divisor += 36; | ||
95 | } else { | ||
96 | /* manual calims 44, seems to be 9 */ | ||
97 | clk->divisor = 9; | ||
98 | } | ||
99 | |||
100 | clk->name = "fclk"; | ||
101 | break; | ||
102 | } | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int s3c2440_serial_resetport(struct uart_port *port, | ||
108 | struct s3c2410_uartcfg *cfg) | ||
109 | { | ||
110 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
111 | |||
112 | dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n", | ||
113 | port, port->mapbase, cfg); | ||
114 | |||
115 | /* ensure we don't change the clock settings... */ | ||
116 | |||
117 | ucon &= (S3C2440_UCON0_DIVMASK | (3<<10)); | ||
118 | |||
119 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); | ||
120 | wr_regl(port, S3C2410_ULCON, cfg->ulcon); | ||
121 | |||
122 | /* reset both fifos */ | ||
123 | |||
124 | wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); | ||
125 | wr_regl(port, S3C2410_UFCON, cfg->ufcon); | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static struct s3c24xx_uart_info s3c2440_uart_inf = { | ||
131 | .name = "Samsung S3C2440 UART", | ||
132 | .type = PORT_S3C2440, | ||
133 | .fifosize = 64, | ||
134 | .rx_fifomask = S3C2440_UFSTAT_RXMASK, | ||
135 | .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, | ||
136 | .rx_fifofull = S3C2440_UFSTAT_RXFULL, | ||
137 | .tx_fifofull = S3C2440_UFSTAT_TXFULL, | ||
138 | .tx_fifomask = S3C2440_UFSTAT_TXMASK, | ||
139 | .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, | ||
140 | .get_clksrc = s3c2440_serial_getsource, | ||
141 | .set_clksrc = s3c2440_serial_setsource, | ||
142 | .reset_port = s3c2440_serial_resetport, | ||
143 | }; | ||
144 | |||
145 | /* device management */ | ||
146 | |||
147 | static int s3c2440_serial_probe(struct platform_device *dev) | ||
148 | { | ||
149 | dbg("s3c2440_serial_probe: dev=%p\n", dev); | ||
150 | return s3c24xx_serial_probe(dev, &s3c2440_uart_inf); | ||
151 | } | ||
152 | |||
153 | static struct platform_driver s3c2440_serial_driver = { | ||
154 | .probe = s3c2440_serial_probe, | ||
155 | .remove = __devexit_p(s3c24xx_serial_remove), | ||
156 | .driver = { | ||
157 | .name = "s3c2440-uart", | ||
158 | .owner = THIS_MODULE, | ||
159 | }, | ||
160 | }; | ||
161 | |||
162 | static int __init s3c2440_serial_init(void) | ||
163 | { | ||
164 | return s3c24xx_serial_init(&s3c2440_serial_driver, &s3c2440_uart_inf); | ||
165 | } | ||
166 | |||
167 | static void __exit s3c2440_serial_exit(void) | ||
168 | { | ||
169 | platform_driver_unregister(&s3c2440_serial_driver); | ||
170 | } | ||
171 | |||
172 | module_init(s3c2440_serial_init); | ||
173 | module_exit(s3c2440_serial_exit); | ||
174 | |||
175 | MODULE_DESCRIPTION("Samsung S3C2440,S3C2442 SoC Serial port driver"); | ||
176 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
177 | MODULE_LICENSE("GPL v2"); | ||
178 | MODULE_ALIAS("platform:s3c2440-uart"); | ||
diff --git a/drivers/tty/serial/s3c6400.c b/drivers/tty/serial/s3c6400.c deleted file mode 100644 index e2f6913d84d5..000000000000 --- a/drivers/tty/serial/s3c6400.c +++ /dev/null | |||
@@ -1,149 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs. | ||
3 | * | ||
4 | * Copyright 2008 Openmoko, Inc. | ||
5 | * Copyright 2008 Simtec Electronics | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * http://armlinux.simtec.co.uk/ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/ioport.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/serial_core.h> | ||
20 | #include <linux/serial.h> | ||
21 | |||
22 | #include <asm/irq.h> | ||
23 | #include <mach/hardware.h> | ||
24 | |||
25 | #include <plat/regs-serial.h> | ||
26 | |||
27 | #include "samsung.h" | ||
28 | |||
29 | static int s3c6400_serial_setsource(struct uart_port *port, | ||
30 | struct s3c24xx_uart_clksrc *clk) | ||
31 | { | ||
32 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
33 | |||
34 | if (strcmp(clk->name, "uclk0") == 0) { | ||
35 | ucon &= ~S3C6400_UCON_CLKMASK; | ||
36 | ucon |= S3C6400_UCON_UCLK0; | ||
37 | } else if (strcmp(clk->name, "uclk1") == 0) | ||
38 | ucon |= S3C6400_UCON_UCLK1; | ||
39 | else if (strcmp(clk->name, "pclk") == 0) { | ||
40 | /* See notes about transitioning from UCLK to PCLK */ | ||
41 | ucon &= ~S3C6400_UCON_UCLK0; | ||
42 | } else { | ||
43 | printk(KERN_ERR "unknown clock source %s\n", clk->name); | ||
44 | return -EINVAL; | ||
45 | } | ||
46 | |||
47 | wr_regl(port, S3C2410_UCON, ucon); | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | |||
52 | static int s3c6400_serial_getsource(struct uart_port *port, | ||
53 | struct s3c24xx_uart_clksrc *clk) | ||
54 | { | ||
55 | u32 ucon = rd_regl(port, S3C2410_UCON); | ||
56 | |||
57 | clk->divisor = 1; | ||
58 | |||
59 | switch (ucon & S3C6400_UCON_CLKMASK) { | ||
60 | case S3C6400_UCON_UCLK0: | ||
61 | clk->name = "uclk0"; | ||
62 | break; | ||
63 | |||
64 | case S3C6400_UCON_UCLK1: | ||
65 | clk->name = "uclk1"; | ||
66 | break; | ||
67 | |||
68 | case S3C6400_UCON_PCLK: | ||
69 | case S3C6400_UCON_PCLK2: | ||
70 | clk->name = "pclk"; | ||
71 | break; | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int s3c6400_serial_resetport(struct uart_port *port, | ||
78 | struct s3c2410_uartcfg *cfg) | ||
79 | { | ||
80 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
81 | |||
82 | dbg("s3c6400_serial_resetport: port=%p (%08lx), cfg=%p\n", | ||
83 | port, port->mapbase, cfg); | ||
84 | |||
85 | /* ensure we don't change the clock settings... */ | ||
86 | |||
87 | ucon &= S3C6400_UCON_CLKMASK; | ||
88 | |||
89 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); | ||
90 | wr_regl(port, S3C2410_ULCON, cfg->ulcon); | ||
91 | |||
92 | /* reset both fifos */ | ||
93 | |||
94 | wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); | ||
95 | wr_regl(port, S3C2410_UFCON, cfg->ufcon); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static struct s3c24xx_uart_info s3c6400_uart_inf = { | ||
101 | .name = "Samsung S3C6400 UART", | ||
102 | .type = PORT_S3C6400, | ||
103 | .fifosize = 64, | ||
104 | .has_divslot = 1, | ||
105 | .rx_fifomask = S3C2440_UFSTAT_RXMASK, | ||
106 | .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, | ||
107 | .rx_fifofull = S3C2440_UFSTAT_RXFULL, | ||
108 | .tx_fifofull = S3C2440_UFSTAT_TXFULL, | ||
109 | .tx_fifomask = S3C2440_UFSTAT_TXMASK, | ||
110 | .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, | ||
111 | .get_clksrc = s3c6400_serial_getsource, | ||
112 | .set_clksrc = s3c6400_serial_setsource, | ||
113 | .reset_port = s3c6400_serial_resetport, | ||
114 | }; | ||
115 | |||
116 | /* device management */ | ||
117 | |||
118 | static int s3c6400_serial_probe(struct platform_device *dev) | ||
119 | { | ||
120 | dbg("s3c6400_serial_probe: dev=%p\n", dev); | ||
121 | return s3c24xx_serial_probe(dev, &s3c6400_uart_inf); | ||
122 | } | ||
123 | |||
124 | static struct platform_driver s3c6400_serial_driver = { | ||
125 | .probe = s3c6400_serial_probe, | ||
126 | .remove = __devexit_p(s3c24xx_serial_remove), | ||
127 | .driver = { | ||
128 | .name = "s3c6400-uart", | ||
129 | .owner = THIS_MODULE, | ||
130 | }, | ||
131 | }; | ||
132 | |||
133 | static int __init s3c6400_serial_init(void) | ||
134 | { | ||
135 | return s3c24xx_serial_init(&s3c6400_serial_driver, &s3c6400_uart_inf); | ||
136 | } | ||
137 | |||
138 | static void __exit s3c6400_serial_exit(void) | ||
139 | { | ||
140 | platform_driver_unregister(&s3c6400_serial_driver); | ||
141 | } | ||
142 | |||
143 | module_init(s3c6400_serial_init); | ||
144 | module_exit(s3c6400_serial_exit); | ||
145 | |||
146 | MODULE_DESCRIPTION("Samsung S3C6400,S3C6410 SoC Serial port driver"); | ||
147 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
148 | MODULE_LICENSE("GPL v2"); | ||
149 | MODULE_ALIAS("platform:s3c6400-uart"); | ||
diff --git a/drivers/tty/serial/s5pv210.c b/drivers/tty/serial/s5pv210.c deleted file mode 100644 index 8b0b888a1b76..000000000000 --- a/drivers/tty/serial/s5pv210.c +++ /dev/null | |||
@@ -1,158 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
3 | * http://www.samsung.com/ | ||
4 | * | ||
5 | * Based on drivers/serial/s3c6400.c | ||
6 | * | ||
7 | * Driver for Samsung S5PV210 SoC UARTs. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/ioport.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/serial_core.h> | ||
20 | #include <linux/serial.h> | ||
21 | #include <linux/delay.h> | ||
22 | |||
23 | #include <asm/irq.h> | ||
24 | #include <mach/hardware.h> | ||
25 | #include <plat/regs-serial.h> | ||
26 | #include "samsung.h" | ||
27 | |||
28 | static int s5pv210_serial_setsource(struct uart_port *port, | ||
29 | struct s3c24xx_uart_clksrc *clk) | ||
30 | { | ||
31 | struct s3c2410_uartcfg *cfg = port->dev->platform_data; | ||
32 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
33 | |||
34 | if (cfg->flags & NO_NEED_CHECK_CLKSRC) | ||
35 | return 0; | ||
36 | |||
37 | if (strcmp(clk->name, "pclk") == 0) | ||
38 | ucon &= ~S5PV210_UCON_CLKMASK; | ||
39 | else if (strcmp(clk->name, "uclk1") == 0) | ||
40 | ucon |= S5PV210_UCON_CLKMASK; | ||
41 | else { | ||
42 | printk(KERN_ERR "unknown clock source %s\n", clk->name); | ||
43 | return -EINVAL; | ||
44 | } | ||
45 | |||
46 | wr_regl(port, S3C2410_UCON, ucon); | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | |||
51 | static int s5pv210_serial_getsource(struct uart_port *port, | ||
52 | struct s3c24xx_uart_clksrc *clk) | ||
53 | { | ||
54 | struct s3c2410_uartcfg *cfg = port->dev->platform_data; | ||
55 | u32 ucon = rd_regl(port, S3C2410_UCON); | ||
56 | |||
57 | clk->divisor = 1; | ||
58 | |||
59 | if (cfg->flags & NO_NEED_CHECK_CLKSRC) | ||
60 | return 0; | ||
61 | |||
62 | switch (ucon & S5PV210_UCON_CLKMASK) { | ||
63 | case S5PV210_UCON_PCLK: | ||
64 | clk->name = "pclk"; | ||
65 | break; | ||
66 | case S5PV210_UCON_UCLK: | ||
67 | clk->name = "uclk1"; | ||
68 | break; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int s5pv210_serial_resetport(struct uart_port *port, | ||
75 | struct s3c2410_uartcfg *cfg) | ||
76 | { | ||
77 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
78 | |||
79 | ucon &= S5PV210_UCON_CLKMASK; | ||
80 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); | ||
81 | wr_regl(port, S3C2410_ULCON, cfg->ulcon); | ||
82 | |||
83 | /* reset both fifos */ | ||
84 | wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); | ||
85 | wr_regl(port, S3C2410_UFCON, cfg->ufcon); | ||
86 | |||
87 | /* It is need to delay When reset FIFO register */ | ||
88 | udelay(1); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | #define S5PV210_UART_DEFAULT_INFO(fifo_size) \ | ||
94 | .name = "Samsung S5PV210 UART0", \ | ||
95 | .type = PORT_S3C6400, \ | ||
96 | .fifosize = fifo_size, \ | ||
97 | .has_divslot = 1, \ | ||
98 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, \ | ||
99 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \ | ||
100 | .rx_fifofull = S5PV210_UFSTAT_RXFULL, \ | ||
101 | .tx_fifofull = S5PV210_UFSTAT_TXFULL, \ | ||
102 | .tx_fifomask = S5PV210_UFSTAT_TXMASK, \ | ||
103 | .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, \ | ||
104 | .get_clksrc = s5pv210_serial_getsource, \ | ||
105 | .set_clksrc = s5pv210_serial_setsource, \ | ||
106 | .reset_port = s5pv210_serial_resetport | ||
107 | |||
108 | static struct s3c24xx_uart_info s5p_port_fifo256 = { | ||
109 | S5PV210_UART_DEFAULT_INFO(256), | ||
110 | }; | ||
111 | |||
112 | static struct s3c24xx_uart_info s5p_port_fifo64 = { | ||
113 | S5PV210_UART_DEFAULT_INFO(64), | ||
114 | }; | ||
115 | |||
116 | static struct s3c24xx_uart_info s5p_port_fifo16 = { | ||
117 | S5PV210_UART_DEFAULT_INFO(16), | ||
118 | }; | ||
119 | |||
120 | static struct s3c24xx_uart_info *s5p_uart_inf[] = { | ||
121 | [0] = &s5p_port_fifo256, | ||
122 | [1] = &s5p_port_fifo64, | ||
123 | [2] = &s5p_port_fifo16, | ||
124 | [3] = &s5p_port_fifo16, | ||
125 | }; | ||
126 | |||
127 | /* device management */ | ||
128 | static int s5p_serial_probe(struct platform_device *pdev) | ||
129 | { | ||
130 | return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]); | ||
131 | } | ||
132 | |||
133 | static struct platform_driver s5p_serial_driver = { | ||
134 | .probe = s5p_serial_probe, | ||
135 | .remove = __devexit_p(s3c24xx_serial_remove), | ||
136 | .driver = { | ||
137 | .name = "s5pv210-uart", | ||
138 | .owner = THIS_MODULE, | ||
139 | }, | ||
140 | }; | ||
141 | |||
142 | static int __init s5p_serial_init(void) | ||
143 | { | ||
144 | return s3c24xx_serial_init(&s5p_serial_driver, *s5p_uart_inf); | ||
145 | } | ||
146 | |||
147 | static void __exit s5p_serial_exit(void) | ||
148 | { | ||
149 | platform_driver_unregister(&s5p_serial_driver); | ||
150 | } | ||
151 | |||
152 | module_init(s5p_serial_init); | ||
153 | module_exit(s5p_serial_exit); | ||
154 | |||
155 | MODULE_LICENSE("GPL"); | ||
156 | MODULE_ALIAS("platform:s5pv210-uart"); | ||
157 | MODULE_DESCRIPTION("Samsung S5PV210 UART Driver support"); | ||
158 | MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>"); | ||
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index b31f1c3a2c4c..f96f37b5fec6 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/delay.h> | 42 | #include <linux/delay.h> |
43 | #include <linux/clk.h> | 43 | #include <linux/clk.h> |
44 | #include <linux/cpufreq.h> | 44 | #include <linux/cpufreq.h> |
45 | #include <linux/of.h> | ||
45 | 46 | ||
46 | #include <asm/irq.h> | 47 | #include <asm/irq.h> |
47 | 48 | ||
@@ -49,6 +50,7 @@ | |||
49 | #include <mach/map.h> | 50 | #include <mach/map.h> |
50 | 51 | ||
51 | #include <plat/regs-serial.h> | 52 | #include <plat/regs-serial.h> |
53 | #include <plat/clock.h> | ||
52 | 54 | ||
53 | #include "samsung.h" | 55 | #include "samsung.h" |
54 | 56 | ||
@@ -190,10 +192,13 @@ static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *p | |||
190 | 192 | ||
191 | static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port) | 193 | static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port) |
192 | { | 194 | { |
195 | struct s3c24xx_uart_port *ourport; | ||
196 | |||
193 | if (port->dev == NULL) | 197 | if (port->dev == NULL) |
194 | return NULL; | 198 | return NULL; |
195 | 199 | ||
196 | return (struct s3c2410_uartcfg *)port->dev->platform_data; | 200 | ourport = container_of(port, struct s3c24xx_uart_port, port); |
201 | return ourport->cfg; | ||
197 | } | 202 | } |
198 | 203 | ||
199 | static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, | 204 | static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, |
@@ -202,7 +207,7 @@ static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, | |||
202 | struct s3c24xx_uart_info *info = ourport->info; | 207 | struct s3c24xx_uart_info *info = ourport->info; |
203 | 208 | ||
204 | if (ufstat & info->rx_fifofull) | 209 | if (ufstat & info->rx_fifofull) |
205 | return info->fifosize; | 210 | return ourport->port.fifosize; |
206 | 211 | ||
207 | return (ufstat & info->rx_fifomask) >> info->rx_fifoshift; | 212 | return (ufstat & info->rx_fifomask) >> info->rx_fifoshift; |
208 | } | 213 | } |
@@ -555,154 +560,98 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, | |||
555 | * | 560 | * |
556 | */ | 561 | */ |
557 | 562 | ||
563 | #define MAX_CLK_NAME_LENGTH 15 | ||
558 | 564 | ||
559 | #define MAX_CLKS (8) | 565 | static inline int s3c24xx_serial_getsource(struct uart_port *port) |
560 | |||
561 | static struct s3c24xx_uart_clksrc tmp_clksrc = { | ||
562 | .name = "pclk", | ||
563 | .min_baud = 0, | ||
564 | .max_baud = 0, | ||
565 | .divisor = 1, | ||
566 | }; | ||
567 | |||
568 | static inline int | ||
569 | s3c24xx_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) | ||
570 | { | 566 | { |
571 | struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); | 567 | struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
568 | unsigned int ucon; | ||
572 | 569 | ||
573 | return (info->get_clksrc)(port, c); | 570 | if (info->num_clks == 1) |
574 | } | 571 | return 0; |
575 | |||
576 | static inline int | ||
577 | s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) | ||
578 | { | ||
579 | struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); | ||
580 | 572 | ||
581 | return (info->set_clksrc)(port, c); | 573 | ucon = rd_regl(port, S3C2410_UCON); |
574 | ucon &= info->clksel_mask; | ||
575 | return ucon >> info->clksel_shift; | ||
582 | } | 576 | } |
583 | 577 | ||
584 | struct baud_calc { | 578 | static void s3c24xx_serial_setsource(struct uart_port *port, |
585 | struct s3c24xx_uart_clksrc *clksrc; | 579 | unsigned int clk_sel) |
586 | unsigned int calc; | ||
587 | unsigned int divslot; | ||
588 | unsigned int quot; | ||
589 | struct clk *src; | ||
590 | }; | ||
591 | |||
592 | static int s3c24xx_serial_calcbaud(struct baud_calc *calc, | ||
593 | struct uart_port *port, | ||
594 | struct s3c24xx_uart_clksrc *clksrc, | ||
595 | unsigned int baud) | ||
596 | { | 580 | { |
597 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 581 | struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
598 | unsigned long rate; | 582 | unsigned int ucon; |
599 | |||
600 | calc->src = clk_get(port->dev, clksrc->name); | ||
601 | if (calc->src == NULL || IS_ERR(calc->src)) | ||
602 | return 0; | ||
603 | |||
604 | rate = clk_get_rate(calc->src); | ||
605 | rate /= clksrc->divisor; | ||
606 | 583 | ||
607 | calc->clksrc = clksrc; | 584 | if (info->num_clks == 1) |
585 | return; | ||
608 | 586 | ||
609 | if (ourport->info->has_divslot) { | 587 | ucon = rd_regl(port, S3C2410_UCON); |
610 | unsigned long div = rate / baud; | 588 | if ((ucon & info->clksel_mask) >> info->clksel_shift == clk_sel) |
611 | 589 | return; | |
612 | /* The UDIVSLOT register on the newer UARTs allows us to | ||
613 | * get a divisor adjustment of 1/16th on the baud clock. | ||
614 | * | ||
615 | * We don't keep the UDIVSLOT value (the 16ths we calculated | ||
616 | * by not multiplying the baud by 16) as it is easy enough | ||
617 | * to recalculate. | ||
618 | */ | ||
619 | |||
620 | calc->quot = div / 16; | ||
621 | calc->calc = rate / div; | ||
622 | } else { | ||
623 | calc->quot = (rate + (8 * baud)) / (16 * baud); | ||
624 | calc->calc = (rate / (calc->quot * 16)); | ||
625 | } | ||
626 | 590 | ||
627 | calc->quot--; | 591 | ucon &= ~info->clksel_mask; |
628 | return 1; | 592 | ucon |= clk_sel << info->clksel_shift; |
593 | wr_regl(port, S3C2410_UCON, ucon); | ||
629 | } | 594 | } |
630 | 595 | ||
631 | static unsigned int s3c24xx_serial_getclk(struct uart_port *port, | 596 | static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, |
632 | struct s3c24xx_uart_clksrc **clksrc, | 597 | unsigned int req_baud, struct clk **best_clk, |
633 | struct clk **clk, | 598 | unsigned int *clk_num) |
634 | unsigned int baud) | ||
635 | { | 599 | { |
636 | struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); | 600 | struct s3c24xx_uart_info *info = ourport->info; |
637 | struct s3c24xx_uart_clksrc *clkp; | 601 | struct clk *clk; |
638 | struct baud_calc res[MAX_CLKS]; | 602 | unsigned long rate; |
639 | struct baud_calc *resptr, *best, *sptr; | 603 | unsigned int cnt, baud, quot, clk_sel, best_quot = 0; |
640 | int i; | 604 | char clkname[MAX_CLK_NAME_LENGTH]; |
641 | 605 | int calc_deviation, deviation = (1 << 30) - 1; | |
642 | clkp = cfg->clocks; | 606 | |
643 | best = NULL; | 607 | *best_clk = NULL; |
644 | 608 | clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel : | |
645 | if (cfg->clocks_size < 2) { | 609 | ourport->info->def_clk_sel; |
646 | if (cfg->clocks_size == 0) | 610 | for (cnt = 0; cnt < info->num_clks; cnt++) { |
647 | clkp = &tmp_clksrc; | 611 | if (!(clk_sel & (1 << cnt))) |
648 | 612 | continue; | |
649 | /* check to see if we're sourcing fclk, and if so we're | 613 | |
650 | * going to have to update the clock source | 614 | sprintf(clkname, "clk_uart_baud%d", cnt); |
651 | */ | 615 | clk = clk_get(ourport->port.dev, clkname); |
652 | 616 | if (IS_ERR_OR_NULL(clk)) | |
653 | if (strcmp(clkp->name, "fclk") == 0) { | 617 | continue; |
654 | struct s3c24xx_uart_clksrc src; | 618 | |
655 | 619 | rate = clk_get_rate(clk); | |
656 | s3c24xx_serial_getsource(port, &src); | 620 | if (!rate) |
657 | 621 | continue; | |
658 | /* check that the port already using fclk, and if | 622 | |
659 | * not, then re-select fclk | 623 | if (ourport->info->has_divslot) { |
624 | unsigned long div = rate / req_baud; | ||
625 | |||
626 | /* The UDIVSLOT register on the newer UARTs allows us to | ||
627 | * get a divisor adjustment of 1/16th on the baud clock. | ||
628 | * | ||
629 | * We don't keep the UDIVSLOT value (the 16ths we | ||
630 | * calculated by not multiplying the baud by 16) as it | ||
631 | * is easy enough to recalculate. | ||
660 | */ | 632 | */ |
661 | 633 | ||
662 | if (strcmp(src.name, clkp->name) == 0) { | 634 | quot = div / 16; |
663 | s3c24xx_serial_setsource(port, clkp); | 635 | baud = rate / div; |
664 | s3c24xx_serial_getsource(port, &src); | 636 | } else { |
665 | } | 637 | quot = (rate + (8 * req_baud)) / (16 * req_baud); |
666 | 638 | baud = rate / (quot * 16); | |
667 | clkp->divisor = src.divisor; | ||
668 | } | ||
669 | |||
670 | s3c24xx_serial_calcbaud(res, port, clkp, baud); | ||
671 | best = res; | ||
672 | resptr = best + 1; | ||
673 | } else { | ||
674 | resptr = res; | ||
675 | |||
676 | for (i = 0; i < cfg->clocks_size; i++, clkp++) { | ||
677 | if (s3c24xx_serial_calcbaud(resptr, port, clkp, baud)) | ||
678 | resptr++; | ||
679 | } | 639 | } |
680 | } | 640 | quot--; |
681 | |||
682 | /* ok, we now need to select the best clock we found */ | ||
683 | |||
684 | if (!best) { | ||
685 | unsigned int deviation = (1<<30)|((1<<30)-1); | ||
686 | int calc_deviation; | ||
687 | 641 | ||
688 | for (sptr = res; sptr < resptr; sptr++) { | 642 | calc_deviation = req_baud - baud; |
689 | calc_deviation = baud - sptr->calc; | 643 | if (calc_deviation < 0) |
690 | if (calc_deviation < 0) | 644 | calc_deviation = -calc_deviation; |
691 | calc_deviation = -calc_deviation; | ||
692 | 645 | ||
693 | if (calc_deviation < deviation) { | 646 | if (calc_deviation < deviation) { |
694 | best = sptr; | 647 | *best_clk = clk; |
695 | deviation = calc_deviation; | 648 | best_quot = quot; |
696 | } | 649 | *clk_num = cnt; |
650 | deviation = calc_deviation; | ||
697 | } | 651 | } |
698 | } | 652 | } |
699 | 653 | ||
700 | /* store results to pass back */ | 654 | return best_quot; |
701 | |||
702 | *clksrc = best->clksrc; | ||
703 | *clk = best->src; | ||
704 | |||
705 | return best->quot; | ||
706 | } | 655 | } |
707 | 656 | ||
708 | /* udivslot_table[] | 657 | /* udivslot_table[] |
@@ -735,10 +684,9 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, | |||
735 | { | 684 | { |
736 | struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); | 685 | struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); |
737 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 686 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
738 | struct s3c24xx_uart_clksrc *clksrc = NULL; | ||
739 | struct clk *clk = NULL; | 687 | struct clk *clk = NULL; |
740 | unsigned long flags; | 688 | unsigned long flags; |
741 | unsigned int baud, quot; | 689 | unsigned int baud, quot, clk_sel = 0; |
742 | unsigned int ulcon; | 690 | unsigned int ulcon; |
743 | unsigned int umcon; | 691 | unsigned int umcon; |
744 | unsigned int udivslot = 0; | 692 | unsigned int udivslot = 0; |
@@ -754,17 +702,16 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, | |||
754 | */ | 702 | */ |
755 | 703 | ||
756 | baud = uart_get_baud_rate(port, termios, old, 0, 115200*8); | 704 | baud = uart_get_baud_rate(port, termios, old, 0, 115200*8); |
757 | 705 | quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel); | |
758 | if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) | 706 | if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) |
759 | quot = port->custom_divisor; | 707 | quot = port->custom_divisor; |
760 | else | 708 | if (!clk) |
761 | quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud); | 709 | return; |
762 | 710 | ||
763 | /* check to see if we need to change clock source */ | 711 | /* check to see if we need to change clock source */ |
764 | 712 | ||
765 | if (ourport->clksrc != clksrc || ourport->baudclk != clk) { | 713 | if (ourport->baudclk != clk) { |
766 | dbg("selecting clock %p\n", clk); | 714 | s3c24xx_serial_setsource(port, clk_sel); |
767 | s3c24xx_serial_setsource(port, clksrc); | ||
768 | 715 | ||
769 | if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) { | 716 | if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) { |
770 | clk_disable(ourport->baudclk); | 717 | clk_disable(ourport->baudclk); |
@@ -773,7 +720,6 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, | |||
773 | 720 | ||
774 | clk_enable(clk); | 721 | clk_enable(clk); |
775 | 722 | ||
776 | ourport->clksrc = clksrc; | ||
777 | ourport->baudclk = clk; | 723 | ourport->baudclk = clk; |
778 | ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0; | 724 | ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0; |
779 | } | 725 | } |
@@ -1020,16 +966,29 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS | |||
1020 | 966 | ||
1021 | /* s3c24xx_serial_resetport | 967 | /* s3c24xx_serial_resetport |
1022 | * | 968 | * |
1023 | * wrapper to call the specific reset for this port (reset the fifos | 969 | * reset the fifos and other the settings. |
1024 | * and the settings) | ||
1025 | */ | 970 | */ |
1026 | 971 | ||
1027 | static inline int s3c24xx_serial_resetport(struct uart_port *port, | 972 | static void s3c24xx_serial_resetport(struct uart_port *port, |
1028 | struct s3c2410_uartcfg *cfg) | 973 | struct s3c2410_uartcfg *cfg) |
1029 | { | 974 | { |
1030 | struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); | 975 | struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
976 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
977 | unsigned int ucon_mask; | ||
978 | |||
979 | ucon_mask = info->clksel_mask; | ||
980 | if (info->type == PORT_S3C2440) | ||
981 | ucon_mask |= S3C2440_UCON0_DIVMASK; | ||
1031 | 982 | ||
1032 | return (info->reset_port)(port, cfg); | 983 | ucon &= ucon_mask; |
984 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); | ||
985 | |||
986 | /* reset both fifos */ | ||
987 | wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); | ||
988 | wr_regl(port, S3C2410_UFCON, cfg->ufcon); | ||
989 | |||
990 | /* some delay is required after fifo reset */ | ||
991 | udelay(1); | ||
1033 | } | 992 | } |
1034 | 993 | ||
1035 | 994 | ||
@@ -1121,11 +1080,10 @@ static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *p | |||
1121 | */ | 1080 | */ |
1122 | 1081 | ||
1123 | static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, | 1082 | static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, |
1124 | struct s3c24xx_uart_info *info, | ||
1125 | struct platform_device *platdev) | 1083 | struct platform_device *platdev) |
1126 | { | 1084 | { |
1127 | struct uart_port *port = &ourport->port; | 1085 | struct uart_port *port = &ourport->port; |
1128 | struct s3c2410_uartcfg *cfg; | 1086 | struct s3c2410_uartcfg *cfg = ourport->cfg; |
1129 | struct resource *res; | 1087 | struct resource *res; |
1130 | int ret; | 1088 | int ret; |
1131 | 1089 | ||
@@ -1134,30 +1092,16 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, | |||
1134 | if (platdev == NULL) | 1092 | if (platdev == NULL) |
1135 | return -ENODEV; | 1093 | return -ENODEV; |
1136 | 1094 | ||
1137 | cfg = s3c24xx_dev_to_cfg(&platdev->dev); | ||
1138 | |||
1139 | if (port->mapbase != 0) | 1095 | if (port->mapbase != 0) |
1140 | return 0; | 1096 | return 0; |
1141 | 1097 | ||
1142 | if (cfg->hwport > CONFIG_SERIAL_SAMSUNG_UARTS) { | ||
1143 | printk(KERN_ERR "%s: port %d bigger than %d\n", __func__, | ||
1144 | cfg->hwport, CONFIG_SERIAL_SAMSUNG_UARTS); | ||
1145 | return -ERANGE; | ||
1146 | } | ||
1147 | |||
1148 | /* setup info for port */ | 1098 | /* setup info for port */ |
1149 | port->dev = &platdev->dev; | 1099 | port->dev = &platdev->dev; |
1150 | ourport->info = info; | ||
1151 | 1100 | ||
1152 | /* Startup sequence is different for s3c64xx and higher SoC's */ | 1101 | /* Startup sequence is different for s3c64xx and higher SoC's */ |
1153 | if (s3c24xx_serial_has_interrupt_mask(port)) | 1102 | if (s3c24xx_serial_has_interrupt_mask(port)) |
1154 | s3c24xx_serial_ops.startup = s3c64xx_serial_startup; | 1103 | s3c24xx_serial_ops.startup = s3c64xx_serial_startup; |
1155 | 1104 | ||
1156 | /* copy the info in from provided structure */ | ||
1157 | ourport->port.fifosize = info->fifosize; | ||
1158 | |||
1159 | dbg("s3c24xx_serial_init_port: %p (hw %d)...\n", port, cfg->hwport); | ||
1160 | |||
1161 | port->uartclk = 1; | 1105 | port->uartclk = 1; |
1162 | 1106 | ||
1163 | if (cfg->uart_flags & UPF_CONS_FLOW) { | 1107 | if (cfg->uart_flags & UPF_CONS_FLOW) { |
@@ -1215,43 +1159,74 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev, | |||
1215 | struct uart_port *port = s3c24xx_dev_to_port(dev); | 1159 | struct uart_port *port = s3c24xx_dev_to_port(dev); |
1216 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 1160 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
1217 | 1161 | ||
1218 | return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->clksrc->name); | 1162 | return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->baudclk->name); |
1219 | } | 1163 | } |
1220 | 1164 | ||
1221 | static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL); | 1165 | static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL); |
1222 | 1166 | ||
1167 | |||
1223 | /* Device driver serial port probe */ | 1168 | /* Device driver serial port probe */ |
1224 | 1169 | ||
1170 | static const struct of_device_id s3c24xx_uart_dt_match[]; | ||
1225 | static int probe_index; | 1171 | static int probe_index; |
1226 | 1172 | ||
1227 | int s3c24xx_serial_probe(struct platform_device *dev, | 1173 | static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data( |
1228 | struct s3c24xx_uart_info *info) | 1174 | struct platform_device *pdev) |
1175 | { | ||
1176 | #ifdef CONFIG_OF | ||
1177 | if (pdev->dev.of_node) { | ||
1178 | const struct of_device_id *match; | ||
1179 | match = of_match_node(s3c24xx_uart_dt_match, pdev->dev.of_node); | ||
1180 | return (struct s3c24xx_serial_drv_data *)match->data; | ||
1181 | } | ||
1182 | #endif | ||
1183 | return (struct s3c24xx_serial_drv_data *) | ||
1184 | platform_get_device_id(pdev)->driver_data; | ||
1185 | } | ||
1186 | |||
1187 | static int s3c24xx_serial_probe(struct platform_device *pdev) | ||
1229 | { | 1188 | { |
1230 | struct s3c24xx_uart_port *ourport; | 1189 | struct s3c24xx_uart_port *ourport; |
1231 | int ret; | 1190 | int ret; |
1232 | 1191 | ||
1233 | dbg("s3c24xx_serial_probe(%p, %p) %d\n", dev, info, probe_index); | 1192 | dbg("s3c24xx_serial_probe(%p) %d\n", pdev, probe_index); |
1234 | 1193 | ||
1235 | ourport = &s3c24xx_serial_ports[probe_index]; | 1194 | ourport = &s3c24xx_serial_ports[probe_index]; |
1195 | |||
1196 | ourport->drv_data = s3c24xx_get_driver_data(pdev); | ||
1197 | if (!ourport->drv_data) { | ||
1198 | dev_err(&pdev->dev, "could not find driver data\n"); | ||
1199 | return -ENODEV; | ||
1200 | } | ||
1201 | |||
1202 | ourport->info = ourport->drv_data->info; | ||
1203 | ourport->cfg = (pdev->dev.platform_data) ? | ||
1204 | (struct s3c2410_uartcfg *)pdev->dev.platform_data : | ||
1205 | ourport->drv_data->def_cfg; | ||
1206 | |||
1207 | ourport->port.fifosize = (ourport->info->fifosize) ? | ||
1208 | ourport->info->fifosize : | ||
1209 | ourport->drv_data->fifosize[probe_index]; | ||
1210 | |||
1236 | probe_index++; | 1211 | probe_index++; |
1237 | 1212 | ||
1238 | dbg("%s: initialising port %p...\n", __func__, ourport); | 1213 | dbg("%s: initialising port %p...\n", __func__, ourport); |
1239 | 1214 | ||
1240 | ret = s3c24xx_serial_init_port(ourport, info, dev); | 1215 | ret = s3c24xx_serial_init_port(ourport, pdev); |
1241 | if (ret < 0) | 1216 | if (ret < 0) |
1242 | goto probe_err; | 1217 | goto probe_err; |
1243 | 1218 | ||
1244 | dbg("%s: adding port\n", __func__); | 1219 | dbg("%s: adding port\n", __func__); |
1245 | uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); | 1220 | uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); |
1246 | platform_set_drvdata(dev, &ourport->port); | 1221 | platform_set_drvdata(pdev, &ourport->port); |
1247 | 1222 | ||
1248 | ret = device_create_file(&dev->dev, &dev_attr_clock_source); | 1223 | ret = device_create_file(&pdev->dev, &dev_attr_clock_source); |
1249 | if (ret < 0) | 1224 | if (ret < 0) |
1250 | printk(KERN_ERR "%s: failed to add clksrc attr.\n", __func__); | 1225 | dev_err(&pdev->dev, "failed to add clock source attr.\n"); |
1251 | 1226 | ||
1252 | ret = s3c24xx_serial_cpufreq_register(ourport); | 1227 | ret = s3c24xx_serial_cpufreq_register(ourport); |
1253 | if (ret < 0) | 1228 | if (ret < 0) |
1254 | dev_err(&dev->dev, "failed to add cpufreq notifier\n"); | 1229 | dev_err(&pdev->dev, "failed to add cpufreq notifier\n"); |
1255 | 1230 | ||
1256 | return 0; | 1231 | return 0; |
1257 | 1232 | ||
@@ -1259,9 +1234,7 @@ int s3c24xx_serial_probe(struct platform_device *dev, | |||
1259 | return ret; | 1234 | return ret; |
1260 | } | 1235 | } |
1261 | 1236 | ||
1262 | EXPORT_SYMBOL_GPL(s3c24xx_serial_probe); | 1237 | static int __devexit s3c24xx_serial_remove(struct platform_device *dev) |
1263 | |||
1264 | int __devexit s3c24xx_serial_remove(struct platform_device *dev) | ||
1265 | { | 1238 | { |
1266 | struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); | 1239 | struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); |
1267 | 1240 | ||
@@ -1274,8 +1247,6 @@ int __devexit s3c24xx_serial_remove(struct platform_device *dev) | |||
1274 | return 0; | 1247 | return 0; |
1275 | } | 1248 | } |
1276 | 1249 | ||
1277 | EXPORT_SYMBOL_GPL(s3c24xx_serial_remove); | ||
1278 | |||
1279 | /* UART power management code */ | 1250 | /* UART power management code */ |
1280 | #ifdef CONFIG_PM_SLEEP | 1251 | #ifdef CONFIG_PM_SLEEP |
1281 | static int s3c24xx_serial_suspend(struct device *dev) | 1252 | static int s3c24xx_serial_suspend(struct device *dev) |
@@ -1315,41 +1286,6 @@ static const struct dev_pm_ops s3c24xx_serial_pm_ops = { | |||
1315 | #define SERIAL_SAMSUNG_PM_OPS NULL | 1286 | #define SERIAL_SAMSUNG_PM_OPS NULL |
1316 | #endif /* CONFIG_PM_SLEEP */ | 1287 | #endif /* CONFIG_PM_SLEEP */ |
1317 | 1288 | ||
1318 | int s3c24xx_serial_init(struct platform_driver *drv, | ||
1319 | struct s3c24xx_uart_info *info) | ||
1320 | { | ||
1321 | dbg("s3c24xx_serial_init(%p,%p)\n", drv, info); | ||
1322 | |||
1323 | drv->driver.pm = SERIAL_SAMSUNG_PM_OPS; | ||
1324 | |||
1325 | return platform_driver_register(drv); | ||
1326 | } | ||
1327 | |||
1328 | EXPORT_SYMBOL_GPL(s3c24xx_serial_init); | ||
1329 | |||
1330 | /* module initialisation code */ | ||
1331 | |||
1332 | static int __init s3c24xx_serial_modinit(void) | ||
1333 | { | ||
1334 | int ret; | ||
1335 | |||
1336 | ret = uart_register_driver(&s3c24xx_uart_drv); | ||
1337 | if (ret < 0) { | ||
1338 | printk(KERN_ERR "failed to register UART driver\n"); | ||
1339 | return -1; | ||
1340 | } | ||
1341 | |||
1342 | return 0; | ||
1343 | } | ||
1344 | |||
1345 | static void __exit s3c24xx_serial_modexit(void) | ||
1346 | { | ||
1347 | uart_unregister_driver(&s3c24xx_uart_drv); | ||
1348 | } | ||
1349 | |||
1350 | module_init(s3c24xx_serial_modinit); | ||
1351 | module_exit(s3c24xx_serial_modexit); | ||
1352 | |||
1353 | /* Console code */ | 1289 | /* Console code */ |
1354 | 1290 | ||
1355 | #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE | 1291 | #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE |
@@ -1395,12 +1331,13 @@ static void __init | |||
1395 | s3c24xx_serial_get_options(struct uart_port *port, int *baud, | 1331 | s3c24xx_serial_get_options(struct uart_port *port, int *baud, |
1396 | int *parity, int *bits) | 1332 | int *parity, int *bits) |
1397 | { | 1333 | { |
1398 | struct s3c24xx_uart_clksrc clksrc; | ||
1399 | struct clk *clk; | 1334 | struct clk *clk; |
1400 | unsigned int ulcon; | 1335 | unsigned int ulcon; |
1401 | unsigned int ucon; | 1336 | unsigned int ucon; |
1402 | unsigned int ubrdiv; | 1337 | unsigned int ubrdiv; |
1403 | unsigned long rate; | 1338 | unsigned long rate; |
1339 | unsigned int clk_sel; | ||
1340 | char clk_name[MAX_CLK_NAME_LENGTH]; | ||
1404 | 1341 | ||
1405 | ulcon = rd_regl(port, S3C2410_ULCON); | 1342 | ulcon = rd_regl(port, S3C2410_ULCON); |
1406 | ucon = rd_regl(port, S3C2410_UCON); | 1343 | ucon = rd_regl(port, S3C2410_UCON); |
@@ -1445,44 +1382,21 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, | |||
1445 | 1382 | ||
1446 | /* now calculate the baud rate */ | 1383 | /* now calculate the baud rate */ |
1447 | 1384 | ||
1448 | s3c24xx_serial_getsource(port, &clksrc); | 1385 | clk_sel = s3c24xx_serial_getsource(port); |
1386 | sprintf(clk_name, "clk_uart_baud%d", clk_sel); | ||
1449 | 1387 | ||
1450 | clk = clk_get(port->dev, clksrc.name); | 1388 | clk = clk_get(port->dev, clk_name); |
1451 | if (!IS_ERR(clk) && clk != NULL) | 1389 | if (!IS_ERR(clk) && clk != NULL) |
1452 | rate = clk_get_rate(clk) / clksrc.divisor; | 1390 | rate = clk_get_rate(clk); |
1453 | else | 1391 | else |
1454 | rate = 1; | 1392 | rate = 1; |
1455 | 1393 | ||
1456 | |||
1457 | *baud = rate / (16 * (ubrdiv + 1)); | 1394 | *baud = rate / (16 * (ubrdiv + 1)); |
1458 | dbg("calculated baud %d\n", *baud); | 1395 | dbg("calculated baud %d\n", *baud); |
1459 | } | 1396 | } |
1460 | 1397 | ||
1461 | } | 1398 | } |
1462 | 1399 | ||
1463 | /* s3c24xx_serial_init_ports | ||
1464 | * | ||
1465 | * initialise the serial ports from the machine provided initialisation | ||
1466 | * data. | ||
1467 | */ | ||
1468 | |||
1469 | static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info **info) | ||
1470 | { | ||
1471 | struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports; | ||
1472 | struct platform_device **platdev_ptr; | ||
1473 | int i; | ||
1474 | |||
1475 | dbg("s3c24xx_serial_init_ports: initialising ports...\n"); | ||
1476 | |||
1477 | platdev_ptr = s3c24xx_uart_devs; | ||
1478 | |||
1479 | for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) { | ||
1480 | s3c24xx_serial_init_port(ptr, info[i], *platdev_ptr); | ||
1481 | } | ||
1482 | |||
1483 | return 0; | ||
1484 | } | ||
1485 | |||
1486 | static int __init | 1400 | static int __init |
1487 | s3c24xx_serial_console_setup(struct console *co, char *options) | 1401 | s3c24xx_serial_console_setup(struct console *co, char *options) |
1488 | { | 1402 | { |
@@ -1526,11 +1440,6 @@ s3c24xx_serial_console_setup(struct console *co, char *options) | |||
1526 | return uart_set_options(port, co, baud, parity, bits, flow); | 1440 | return uart_set_options(port, co, baud, parity, bits, flow); |
1527 | } | 1441 | } |
1528 | 1442 | ||
1529 | /* s3c24xx_serial_initconsole | ||
1530 | * | ||
1531 | * initialise the console from one of the uart drivers | ||
1532 | */ | ||
1533 | |||
1534 | static struct console s3c24xx_serial_console = { | 1443 | static struct console s3c24xx_serial_console = { |
1535 | .name = S3C24XX_SERIAL_NAME, | 1444 | .name = S3C24XX_SERIAL_NAME, |
1536 | .device = uart_console_device, | 1445 | .device = uart_console_device, |
@@ -1540,34 +1449,250 @@ static struct console s3c24xx_serial_console = { | |||
1540 | .setup = s3c24xx_serial_console_setup, | 1449 | .setup = s3c24xx_serial_console_setup, |
1541 | .data = &s3c24xx_uart_drv, | 1450 | .data = &s3c24xx_uart_drv, |
1542 | }; | 1451 | }; |
1452 | #endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */ | ||
1543 | 1453 | ||
1544 | int s3c24xx_serial_initconsole(struct platform_driver *drv, | 1454 | #ifdef CONFIG_CPU_S3C2410 |
1545 | struct s3c24xx_uart_info **info) | 1455 | static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = { |
1456 | .info = &(struct s3c24xx_uart_info) { | ||
1457 | .name = "Samsung S3C2410 UART", | ||
1458 | .type = PORT_S3C2410, | ||
1459 | .fifosize = 16, | ||
1460 | .rx_fifomask = S3C2410_UFSTAT_RXMASK, | ||
1461 | .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT, | ||
1462 | .rx_fifofull = S3C2410_UFSTAT_RXFULL, | ||
1463 | .tx_fifofull = S3C2410_UFSTAT_TXFULL, | ||
1464 | .tx_fifomask = S3C2410_UFSTAT_TXMASK, | ||
1465 | .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT, | ||
1466 | .def_clk_sel = S3C2410_UCON_CLKSEL0, | ||
1467 | .num_clks = 2, | ||
1468 | .clksel_mask = S3C2410_UCON_CLKMASK, | ||
1469 | .clksel_shift = S3C2410_UCON_CLKSHIFT, | ||
1470 | }, | ||
1471 | .def_cfg = &(struct s3c2410_uartcfg) { | ||
1472 | .ucon = S3C2410_UCON_DEFAULT, | ||
1473 | .ufcon = S3C2410_UFCON_DEFAULT, | ||
1474 | }, | ||
1475 | }; | ||
1476 | #define S3C2410_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2410_serial_drv_data) | ||
1477 | #else | ||
1478 | #define S3C2410_SERIAL_DRV_DATA (kernel_ulong_t)NULL | ||
1479 | #endif | ||
1546 | 1480 | ||
1547 | { | 1481 | #ifdef CONFIG_CPU_S3C2412 |
1548 | struct platform_device *dev = s3c24xx_uart_devs[0]; | 1482 | static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = { |
1483 | .info = &(struct s3c24xx_uart_info) { | ||
1484 | .name = "Samsung S3C2412 UART", | ||
1485 | .type = PORT_S3C2412, | ||
1486 | .fifosize = 64, | ||
1487 | .has_divslot = 1, | ||
1488 | .rx_fifomask = S3C2440_UFSTAT_RXMASK, | ||
1489 | .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, | ||
1490 | .rx_fifofull = S3C2440_UFSTAT_RXFULL, | ||
1491 | .tx_fifofull = S3C2440_UFSTAT_TXFULL, | ||
1492 | .tx_fifomask = S3C2440_UFSTAT_TXMASK, | ||
1493 | .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, | ||
1494 | .def_clk_sel = S3C2410_UCON_CLKSEL2, | ||
1495 | .num_clks = 4, | ||
1496 | .clksel_mask = S3C2412_UCON_CLKMASK, | ||
1497 | .clksel_shift = S3C2412_UCON_CLKSHIFT, | ||
1498 | }, | ||
1499 | .def_cfg = &(struct s3c2410_uartcfg) { | ||
1500 | .ucon = S3C2410_UCON_DEFAULT, | ||
1501 | .ufcon = S3C2410_UFCON_DEFAULT, | ||
1502 | }, | ||
1503 | }; | ||
1504 | #define S3C2412_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2412_serial_drv_data) | ||
1505 | #else | ||
1506 | #define S3C2412_SERIAL_DRV_DATA (kernel_ulong_t)NULL | ||
1507 | #endif | ||
1549 | 1508 | ||
1550 | dbg("s3c24xx_serial_initconsole\n"); | 1509 | #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \ |
1510 | defined(CONFIG_CPU_S3C2443) | ||
1511 | static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = { | ||
1512 | .info = &(struct s3c24xx_uart_info) { | ||
1513 | .name = "Samsung S3C2440 UART", | ||
1514 | .type = PORT_S3C2440, | ||
1515 | .fifosize = 64, | ||
1516 | .has_divslot = 1, | ||
1517 | .rx_fifomask = S3C2440_UFSTAT_RXMASK, | ||
1518 | .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, | ||
1519 | .rx_fifofull = S3C2440_UFSTAT_RXFULL, | ||
1520 | .tx_fifofull = S3C2440_UFSTAT_TXFULL, | ||
1521 | .tx_fifomask = S3C2440_UFSTAT_TXMASK, | ||
1522 | .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, | ||
1523 | .def_clk_sel = S3C2410_UCON_CLKSEL2, | ||
1524 | .num_clks = 4, | ||
1525 | .clksel_mask = S3C2412_UCON_CLKMASK, | ||
1526 | .clksel_shift = S3C2412_UCON_CLKSHIFT, | ||
1527 | }, | ||
1528 | .def_cfg = &(struct s3c2410_uartcfg) { | ||
1529 | .ucon = S3C2410_UCON_DEFAULT, | ||
1530 | .ufcon = S3C2410_UFCON_DEFAULT, | ||
1531 | }, | ||
1532 | }; | ||
1533 | #define S3C2440_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2440_serial_drv_data) | ||
1534 | #else | ||
1535 | #define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL | ||
1536 | #endif | ||
1551 | 1537 | ||
1552 | /* select driver based on the cpu */ | 1538 | #if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410) || \ |
1539 | defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450) || \ | ||
1540 | defined(CONFIG_CPU_S5PC100) | ||
1541 | static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = { | ||
1542 | .info = &(struct s3c24xx_uart_info) { | ||
1543 | .name = "Samsung S3C6400 UART", | ||
1544 | .type = PORT_S3C6400, | ||
1545 | .fifosize = 64, | ||
1546 | .has_divslot = 1, | ||
1547 | .rx_fifomask = S3C2440_UFSTAT_RXMASK, | ||
1548 | .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, | ||
1549 | .rx_fifofull = S3C2440_UFSTAT_RXFULL, | ||
1550 | .tx_fifofull = S3C2440_UFSTAT_TXFULL, | ||
1551 | .tx_fifomask = S3C2440_UFSTAT_TXMASK, | ||
1552 | .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, | ||
1553 | .def_clk_sel = S3C2410_UCON_CLKSEL2, | ||
1554 | .num_clks = 4, | ||
1555 | .clksel_mask = S3C6400_UCON_CLKMASK, | ||
1556 | .clksel_shift = S3C6400_UCON_CLKSHIFT, | ||
1557 | }, | ||
1558 | .def_cfg = &(struct s3c2410_uartcfg) { | ||
1559 | .ucon = S3C2410_UCON_DEFAULT, | ||
1560 | .ufcon = S3C2410_UFCON_DEFAULT, | ||
1561 | }, | ||
1562 | }; | ||
1563 | #define S3C6400_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c6400_serial_drv_data) | ||
1564 | #else | ||
1565 | #define S3C6400_SERIAL_DRV_DATA (kernel_ulong_t)NULL | ||
1566 | #endif | ||
1553 | 1567 | ||
1554 | if (dev == NULL) { | 1568 | #ifdef CONFIG_CPU_S5PV210 |
1555 | printk(KERN_ERR "s3c24xx: no devices for console init\n"); | 1569 | static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { |
1556 | return 0; | 1570 | .info = &(struct s3c24xx_uart_info) { |
1557 | } | 1571 | .name = "Samsung S5PV210 UART", |
1572 | .type = PORT_S3C6400, | ||
1573 | .has_divslot = 1, | ||
1574 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, | ||
1575 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, | ||
1576 | .rx_fifofull = S5PV210_UFSTAT_RXFULL, | ||
1577 | .tx_fifofull = S5PV210_UFSTAT_TXFULL, | ||
1578 | .tx_fifomask = S5PV210_UFSTAT_TXMASK, | ||
1579 | .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, | ||
1580 | .def_clk_sel = S3C2410_UCON_CLKSEL0, | ||
1581 | .num_clks = 2, | ||
1582 | .clksel_mask = S5PV210_UCON_CLKMASK, | ||
1583 | .clksel_shift = S5PV210_UCON_CLKSHIFT, | ||
1584 | }, | ||
1585 | .def_cfg = &(struct s3c2410_uartcfg) { | ||
1586 | .ucon = S5PV210_UCON_DEFAULT, | ||
1587 | .ufcon = S5PV210_UFCON_DEFAULT, | ||
1588 | }, | ||
1589 | .fifosize = { 256, 64, 16, 16 }, | ||
1590 | }; | ||
1591 | #define S5PV210_SERIAL_DRV_DATA ((kernel_ulong_t)&s5pv210_serial_drv_data) | ||
1592 | #else | ||
1593 | #define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL | ||
1594 | #endif | ||
1558 | 1595 | ||
1559 | if (strcmp(dev->name, drv->driver.name) != 0) | 1596 | #ifdef CONFIG_CPU_EXYNOS4210 |
1560 | return 0; | 1597 | static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = { |
1598 | .info = &(struct s3c24xx_uart_info) { | ||
1599 | .name = "Samsung Exynos4 UART", | ||
1600 | .type = PORT_S3C6400, | ||
1601 | .has_divslot = 1, | ||
1602 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, | ||
1603 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, | ||
1604 | .rx_fifofull = S5PV210_UFSTAT_RXFULL, | ||
1605 | .tx_fifofull = S5PV210_UFSTAT_TXFULL, | ||
1606 | .tx_fifomask = S5PV210_UFSTAT_TXMASK, | ||
1607 | .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, | ||
1608 | .def_clk_sel = S3C2410_UCON_CLKSEL0, | ||
1609 | .num_clks = 1, | ||
1610 | .clksel_mask = 0, | ||
1611 | .clksel_shift = 0, | ||
1612 | }, | ||
1613 | .def_cfg = &(struct s3c2410_uartcfg) { | ||
1614 | .ucon = S5PV210_UCON_DEFAULT, | ||
1615 | .ufcon = S5PV210_UFCON_DEFAULT, | ||
1616 | .has_fracval = 1, | ||
1617 | }, | ||
1618 | .fifosize = { 256, 64, 16, 16 }, | ||
1619 | }; | ||
1620 | #define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data) | ||
1621 | #else | ||
1622 | #define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL | ||
1623 | #endif | ||
1561 | 1624 | ||
1562 | s3c24xx_serial_console.data = &s3c24xx_uart_drv; | 1625 | static struct platform_device_id s3c24xx_serial_driver_ids[] = { |
1563 | s3c24xx_serial_init_ports(info); | 1626 | { |
1627 | .name = "s3c2410-uart", | ||
1628 | .driver_data = S3C2410_SERIAL_DRV_DATA, | ||
1629 | }, { | ||
1630 | .name = "s3c2412-uart", | ||
1631 | .driver_data = S3C2412_SERIAL_DRV_DATA, | ||
1632 | }, { | ||
1633 | .name = "s3c2440-uart", | ||
1634 | .driver_data = S3C2440_SERIAL_DRV_DATA, | ||
1635 | }, { | ||
1636 | .name = "s3c6400-uart", | ||
1637 | .driver_data = S3C6400_SERIAL_DRV_DATA, | ||
1638 | }, { | ||
1639 | .name = "s5pv210-uart", | ||
1640 | .driver_data = S5PV210_SERIAL_DRV_DATA, | ||
1641 | }, { | ||
1642 | .name = "exynos4210-uart", | ||
1643 | .driver_data = EXYNOS4210_SERIAL_DRV_DATA, | ||
1644 | }, | ||
1645 | { }, | ||
1646 | }; | ||
1647 | MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids); | ||
1564 | 1648 | ||
1565 | register_console(&s3c24xx_serial_console); | 1649 | #ifdef CONFIG_OF |
1566 | return 0; | 1650 | static const struct of_device_id s3c24xx_uart_dt_match[] = { |
1651 | { .compatible = "samsung,exynos4210-uart", | ||
1652 | .data = (void *)EXYNOS4210_SERIAL_DRV_DATA }, | ||
1653 | {}, | ||
1654 | }; | ||
1655 | MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match); | ||
1656 | #else | ||
1657 | #define s3c24xx_uart_dt_match NULL | ||
1658 | #endif | ||
1659 | |||
1660 | static struct platform_driver samsung_serial_driver = { | ||
1661 | .probe = s3c24xx_serial_probe, | ||
1662 | .remove = __devexit_p(s3c24xx_serial_remove), | ||
1663 | .id_table = s3c24xx_serial_driver_ids, | ||
1664 | .driver = { | ||
1665 | .name = "samsung-uart", | ||
1666 | .owner = THIS_MODULE, | ||
1667 | .pm = SERIAL_SAMSUNG_PM_OPS, | ||
1668 | .of_match_table = s3c24xx_uart_dt_match, | ||
1669 | }, | ||
1670 | }; | ||
1671 | |||
1672 | /* module initialisation code */ | ||
1673 | |||
1674 | static int __init s3c24xx_serial_modinit(void) | ||
1675 | { | ||
1676 | int ret; | ||
1677 | |||
1678 | ret = uart_register_driver(&s3c24xx_uart_drv); | ||
1679 | if (ret < 0) { | ||
1680 | printk(KERN_ERR "failed to register UART driver\n"); | ||
1681 | return -1; | ||
1682 | } | ||
1683 | |||
1684 | return platform_driver_register(&samsung_serial_driver); | ||
1567 | } | 1685 | } |
1568 | 1686 | ||
1569 | #endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */ | 1687 | static void __exit s3c24xx_serial_modexit(void) |
1688 | { | ||
1689 | uart_unregister_driver(&s3c24xx_uart_drv); | ||
1690 | } | ||
1691 | |||
1692 | module_init(s3c24xx_serial_modinit); | ||
1693 | module_exit(s3c24xx_serial_modexit); | ||
1570 | 1694 | ||
1695 | MODULE_ALIAS("platform:samsung-uart"); | ||
1571 | MODULE_DESCRIPTION("Samsung SoC Serial port driver"); | 1696 | MODULE_DESCRIPTION("Samsung SoC Serial port driver"); |
1572 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | 1697 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); |
1573 | MODULE_LICENSE("GPL v2"); | 1698 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h index 8e87b788e5c6..1a4bca3e4179 100644 --- a/drivers/tty/serial/samsung.h +++ b/drivers/tty/serial/samsung.h | |||
@@ -19,20 +19,25 @@ struct s3c24xx_uart_info { | |||
19 | unsigned long tx_fifomask; | 19 | unsigned long tx_fifomask; |
20 | unsigned long tx_fifoshift; | 20 | unsigned long tx_fifoshift; |
21 | unsigned long tx_fifofull; | 21 | unsigned long tx_fifofull; |
22 | unsigned int def_clk_sel; | ||
23 | unsigned long num_clks; | ||
24 | unsigned long clksel_mask; | ||
25 | unsigned long clksel_shift; | ||
22 | 26 | ||
23 | /* uart port features */ | 27 | /* uart port features */ |
24 | 28 | ||
25 | unsigned int has_divslot:1; | 29 | unsigned int has_divslot:1; |
26 | 30 | ||
27 | /* clock source control */ | ||
28 | |||
29 | int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk); | ||
30 | int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk); | ||
31 | |||
32 | /* uart controls */ | 31 | /* uart controls */ |
33 | int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *); | 32 | int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *); |
34 | }; | 33 | }; |
35 | 34 | ||
35 | struct s3c24xx_serial_drv_data { | ||
36 | struct s3c24xx_uart_info *info; | ||
37 | struct s3c2410_uartcfg *def_cfg; | ||
38 | unsigned int fifosize[CONFIG_SERIAL_SAMSUNG_UARTS]; | ||
39 | }; | ||
40 | |||
36 | struct s3c24xx_uart_port { | 41 | struct s3c24xx_uart_port { |
37 | unsigned char rx_claimed; | 42 | unsigned char rx_claimed; |
38 | unsigned char tx_claimed; | 43 | unsigned char tx_claimed; |
@@ -43,10 +48,13 @@ struct s3c24xx_uart_port { | |||
43 | unsigned int tx_irq; | 48 | unsigned int tx_irq; |
44 | 49 | ||
45 | struct s3c24xx_uart_info *info; | 50 | struct s3c24xx_uart_info *info; |
46 | struct s3c24xx_uart_clksrc *clksrc; | ||
47 | struct clk *clk; | 51 | struct clk *clk; |
48 | struct clk *baudclk; | 52 | struct clk *baudclk; |
49 | struct uart_port port; | 53 | struct uart_port port; |
54 | struct s3c24xx_serial_drv_data *drv_data; | ||
55 | |||
56 | /* reference to platform data */ | ||
57 | struct s3c2410_uartcfg *cfg; | ||
50 | 58 | ||
51 | #ifdef CONFIG_CPU_FREQ | 59 | #ifdef CONFIG_CPU_FREQ |
52 | struct notifier_block freq_transition; | 60 | struct notifier_block freq_transition; |
@@ -56,7 +64,6 @@ struct s3c24xx_uart_port { | |||
56 | /* conversion functions */ | 64 | /* conversion functions */ |
57 | 65 | ||
58 | #define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev) | 66 | #define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev) |
59 | #define s3c24xx_dev_to_cfg(__dev) (struct s3c2410_uartcfg *)((__dev)->platform_data) | ||
60 | 67 | ||
61 | /* register access controls */ | 68 | /* register access controls */ |
62 | 69 | ||
@@ -69,17 +76,6 @@ struct s3c24xx_uart_port { | |||
69 | #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg)) | 76 | #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg)) |
70 | #define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg)) | 77 | #define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg)) |
71 | 78 | ||
72 | extern int s3c24xx_serial_probe(struct platform_device *dev, | ||
73 | struct s3c24xx_uart_info *uart); | ||
74 | |||
75 | extern int __devexit s3c24xx_serial_remove(struct platform_device *dev); | ||
76 | |||
77 | extern int s3c24xx_serial_initconsole(struct platform_driver *drv, | ||
78 | struct s3c24xx_uart_info **uart); | ||
79 | |||
80 | extern int s3c24xx_serial_init(struct platform_driver *drv, | ||
81 | struct s3c24xx_uart_info *info); | ||
82 | |||
83 | #ifdef CONFIG_SERIAL_SAMSUNG_DEBUG | 79 | #ifdef CONFIG_SERIAL_SAMSUNG_DEBUG |
84 | 80 | ||
85 | extern void printascii(const char *); | 81 | extern void printascii(const char *); |
diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c index 75038ad2b242..e0b4b0a30a5a 100644 --- a/drivers/tty/serial/sc26xx.c +++ b/drivers/tty/serial/sc26xx.c | |||
@@ -736,19 +736,7 @@ static struct platform_driver sc26xx_driver = { | |||
736 | }, | 736 | }, |
737 | }; | 737 | }; |
738 | 738 | ||
739 | static int __init sc26xx_init(void) | 739 | module_platform_driver(sc26xx_driver); |
740 | { | ||
741 | return platform_driver_register(&sc26xx_driver); | ||
742 | } | ||
743 | |||
744 | static void __exit sc26xx_exit(void) | ||
745 | { | ||
746 | platform_driver_unregister(&sc26xx_driver); | ||
747 | } | ||
748 | |||
749 | module_init(sc26xx_init); | ||
750 | module_exit(sc26xx_exit); | ||
751 | |||
752 | 740 | ||
753 | MODULE_AUTHOR("Thomas Bogendörfer"); | 741 | MODULE_AUTHOR("Thomas Bogendörfer"); |
754 | MODULE_DESCRIPTION("SC681/SC2692 serial driver"); | 742 | MODULE_DESCRIPTION("SC681/SC2692 serial driver"); |
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 0406d7ff505e..c7bf31a6a7e7 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/tty.h> | 24 | #include <linux/tty.h> |
25 | #include <linux/tty_flip.h> | ||
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | #include <linux/init.h> | 27 | #include <linux/init.h> |
27 | #include <linux/console.h> | 28 | #include <linux/console.h> |
@@ -60,6 +61,8 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, | |||
60 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); | 61 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); |
61 | static void uart_change_pm(struct uart_state *state, int pm_state); | 62 | static void uart_change_pm(struct uart_state *state, int pm_state); |
62 | 63 | ||
64 | static void uart_port_shutdown(struct tty_port *port); | ||
65 | |||
63 | /* | 66 | /* |
64 | * This routine is used by the interrupt handler to schedule processing in | 67 | * This routine is used by the interrupt handler to schedule processing in |
65 | * the software interrupt portion of the driver. | 68 | * the software interrupt portion of the driver. |
@@ -128,25 +131,16 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) | |||
128 | * Startup the port. This will be called once per open. All calls | 131 | * Startup the port. This will be called once per open. All calls |
129 | * will be serialised by the per-port mutex. | 132 | * will be serialised by the per-port mutex. |
130 | */ | 133 | */ |
131 | static int uart_startup(struct tty_struct *tty, struct uart_state *state, int init_hw) | 134 | static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, |
135 | int init_hw) | ||
132 | { | 136 | { |
133 | struct uart_port *uport = state->uart_port; | 137 | struct uart_port *uport = state->uart_port; |
134 | struct tty_port *port = &state->port; | 138 | struct tty_port *port = &state->port; |
135 | unsigned long page; | 139 | unsigned long page; |
136 | int retval = 0; | 140 | int retval = 0; |
137 | 141 | ||
138 | if (port->flags & ASYNC_INITIALIZED) | ||
139 | return 0; | ||
140 | |||
141 | /* | ||
142 | * Set the TTY IO error marker - we will only clear this | ||
143 | * once we have successfully opened the port. Also set | ||
144 | * up the tty->alt_speed kludge | ||
145 | */ | ||
146 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
147 | |||
148 | if (uport->type == PORT_UNKNOWN) | 142 | if (uport->type == PORT_UNKNOWN) |
149 | return 0; | 143 | return 1; |
150 | 144 | ||
151 | /* | 145 | /* |
152 | * Initialise and allocate the transmit and temporary | 146 | * Initialise and allocate the transmit and temporary |
@@ -188,10 +182,6 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, int in | |||
188 | tty->hw_stopped = 1; | 182 | tty->hw_stopped = 1; |
189 | spin_unlock_irq(&uport->lock); | 183 | spin_unlock_irq(&uport->lock); |
190 | } | 184 | } |
191 | |||
192 | set_bit(ASYNCB_INITIALIZED, &port->flags); | ||
193 | |||
194 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
195 | } | 185 | } |
196 | 186 | ||
197 | /* | 187 | /* |
@@ -200,6 +190,31 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, int in | |||
200 | * now. | 190 | * now. |
201 | */ | 191 | */ |
202 | if (retval && capable(CAP_SYS_ADMIN)) | 192 | if (retval && capable(CAP_SYS_ADMIN)) |
193 | return 1; | ||
194 | |||
195 | return retval; | ||
196 | } | ||
197 | |||
198 | static int uart_startup(struct tty_struct *tty, struct uart_state *state, | ||
199 | int init_hw) | ||
200 | { | ||
201 | struct tty_port *port = &state->port; | ||
202 | int retval; | ||
203 | |||
204 | if (port->flags & ASYNC_INITIALIZED) | ||
205 | return 0; | ||
206 | |||
207 | /* | ||
208 | * Set the TTY IO error marker - we will only clear this | ||
209 | * once we have successfully opened the port. | ||
210 | */ | ||
211 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
212 | |||
213 | retval = uart_port_startup(tty, state, init_hw); | ||
214 | if (!retval) { | ||
215 | set_bit(ASYNCB_INITIALIZED, &port->flags); | ||
216 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
217 | } else if (retval > 0) | ||
203 | retval = 0; | 218 | retval = 0; |
204 | 219 | ||
205 | return retval; | 220 | return retval; |
@@ -228,24 +243,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) | |||
228 | if (!tty || (tty->termios->c_cflag & HUPCL)) | 243 | if (!tty || (tty->termios->c_cflag & HUPCL)) |
229 | uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); | 244 | uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); |
230 | 245 | ||
231 | /* | 246 | uart_port_shutdown(port); |
232 | * clear delta_msr_wait queue to avoid mem leaks: we may free | ||
233 | * the irq here so the queue might never be woken up. Note | ||
234 | * that we won't end up waiting on delta_msr_wait again since | ||
235 | * any outstanding file descriptors should be pointing at | ||
236 | * hung_up_tty_fops now. | ||
237 | */ | ||
238 | wake_up_interruptible(&port->delta_msr_wait); | ||
239 | |||
240 | /* | ||
241 | * Free the IRQ and disable the port. | ||
242 | */ | ||
243 | uport->ops->shutdown(uport); | ||
244 | |||
245 | /* | ||
246 | * Ensure that the IRQ handler isn't running on another CPU. | ||
247 | */ | ||
248 | synchronize_irq(uport->irq); | ||
249 | } | 247 | } |
250 | 248 | ||
251 | /* | 249 | /* |
@@ -423,7 +421,7 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) | |||
423 | if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) | 421 | if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) |
424 | quot = port->custom_divisor; | 422 | quot = port->custom_divisor; |
425 | else | 423 | else |
426 | quot = (port->uartclk + (8 * baud)) / (16 * baud); | 424 | quot = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud); |
427 | 425 | ||
428 | return quot; | 426 | return quot; |
429 | } | 427 | } |
@@ -658,10 +656,10 @@ static int uart_get_info(struct uart_state *state, | |||
658 | tmp.flags = uport->flags; | 656 | tmp.flags = uport->flags; |
659 | tmp.xmit_fifo_size = uport->fifosize; | 657 | tmp.xmit_fifo_size = uport->fifosize; |
660 | tmp.baud_base = uport->uartclk / 16; | 658 | tmp.baud_base = uport->uartclk / 16; |
661 | tmp.close_delay = port->close_delay / 10; | 659 | tmp.close_delay = jiffies_to_msecs(port->close_delay) / 10; |
662 | tmp.closing_wait = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ? | 660 | tmp.closing_wait = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
663 | ASYNC_CLOSING_WAIT_NONE : | 661 | ASYNC_CLOSING_WAIT_NONE : |
664 | port->closing_wait / 10; | 662 | jiffies_to_msecs(port->closing_wait) / 10; |
665 | tmp.custom_divisor = uport->custom_divisor; | 663 | tmp.custom_divisor = uport->custom_divisor; |
666 | tmp.hub6 = uport->hub6; | 664 | tmp.hub6 = uport->hub6; |
667 | tmp.io_type = uport->iotype; | 665 | tmp.io_type = uport->iotype; |
@@ -695,9 +693,10 @@ static int uart_set_info(struct tty_struct *tty, struct uart_state *state, | |||
695 | new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; | 693 | new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; |
696 | 694 | ||
697 | new_serial.irq = irq_canonicalize(new_serial.irq); | 695 | new_serial.irq = irq_canonicalize(new_serial.irq); |
698 | close_delay = new_serial.close_delay * 10; | 696 | close_delay = msecs_to_jiffies(new_serial.close_delay * 10); |
699 | closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? | 697 | closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
700 | ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; | 698 | ASYNC_CLOSING_WAIT_NONE : |
699 | msecs_to_jiffies(new_serial.closing_wait * 10); | ||
701 | 700 | ||
702 | /* | 701 | /* |
703 | * This semaphore protects port->count. It is also | 702 | * This semaphore protects port->count. It is also |
@@ -1265,47 +1264,8 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1265 | 1264 | ||
1266 | pr_debug("uart_close(%d) called\n", uport->line); | 1265 | pr_debug("uart_close(%d) called\n", uport->line); |
1267 | 1266 | ||
1268 | spin_lock_irqsave(&port->lock, flags); | 1267 | if (tty_port_close_start(port, tty, filp) == 0) |
1269 | |||
1270 | if (tty_hung_up_p(filp)) { | ||
1271 | spin_unlock_irqrestore(&port->lock, flags); | ||
1272 | return; | 1268 | return; |
1273 | } | ||
1274 | |||
1275 | if ((tty->count == 1) && (port->count != 1)) { | ||
1276 | /* | ||
1277 | * Uh, oh. tty->count is 1, which means that the tty | ||
1278 | * structure will be freed. port->count should always | ||
1279 | * be one in these conditions. If it's greater than | ||
1280 | * one, we've got real problems, since it means the | ||
1281 | * serial port won't be shutdown. | ||
1282 | */ | ||
1283 | printk(KERN_ERR "uart_close: bad serial port count; tty->count is 1, " | ||
1284 | "port->count is %d\n", port->count); | ||
1285 | port->count = 1; | ||
1286 | } | ||
1287 | if (--port->count < 0) { | ||
1288 | printk(KERN_ERR "uart_close: bad serial port count for %s: %d\n", | ||
1289 | tty->name, port->count); | ||
1290 | port->count = 0; | ||
1291 | } | ||
1292 | if (port->count) { | ||
1293 | spin_unlock_irqrestore(&port->lock, flags); | ||
1294 | return; | ||
1295 | } | ||
1296 | |||
1297 | /* | ||
1298 | * Now we wait for the transmit buffer to clear; and we notify | ||
1299 | * the line discipline to only process XON/XOFF characters by | ||
1300 | * setting tty->closing. | ||
1301 | */ | ||
1302 | set_bit(ASYNCB_CLOSING, &port->flags); | ||
1303 | tty->closing = 1; | ||
1304 | spin_unlock_irqrestore(&port->lock, flags); | ||
1305 | |||
1306 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
1307 | tty_wait_until_sent_from_close(tty, | ||
1308 | msecs_to_jiffies(port->closing_wait)); | ||
1309 | 1269 | ||
1310 | /* | 1270 | /* |
1311 | * At this point, we stop accepting input. To do this, we | 1271 | * At this point, we stop accepting input. To do this, we |
@@ -1337,7 +1297,8 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1337 | if (port->blocked_open) { | 1297 | if (port->blocked_open) { |
1338 | spin_unlock_irqrestore(&port->lock, flags); | 1298 | spin_unlock_irqrestore(&port->lock, flags); |
1339 | if (port->close_delay) | 1299 | if (port->close_delay) |
1340 | msleep_interruptible(port->close_delay); | 1300 | msleep_interruptible( |
1301 | jiffies_to_msecs(port->close_delay)); | ||
1341 | spin_lock_irqsave(&port->lock, flags); | 1302 | spin_lock_irqsave(&port->lock, flags); |
1342 | } else if (!uart_console(uport)) { | 1303 | } else if (!uart_console(uport)) { |
1343 | spin_unlock_irqrestore(&port->lock, flags); | 1304 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -1441,6 +1402,36 @@ static void uart_hangup(struct tty_struct *tty) | |||
1441 | mutex_unlock(&port->mutex); | 1402 | mutex_unlock(&port->mutex); |
1442 | } | 1403 | } |
1443 | 1404 | ||
1405 | static int uart_port_activate(struct tty_port *port, struct tty_struct *tty) | ||
1406 | { | ||
1407 | return 0; | ||
1408 | } | ||
1409 | |||
1410 | static void uart_port_shutdown(struct tty_port *port) | ||
1411 | { | ||
1412 | struct uart_state *state = container_of(port, struct uart_state, port); | ||
1413 | struct uart_port *uport = state->uart_port; | ||
1414 | |||
1415 | /* | ||
1416 | * clear delta_msr_wait queue to avoid mem leaks: we may free | ||
1417 | * the irq here so the queue might never be woken up. Note | ||
1418 | * that we won't end up waiting on delta_msr_wait again since | ||
1419 | * any outstanding file descriptors should be pointing at | ||
1420 | * hung_up_tty_fops now. | ||
1421 | */ | ||
1422 | wake_up_interruptible(&port->delta_msr_wait); | ||
1423 | |||
1424 | /* | ||
1425 | * Free the IRQ and disable the port. | ||
1426 | */ | ||
1427 | uport->ops->shutdown(uport); | ||
1428 | |||
1429 | /* | ||
1430 | * Ensure that the IRQ handler isn't running on another CPU. | ||
1431 | */ | ||
1432 | synchronize_irq(uport->irq); | ||
1433 | } | ||
1434 | |||
1444 | static int uart_carrier_raised(struct tty_port *port) | 1435 | static int uart_carrier_raised(struct tty_port *port) |
1445 | { | 1436 | { |
1446 | struct uart_state *state = container_of(port, struct uart_state, port); | 1437 | struct uart_state *state = container_of(port, struct uart_state, port); |
@@ -1466,33 +1457,6 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) | |||
1466 | uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); | 1457 | uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); |
1467 | } | 1458 | } |
1468 | 1459 | ||
1469 | static struct uart_state *uart_get(struct uart_driver *drv, int line) | ||
1470 | { | ||
1471 | struct uart_state *state; | ||
1472 | struct tty_port *port; | ||
1473 | int ret = 0; | ||
1474 | |||
1475 | state = drv->state + line; | ||
1476 | port = &state->port; | ||
1477 | if (mutex_lock_interruptible(&port->mutex)) { | ||
1478 | ret = -ERESTARTSYS; | ||
1479 | goto err; | ||
1480 | } | ||
1481 | |||
1482 | port->count++; | ||
1483 | if (!state->uart_port || state->uart_port->flags & UPF_DEAD) { | ||
1484 | ret = -ENXIO; | ||
1485 | goto err_unlock; | ||
1486 | } | ||
1487 | return state; | ||
1488 | |||
1489 | err_unlock: | ||
1490 | port->count--; | ||
1491 | mutex_unlock(&port->mutex); | ||
1492 | err: | ||
1493 | return ERR_PTR(ret); | ||
1494 | } | ||
1495 | |||
1496 | /* | 1460 | /* |
1497 | * calls to uart_open are serialised by the BKL in | 1461 | * calls to uart_open are serialised by the BKL in |
1498 | * fs/char_dev.c:chrdev_open() | 1462 | * fs/char_dev.c:chrdev_open() |
@@ -1506,26 +1470,29 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) | |||
1506 | static int uart_open(struct tty_struct *tty, struct file *filp) | 1470 | static int uart_open(struct tty_struct *tty, struct file *filp) |
1507 | { | 1471 | { |
1508 | struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state; | 1472 | struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state; |
1509 | struct uart_state *state; | ||
1510 | struct tty_port *port; | ||
1511 | int retval, line = tty->index; | 1473 | int retval, line = tty->index; |
1474 | struct uart_state *state = drv->state + line; | ||
1475 | struct tty_port *port = &state->port; | ||
1512 | 1476 | ||
1513 | pr_debug("uart_open(%d) called\n", line); | 1477 | pr_debug("uart_open(%d) called\n", line); |
1514 | 1478 | ||
1515 | /* | 1479 | /* |
1516 | * We take the semaphore inside uart_get to guarantee that we won't | 1480 | * We take the semaphore here to guarantee that we won't be re-entered |
1517 | * be re-entered while allocating the state structure, or while we | 1481 | * while allocating the state structure, or while we request any IRQs |
1518 | * request any IRQs that the driver may need. This also has the nice | 1482 | * that the driver may need. This also has the nice side-effect that |
1519 | * side-effect that it delays the action of uart_hangup, so we can | 1483 | * it delays the action of uart_hangup, so we can guarantee that |
1520 | * guarantee that state->port.tty will always contain something | 1484 | * state->port.tty will always contain something reasonable. |
1521 | * reasonable. | ||
1522 | */ | 1485 | */ |
1523 | state = uart_get(drv, line); | 1486 | if (mutex_lock_interruptible(&port->mutex)) { |
1524 | if (IS_ERR(state)) { | 1487 | retval = -ERESTARTSYS; |
1525 | retval = PTR_ERR(state); | 1488 | goto end; |
1526 | goto fail; | 1489 | } |
1490 | |||
1491 | port->count++; | ||
1492 | if (!state->uart_port || state->uart_port->flags & UPF_DEAD) { | ||
1493 | retval = -ENXIO; | ||
1494 | goto err_dec_count; | ||
1527 | } | 1495 | } |
1528 | port = &state->port; | ||
1529 | 1496 | ||
1530 | /* | 1497 | /* |
1531 | * Once we set tty->driver_data here, we are guaranteed that | 1498 | * Once we set tty->driver_data here, we are guaranteed that |
@@ -1535,7 +1502,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1535 | tty->driver_data = state; | 1502 | tty->driver_data = state; |
1536 | state->uart_port->state = state; | 1503 | state->uart_port->state = state; |
1537 | tty->low_latency = (state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0; | 1504 | tty->low_latency = (state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0; |
1538 | tty->alt_speed = 0; | ||
1539 | tty_port_tty_set(port, tty); | 1505 | tty_port_tty_set(port, tty); |
1540 | 1506 | ||
1541 | /* | 1507 | /* |
@@ -1543,9 +1509,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1543 | */ | 1509 | */ |
1544 | if (tty_hung_up_p(filp)) { | 1510 | if (tty_hung_up_p(filp)) { |
1545 | retval = -EAGAIN; | 1511 | retval = -EAGAIN; |
1546 | port->count--; | 1512 | goto err_dec_count; |
1547 | mutex_unlock(&port->mutex); | ||
1548 | goto fail; | ||
1549 | } | 1513 | } |
1550 | 1514 | ||
1551 | /* | 1515 | /* |
@@ -1566,8 +1530,12 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1566 | if (retval == 0) | 1530 | if (retval == 0) |
1567 | retval = tty_port_block_til_ready(port, tty, filp); | 1531 | retval = tty_port_block_til_ready(port, tty, filp); |
1568 | 1532 | ||
1569 | fail: | 1533 | end: |
1570 | return retval; | 1534 | return retval; |
1535 | err_dec_count: | ||
1536 | port->count--; | ||
1537 | mutex_unlock(&port->mutex); | ||
1538 | goto end; | ||
1571 | } | 1539 | } |
1572 | 1540 | ||
1573 | static const char *uart_type(struct uart_port *port) | 1541 | static const char *uart_type(struct uart_port *port) |
@@ -1858,6 +1826,14 @@ uart_set_options(struct uart_port *port, struct console *co, | |||
1858 | EXPORT_SYMBOL_GPL(uart_set_options); | 1826 | EXPORT_SYMBOL_GPL(uart_set_options); |
1859 | #endif /* CONFIG_SERIAL_CORE_CONSOLE */ | 1827 | #endif /* CONFIG_SERIAL_CORE_CONSOLE */ |
1860 | 1828 | ||
1829 | /** | ||
1830 | * uart_change_pm - set power state of the port | ||
1831 | * | ||
1832 | * @state: port descriptor | ||
1833 | * @pm_state: new state | ||
1834 | * | ||
1835 | * Locking: port->mutex has to be held | ||
1836 | */ | ||
1861 | static void uart_change_pm(struct uart_state *state, int pm_state) | 1837 | static void uart_change_pm(struct uart_state *state, int pm_state) |
1862 | { | 1838 | { |
1863 | struct uart_port *port = state->uart_port; | 1839 | struct uart_port *port = state->uart_port; |
@@ -2214,6 +2190,8 @@ static const struct tty_operations uart_ops = { | |||
2214 | }; | 2190 | }; |
2215 | 2191 | ||
2216 | static const struct tty_port_operations uart_port_ops = { | 2192 | static const struct tty_port_operations uart_port_ops = { |
2193 | .activate = uart_port_activate, | ||
2194 | .shutdown = uart_port_shutdown, | ||
2217 | .carrier_raised = uart_carrier_raised, | 2195 | .carrier_raised = uart_carrier_raised, |
2218 | .dtr_rts = uart_dtr_rts, | 2196 | .dtr_rts = uart_dtr_rts, |
2219 | }; | 2197 | }; |
@@ -2275,8 +2253,8 @@ int uart_register_driver(struct uart_driver *drv) | |||
2275 | 2253 | ||
2276 | tty_port_init(port); | 2254 | tty_port_init(port); |
2277 | port->ops = &uart_port_ops; | 2255 | port->ops = &uart_port_ops; |
2278 | port->close_delay = 500; /* .5 seconds */ | 2256 | port->close_delay = HZ / 2; /* .5 seconds */ |
2279 | port->closing_wait = 30000; /* 30 seconds */ | 2257 | port->closing_wait = 30 * HZ;/* 30 seconds */ |
2280 | } | 2258 | } |
2281 | 2259 | ||
2282 | retval = tty_register_driver(normal); | 2260 | retval = tty_register_driver(normal); |
@@ -2467,6 +2445,99 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2) | |||
2467 | } | 2445 | } |
2468 | EXPORT_SYMBOL(uart_match_port); | 2446 | EXPORT_SYMBOL(uart_match_port); |
2469 | 2447 | ||
2448 | /** | ||
2449 | * uart_handle_dcd_change - handle a change of carrier detect state | ||
2450 | * @uport: uart_port structure for the open port | ||
2451 | * @status: new carrier detect status, nonzero if active | ||
2452 | */ | ||
2453 | void uart_handle_dcd_change(struct uart_port *uport, unsigned int status) | ||
2454 | { | ||
2455 | struct uart_state *state = uport->state; | ||
2456 | struct tty_port *port = &state->port; | ||
2457 | struct tty_ldisc *ld = tty_ldisc_ref(port->tty); | ||
2458 | struct pps_event_time ts; | ||
2459 | |||
2460 | if (ld && ld->ops->dcd_change) | ||
2461 | pps_get_ts(&ts); | ||
2462 | |||
2463 | uport->icount.dcd++; | ||
2464 | #ifdef CONFIG_HARD_PPS | ||
2465 | if ((uport->flags & UPF_HARDPPS_CD) && status) | ||
2466 | hardpps(); | ||
2467 | #endif | ||
2468 | |||
2469 | if (port->flags & ASYNC_CHECK_CD) { | ||
2470 | if (status) | ||
2471 | wake_up_interruptible(&port->open_wait); | ||
2472 | else if (port->tty) | ||
2473 | tty_hangup(port->tty); | ||
2474 | } | ||
2475 | |||
2476 | if (ld && ld->ops->dcd_change) | ||
2477 | ld->ops->dcd_change(port->tty, status, &ts); | ||
2478 | if (ld) | ||
2479 | tty_ldisc_deref(ld); | ||
2480 | } | ||
2481 | EXPORT_SYMBOL_GPL(uart_handle_dcd_change); | ||
2482 | |||
2483 | /** | ||
2484 | * uart_handle_cts_change - handle a change of clear-to-send state | ||
2485 | * @uport: uart_port structure for the open port | ||
2486 | * @status: new clear to send status, nonzero if active | ||
2487 | */ | ||
2488 | void uart_handle_cts_change(struct uart_port *uport, unsigned int status) | ||
2489 | { | ||
2490 | struct tty_port *port = &uport->state->port; | ||
2491 | struct tty_struct *tty = port->tty; | ||
2492 | |||
2493 | uport->icount.cts++; | ||
2494 | |||
2495 | if (port->flags & ASYNC_CTS_FLOW) { | ||
2496 | if (tty->hw_stopped) { | ||
2497 | if (status) { | ||
2498 | tty->hw_stopped = 0; | ||
2499 | uport->ops->start_tx(uport); | ||
2500 | uart_write_wakeup(uport); | ||
2501 | } | ||
2502 | } else { | ||
2503 | if (!status) { | ||
2504 | tty->hw_stopped = 1; | ||
2505 | uport->ops->stop_tx(uport); | ||
2506 | } | ||
2507 | } | ||
2508 | } | ||
2509 | } | ||
2510 | EXPORT_SYMBOL_GPL(uart_handle_cts_change); | ||
2511 | |||
2512 | /** | ||
2513 | * uart_insert_char - push a char to the uart layer | ||
2514 | * | ||
2515 | * User is responsible to call tty_flip_buffer_push when they are done with | ||
2516 | * insertion. | ||
2517 | * | ||
2518 | * @port: corresponding port | ||
2519 | * @status: state of the serial port RX buffer (LSR for 8250) | ||
2520 | * @overrun: mask of overrun bits in @status | ||
2521 | * @ch: character to push | ||
2522 | * @flag: flag for the character (see TTY_NORMAL and friends) | ||
2523 | */ | ||
2524 | void uart_insert_char(struct uart_port *port, unsigned int status, | ||
2525 | unsigned int overrun, unsigned int ch, unsigned int flag) | ||
2526 | { | ||
2527 | struct tty_struct *tty = port->state->port.tty; | ||
2528 | |||
2529 | if ((status & port->ignore_status_mask & ~overrun) == 0) | ||
2530 | tty_insert_flip_char(tty, ch, flag); | ||
2531 | |||
2532 | /* | ||
2533 | * Overrun is special. Since it's reported immediately, | ||
2534 | * it doesn't affect the current character. | ||
2535 | */ | ||
2536 | if (status & ~port->ignore_status_mask & overrun) | ||
2537 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
2538 | } | ||
2539 | EXPORT_SYMBOL_GPL(uart_insert_char); | ||
2540 | |||
2470 | EXPORT_SYMBOL(uart_write_wakeup); | 2541 | EXPORT_SYMBOL(uart_write_wakeup); |
2471 | EXPORT_SYMBOL(uart_register_driver); | 2542 | EXPORT_SYMBOL(uart_register_driver); |
2472 | EXPORT_SYMBOL(uart_unregister_driver); | 2543 | EXPORT_SYMBOL(uart_unregister_driver); |
diff --git a/drivers/tty/serial/serial_cs.c b/drivers/tty/serial/serial_cs.c index eef736ff810a..86090605a84e 100644 --- a/drivers/tty/serial/serial_cs.c +++ b/drivers/tty/serial/serial_cs.c | |||
@@ -317,7 +317,7 @@ static int serial_probe(struct pcmcia_device *link) | |||
317 | info->p_dev = link; | 317 | info->p_dev = link; |
318 | link->priv = info; | 318 | link->priv = info; |
319 | 319 | ||
320 | link->config_flags |= CONF_ENABLE_IRQ; | 320 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
321 | if (do_sound) | 321 | if (do_sound) |
322 | link->config_flags |= CONF_ENABLE_SPKR; | 322 | link->config_flags |= CONF_ENABLE_SPKR; |
323 | 323 | ||
@@ -445,7 +445,7 @@ static int simple_config(struct pcmcia_device *link) | |||
445 | 445 | ||
446 | /* First pass: look for a config entry that looks normal. | 446 | /* First pass: look for a config entry that looks normal. |
447 | * Two tries: without IO aliases, then with aliases */ | 447 | * Two tries: without IO aliases, then with aliases */ |
448 | link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_SET_IO; | 448 | link->config_flags |= CONF_AUTO_SET_VPP; |
449 | for (try = 0; try < 4; try++) | 449 | for (try = 0; try < 4; try++) |
450 | if (!pcmcia_loop_config(link, simple_config_check, &try)) | 450 | if (!pcmcia_loop_config(link, simple_config_check, &try)) |
451 | goto found_port; | 451 | goto found_port; |
@@ -501,7 +501,8 @@ static int multi_config_check_notpicky(struct pcmcia_device *p_dev, | |||
501 | { | 501 | { |
502 | int *base2 = priv_data; | 502 | int *base2 = priv_data; |
503 | 503 | ||
504 | if (!p_dev->resource[0]->end || !p_dev->resource[1]->end) | 504 | if (!p_dev->resource[0]->end || !p_dev->resource[1]->end || |
505 | p_dev->resource[0]->start + 8 != p_dev->resource[1]->start) | ||
505 | return -ENODEV; | 506 | return -ENODEV; |
506 | 507 | ||
507 | p_dev->resource[0]->end = p_dev->resource[1]->end = 8; | 508 | p_dev->resource[0]->end = p_dev->resource[1]->end = 8; |
@@ -520,7 +521,6 @@ static int multi_config(struct pcmcia_device *link) | |||
520 | struct serial_info *info = link->priv; | 521 | struct serial_info *info = link->priv; |
521 | int i, base2 = 0; | 522 | int i, base2 = 0; |
522 | 523 | ||
523 | link->config_flags |= CONF_AUTO_SET_IO; | ||
524 | /* First, look for a generic full-sized window */ | 524 | /* First, look for a generic full-sized window */ |
525 | if (!pcmcia_loop_config(link, multi_config_check, &info->multi)) | 525 | if (!pcmcia_loop_config(link, multi_config_check, &info->multi)) |
526 | base2 = link->resource[0]->start + 8; | 526 | base2 = link->resource[0]->start + 8; |
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c new file mode 100644 index 000000000000..a60523fee11b --- /dev/null +++ b/drivers/tty/serial/sirfsoc_uart.c | |||
@@ -0,0 +1,783 @@ | |||
1 | /* | ||
2 | * Driver for CSR SiRFprimaII onboard UARTs. | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/ioport.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/sysrq.h> | ||
14 | #include <linux/console.h> | ||
15 | #include <linux/tty.h> | ||
16 | #include <linux/tty_flip.h> | ||
17 | #include <linux/serial_core.h> | ||
18 | #include <linux/serial.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/of.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <asm/irq.h> | ||
24 | #include <asm/mach/irq.h> | ||
25 | #include <linux/pinctrl/pinmux.h> | ||
26 | |||
27 | #include "sirfsoc_uart.h" | ||
28 | |||
29 | static unsigned int | ||
30 | sirfsoc_uart_pio_tx_chars(struct sirfsoc_uart_port *sirfport, int count); | ||
31 | static unsigned int | ||
32 | sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count); | ||
33 | static struct uart_driver sirfsoc_uart_drv; | ||
34 | |||
35 | static const struct sirfsoc_baudrate_to_regv baudrate_to_regv[] = { | ||
36 | {4000000, 2359296}, | ||
37 | {3500000, 1310721}, | ||
38 | {3000000, 1572865}, | ||
39 | {2500000, 1245186}, | ||
40 | {2000000, 1572866}, | ||
41 | {1500000, 1245188}, | ||
42 | {1152000, 1638404}, | ||
43 | {1000000, 1572869}, | ||
44 | {921600, 1114120}, | ||
45 | {576000, 1245196}, | ||
46 | {500000, 1245198}, | ||
47 | {460800, 1572876}, | ||
48 | {230400, 1310750}, | ||
49 | {115200, 1310781}, | ||
50 | {57600, 1310843}, | ||
51 | {38400, 1114328}, | ||
52 | {19200, 1114545}, | ||
53 | {9600, 1114979}, | ||
54 | }; | ||
55 | |||
56 | static struct sirfsoc_uart_port sirfsoc_uart_ports[SIRFSOC_UART_NR] = { | ||
57 | [0] = { | ||
58 | .port = { | ||
59 | .iotype = UPIO_MEM, | ||
60 | .flags = UPF_BOOT_AUTOCONF, | ||
61 | .line = 0, | ||
62 | }, | ||
63 | }, | ||
64 | [1] = { | ||
65 | .port = { | ||
66 | .iotype = UPIO_MEM, | ||
67 | .flags = UPF_BOOT_AUTOCONF, | ||
68 | .line = 1, | ||
69 | }, | ||
70 | }, | ||
71 | [2] = { | ||
72 | .port = { | ||
73 | .iotype = UPIO_MEM, | ||
74 | .flags = UPF_BOOT_AUTOCONF, | ||
75 | .line = 2, | ||
76 | }, | ||
77 | }, | ||
78 | }; | ||
79 | |||
80 | static inline struct sirfsoc_uart_port *to_sirfport(struct uart_port *port) | ||
81 | { | ||
82 | return container_of(port, struct sirfsoc_uart_port, port); | ||
83 | } | ||
84 | |||
85 | static inline unsigned int sirfsoc_uart_tx_empty(struct uart_port *port) | ||
86 | { | ||
87 | unsigned long reg; | ||
88 | reg = rd_regl(port, SIRFUART_TX_FIFO_STATUS); | ||
89 | if (reg & SIRFUART_FIFOEMPTY_MASK(port)) | ||
90 | return TIOCSER_TEMT; | ||
91 | else | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static unsigned int sirfsoc_uart_get_mctrl(struct uart_port *port) | ||
96 | { | ||
97 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
98 | if (!(sirfport->ms_enabled)) { | ||
99 | goto cts_asserted; | ||
100 | } else if (sirfport->hw_flow_ctrl) { | ||
101 | if (!(rd_regl(port, SIRFUART_AFC_CTRL) & | ||
102 | SIRFUART_CTS_IN_STATUS)) | ||
103 | goto cts_asserted; | ||
104 | else | ||
105 | goto cts_deasserted; | ||
106 | } | ||
107 | cts_deasserted: | ||
108 | return TIOCM_CAR | TIOCM_DSR; | ||
109 | cts_asserted: | ||
110 | return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; | ||
111 | } | ||
112 | |||
113 | static void sirfsoc_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
114 | { | ||
115 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
116 | unsigned int assert = mctrl & TIOCM_RTS; | ||
117 | unsigned int val = assert ? SIRFUART_AFC_CTRL_RX_THD : 0x0; | ||
118 | unsigned int current_val; | ||
119 | if (sirfport->hw_flow_ctrl) { | ||
120 | current_val = rd_regl(port, SIRFUART_AFC_CTRL) & ~0xFF; | ||
121 | val |= current_val; | ||
122 | wr_regl(port, SIRFUART_AFC_CTRL, val); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static void sirfsoc_uart_stop_tx(struct uart_port *port) | ||
127 | { | ||
128 | unsigned int regv; | ||
129 | regv = rd_regl(port, SIRFUART_INT_EN); | ||
130 | wr_regl(port, SIRFUART_INT_EN, regv & ~SIRFUART_TX_INT_EN); | ||
131 | } | ||
132 | |||
133 | void sirfsoc_uart_start_tx(struct uart_port *port) | ||
134 | { | ||
135 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
136 | unsigned long regv; | ||
137 | sirfsoc_uart_pio_tx_chars(sirfport, 1); | ||
138 | wr_regl(port, SIRFUART_TX_FIFO_OP, SIRFUART_TX_FIFO_START); | ||
139 | regv = rd_regl(port, SIRFUART_INT_EN); | ||
140 | wr_regl(port, SIRFUART_INT_EN, regv | SIRFUART_TX_INT_EN); | ||
141 | } | ||
142 | |||
143 | static void sirfsoc_uart_stop_rx(struct uart_port *port) | ||
144 | { | ||
145 | unsigned long regv; | ||
146 | wr_regl(port, SIRFUART_RX_FIFO_OP, 0); | ||
147 | regv = rd_regl(port, SIRFUART_INT_EN); | ||
148 | wr_regl(port, SIRFUART_INT_EN, regv & ~SIRFUART_RX_IO_INT_EN); | ||
149 | } | ||
150 | |||
151 | static void sirfsoc_uart_disable_ms(struct uart_port *port) | ||
152 | { | ||
153 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
154 | unsigned long reg; | ||
155 | sirfport->ms_enabled = 0; | ||
156 | if (!sirfport->hw_flow_ctrl) | ||
157 | return; | ||
158 | reg = rd_regl(port, SIRFUART_AFC_CTRL); | ||
159 | wr_regl(port, SIRFUART_AFC_CTRL, reg & ~0x3FF); | ||
160 | reg = rd_regl(port, SIRFUART_INT_EN); | ||
161 | wr_regl(port, SIRFUART_INT_EN, reg & ~SIRFUART_CTS_INT_EN); | ||
162 | } | ||
163 | |||
164 | static void sirfsoc_uart_enable_ms(struct uart_port *port) | ||
165 | { | ||
166 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
167 | unsigned long reg; | ||
168 | unsigned long flg; | ||
169 | if (!sirfport->hw_flow_ctrl) | ||
170 | return; | ||
171 | flg = SIRFUART_AFC_RX_EN | SIRFUART_AFC_TX_EN; | ||
172 | reg = rd_regl(port, SIRFUART_AFC_CTRL); | ||
173 | wr_regl(port, SIRFUART_AFC_CTRL, reg | flg); | ||
174 | reg = rd_regl(port, SIRFUART_INT_EN); | ||
175 | wr_regl(port, SIRFUART_INT_EN, reg | SIRFUART_CTS_INT_EN); | ||
176 | uart_handle_cts_change(port, | ||
177 | !(rd_regl(port, SIRFUART_AFC_CTRL) & SIRFUART_CTS_IN_STATUS)); | ||
178 | sirfport->ms_enabled = 1; | ||
179 | } | ||
180 | |||
181 | static void sirfsoc_uart_break_ctl(struct uart_port *port, int break_state) | ||
182 | { | ||
183 | unsigned long ulcon = rd_regl(port, SIRFUART_LINE_CTRL); | ||
184 | if (break_state) | ||
185 | ulcon |= SIRFUART_SET_BREAK; | ||
186 | else | ||
187 | ulcon &= ~SIRFUART_SET_BREAK; | ||
188 | wr_regl(port, SIRFUART_LINE_CTRL, ulcon); | ||
189 | } | ||
190 | |||
191 | static unsigned int | ||
192 | sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count) | ||
193 | { | ||
194 | unsigned int ch, rx_count = 0; | ||
195 | struct tty_struct *tty; | ||
196 | |||
197 | tty = tty_port_tty_get(&port->state->port); | ||
198 | if (!tty) | ||
199 | return -ENODEV; | ||
200 | |||
201 | while (!(rd_regl(port, SIRFUART_RX_FIFO_STATUS) & | ||
202 | SIRFUART_FIFOEMPTY_MASK(port))) { | ||
203 | ch = rd_regl(port, SIRFUART_RX_FIFO_DATA) | SIRFUART_DUMMY_READ; | ||
204 | if (unlikely(uart_handle_sysrq_char(port, ch))) | ||
205 | continue; | ||
206 | uart_insert_char(port, 0, 0, ch, TTY_NORMAL); | ||
207 | rx_count++; | ||
208 | if (rx_count >= max_rx_count) | ||
209 | break; | ||
210 | } | ||
211 | |||
212 | port->icount.rx += rx_count; | ||
213 | tty_flip_buffer_push(tty); | ||
214 | tty_kref_put(tty); | ||
215 | |||
216 | return rx_count; | ||
217 | } | ||
218 | |||
219 | static unsigned int | ||
220 | sirfsoc_uart_pio_tx_chars(struct sirfsoc_uart_port *sirfport, int count) | ||
221 | { | ||
222 | struct uart_port *port = &sirfport->port; | ||
223 | struct circ_buf *xmit = &port->state->xmit; | ||
224 | unsigned int num_tx = 0; | ||
225 | while (!uart_circ_empty(xmit) && | ||
226 | !(rd_regl(port, SIRFUART_TX_FIFO_STATUS) & | ||
227 | SIRFUART_FIFOFULL_MASK(port)) && | ||
228 | count--) { | ||
229 | wr_regl(port, SIRFUART_TX_FIFO_DATA, xmit->buf[xmit->tail]); | ||
230 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
231 | port->icount.tx++; | ||
232 | num_tx++; | ||
233 | } | ||
234 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
235 | uart_write_wakeup(port); | ||
236 | return num_tx; | ||
237 | } | ||
238 | |||
239 | static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id) | ||
240 | { | ||
241 | unsigned long intr_status; | ||
242 | unsigned long cts_status; | ||
243 | unsigned long flag = TTY_NORMAL; | ||
244 | struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)dev_id; | ||
245 | struct uart_port *port = &sirfport->port; | ||
246 | struct uart_state *state = port->state; | ||
247 | struct circ_buf *xmit = &port->state->xmit; | ||
248 | intr_status = rd_regl(port, SIRFUART_INT_STATUS); | ||
249 | wr_regl(port, SIRFUART_INT_STATUS, intr_status); | ||
250 | intr_status &= rd_regl(port, SIRFUART_INT_EN); | ||
251 | if (unlikely(intr_status & (SIRFUART_ERR_INT_STAT))) { | ||
252 | if (intr_status & SIRFUART_RXD_BREAK) { | ||
253 | if (uart_handle_break(port)) | ||
254 | goto recv_char; | ||
255 | uart_insert_char(port, intr_status, | ||
256 | SIRFUART_RX_OFLOW, 0, TTY_BREAK); | ||
257 | return IRQ_HANDLED; | ||
258 | } | ||
259 | if (intr_status & SIRFUART_RX_OFLOW) | ||
260 | port->icount.overrun++; | ||
261 | if (intr_status & SIRFUART_FRM_ERR) { | ||
262 | port->icount.frame++; | ||
263 | flag = TTY_FRAME; | ||
264 | } | ||
265 | if (intr_status & SIRFUART_PARITY_ERR) | ||
266 | flag = TTY_PARITY; | ||
267 | wr_regl(port, SIRFUART_RX_FIFO_OP, SIRFUART_RX_FIFO_RESET); | ||
268 | wr_regl(port, SIRFUART_RX_FIFO_OP, 0); | ||
269 | wr_regl(port, SIRFUART_RX_FIFO_OP, SIRFUART_RX_FIFO_START); | ||
270 | intr_status &= port->read_status_mask; | ||
271 | uart_insert_char(port, intr_status, | ||
272 | SIRFUART_RX_OFLOW_INT, 0, flag); | ||
273 | } | ||
274 | recv_char: | ||
275 | if (intr_status & SIRFUART_CTS_INT_EN) { | ||
276 | cts_status = !(rd_regl(port, SIRFUART_AFC_CTRL) & | ||
277 | SIRFUART_CTS_IN_STATUS); | ||
278 | if (cts_status != 0) { | ||
279 | uart_handle_cts_change(port, 1); | ||
280 | } else { | ||
281 | uart_handle_cts_change(port, 0); | ||
282 | wake_up_interruptible(&state->port.delta_msr_wait); | ||
283 | } | ||
284 | } | ||
285 | if (intr_status & SIRFUART_RX_IO_INT_EN) | ||
286 | sirfsoc_uart_pio_rx_chars(port, SIRFSOC_UART_IO_RX_MAX_CNT); | ||
287 | if (intr_status & SIRFUART_TX_INT_EN) { | ||
288 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | ||
289 | return IRQ_HANDLED; | ||
290 | } else { | ||
291 | sirfsoc_uart_pio_tx_chars(sirfport, | ||
292 | SIRFSOC_UART_IO_TX_REASONABLE_CNT); | ||
293 | if ((uart_circ_empty(xmit)) && | ||
294 | (rd_regl(port, SIRFUART_TX_FIFO_STATUS) & | ||
295 | SIRFUART_FIFOEMPTY_MASK(port))) | ||
296 | sirfsoc_uart_stop_tx(port); | ||
297 | } | ||
298 | } | ||
299 | return IRQ_HANDLED; | ||
300 | } | ||
301 | |||
302 | static void sirfsoc_uart_start_rx(struct uart_port *port) | ||
303 | { | ||
304 | unsigned long regv; | ||
305 | regv = rd_regl(port, SIRFUART_INT_EN); | ||
306 | wr_regl(port, SIRFUART_INT_EN, regv | SIRFUART_RX_IO_INT_EN); | ||
307 | wr_regl(port, SIRFUART_RX_FIFO_OP, SIRFUART_RX_FIFO_RESET); | ||
308 | wr_regl(port, SIRFUART_RX_FIFO_OP, 0); | ||
309 | wr_regl(port, SIRFUART_RX_FIFO_OP, SIRFUART_RX_FIFO_START); | ||
310 | } | ||
311 | |||
312 | static unsigned int | ||
313 | sirfsoc_calc_sample_div(unsigned long baud_rate, | ||
314 | unsigned long ioclk_rate, unsigned long *setted_baud) | ||
315 | { | ||
316 | unsigned long min_delta = ~0UL; | ||
317 | unsigned short sample_div; | ||
318 | unsigned int regv = 0; | ||
319 | unsigned long ioclk_div; | ||
320 | unsigned long baud_tmp; | ||
321 | int temp_delta; | ||
322 | |||
323 | for (sample_div = SIRF_MIN_SAMPLE_DIV; | ||
324 | sample_div <= SIRF_MAX_SAMPLE_DIV; sample_div++) { | ||
325 | ioclk_div = (ioclk_rate / (baud_rate * (sample_div + 1))) - 1; | ||
326 | if (ioclk_div > SIRF_IOCLK_DIV_MAX) | ||
327 | continue; | ||
328 | baud_tmp = ioclk_rate / ((ioclk_div + 1) * (sample_div + 1)); | ||
329 | temp_delta = baud_tmp - baud_rate; | ||
330 | temp_delta = (temp_delta > 0) ? temp_delta : -temp_delta; | ||
331 | if (temp_delta < min_delta) { | ||
332 | regv = regv & (~SIRF_IOCLK_DIV_MASK); | ||
333 | regv = regv | ioclk_div; | ||
334 | regv = regv & (~SIRF_SAMPLE_DIV_MASK); | ||
335 | regv = regv | (sample_div << SIRF_SAMPLE_DIV_SHIFT); | ||
336 | min_delta = temp_delta; | ||
337 | *setted_baud = baud_tmp; | ||
338 | } | ||
339 | } | ||
340 | return regv; | ||
341 | } | ||
342 | |||
343 | static void sirfsoc_uart_set_termios(struct uart_port *port, | ||
344 | struct ktermios *termios, | ||
345 | struct ktermios *old) | ||
346 | { | ||
347 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
348 | unsigned long ioclk_rate; | ||
349 | unsigned long config_reg = 0; | ||
350 | unsigned long baud_rate; | ||
351 | unsigned long setted_baud; | ||
352 | unsigned long flags; | ||
353 | unsigned long ic; | ||
354 | unsigned int clk_div_reg = 0; | ||
355 | unsigned long temp_reg_val; | ||
356 | unsigned long rx_time_out; | ||
357 | int threshold_div; | ||
358 | int temp; | ||
359 | |||
360 | ioclk_rate = 150000000; | ||
361 | switch (termios->c_cflag & CSIZE) { | ||
362 | default: | ||
363 | case CS8: | ||
364 | config_reg |= SIRFUART_DATA_BIT_LEN_8; | ||
365 | break; | ||
366 | case CS7: | ||
367 | config_reg |= SIRFUART_DATA_BIT_LEN_7; | ||
368 | break; | ||
369 | case CS6: | ||
370 | config_reg |= SIRFUART_DATA_BIT_LEN_6; | ||
371 | break; | ||
372 | case CS5: | ||
373 | config_reg |= SIRFUART_DATA_BIT_LEN_5; | ||
374 | break; | ||
375 | } | ||
376 | if (termios->c_cflag & CSTOPB) | ||
377 | config_reg |= SIRFUART_STOP_BIT_LEN_2; | ||
378 | baud_rate = uart_get_baud_rate(port, termios, old, 0, 4000000); | ||
379 | spin_lock_irqsave(&port->lock, flags); | ||
380 | port->read_status_mask = SIRFUART_RX_OFLOW_INT; | ||
381 | port->ignore_status_mask = 0; | ||
382 | /* read flags */ | ||
383 | if (termios->c_iflag & INPCK) | ||
384 | port->read_status_mask |= | ||
385 | SIRFUART_FRM_ERR_INT | SIRFUART_PARITY_ERR_INT; | ||
386 | if (termios->c_iflag & (BRKINT | PARMRK)) | ||
387 | port->read_status_mask |= SIRFUART_RXD_BREAK_INT; | ||
388 | /* ignore flags */ | ||
389 | if (termios->c_iflag & IGNPAR) | ||
390 | port->ignore_status_mask |= | ||
391 | SIRFUART_FRM_ERR_INT | SIRFUART_PARITY_ERR_INT; | ||
392 | if ((termios->c_cflag & CREAD) == 0) | ||
393 | port->ignore_status_mask |= SIRFUART_DUMMY_READ; | ||
394 | /* enable parity if PARENB is set*/ | ||
395 | if (termios->c_cflag & PARENB) { | ||
396 | if (termios->c_cflag & CMSPAR) { | ||
397 | if (termios->c_cflag & PARODD) | ||
398 | config_reg |= SIRFUART_STICK_BIT_MARK; | ||
399 | else | ||
400 | config_reg |= SIRFUART_STICK_BIT_SPACE; | ||
401 | } else if (termios->c_cflag & PARODD) { | ||
402 | config_reg |= SIRFUART_STICK_BIT_ODD; | ||
403 | } else { | ||
404 | config_reg |= SIRFUART_STICK_BIT_EVEN; | ||
405 | } | ||
406 | } | ||
407 | /* Hardware Flow Control Settings */ | ||
408 | if (UART_ENABLE_MS(port, termios->c_cflag)) { | ||
409 | if (!sirfport->ms_enabled) | ||
410 | sirfsoc_uart_enable_ms(port); | ||
411 | } else { | ||
412 | if (sirfport->ms_enabled) | ||
413 | sirfsoc_uart_disable_ms(port); | ||
414 | } | ||
415 | |||
416 | /* common rate: fast calculation */ | ||
417 | for (ic = 0; ic < SIRF_BAUD_RATE_SUPPORT_NR; ic++) | ||
418 | if (baud_rate == baudrate_to_regv[ic].baud_rate) | ||
419 | clk_div_reg = baudrate_to_regv[ic].reg_val; | ||
420 | setted_baud = baud_rate; | ||
421 | /* arbitary rate setting */ | ||
422 | if (unlikely(clk_div_reg == 0)) | ||
423 | clk_div_reg = sirfsoc_calc_sample_div(baud_rate, ioclk_rate, | ||
424 | &setted_baud); | ||
425 | wr_regl(port, SIRFUART_DIVISOR, clk_div_reg); | ||
426 | |||
427 | if (tty_termios_baud_rate(termios)) | ||
428 | tty_termios_encode_baud_rate(termios, setted_baud, setted_baud); | ||
429 | |||
430 | /* set receive timeout */ | ||
431 | rx_time_out = SIRFSOC_UART_RX_TIMEOUT(baud_rate, 20000); | ||
432 | rx_time_out = (rx_time_out > 0xFFFF) ? 0xFFFF : rx_time_out; | ||
433 | config_reg |= SIRFUART_RECV_TIMEOUT(rx_time_out); | ||
434 | temp_reg_val = rd_regl(port, SIRFUART_TX_FIFO_OP); | ||
435 | wr_regl(port, SIRFUART_RX_FIFO_OP, 0); | ||
436 | wr_regl(port, SIRFUART_TX_FIFO_OP, | ||
437 | temp_reg_val & ~SIRFUART_TX_FIFO_START); | ||
438 | wr_regl(port, SIRFUART_TX_DMA_IO_CTRL, SIRFUART_TX_MODE_IO); | ||
439 | wr_regl(port, SIRFUART_RX_DMA_IO_CTRL, SIRFUART_RX_MODE_IO); | ||
440 | wr_regl(port, SIRFUART_LINE_CTRL, config_reg); | ||
441 | |||
442 | /* Reset Rx/Tx FIFO Threshold level for proper baudrate */ | ||
443 | if (baud_rate < 1000000) | ||
444 | threshold_div = 1; | ||
445 | else | ||
446 | threshold_div = 2; | ||
447 | temp = port->line == 1 ? 16 : 64; | ||
448 | wr_regl(port, SIRFUART_TX_FIFO_CTRL, temp / threshold_div); | ||
449 | wr_regl(port, SIRFUART_RX_FIFO_CTRL, temp / threshold_div); | ||
450 | temp_reg_val |= SIRFUART_TX_FIFO_START; | ||
451 | wr_regl(port, SIRFUART_TX_FIFO_OP, temp_reg_val); | ||
452 | uart_update_timeout(port, termios->c_cflag, baud_rate); | ||
453 | sirfsoc_uart_start_rx(port); | ||
454 | wr_regl(port, SIRFUART_TX_RX_EN, SIRFUART_TX_EN | SIRFUART_RX_EN); | ||
455 | spin_unlock_irqrestore(&port->lock, flags); | ||
456 | } | ||
457 | |||
458 | static void startup_uart_controller(struct uart_port *port) | ||
459 | { | ||
460 | unsigned long temp_regv; | ||
461 | int temp; | ||
462 | temp_regv = rd_regl(port, SIRFUART_TX_DMA_IO_CTRL); | ||
463 | wr_regl(port, SIRFUART_TX_DMA_IO_CTRL, temp_regv | SIRFUART_TX_MODE_IO); | ||
464 | temp_regv = rd_regl(port, SIRFUART_RX_DMA_IO_CTRL); | ||
465 | wr_regl(port, SIRFUART_RX_DMA_IO_CTRL, temp_regv | SIRFUART_RX_MODE_IO); | ||
466 | wr_regl(port, SIRFUART_TX_DMA_IO_LEN, 0); | ||
467 | wr_regl(port, SIRFUART_RX_DMA_IO_LEN, 0); | ||
468 | wr_regl(port, SIRFUART_TX_RX_EN, SIRFUART_RX_EN | SIRFUART_TX_EN); | ||
469 | wr_regl(port, SIRFUART_TX_FIFO_OP, SIRFUART_TX_FIFO_RESET); | ||
470 | wr_regl(port, SIRFUART_TX_FIFO_OP, 0); | ||
471 | wr_regl(port, SIRFUART_RX_FIFO_OP, SIRFUART_RX_FIFO_RESET); | ||
472 | wr_regl(port, SIRFUART_RX_FIFO_OP, 0); | ||
473 | temp = port->line == 1 ? 16 : 64; | ||
474 | wr_regl(port, SIRFUART_TX_FIFO_CTRL, temp); | ||
475 | wr_regl(port, SIRFUART_RX_FIFO_CTRL, temp); | ||
476 | } | ||
477 | |||
478 | static int sirfsoc_uart_startup(struct uart_port *port) | ||
479 | { | ||
480 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
481 | unsigned int index = port->line; | ||
482 | int ret; | ||
483 | set_irq_flags(port->irq, IRQF_VALID | IRQF_NOAUTOEN); | ||
484 | ret = request_irq(port->irq, | ||
485 | sirfsoc_uart_isr, | ||
486 | 0, | ||
487 | SIRFUART_PORT_NAME, | ||
488 | sirfport); | ||
489 | if (ret != 0) { | ||
490 | dev_err(port->dev, "UART%d request IRQ line (%d) failed.\n", | ||
491 | index, port->irq); | ||
492 | goto irq_err; | ||
493 | } | ||
494 | startup_uart_controller(port); | ||
495 | enable_irq(port->irq); | ||
496 | irq_err: | ||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | static void sirfsoc_uart_shutdown(struct uart_port *port) | ||
501 | { | ||
502 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
503 | wr_regl(port, SIRFUART_INT_EN, 0); | ||
504 | free_irq(port->irq, sirfport); | ||
505 | if (sirfport->ms_enabled) { | ||
506 | sirfsoc_uart_disable_ms(port); | ||
507 | sirfport->ms_enabled = 0; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | static const char *sirfsoc_uart_type(struct uart_port *port) | ||
512 | { | ||
513 | return port->type == SIRFSOC_PORT_TYPE ? SIRFUART_PORT_NAME : NULL; | ||
514 | } | ||
515 | |||
516 | static int sirfsoc_uart_request_port(struct uart_port *port) | ||
517 | { | ||
518 | void *ret; | ||
519 | ret = request_mem_region(port->mapbase, | ||
520 | SIRFUART_MAP_SIZE, SIRFUART_PORT_NAME); | ||
521 | return ret ? 0 : -EBUSY; | ||
522 | } | ||
523 | |||
524 | static void sirfsoc_uart_release_port(struct uart_port *port) | ||
525 | { | ||
526 | release_mem_region(port->mapbase, SIRFUART_MAP_SIZE); | ||
527 | } | ||
528 | |||
529 | static void sirfsoc_uart_config_port(struct uart_port *port, int flags) | ||
530 | { | ||
531 | if (flags & UART_CONFIG_TYPE) { | ||
532 | port->type = SIRFSOC_PORT_TYPE; | ||
533 | sirfsoc_uart_request_port(port); | ||
534 | } | ||
535 | } | ||
536 | |||
537 | static struct uart_ops sirfsoc_uart_ops = { | ||
538 | .tx_empty = sirfsoc_uart_tx_empty, | ||
539 | .get_mctrl = sirfsoc_uart_get_mctrl, | ||
540 | .set_mctrl = sirfsoc_uart_set_mctrl, | ||
541 | .stop_tx = sirfsoc_uart_stop_tx, | ||
542 | .start_tx = sirfsoc_uart_start_tx, | ||
543 | .stop_rx = sirfsoc_uart_stop_rx, | ||
544 | .enable_ms = sirfsoc_uart_enable_ms, | ||
545 | .break_ctl = sirfsoc_uart_break_ctl, | ||
546 | .startup = sirfsoc_uart_startup, | ||
547 | .shutdown = sirfsoc_uart_shutdown, | ||
548 | .set_termios = sirfsoc_uart_set_termios, | ||
549 | .type = sirfsoc_uart_type, | ||
550 | .release_port = sirfsoc_uart_release_port, | ||
551 | .request_port = sirfsoc_uart_request_port, | ||
552 | .config_port = sirfsoc_uart_config_port, | ||
553 | }; | ||
554 | |||
555 | #ifdef CONFIG_SERIAL_SIRFSOC_CONSOLE | ||
556 | static int __init sirfsoc_uart_console_setup(struct console *co, char *options) | ||
557 | { | ||
558 | unsigned int baud = 115200; | ||
559 | unsigned int bits = 8; | ||
560 | unsigned int parity = 'n'; | ||
561 | unsigned int flow = 'n'; | ||
562 | struct uart_port *port = &sirfsoc_uart_ports[co->index].port; | ||
563 | |||
564 | if (co->index < 0 || co->index >= SIRFSOC_UART_NR) | ||
565 | return -EINVAL; | ||
566 | |||
567 | if (!port->mapbase) | ||
568 | return -ENODEV; | ||
569 | |||
570 | if (options) | ||
571 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
572 | port->cons = co; | ||
573 | return uart_set_options(port, co, baud, parity, bits, flow); | ||
574 | } | ||
575 | |||
576 | static void sirfsoc_uart_console_putchar(struct uart_port *port, int ch) | ||
577 | { | ||
578 | while (rd_regl(port, | ||
579 | SIRFUART_TX_FIFO_STATUS) & SIRFUART_FIFOFULL_MASK(port)) | ||
580 | cpu_relax(); | ||
581 | wr_regb(port, SIRFUART_TX_FIFO_DATA, ch); | ||
582 | } | ||
583 | |||
584 | static void sirfsoc_uart_console_write(struct console *co, const char *s, | ||
585 | unsigned int count) | ||
586 | { | ||
587 | struct uart_port *port = &sirfsoc_uart_ports[co->index].port; | ||
588 | uart_console_write(port, s, count, sirfsoc_uart_console_putchar); | ||
589 | } | ||
590 | |||
591 | static struct console sirfsoc_uart_console = { | ||
592 | .name = SIRFSOC_UART_NAME, | ||
593 | .device = uart_console_device, | ||
594 | .flags = CON_PRINTBUFFER, | ||
595 | .index = -1, | ||
596 | .write = sirfsoc_uart_console_write, | ||
597 | .setup = sirfsoc_uart_console_setup, | ||
598 | .data = &sirfsoc_uart_drv, | ||
599 | }; | ||
600 | |||
601 | static int __init sirfsoc_uart_console_init(void) | ||
602 | { | ||
603 | register_console(&sirfsoc_uart_console); | ||
604 | return 0; | ||
605 | } | ||
606 | console_initcall(sirfsoc_uart_console_init); | ||
607 | #endif | ||
608 | |||
609 | static struct uart_driver sirfsoc_uart_drv = { | ||
610 | .owner = THIS_MODULE, | ||
611 | .driver_name = SIRFUART_PORT_NAME, | ||
612 | .nr = SIRFSOC_UART_NR, | ||
613 | .dev_name = SIRFSOC_UART_NAME, | ||
614 | .major = SIRFSOC_UART_MAJOR, | ||
615 | .minor = SIRFSOC_UART_MINOR, | ||
616 | #ifdef CONFIG_SERIAL_SIRFSOC_CONSOLE | ||
617 | .cons = &sirfsoc_uart_console, | ||
618 | #else | ||
619 | .cons = NULL, | ||
620 | #endif | ||
621 | }; | ||
622 | |||
623 | int sirfsoc_uart_probe(struct platform_device *pdev) | ||
624 | { | ||
625 | struct sirfsoc_uart_port *sirfport; | ||
626 | struct uart_port *port; | ||
627 | struct resource *res; | ||
628 | int ret; | ||
629 | |||
630 | if (of_property_read_u32(pdev->dev.of_node, "cell-index", &pdev->id)) { | ||
631 | dev_err(&pdev->dev, | ||
632 | "Unable to find cell-index in uart node.\n"); | ||
633 | ret = -EFAULT; | ||
634 | goto err; | ||
635 | } | ||
636 | |||
637 | sirfport = &sirfsoc_uart_ports[pdev->id]; | ||
638 | port = &sirfport->port; | ||
639 | port->dev = &pdev->dev; | ||
640 | port->private_data = sirfport; | ||
641 | |||
642 | if (of_find_property(pdev->dev.of_node, "hw_flow_ctrl", NULL)) | ||
643 | sirfport->hw_flow_ctrl = 1; | ||
644 | |||
645 | if (of_property_read_u32(pdev->dev.of_node, | ||
646 | "fifosize", | ||
647 | &port->fifosize)) { | ||
648 | dev_err(&pdev->dev, | ||
649 | "Unable to find fifosize in uart node.\n"); | ||
650 | ret = -EFAULT; | ||
651 | goto err; | ||
652 | } | ||
653 | |||
654 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
655 | if (res == NULL) { | ||
656 | dev_err(&pdev->dev, "Insufficient resources.\n"); | ||
657 | ret = -EFAULT; | ||
658 | goto err; | ||
659 | } | ||
660 | port->mapbase = res->start; | ||
661 | port->membase = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | ||
662 | if (!port->membase) { | ||
663 | dev_err(&pdev->dev, "Cannot remap resource.\n"); | ||
664 | ret = -ENOMEM; | ||
665 | goto err; | ||
666 | } | ||
667 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
668 | if (res == NULL) { | ||
669 | dev_err(&pdev->dev, "Insufficient resources.\n"); | ||
670 | ret = -EFAULT; | ||
671 | goto irq_err; | ||
672 | } | ||
673 | port->irq = res->start; | ||
674 | |||
675 | if (sirfport->hw_flow_ctrl) { | ||
676 | sirfport->pmx = pinmux_get(&pdev->dev, NULL); | ||
677 | ret = IS_ERR(sirfport->pmx); | ||
678 | if (ret) | ||
679 | goto pmx_err; | ||
680 | |||
681 | pinmux_enable(sirfport->pmx); | ||
682 | } | ||
683 | |||
684 | port->ops = &sirfsoc_uart_ops; | ||
685 | spin_lock_init(&port->lock); | ||
686 | |||
687 | platform_set_drvdata(pdev, sirfport); | ||
688 | ret = uart_add_one_port(&sirfsoc_uart_drv, port); | ||
689 | if (ret != 0) { | ||
690 | dev_err(&pdev->dev, "Cannot add UART port(%d).\n", pdev->id); | ||
691 | goto port_err; | ||
692 | } | ||
693 | |||
694 | return 0; | ||
695 | |||
696 | port_err: | ||
697 | platform_set_drvdata(pdev, NULL); | ||
698 | if (sirfport->hw_flow_ctrl) { | ||
699 | pinmux_disable(sirfport->pmx); | ||
700 | pinmux_put(sirfport->pmx); | ||
701 | } | ||
702 | pmx_err: | ||
703 | irq_err: | ||
704 | devm_iounmap(&pdev->dev, port->membase); | ||
705 | err: | ||
706 | return ret; | ||
707 | } | ||
708 | |||
709 | static int sirfsoc_uart_remove(struct platform_device *pdev) | ||
710 | { | ||
711 | struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); | ||
712 | struct uart_port *port = &sirfport->port; | ||
713 | platform_set_drvdata(pdev, NULL); | ||
714 | if (sirfport->hw_flow_ctrl) { | ||
715 | pinmux_disable(sirfport->pmx); | ||
716 | pinmux_put(sirfport->pmx); | ||
717 | } | ||
718 | devm_iounmap(&pdev->dev, port->membase); | ||
719 | uart_remove_one_port(&sirfsoc_uart_drv, port); | ||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | static int | ||
724 | sirfsoc_uart_suspend(struct platform_device *pdev, pm_message_t state) | ||
725 | { | ||
726 | struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); | ||
727 | struct uart_port *port = &sirfport->port; | ||
728 | uart_suspend_port(&sirfsoc_uart_drv, port); | ||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static int sirfsoc_uart_resume(struct platform_device *pdev) | ||
733 | { | ||
734 | struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); | ||
735 | struct uart_port *port = &sirfport->port; | ||
736 | uart_resume_port(&sirfsoc_uart_drv, port); | ||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static struct of_device_id sirfsoc_uart_ids[] __devinitdata = { | ||
741 | { .compatible = "sirf,prima2-uart", }, | ||
742 | {} | ||
743 | }; | ||
744 | MODULE_DEVICE_TABLE(of, sirfsoc_serial_of_match); | ||
745 | |||
746 | static struct platform_driver sirfsoc_uart_driver = { | ||
747 | .probe = sirfsoc_uart_probe, | ||
748 | .remove = __devexit_p(sirfsoc_uart_remove), | ||
749 | .suspend = sirfsoc_uart_suspend, | ||
750 | .resume = sirfsoc_uart_resume, | ||
751 | .driver = { | ||
752 | .name = SIRFUART_PORT_NAME, | ||
753 | .owner = THIS_MODULE, | ||
754 | .of_match_table = sirfsoc_uart_ids, | ||
755 | }, | ||
756 | }; | ||
757 | |||
758 | static int __init sirfsoc_uart_init(void) | ||
759 | { | ||
760 | int ret = 0; | ||
761 | |||
762 | ret = uart_register_driver(&sirfsoc_uart_drv); | ||
763 | if (ret) | ||
764 | goto out; | ||
765 | |||
766 | ret = platform_driver_register(&sirfsoc_uart_driver); | ||
767 | if (ret) | ||
768 | uart_unregister_driver(&sirfsoc_uart_drv); | ||
769 | out: | ||
770 | return ret; | ||
771 | } | ||
772 | module_init(sirfsoc_uart_init); | ||
773 | |||
774 | static void __exit sirfsoc_uart_exit(void) | ||
775 | { | ||
776 | platform_driver_unregister(&sirfsoc_uart_driver); | ||
777 | uart_unregister_driver(&sirfsoc_uart_drv); | ||
778 | } | ||
779 | module_exit(sirfsoc_uart_exit); | ||
780 | |||
781 | MODULE_LICENSE("GPL v2"); | ||
782 | MODULE_AUTHOR("Bin Shi <Bin.Shi@csr.com>, Rong Wang<Rong.Wang@csr.com>"); | ||
783 | MODULE_DESCRIPTION("CSR SiRFprimaII Uart Driver"); | ||
diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h new file mode 100644 index 000000000000..fc64260fa93c --- /dev/null +++ b/drivers/tty/serial/sirfsoc_uart.h | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * Drivers for CSR SiRFprimaII onboard UARTs. | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | #include <linux/bitops.h> | ||
9 | |||
10 | /* UART Register Offset Define */ | ||
11 | #define SIRFUART_LINE_CTRL 0x0040 | ||
12 | #define SIRFUART_TX_RX_EN 0x004c | ||
13 | #define SIRFUART_DIVISOR 0x0050 | ||
14 | #define SIRFUART_INT_EN 0x0054 | ||
15 | #define SIRFUART_INT_STATUS 0x0058 | ||
16 | #define SIRFUART_TX_DMA_IO_CTRL 0x0100 | ||
17 | #define SIRFUART_TX_DMA_IO_LEN 0x0104 | ||
18 | #define SIRFUART_TX_FIFO_CTRL 0x0108 | ||
19 | #define SIRFUART_TX_FIFO_LEVEL_CHK 0x010C | ||
20 | #define SIRFUART_TX_FIFO_OP 0x0110 | ||
21 | #define SIRFUART_TX_FIFO_STATUS 0x0114 | ||
22 | #define SIRFUART_TX_FIFO_DATA 0x0118 | ||
23 | #define SIRFUART_RX_DMA_IO_CTRL 0x0120 | ||
24 | #define SIRFUART_RX_DMA_IO_LEN 0x0124 | ||
25 | #define SIRFUART_RX_FIFO_CTRL 0x0128 | ||
26 | #define SIRFUART_RX_FIFO_LEVEL_CHK 0x012C | ||
27 | #define SIRFUART_RX_FIFO_OP 0x0130 | ||
28 | #define SIRFUART_RX_FIFO_STATUS 0x0134 | ||
29 | #define SIRFUART_RX_FIFO_DATA 0x0138 | ||
30 | #define SIRFUART_AFC_CTRL 0x0140 | ||
31 | #define SIRFUART_SWH_DMA_IO 0x0148 | ||
32 | |||
33 | /* UART Line Control Register */ | ||
34 | #define SIRFUART_DATA_BIT_LEN_MASK 0x3 | ||
35 | #define SIRFUART_DATA_BIT_LEN_5 BIT(0) | ||
36 | #define SIRFUART_DATA_BIT_LEN_6 1 | ||
37 | #define SIRFUART_DATA_BIT_LEN_7 2 | ||
38 | #define SIRFUART_DATA_BIT_LEN_8 3 | ||
39 | #define SIRFUART_STOP_BIT_LEN_1 0 | ||
40 | #define SIRFUART_STOP_BIT_LEN_2 BIT(2) | ||
41 | #define SIRFUART_PARITY_EN BIT(3) | ||
42 | #define SIRFUART_EVEN_BIT BIT(4) | ||
43 | #define SIRFUART_STICK_BIT_MASK (7 << 3) | ||
44 | #define SIRFUART_STICK_BIT_NONE (0 << 3) | ||
45 | #define SIRFUART_STICK_BIT_EVEN BIT(3) | ||
46 | #define SIRFUART_STICK_BIT_ODD (3 << 3) | ||
47 | #define SIRFUART_STICK_BIT_MARK (5 << 3) | ||
48 | #define SIRFUART_STICK_BIT_SPACE (7 << 3) | ||
49 | #define SIRFUART_SET_BREAK BIT(6) | ||
50 | #define SIRFUART_LOOP_BACK BIT(7) | ||
51 | #define SIRFUART_PARITY_MASK (7 << 3) | ||
52 | #define SIRFUART_DUMMY_READ BIT(16) | ||
53 | |||
54 | #define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000) | ||
55 | #define SIRFUART_RECV_TIMEOUT_MASK (0xFFFF << 16) | ||
56 | #define SIRFUART_RECV_TIMEOUT(x) (((x) & 0xFFFF) << 16) | ||
57 | |||
58 | /* UART Auto Flow Control */ | ||
59 | #define SIRFUART_AFC_RX_THD_MASK 0x000000FF | ||
60 | #define SIRFUART_AFC_RX_EN BIT(8) | ||
61 | #define SIRFUART_AFC_TX_EN BIT(9) | ||
62 | #define SIRFUART_CTS_CTRL BIT(10) | ||
63 | #define SIRFUART_RTS_CTRL BIT(11) | ||
64 | #define SIRFUART_CTS_IN_STATUS BIT(12) | ||
65 | #define SIRFUART_RTS_OUT_STATUS BIT(13) | ||
66 | |||
67 | /* UART Interrupt Enable Register */ | ||
68 | #define SIRFUART_RX_DONE_INT BIT(0) | ||
69 | #define SIRFUART_TX_DONE_INT BIT(1) | ||
70 | #define SIRFUART_RX_OFLOW_INT BIT(2) | ||
71 | #define SIRFUART_TX_ALLOUT_INT BIT(3) | ||
72 | #define SIRFUART_RX_IO_DMA_INT BIT(4) | ||
73 | #define SIRFUART_TX_IO_DMA_INT BIT(5) | ||
74 | #define SIRFUART_RXFIFO_FULL_INT BIT(6) | ||
75 | #define SIRFUART_TXFIFO_EMPTY_INT BIT(7) | ||
76 | #define SIRFUART_RXFIFO_THD_INT BIT(8) | ||
77 | #define SIRFUART_TXFIFO_THD_INT BIT(9) | ||
78 | #define SIRFUART_FRM_ERR_INT BIT(10) | ||
79 | #define SIRFUART_RXD_BREAK_INT BIT(11) | ||
80 | #define SIRFUART_RX_TIMEOUT_INT BIT(12) | ||
81 | #define SIRFUART_PARITY_ERR_INT BIT(13) | ||
82 | #define SIRFUART_CTS_INT_EN BIT(14) | ||
83 | #define SIRFUART_RTS_INT_EN BIT(15) | ||
84 | |||
85 | /* UART Interrupt Status Register */ | ||
86 | #define SIRFUART_RX_DONE BIT(0) | ||
87 | #define SIRFUART_TX_DONE BIT(1) | ||
88 | #define SIRFUART_RX_OFLOW BIT(2) | ||
89 | #define SIRFUART_TX_ALL_EMPTY BIT(3) | ||
90 | #define SIRFUART_DMA_IO_RX_DONE BIT(4) | ||
91 | #define SIRFUART_DMA_IO_TX_DONE BIT(5) | ||
92 | #define SIRFUART_RXFIFO_FULL BIT(6) | ||
93 | #define SIRFUART_TXFIFO_EMPTY BIT(7) | ||
94 | #define SIRFUART_RXFIFO_THD_REACH BIT(8) | ||
95 | #define SIRFUART_TXFIFO_THD_REACH BIT(9) | ||
96 | #define SIRFUART_FRM_ERR BIT(10) | ||
97 | #define SIRFUART_RXD_BREAK BIT(11) | ||
98 | #define SIRFUART_RX_TIMEOUT BIT(12) | ||
99 | #define SIRFUART_PARITY_ERR BIT(13) | ||
100 | #define SIRFUART_CTS_CHANGE BIT(14) | ||
101 | #define SIRFUART_RTS_CHANGE BIT(15) | ||
102 | #define SIRFUART_PLUG_IN BIT(16) | ||
103 | |||
104 | #define SIRFUART_ERR_INT_STAT \ | ||
105 | (SIRFUART_RX_OFLOW | \ | ||
106 | SIRFUART_FRM_ERR | \ | ||
107 | SIRFUART_RXD_BREAK | \ | ||
108 | SIRFUART_PARITY_ERR) | ||
109 | #define SIRFUART_ERR_INT_EN \ | ||
110 | (SIRFUART_RX_OFLOW_INT | \ | ||
111 | SIRFUART_FRM_ERR_INT | \ | ||
112 | SIRFUART_RXD_BREAK_INT | \ | ||
113 | SIRFUART_PARITY_ERR_INT) | ||
114 | #define SIRFUART_TX_INT_EN SIRFUART_TXFIFO_EMPTY_INT | ||
115 | #define SIRFUART_RX_IO_INT_EN \ | ||
116 | (SIRFUART_RX_TIMEOUT_INT | \ | ||
117 | SIRFUART_RXFIFO_THD_INT | \ | ||
118 | SIRFUART_RXFIFO_FULL_INT | \ | ||
119 | SIRFUART_ERR_INT_EN) | ||
120 | |||
121 | /* UART FIFO Register */ | ||
122 | #define SIRFUART_TX_FIFO_STOP 0x0 | ||
123 | #define SIRFUART_TX_FIFO_RESET 0x1 | ||
124 | #define SIRFUART_TX_FIFO_START 0x2 | ||
125 | #define SIRFUART_RX_FIFO_STOP 0x0 | ||
126 | #define SIRFUART_RX_FIFO_RESET 0x1 | ||
127 | #define SIRFUART_RX_FIFO_START 0x2 | ||
128 | #define SIRFUART_TX_MODE_DMA 0 | ||
129 | #define SIRFUART_TX_MODE_IO 1 | ||
130 | #define SIRFUART_RX_MODE_DMA 0 | ||
131 | #define SIRFUART_RX_MODE_IO 1 | ||
132 | |||
133 | #define SIRFUART_RX_EN 0x1 | ||
134 | #define SIRFUART_TX_EN 0x2 | ||
135 | |||
136 | /* Generic Definitions */ | ||
137 | #define SIRFSOC_UART_NAME "ttySiRF" | ||
138 | #define SIRFSOC_UART_MAJOR 0 | ||
139 | #define SIRFSOC_UART_MINOR 0 | ||
140 | #define SIRFUART_PORT_NAME "sirfsoc-uart" | ||
141 | #define SIRFUART_MAP_SIZE 0x200 | ||
142 | #define SIRFSOC_UART_NR 3 | ||
143 | #define SIRFSOC_PORT_TYPE 0xa5 | ||
144 | |||
145 | /* Baud Rate Calculation */ | ||
146 | #define SIRF_MIN_SAMPLE_DIV 0xf | ||
147 | #define SIRF_MAX_SAMPLE_DIV 0x3f | ||
148 | #define SIRF_IOCLK_DIV_MAX 0xffff | ||
149 | #define SIRF_SAMPLE_DIV_SHIFT 16 | ||
150 | #define SIRF_IOCLK_DIV_MASK 0xffff | ||
151 | #define SIRF_SAMPLE_DIV_MASK 0x3f0000 | ||
152 | #define SIRF_BAUD_RATE_SUPPORT_NR 18 | ||
153 | |||
154 | /* For Fast Baud Rate Calculation */ | ||
155 | struct sirfsoc_baudrate_to_regv { | ||
156 | unsigned int baud_rate; | ||
157 | unsigned int reg_val; | ||
158 | }; | ||
159 | |||
160 | struct sirfsoc_uart_port { | ||
161 | unsigned char hw_flow_ctrl; | ||
162 | unsigned char ms_enabled; | ||
163 | |||
164 | struct uart_port port; | ||
165 | struct pinmux *pmx; | ||
166 | }; | ||
167 | |||
168 | /* Hardware Flow Control */ | ||
169 | #define SIRFUART_AFC_CTRL_RX_THD 0x70 | ||
170 | |||
171 | /* Register Access Control */ | ||
172 | #define portaddr(port, reg) ((port)->membase + (reg)) | ||
173 | #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg))) | ||
174 | #define rd_regl(port, reg) (__raw_readl(portaddr(port, reg))) | ||
175 | #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg)) | ||
176 | #define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg)) | ||
177 | |||
178 | /* UART Port Mask */ | ||
179 | #define SIRFUART_FIFOLEVEL_MASK(port) ((port->line == 1) ? (0x1f) : (0x7f)) | ||
180 | #define SIRFUART_FIFOFULL_MASK(port) ((port->line == 1) ? (0x20) : (0x80)) | ||
181 | #define SIRFUART_FIFOEMPTY_MASK(port) ((port->line == 1) ? (0x40) : (0x100)) | ||
182 | |||
183 | /* I/O Mode */ | ||
184 | #define SIRFSOC_UART_IO_RX_MAX_CNT 256 | ||
185 | #define SIRFSOC_UART_IO_TX_REASONABLE_CNT 6 | ||
diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c index e76c8b747fb8..70f97491d8f2 100644 --- a/drivers/tty/serial/timbuart.c +++ b/drivers/tty/serial/timbuart.c | |||
@@ -513,20 +513,7 @@ static struct platform_driver timbuart_platform_driver = { | |||
513 | .remove = __devexit_p(timbuart_remove), | 513 | .remove = __devexit_p(timbuart_remove), |
514 | }; | 514 | }; |
515 | 515 | ||
516 | /*--------------------------------------------------------------------------*/ | 516 | module_platform_driver(timbuart_platform_driver); |
517 | |||
518 | static int __init timbuart_init(void) | ||
519 | { | ||
520 | return platform_driver_register(&timbuart_platform_driver); | ||
521 | } | ||
522 | |||
523 | static void __exit timbuart_exit(void) | ||
524 | { | ||
525 | platform_driver_unregister(&timbuart_platform_driver); | ||
526 | } | ||
527 | |||
528 | module_init(timbuart_init); | ||
529 | module_exit(timbuart_exit); | ||
530 | 517 | ||
531 | MODULE_DESCRIPTION("Timberdale UART driver"); | 518 | MODULE_DESCRIPTION("Timberdale UART driver"); |
532 | MODULE_LICENSE("GPL v2"); | 519 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c index 3beb6ab4fa68..83148e79ca13 100644 --- a/drivers/tty/serial/vr41xx_siu.c +++ b/drivers/tty/serial/vr41xx_siu.c | |||
@@ -961,18 +961,7 @@ static struct platform_driver siu_device_driver = { | |||
961 | }, | 961 | }, |
962 | }; | 962 | }; |
963 | 963 | ||
964 | static int __init vr41xx_siu_init(void) | 964 | module_platform_driver(siu_device_driver); |
965 | { | ||
966 | return platform_driver_register(&siu_device_driver); | ||
967 | } | ||
968 | |||
969 | static void __exit vr41xx_siu_exit(void) | ||
970 | { | ||
971 | platform_driver_unregister(&siu_device_driver); | ||
972 | } | ||
973 | |||
974 | module_init(vr41xx_siu_init); | ||
975 | module_exit(vr41xx_siu_exit); | ||
976 | 965 | ||
977 | MODULE_LICENSE("GPL"); | 966 | MODULE_LICENSE("GPL"); |
978 | MODULE_ALIAS("platform:SIU"); | 967 | MODULE_ALIAS("platform:SIU"); |
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 3fdebd306b94..e41b9bbc107d 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -790,19 +790,24 @@ static void session_clear_tty(struct pid *session) | |||
790 | void disassociate_ctty(int on_exit) | 790 | void disassociate_ctty(int on_exit) |
791 | { | 791 | { |
792 | struct tty_struct *tty; | 792 | struct tty_struct *tty; |
793 | struct pid *tty_pgrp = NULL; | ||
794 | 793 | ||
795 | if (!current->signal->leader) | 794 | if (!current->signal->leader) |
796 | return; | 795 | return; |
797 | 796 | ||
798 | tty = get_current_tty(); | 797 | tty = get_current_tty(); |
799 | if (tty) { | 798 | if (tty) { |
800 | tty_pgrp = get_pid(tty->pgrp); | 799 | struct pid *tty_pgrp = get_pid(tty->pgrp); |
801 | if (on_exit) { | 800 | if (on_exit) { |
802 | if (tty->driver->type != TTY_DRIVER_TYPE_PTY) | 801 | if (tty->driver->type != TTY_DRIVER_TYPE_PTY) |
803 | tty_vhangup(tty); | 802 | tty_vhangup(tty); |
804 | } | 803 | } |
805 | tty_kref_put(tty); | 804 | tty_kref_put(tty); |
805 | if (tty_pgrp) { | ||
806 | kill_pgrp(tty_pgrp, SIGHUP, on_exit); | ||
807 | if (!on_exit) | ||
808 | kill_pgrp(tty_pgrp, SIGCONT, on_exit); | ||
809 | put_pid(tty_pgrp); | ||
810 | } | ||
806 | } else if (on_exit) { | 811 | } else if (on_exit) { |
807 | struct pid *old_pgrp; | 812 | struct pid *old_pgrp; |
808 | spin_lock_irq(¤t->sighand->siglock); | 813 | spin_lock_irq(¤t->sighand->siglock); |
@@ -816,12 +821,6 @@ void disassociate_ctty(int on_exit) | |||
816 | } | 821 | } |
817 | return; | 822 | return; |
818 | } | 823 | } |
819 | if (tty_pgrp) { | ||
820 | kill_pgrp(tty_pgrp, SIGHUP, on_exit); | ||
821 | if (!on_exit) | ||
822 | kill_pgrp(tty_pgrp, SIGCONT, on_exit); | ||
823 | put_pid(tty_pgrp); | ||
824 | } | ||
825 | 824 | ||
826 | spin_lock_irq(¤t->sighand->siglock); | 825 | spin_lock_irq(¤t->sighand->siglock); |
827 | put_pid(current->signal->tty_old_pgrp); | 826 | put_pid(current->signal->tty_old_pgrp); |
@@ -1558,6 +1557,59 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
1558 | } | 1557 | } |
1559 | 1558 | ||
1560 | /** | 1559 | /** |
1560 | * tty_release_checks - check a tty before real release | ||
1561 | * @tty: tty to check | ||
1562 | * @o_tty: link of @tty (if any) | ||
1563 | * @idx: index of the tty | ||
1564 | * | ||
1565 | * Performs some paranoid checking before true release of the @tty. | ||
1566 | * This is a no-op unless TTY_PARANOIA_CHECK is defined. | ||
1567 | */ | ||
1568 | static int tty_release_checks(struct tty_struct *tty, struct tty_struct *o_tty, | ||
1569 | int idx) | ||
1570 | { | ||
1571 | #ifdef TTY_PARANOIA_CHECK | ||
1572 | if (idx < 0 || idx >= tty->driver->num) { | ||
1573 | printk(KERN_DEBUG "%s: bad idx when trying to free (%s)\n", | ||
1574 | __func__, tty->name); | ||
1575 | return -1; | ||
1576 | } | ||
1577 | |||
1578 | /* not much to check for devpts */ | ||
1579 | if (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) | ||
1580 | return 0; | ||
1581 | |||
1582 | if (tty != tty->driver->ttys[idx]) { | ||
1583 | printk(KERN_DEBUG "%s: driver.table[%d] not tty for (%s)\n", | ||
1584 | __func__, idx, tty->name); | ||
1585 | return -1; | ||
1586 | } | ||
1587 | if (tty->termios != tty->driver->termios[idx]) { | ||
1588 | printk(KERN_DEBUG "%s: driver.termios[%d] not termios for (%s)\n", | ||
1589 | __func__, idx, tty->name); | ||
1590 | return -1; | ||
1591 | } | ||
1592 | if (tty->driver->other) { | ||
1593 | if (o_tty != tty->driver->other->ttys[idx]) { | ||
1594 | printk(KERN_DEBUG "%s: other->table[%d] not o_tty for (%s)\n", | ||
1595 | __func__, idx, tty->name); | ||
1596 | return -1; | ||
1597 | } | ||
1598 | if (o_tty->termios != tty->driver->other->termios[idx]) { | ||
1599 | printk(KERN_DEBUG "%s: other->termios[%d] not o_termios for (%s)\n", | ||
1600 | __func__, idx, tty->name); | ||
1601 | return -1; | ||
1602 | } | ||
1603 | if (o_tty->link != tty) { | ||
1604 | printk(KERN_DEBUG "%s: bad pty pointers\n", __func__); | ||
1605 | return -1; | ||
1606 | } | ||
1607 | } | ||
1608 | #endif | ||
1609 | return 0; | ||
1610 | } | ||
1611 | |||
1612 | /** | ||
1561 | * tty_release - vfs callback for close | 1613 | * tty_release - vfs callback for close |
1562 | * @inode: inode of tty | 1614 | * @inode: inode of tty |
1563 | * @filp: file pointer for handle to tty | 1615 | * @filp: file pointer for handle to tty |
@@ -1585,11 +1637,11 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1585 | int idx; | 1637 | int idx; |
1586 | char buf[64]; | 1638 | char buf[64]; |
1587 | 1639 | ||
1588 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) | 1640 | if (tty_paranoia_check(tty, inode, __func__)) |
1589 | return 0; | 1641 | return 0; |
1590 | 1642 | ||
1591 | tty_lock(); | 1643 | tty_lock(); |
1592 | check_tty_count(tty, "tty_release_dev"); | 1644 | check_tty_count(tty, __func__); |
1593 | 1645 | ||
1594 | __tty_fasync(-1, filp, 0); | 1646 | __tty_fasync(-1, filp, 0); |
1595 | 1647 | ||
@@ -1599,59 +1651,16 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1599 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; | 1651 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; |
1600 | o_tty = tty->link; | 1652 | o_tty = tty->link; |
1601 | 1653 | ||
1602 | #ifdef TTY_PARANOIA_CHECK | 1654 | if (tty_release_checks(tty, o_tty, idx)) { |
1603 | if (idx < 0 || idx >= tty->driver->num) { | ||
1604 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " | ||
1605 | "free (%s)\n", tty->name); | ||
1606 | tty_unlock(); | 1655 | tty_unlock(); |
1607 | return 0; | 1656 | return 0; |
1608 | } | 1657 | } |
1609 | if (!devpts) { | ||
1610 | if (tty != tty->driver->ttys[idx]) { | ||
1611 | tty_unlock(); | ||
1612 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " | ||
1613 | "for (%s)\n", idx, tty->name); | ||
1614 | return 0; | ||
1615 | } | ||
1616 | if (tty->termios != tty->driver->termios[idx]) { | ||
1617 | tty_unlock(); | ||
1618 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " | ||
1619 | "for (%s)\n", | ||
1620 | idx, tty->name); | ||
1621 | return 0; | ||
1622 | } | ||
1623 | } | ||
1624 | #endif | ||
1625 | 1658 | ||
1626 | #ifdef TTY_DEBUG_HANGUP | 1659 | #ifdef TTY_DEBUG_HANGUP |
1627 | printk(KERN_DEBUG "tty_release_dev of %s (tty count=%d)...", | 1660 | printk(KERN_DEBUG "%s: %s (tty count=%d)...\n", __func__, |
1628 | tty_name(tty, buf), tty->count); | 1661 | tty_name(tty, buf), tty->count); |
1629 | #endif | 1662 | #endif |
1630 | 1663 | ||
1631 | #ifdef TTY_PARANOIA_CHECK | ||
1632 | if (tty->driver->other && | ||
1633 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | ||
1634 | if (o_tty != tty->driver->other->ttys[idx]) { | ||
1635 | tty_unlock(); | ||
1636 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " | ||
1637 | "not o_tty for (%s)\n", | ||
1638 | idx, tty->name); | ||
1639 | return 0 ; | ||
1640 | } | ||
1641 | if (o_tty->termios != tty->driver->other->termios[idx]) { | ||
1642 | tty_unlock(); | ||
1643 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " | ||
1644 | "not o_termios for (%s)\n", | ||
1645 | idx, tty->name); | ||
1646 | return 0; | ||
1647 | } | ||
1648 | if (o_tty->link != tty) { | ||
1649 | tty_unlock(); | ||
1650 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); | ||
1651 | return 0; | ||
1652 | } | ||
1653 | } | ||
1654 | #endif | ||
1655 | if (tty->ops->close) | 1664 | if (tty->ops->close) |
1656 | tty->ops->close(tty, filp); | 1665 | tty->ops->close(tty, filp); |
1657 | 1666 | ||
@@ -1707,8 +1716,8 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1707 | if (!do_sleep) | 1716 | if (!do_sleep) |
1708 | break; | 1717 | break; |
1709 | 1718 | ||
1710 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " | 1719 | printk(KERN_WARNING "%s: %s: read/write wait queue active!\n", |
1711 | "active!\n", tty_name(tty, buf)); | 1720 | __func__, tty_name(tty, buf)); |
1712 | tty_unlock(); | 1721 | tty_unlock(); |
1713 | mutex_unlock(&tty_mutex); | 1722 | mutex_unlock(&tty_mutex); |
1714 | schedule(); | 1723 | schedule(); |
@@ -1721,15 +1730,14 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1721 | */ | 1730 | */ |
1722 | if (pty_master) { | 1731 | if (pty_master) { |
1723 | if (--o_tty->count < 0) { | 1732 | if (--o_tty->count < 0) { |
1724 | printk(KERN_WARNING "tty_release_dev: bad pty slave count " | 1733 | printk(KERN_WARNING "%s: bad pty slave count (%d) for %s\n", |
1725 | "(%d) for %s\n", | 1734 | __func__, o_tty->count, tty_name(o_tty, buf)); |
1726 | o_tty->count, tty_name(o_tty, buf)); | ||
1727 | o_tty->count = 0; | 1735 | o_tty->count = 0; |
1728 | } | 1736 | } |
1729 | } | 1737 | } |
1730 | if (--tty->count < 0) { | 1738 | if (--tty->count < 0) { |
1731 | printk(KERN_WARNING "tty_release_dev: bad tty->count (%d) for %s\n", | 1739 | printk(KERN_WARNING "%s: bad tty->count (%d) for %s\n", |
1732 | tty->count, tty_name(tty, buf)); | 1740 | __func__, tty->count, tty_name(tty, buf)); |
1733 | tty->count = 0; | 1741 | tty->count = 0; |
1734 | } | 1742 | } |
1735 | 1743 | ||
@@ -1778,7 +1786,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1778 | } | 1786 | } |
1779 | 1787 | ||
1780 | #ifdef TTY_DEBUG_HANGUP | 1788 | #ifdef TTY_DEBUG_HANGUP |
1781 | printk(KERN_DEBUG "freeing tty structure..."); | 1789 | printk(KERN_DEBUG "%s: freeing tty structure...\n", __func__); |
1782 | #endif | 1790 | #endif |
1783 | /* | 1791 | /* |
1784 | * Ask the line discipline code to release its structures | 1792 | * Ask the line discipline code to release its structures |
@@ -1798,6 +1806,83 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1798 | } | 1806 | } |
1799 | 1807 | ||
1800 | /** | 1808 | /** |
1809 | * tty_open_current_tty - get tty of current task for open | ||
1810 | * @device: device number | ||
1811 | * @filp: file pointer to tty | ||
1812 | * @return: tty of the current task iff @device is /dev/tty | ||
1813 | * | ||
1814 | * We cannot return driver and index like for the other nodes because | ||
1815 | * devpts will not work then. It expects inodes to be from devpts FS. | ||
1816 | */ | ||
1817 | static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp) | ||
1818 | { | ||
1819 | struct tty_struct *tty; | ||
1820 | |||
1821 | if (device != MKDEV(TTYAUX_MAJOR, 0)) | ||
1822 | return NULL; | ||
1823 | |||
1824 | tty = get_current_tty(); | ||
1825 | if (!tty) | ||
1826 | return ERR_PTR(-ENXIO); | ||
1827 | |||
1828 | filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ | ||
1829 | /* noctty = 1; */ | ||
1830 | tty_kref_put(tty); | ||
1831 | /* FIXME: we put a reference and return a TTY! */ | ||
1832 | return tty; | ||
1833 | } | ||
1834 | |||
1835 | /** | ||
1836 | * tty_lookup_driver - lookup a tty driver for a given device file | ||
1837 | * @device: device number | ||
1838 | * @filp: file pointer to tty | ||
1839 | * @noctty: set if the device should not become a controlling tty | ||
1840 | * @index: index for the device in the @return driver | ||
1841 | * @return: driver for this inode (with increased refcount) | ||
1842 | * | ||
1843 | * If @return is not erroneous, the caller is responsible to decrement the | ||
1844 | * refcount by tty_driver_kref_put. | ||
1845 | * | ||
1846 | * Locking: tty_mutex protects get_tty_driver | ||
1847 | */ | ||
1848 | static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, | ||
1849 | int *noctty, int *index) | ||
1850 | { | ||
1851 | struct tty_driver *driver; | ||
1852 | |||
1853 | switch (device) { | ||
1854 | #ifdef CONFIG_VT | ||
1855 | case MKDEV(TTY_MAJOR, 0): { | ||
1856 | extern struct tty_driver *console_driver; | ||
1857 | driver = tty_driver_kref_get(console_driver); | ||
1858 | *index = fg_console; | ||
1859 | *noctty = 1; | ||
1860 | break; | ||
1861 | } | ||
1862 | #endif | ||
1863 | case MKDEV(TTYAUX_MAJOR, 1): { | ||
1864 | struct tty_driver *console_driver = console_device(index); | ||
1865 | if (console_driver) { | ||
1866 | driver = tty_driver_kref_get(console_driver); | ||
1867 | if (driver) { | ||
1868 | /* Don't let /dev/console block */ | ||
1869 | filp->f_flags |= O_NONBLOCK; | ||
1870 | *noctty = 1; | ||
1871 | break; | ||
1872 | } | ||
1873 | } | ||
1874 | return ERR_PTR(-ENODEV); | ||
1875 | } | ||
1876 | default: | ||
1877 | driver = get_tty_driver(device, index); | ||
1878 | if (!driver) | ||
1879 | return ERR_PTR(-ENODEV); | ||
1880 | break; | ||
1881 | } | ||
1882 | return driver; | ||
1883 | } | ||
1884 | |||
1885 | /** | ||
1801 | * tty_open - open a tty device | 1886 | * tty_open - open a tty device |
1802 | * @inode: inode of device file | 1887 | * @inode: inode of device file |
1803 | * @filp: file pointer to tty | 1888 | * @filp: file pointer to tty |
@@ -1813,16 +1898,16 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1813 | * The termios state of a pty is reset on first open so that | 1898 | * The termios state of a pty is reset on first open so that |
1814 | * settings don't persist across reuse. | 1899 | * settings don't persist across reuse. |
1815 | * | 1900 | * |
1816 | * Locking: tty_mutex protects tty, get_tty_driver and tty_init_dev work. | 1901 | * Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev. |
1817 | * tty->count should protect the rest. | 1902 | * tty->count should protect the rest. |
1818 | * ->siglock protects ->signal/->sighand | 1903 | * ->siglock protects ->signal/->sighand |
1819 | */ | 1904 | */ |
1820 | 1905 | ||
1821 | static int tty_open(struct inode *inode, struct file *filp) | 1906 | static int tty_open(struct inode *inode, struct file *filp) |
1822 | { | 1907 | { |
1823 | struct tty_struct *tty = NULL; | 1908 | struct tty_struct *tty; |
1824 | int noctty, retval; | 1909 | int noctty, retval; |
1825 | struct tty_driver *driver; | 1910 | struct tty_driver *driver = NULL; |
1826 | int index; | 1911 | int index; |
1827 | dev_t device = inode->i_rdev; | 1912 | dev_t device = inode->i_rdev; |
1828 | unsigned saved_flags = filp->f_flags; | 1913 | unsigned saved_flags = filp->f_flags; |
@@ -1841,66 +1926,22 @@ retry_open: | |||
1841 | mutex_lock(&tty_mutex); | 1926 | mutex_lock(&tty_mutex); |
1842 | tty_lock(); | 1927 | tty_lock(); |
1843 | 1928 | ||
1844 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { | 1929 | tty = tty_open_current_tty(device, filp); |
1845 | tty = get_current_tty(); | 1930 | if (IS_ERR(tty)) { |
1846 | if (!tty) { | 1931 | retval = PTR_ERR(tty); |
1847 | tty_unlock(); | 1932 | goto err_unlock; |
1848 | mutex_unlock(&tty_mutex); | 1933 | } else if (!tty) { |
1849 | tty_free_file(filp); | 1934 | driver = tty_lookup_driver(device, filp, &noctty, &index); |
1850 | return -ENXIO; | 1935 | if (IS_ERR(driver)) { |
1851 | } | 1936 | retval = PTR_ERR(driver); |
1852 | driver = tty_driver_kref_get(tty->driver); | 1937 | goto err_unlock; |
1853 | index = tty->index; | ||
1854 | filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ | ||
1855 | /* noctty = 1; */ | ||
1856 | /* FIXME: Should we take a driver reference ? */ | ||
1857 | tty_kref_put(tty); | ||
1858 | goto got_driver; | ||
1859 | } | ||
1860 | #ifdef CONFIG_VT | ||
1861 | if (device == MKDEV(TTY_MAJOR, 0)) { | ||
1862 | extern struct tty_driver *console_driver; | ||
1863 | driver = tty_driver_kref_get(console_driver); | ||
1864 | index = fg_console; | ||
1865 | noctty = 1; | ||
1866 | goto got_driver; | ||
1867 | } | ||
1868 | #endif | ||
1869 | if (device == MKDEV(TTYAUX_MAJOR, 1)) { | ||
1870 | struct tty_driver *console_driver = console_device(&index); | ||
1871 | if (console_driver) { | ||
1872 | driver = tty_driver_kref_get(console_driver); | ||
1873 | if (driver) { | ||
1874 | /* Don't let /dev/console block */ | ||
1875 | filp->f_flags |= O_NONBLOCK; | ||
1876 | noctty = 1; | ||
1877 | goto got_driver; | ||
1878 | } | ||
1879 | } | 1938 | } |
1880 | tty_unlock(); | ||
1881 | mutex_unlock(&tty_mutex); | ||
1882 | tty_free_file(filp); | ||
1883 | return -ENODEV; | ||
1884 | } | ||
1885 | 1939 | ||
1886 | driver = get_tty_driver(device, &index); | ||
1887 | if (!driver) { | ||
1888 | tty_unlock(); | ||
1889 | mutex_unlock(&tty_mutex); | ||
1890 | tty_free_file(filp); | ||
1891 | return -ENODEV; | ||
1892 | } | ||
1893 | got_driver: | ||
1894 | if (!tty) { | ||
1895 | /* check whether we're reopening an existing tty */ | 1940 | /* check whether we're reopening an existing tty */ |
1896 | tty = tty_driver_lookup_tty(driver, inode, index); | 1941 | tty = tty_driver_lookup_tty(driver, inode, index); |
1897 | |||
1898 | if (IS_ERR(tty)) { | 1942 | if (IS_ERR(tty)) { |
1899 | tty_unlock(); | 1943 | retval = PTR_ERR(tty); |
1900 | mutex_unlock(&tty_mutex); | 1944 | goto err_unlock; |
1901 | tty_driver_kref_put(driver); | ||
1902 | tty_free_file(filp); | ||
1903 | return PTR_ERR(tty); | ||
1904 | } | 1945 | } |
1905 | } | 1946 | } |
1906 | 1947 | ||
@@ -1912,21 +1953,22 @@ got_driver: | |||
1912 | tty = tty_init_dev(driver, index, 0); | 1953 | tty = tty_init_dev(driver, index, 0); |
1913 | 1954 | ||
1914 | mutex_unlock(&tty_mutex); | 1955 | mutex_unlock(&tty_mutex); |
1915 | tty_driver_kref_put(driver); | 1956 | if (driver) |
1957 | tty_driver_kref_put(driver); | ||
1916 | if (IS_ERR(tty)) { | 1958 | if (IS_ERR(tty)) { |
1917 | tty_unlock(); | 1959 | tty_unlock(); |
1918 | tty_free_file(filp); | 1960 | retval = PTR_ERR(tty); |
1919 | return PTR_ERR(tty); | 1961 | goto err_file; |
1920 | } | 1962 | } |
1921 | 1963 | ||
1922 | tty_add_file(tty, filp); | 1964 | tty_add_file(tty, filp); |
1923 | 1965 | ||
1924 | check_tty_count(tty, "tty_open"); | 1966 | check_tty_count(tty, __func__); |
1925 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1967 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
1926 | tty->driver->subtype == PTY_TYPE_MASTER) | 1968 | tty->driver->subtype == PTY_TYPE_MASTER) |
1927 | noctty = 1; | 1969 | noctty = 1; |
1928 | #ifdef TTY_DEBUG_HANGUP | 1970 | #ifdef TTY_DEBUG_HANGUP |
1929 | printk(KERN_DEBUG "opening %s...", tty->name); | 1971 | printk(KERN_DEBUG "%s: opening %s...\n", __func__, tty->name); |
1930 | #endif | 1972 | #endif |
1931 | if (tty->ops->open) | 1973 | if (tty->ops->open) |
1932 | retval = tty->ops->open(tty, filp); | 1974 | retval = tty->ops->open(tty, filp); |
@@ -1940,8 +1982,8 @@ got_driver: | |||
1940 | 1982 | ||
1941 | if (retval) { | 1983 | if (retval) { |
1942 | #ifdef TTY_DEBUG_HANGUP | 1984 | #ifdef TTY_DEBUG_HANGUP |
1943 | printk(KERN_DEBUG "error %d in opening %s...", retval, | 1985 | printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__, |
1944 | tty->name); | 1986 | retval, tty->name); |
1945 | #endif | 1987 | #endif |
1946 | tty_unlock(); /* need to call tty_release without BTM */ | 1988 | tty_unlock(); /* need to call tty_release without BTM */ |
1947 | tty_release(inode, filp); | 1989 | tty_release(inode, filp); |
@@ -1976,6 +2018,15 @@ got_driver: | |||
1976 | tty_unlock(); | 2018 | tty_unlock(); |
1977 | mutex_unlock(&tty_mutex); | 2019 | mutex_unlock(&tty_mutex); |
1978 | return 0; | 2020 | return 0; |
2021 | err_unlock: | ||
2022 | tty_unlock(); | ||
2023 | mutex_unlock(&tty_mutex); | ||
2024 | /* after locks to avoid deadlock */ | ||
2025 | if (!IS_ERR_OR_NULL(driver)) | ||
2026 | tty_driver_kref_put(driver); | ||
2027 | err_file: | ||
2028 | tty_free_file(filp); | ||
2029 | return retval; | ||
1979 | } | 2030 | } |
1980 | 2031 | ||
1981 | 2032 | ||
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 8e0924f55446..24b95db75d84 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -1,19 +1,11 @@ | |||
1 | #include <linux/types.h> | 1 | #include <linux/types.h> |
2 | #include <linux/major.h> | ||
3 | #include <linux/errno.h> | 2 | #include <linux/errno.h> |
4 | #include <linux/signal.h> | 3 | #include <linux/kmod.h> |
5 | #include <linux/fcntl.h> | ||
6 | #include <linux/sched.h> | 4 | #include <linux/sched.h> |
7 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
8 | #include <linux/tty.h> | 6 | #include <linux/tty.h> |
9 | #include <linux/tty_driver.h> | 7 | #include <linux/tty_driver.h> |
10 | #include <linux/tty_flip.h> | ||
11 | #include <linux/devpts_fs.h> | ||
12 | #include <linux/file.h> | 8 | #include <linux/file.h> |
13 | #include <linux/console.h> | ||
14 | #include <linux/timer.h> | ||
15 | #include <linux/ctype.h> | ||
16 | #include <linux/kd.h> | ||
17 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
18 | #include <linux/string.h> | 10 | #include <linux/string.h> |
19 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
@@ -24,18 +16,8 @@ | |||
24 | #include <linux/device.h> | 16 | #include <linux/device.h> |
25 | #include <linux/wait.h> | 17 | #include <linux/wait.h> |
26 | #include <linux/bitops.h> | 18 | #include <linux/bitops.h> |
27 | #include <linux/delay.h> | ||
28 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
29 | |||
30 | #include <linux/uaccess.h> | 20 | #include <linux/uaccess.h> |
31 | #include <asm/system.h> | ||
32 | |||
33 | #include <linux/kbd_kern.h> | ||
34 | #include <linux/vt_kern.h> | ||
35 | #include <linux/selection.h> | ||
36 | |||
37 | #include <linux/kmod.h> | ||
38 | #include <linux/nsproxy.h> | ||
39 | #include <linux/ratelimit.h> | 21 | #include <linux/ratelimit.h> |
40 | 22 | ||
41 | /* | 23 | /* |
@@ -558,8 +540,6 @@ static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) | |||
558 | long ret; | 540 | long ret; |
559 | ret = wait_event_timeout(tty_ldisc_idle, | 541 | ret = wait_event_timeout(tty_ldisc_idle, |
560 | atomic_read(&tty->ldisc->users) == 1, timeout); | 542 | atomic_read(&tty->ldisc->users) == 1, timeout); |
561 | if (ret < 0) | ||
562 | return ret; | ||
563 | return ret > 0 ? 0 : -EBUSY; | 543 | return ret > 0 ? 0 : -EBUSY; |
564 | } | 544 | } |
565 | 545 | ||
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c index 45d3e80156d4..a0f3d6c4d39d 100644 --- a/drivers/tty/vt/consolemap.c +++ b/drivers/tty/vt/consolemap.c | |||
@@ -584,7 +584,7 @@ int con_set_default_unimap(struct vc_data *vc) | |||
584 | return 0; | 584 | return 0; |
585 | dflt->refcount++; | 585 | dflt->refcount++; |
586 | *vc->vc_uni_pagedir_loc = (unsigned long)dflt; | 586 | *vc->vc_uni_pagedir_loc = (unsigned long)dflt; |
587 | if (p && --p->refcount) { | 587 | if (p && !--p->refcount) { |
588 | con_release_unimap(p); | 588 | con_release_unimap(p); |
589 | kfree(p); | 589 | kfree(p); |
590 | } | 590 | } |