.. | .. |
---|
73 | 73 | |
---|
74 | 74 | #define UART_OSAMP 0x14 |
---|
75 | 75 | #define OSAMP_DEFAULT_DIVISOR 16 |
---|
| 76 | +#define OSAMP_DIVISORS_MASK 0x3F3F3F3F |
---|
76 | 77 | |
---|
77 | 78 | #define MVEBU_NR_UARTS 2 |
---|
78 | 79 | |
---|
.. | .. |
---|
237 | 238 | struct tty_port *tport = &port->state->port; |
---|
238 | 239 | unsigned char ch = 0; |
---|
239 | 240 | char flag = 0; |
---|
| 241 | + int ret; |
---|
240 | 242 | |
---|
241 | 243 | do { |
---|
242 | 244 | if (status & STAT_RX_RDY(port)) { |
---|
.. | .. |
---|
247 | 249 | |
---|
248 | 250 | if (status & STAT_PAR_ERR) |
---|
249 | 251 | port->icount.parity++; |
---|
| 252 | + } |
---|
| 253 | + |
---|
| 254 | + /* |
---|
| 255 | + * For UART2, error bits are not cleared on buffer read. |
---|
| 256 | + * This causes interrupt loop and system hang. |
---|
| 257 | + */ |
---|
| 258 | + if (IS_EXTENDED(port) && (status & STAT_BRK_ERR)) { |
---|
| 259 | + ret = readl(port->membase + UART_STAT); |
---|
| 260 | + ret |= STAT_BRK_ERR; |
---|
| 261 | + writel(ret, port->membase + UART_STAT); |
---|
250 | 262 | } |
---|
251 | 263 | |
---|
252 | 264 | if (status & STAT_BRK_DET) { |
---|
.. | .. |
---|
442 | 454 | } |
---|
443 | 455 | } |
---|
444 | 456 | |
---|
445 | | -static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud) |
---|
| 457 | +static unsigned int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud) |
---|
446 | 458 | { |
---|
447 | | - struct mvebu_uart *mvuart = to_mvuart(port); |
---|
448 | 459 | unsigned int d_divisor, m_divisor; |
---|
449 | | - u32 brdv; |
---|
| 460 | + u32 brdv, osamp; |
---|
450 | 461 | |
---|
451 | | - if (IS_ERR(mvuart->clk)) |
---|
452 | | - return -PTR_ERR(mvuart->clk); |
---|
| 462 | + if (!port->uartclk) |
---|
| 463 | + return 0; |
---|
453 | 464 | |
---|
454 | 465 | /* |
---|
455 | 466 | * The baudrate is derived from the UART clock thanks to two divisors: |
---|
.. | .. |
---|
469 | 480 | brdv |= d_divisor; |
---|
470 | 481 | writel(brdv, port->membase + UART_BRDV); |
---|
471 | 482 | |
---|
472 | | - return 0; |
---|
| 483 | + osamp = readl(port->membase + UART_OSAMP); |
---|
| 484 | + osamp &= ~OSAMP_DIVISORS_MASK; |
---|
| 485 | + writel(osamp, port->membase + UART_OSAMP); |
---|
| 486 | + |
---|
| 487 | + return DIV_ROUND_CLOSEST(port->uartclk, d_divisor * m_divisor); |
---|
473 | 488 | } |
---|
474 | 489 | |
---|
475 | 490 | static void mvebu_uart_set_termios(struct uart_port *port, |
---|
.. | .. |
---|
506 | 521 | max_baud = 230400; |
---|
507 | 522 | |
---|
508 | 523 | baud = uart_get_baud_rate(port, termios, old, min_baud, max_baud); |
---|
509 | | - if (mvebu_uart_baud_rate_set(port, baud)) { |
---|
510 | | - /* No clock available, baudrate cannot be changed */ |
---|
511 | | - if (old) |
---|
512 | | - baud = uart_get_baud_rate(port, old, NULL, |
---|
513 | | - min_baud, max_baud); |
---|
514 | | - } else { |
---|
515 | | - tty_termios_encode_baud_rate(termios, baud, baud); |
---|
516 | | - uart_update_timeout(port, termios->c_cflag, baud); |
---|
517 | | - } |
---|
| 524 | + baud = mvebu_uart_baud_rate_set(port, baud); |
---|
| 525 | + |
---|
| 526 | + /* In case baudrate cannot be changed, report previous old value */ |
---|
| 527 | + if (baud == 0 && old) |
---|
| 528 | + baud = tty_termios_baud_rate(old); |
---|
518 | 529 | |
---|
519 | 530 | /* Only the following flag changes are supported */ |
---|
520 | 531 | if (old) { |
---|
.. | .. |
---|
523 | 534 | termios->c_cflag &= CREAD | CBAUD; |
---|
524 | 535 | termios->c_cflag |= old->c_cflag & ~(CREAD | CBAUD); |
---|
525 | 536 | termios->c_cflag |= CS8; |
---|
| 537 | + } |
---|
| 538 | + |
---|
| 539 | + if (baud != 0) { |
---|
| 540 | + tty_termios_encode_baud_rate(termios, baud, baud); |
---|
| 541 | + uart_update_timeout(port, termios->c_cflag, baud); |
---|
526 | 542 | } |
---|
527 | 543 | |
---|
528 | 544 | spin_unlock_irqrestore(&port->lock, flags); |
---|
.. | .. |
---|
811 | 827 | &pdev->dev); |
---|
812 | 828 | struct uart_port *port; |
---|
813 | 829 | struct mvebu_uart *mvuart; |
---|
814 | | - int ret, id, irq; |
---|
| 830 | + int id, irq; |
---|
815 | 831 | |
---|
816 | 832 | if (!reg) { |
---|
817 | 833 | dev_err(&pdev->dev, "no registers defined\n"); |
---|
.. | .. |
---|
889 | 905 | if (platform_irq_count(pdev) == 1) { |
---|
890 | 906 | /* Old bindings: no name on the single unamed UART0 IRQ */ |
---|
891 | 907 | irq = platform_get_irq(pdev, 0); |
---|
892 | | - if (irq < 0) { |
---|
893 | | - dev_err(&pdev->dev, "unable to get UART IRQ\n"); |
---|
| 908 | + if (irq < 0) |
---|
894 | 909 | return irq; |
---|
895 | | - } |
---|
896 | 910 | |
---|
897 | 911 | mvuart->irq[UART_IRQ_SUM] = irq; |
---|
898 | 912 | } else { |
---|
.. | .. |
---|
902 | 916 | * uart-sum of UART0 port. |
---|
903 | 917 | */ |
---|
904 | 918 | irq = platform_get_irq_byname(pdev, "uart-rx"); |
---|
905 | | - if (irq < 0) { |
---|
906 | | - dev_err(&pdev->dev, "unable to get 'uart-rx' IRQ\n"); |
---|
| 919 | + if (irq < 0) |
---|
907 | 920 | return irq; |
---|
908 | | - } |
---|
909 | 921 | |
---|
910 | 922 | mvuart->irq[UART_RX_IRQ] = irq; |
---|
911 | 923 | |
---|
912 | 924 | irq = platform_get_irq_byname(pdev, "uart-tx"); |
---|
913 | | - if (irq < 0) { |
---|
914 | | - dev_err(&pdev->dev, "unable to get 'uart-tx' IRQ\n"); |
---|
| 925 | + if (irq < 0) |
---|
915 | 926 | return irq; |
---|
916 | | - } |
---|
917 | 927 | |
---|
918 | 928 | mvuart->irq[UART_TX_IRQ] = irq; |
---|
919 | 929 | } |
---|
.. | .. |
---|
923 | 933 | udelay(1); |
---|
924 | 934 | writel(0, port->membase + UART_CTRL(port)); |
---|
925 | 935 | |
---|
926 | | - ret = uart_add_one_port(&mvebu_uart_driver, port); |
---|
927 | | - if (ret) |
---|
928 | | - return ret; |
---|
929 | | - return 0; |
---|
| 936 | + return uart_add_one_port(&mvebu_uart_driver, port); |
---|
930 | 937 | } |
---|
931 | 938 | |
---|
932 | 939 | static struct mvebu_uart_driver_data uart_std_driver_data = { |
---|