| .. | .. |
|---|
| 16 | 16 | * and hooked into this driver. |
|---|
| 17 | 17 | */ |
|---|
| 18 | 18 | |
|---|
| 19 | | - |
|---|
| 20 | | -#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
|---|
| 21 | | -#define SUPPORT_SYSRQ |
|---|
| 22 | | -#endif |
|---|
| 23 | | - |
|---|
| 24 | 19 | #include <linux/module.h> |
|---|
| 25 | 20 | #include <linux/ioport.h> |
|---|
| 26 | 21 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 417 | 412 | dma_cap_mask_t mask; |
|---|
| 418 | 413 | |
|---|
| 419 | 414 | uap->dma_probed = true; |
|---|
| 420 | | - chan = dma_request_slave_channel_reason(dev, "tx"); |
|---|
| 415 | + chan = dma_request_chan(dev, "tx"); |
|---|
| 421 | 416 | if (IS_ERR(chan)) { |
|---|
| 422 | 417 | if (PTR_ERR(chan) == -EPROBE_DEFER) { |
|---|
| 423 | 418 | uap->dma_probed = false; |
|---|
| .. | .. |
|---|
| 1053 | 1048 | */ |
|---|
| 1054 | 1049 | static inline void pl011_dma_rx_stop(struct uart_amba_port *uap) |
|---|
| 1055 | 1050 | { |
|---|
| 1051 | + if (!uap->using_rx_dma) |
|---|
| 1052 | + return; |
|---|
| 1053 | + |
|---|
| 1056 | 1054 | /* FIXME. Just disable the DMA enable */ |
|---|
| 1057 | 1055 | uap->dmacr &= ~UART011_RXDMAE; |
|---|
| 1058 | 1056 | pl011_write(uap->dmacr, uap, REG_DMACR); |
|---|
| .. | .. |
|---|
| 1237 | 1235 | |
|---|
| 1238 | 1236 | #else |
|---|
| 1239 | 1237 | /* Blank functions if the DMA engine is not available */ |
|---|
| 1240 | | -static inline void pl011_dma_probe(struct uart_amba_port *uap) |
|---|
| 1241 | | -{ |
|---|
| 1242 | | -} |
|---|
| 1243 | | - |
|---|
| 1244 | 1238 | static inline void pl011_dma_remove(struct uart_amba_port *uap) |
|---|
| 1245 | 1239 | { |
|---|
| 1246 | 1240 | } |
|---|
| .. | .. |
|---|
| 1333 | 1327 | pl011_write(uap->im, uap, REG_IMSC); |
|---|
| 1334 | 1328 | |
|---|
| 1335 | 1329 | pl011_dma_rx_stop(uap); |
|---|
| 1330 | +} |
|---|
| 1331 | + |
|---|
| 1332 | +static void pl011_throttle_rx(struct uart_port *port) |
|---|
| 1333 | +{ |
|---|
| 1334 | + unsigned long flags; |
|---|
| 1335 | + |
|---|
| 1336 | + spin_lock_irqsave(&port->lock, flags); |
|---|
| 1337 | + pl011_stop_rx(port); |
|---|
| 1338 | + spin_unlock_irqrestore(&port->lock, flags); |
|---|
| 1336 | 1339 | } |
|---|
| 1337 | 1340 | |
|---|
| 1338 | 1341 | static void pl011_enable_ms(struct uart_port *port) |
|---|
| .. | .. |
|---|
| 1459 | 1462 | |
|---|
| 1460 | 1463 | static void check_apply_cts_event_workaround(struct uart_amba_port *uap) |
|---|
| 1461 | 1464 | { |
|---|
| 1462 | | - unsigned int dummy_read; |
|---|
| 1463 | | - |
|---|
| 1464 | 1465 | if (!uap->vendor->cts_event_workaround) |
|---|
| 1465 | 1466 | return; |
|---|
| 1466 | 1467 | |
|---|
| .. | .. |
|---|
| 1472 | 1473 | * single apb access will incur 2 pclk(133.12Mhz) delay, |
|---|
| 1473 | 1474 | * so add 2 dummy reads |
|---|
| 1474 | 1475 | */ |
|---|
| 1475 | | - dummy_read = pl011_read(uap, REG_ICR); |
|---|
| 1476 | | - dummy_read = pl011_read(uap, REG_ICR); |
|---|
| 1476 | + pl011_read(uap, REG_ICR); |
|---|
| 1477 | + pl011_read(uap, REG_ICR); |
|---|
| 1477 | 1478 | } |
|---|
| 1478 | 1479 | |
|---|
| 1479 | 1480 | static irqreturn_t pl011_int(int irq, void *dev_id) |
|---|
| .. | .. |
|---|
| 1718 | 1719 | { |
|---|
| 1719 | 1720 | pl011_write(uap->im, uap, REG_IMSC); |
|---|
| 1720 | 1721 | |
|---|
| 1721 | | - return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap); |
|---|
| 1722 | + return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011", uap); |
|---|
| 1722 | 1723 | } |
|---|
| 1723 | 1724 | |
|---|
| 1724 | 1725 | /* |
|---|
| .. | .. |
|---|
| 1728 | 1729 | */ |
|---|
| 1729 | 1730 | static void pl011_enable_interrupts(struct uart_amba_port *uap) |
|---|
| 1730 | 1731 | { |
|---|
| 1732 | + unsigned long flags; |
|---|
| 1731 | 1733 | unsigned int i; |
|---|
| 1732 | 1734 | |
|---|
| 1733 | | - spin_lock_irq(&uap->port.lock); |
|---|
| 1735 | + spin_lock_irqsave(&uap->port.lock, flags); |
|---|
| 1734 | 1736 | |
|---|
| 1735 | 1737 | /* Clear out any spuriously appearing RX interrupts */ |
|---|
| 1736 | 1738 | pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR); |
|---|
| .. | .. |
|---|
| 1752 | 1754 | if (!pl011_dma_rx_running(uap)) |
|---|
| 1753 | 1755 | uap->im |= UART011_RXIM; |
|---|
| 1754 | 1756 | pl011_write(uap->im, uap, REG_IMSC); |
|---|
| 1755 | | - spin_unlock_irq(&uap->port.lock); |
|---|
| 1757 | + spin_unlock_irqrestore(&uap->port.lock, flags); |
|---|
| 1758 | +} |
|---|
| 1759 | + |
|---|
| 1760 | +static void pl011_unthrottle_rx(struct uart_port *port) |
|---|
| 1761 | +{ |
|---|
| 1762 | + struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); |
|---|
| 1763 | + unsigned long flags; |
|---|
| 1764 | + |
|---|
| 1765 | + spin_lock_irqsave(&uap->port.lock, flags); |
|---|
| 1766 | + |
|---|
| 1767 | + uap->im = UART011_RTIM; |
|---|
| 1768 | + if (!pl011_dma_rx_running(uap)) |
|---|
| 1769 | + uap->im |= UART011_RXIM; |
|---|
| 1770 | + |
|---|
| 1771 | + pl011_write(uap->im, uap, REG_IMSC); |
|---|
| 1772 | + |
|---|
| 1773 | + spin_unlock_irqrestore(&uap->port.lock, flags); |
|---|
| 1756 | 1774 | } |
|---|
| 1757 | 1775 | |
|---|
| 1758 | 1776 | static int pl011_startup(struct uart_port *port) |
|---|
| .. | .. |
|---|
| 2127 | 2145 | .stop_tx = pl011_stop_tx, |
|---|
| 2128 | 2146 | .start_tx = pl011_start_tx, |
|---|
| 2129 | 2147 | .stop_rx = pl011_stop_rx, |
|---|
| 2148 | + .throttle = pl011_throttle_rx, |
|---|
| 2149 | + .unthrottle = pl011_unthrottle_rx, |
|---|
| 2130 | 2150 | .enable_ms = pl011_enable_ms, |
|---|
| 2131 | 2151 | .break_ctl = pl011_break_ctl, |
|---|
| 2132 | 2152 | .startup = pl011_startup, |
|---|
| .. | .. |
|---|
| 2427 | 2447 | uart_console_write(&dev->port, s, n, pl011_putc); |
|---|
| 2428 | 2448 | } |
|---|
| 2429 | 2449 | |
|---|
| 2450 | +#ifdef CONFIG_CONSOLE_POLL |
|---|
| 2451 | +static int pl011_getc(struct uart_port *port) |
|---|
| 2452 | +{ |
|---|
| 2453 | + if (readl(port->membase + UART01x_FR) & UART01x_FR_RXFE) |
|---|
| 2454 | + return NO_POLL_CHAR; |
|---|
| 2455 | + |
|---|
| 2456 | + if (port->iotype == UPIO_MEM32) |
|---|
| 2457 | + return readl(port->membase + UART01x_DR); |
|---|
| 2458 | + else |
|---|
| 2459 | + return readb(port->membase + UART01x_DR); |
|---|
| 2460 | +} |
|---|
| 2461 | + |
|---|
| 2462 | +static int pl011_early_read(struct console *con, char *s, unsigned int n) |
|---|
| 2463 | +{ |
|---|
| 2464 | + struct earlycon_device *dev = con->data; |
|---|
| 2465 | + int ch, num_read = 0; |
|---|
| 2466 | + |
|---|
| 2467 | + while (num_read < n) { |
|---|
| 2468 | + ch = pl011_getc(&dev->port); |
|---|
| 2469 | + if (ch == NO_POLL_CHAR) |
|---|
| 2470 | + break; |
|---|
| 2471 | + |
|---|
| 2472 | + s[num_read++] = ch; |
|---|
| 2473 | + } |
|---|
| 2474 | + |
|---|
| 2475 | + return num_read; |
|---|
| 2476 | +} |
|---|
| 2477 | +#else |
|---|
| 2478 | +#define pl011_early_read NULL |
|---|
| 2479 | +#endif |
|---|
| 2480 | + |
|---|
| 2430 | 2481 | /* |
|---|
| 2431 | 2482 | * On non-ACPI systems, earlycon is enabled by specifying |
|---|
| 2432 | 2483 | * "earlycon=pl011,<address>" on the kernel command line. |
|---|
| .. | .. |
|---|
| 2446 | 2497 | return -ENODEV; |
|---|
| 2447 | 2498 | |
|---|
| 2448 | 2499 | device->con->write = pl011_early_write; |
|---|
| 2500 | + device->con->read = pl011_early_read; |
|---|
| 2449 | 2501 | |
|---|
| 2450 | 2502 | return 0; |
|---|
| 2451 | 2503 | } |
|---|
| .. | .. |
|---|
| 2564 | 2616 | uap->port.mapbase = mmiobase->start; |
|---|
| 2565 | 2617 | uap->port.membase = base; |
|---|
| 2566 | 2618 | uap->port.fifosize = uap->fifosize; |
|---|
| 2619 | + uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE); |
|---|
| 2567 | 2620 | uap->port.flags = UPF_BOOT_AUTOCONF; |
|---|
| 2568 | 2621 | uap->port.line = index; |
|---|
| 2569 | | - spin_lock_init(&uap->port.lock); |
|---|
| 2570 | 2622 | |
|---|
| 2571 | 2623 | amba_ports[index] = uap; |
|---|
| 2572 | 2624 | |
|---|
| .. | .. |
|---|
| 2637 | 2689 | return pl011_register_port(uap); |
|---|
| 2638 | 2690 | } |
|---|
| 2639 | 2691 | |
|---|
| 2640 | | -static int pl011_remove(struct amba_device *dev) |
|---|
| 2692 | +static void pl011_remove(struct amba_device *dev) |
|---|
| 2641 | 2693 | { |
|---|
| 2642 | 2694 | struct uart_amba_port *uap = amba_get_drvdata(dev); |
|---|
| 2643 | 2695 | |
|---|
| 2644 | 2696 | uart_remove_one_port(&amba_reg, &uap->port); |
|---|
| 2645 | 2697 | pl011_unregister_port(uap); |
|---|
| 2646 | | - return 0; |
|---|
| 2647 | 2698 | } |
|---|
| 2648 | 2699 | |
|---|
| 2649 | 2700 | #ifdef CONFIG_PM_SLEEP |
|---|
| .. | .. |
|---|
| 2701 | 2752 | return -ENOMEM; |
|---|
| 2702 | 2753 | |
|---|
| 2703 | 2754 | ret = platform_get_irq(pdev, 0); |
|---|
| 2704 | | - if (ret < 0) { |
|---|
| 2705 | | - if (ret != -EPROBE_DEFER) |
|---|
| 2706 | | - dev_err(&pdev->dev, "cannot obtain irq\n"); |
|---|
| 2755 | + if (ret < 0) |
|---|
| 2707 | 2756 | return ret; |
|---|
| 2708 | | - } |
|---|
| 2709 | 2757 | uap->port.irq = ret; |
|---|
| 2710 | 2758 | |
|---|
| 2711 | 2759 | #ifdef CONFIG_ACPI_SPCR_TABLE |
|---|
| .. | .. |
|---|
| 2762 | 2810 | .remove = sbsa_uart_remove, |
|---|
| 2763 | 2811 | .driver = { |
|---|
| 2764 | 2812 | .name = "sbsa-uart", |
|---|
| 2813 | + .pm = &pl011_dev_pm_ops, |
|---|
| 2765 | 2814 | .of_match_table = of_match_ptr(sbsa_uart_of_match), |
|---|
| 2766 | 2815 | .acpi_match_table = ACPI_PTR(sbsa_uart_acpi_match), |
|---|
| 2767 | 2816 | .suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_AMBA_PL011), |
|---|