| .. | .. |
|---|
| 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 = { |
|---|