| .. | .. |
|---|
| 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; |
|---|
| .. | .. |
|---|
| 1237 | 1232 | |
|---|
| 1238 | 1233 | #else |
|---|
| 1239 | 1234 | /* 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 | 1235 | static inline void pl011_dma_remove(struct uart_amba_port *uap) |
|---|
| 1245 | 1236 | { |
|---|
| 1246 | 1237 | } |
|---|
| .. | .. |
|---|
| 1333 | 1324 | pl011_write(uap->im, uap, REG_IMSC); |
|---|
| 1334 | 1325 | |
|---|
| 1335 | 1326 | pl011_dma_rx_stop(uap); |
|---|
| 1327 | +} |
|---|
| 1328 | + |
|---|
| 1329 | +static void pl011_throttle_rx(struct uart_port *port) |
|---|
| 1330 | +{ |
|---|
| 1331 | + unsigned long flags; |
|---|
| 1332 | + |
|---|
| 1333 | + spin_lock_irqsave(&port->lock, flags); |
|---|
| 1334 | + pl011_stop_rx(port); |
|---|
| 1335 | + spin_unlock_irqrestore(&port->lock, flags); |
|---|
| 1336 | 1336 | } |
|---|
| 1337 | 1337 | |
|---|
| 1338 | 1338 | static void pl011_enable_ms(struct uart_port *port) |
|---|
| .. | .. |
|---|
| 1459 | 1459 | |
|---|
| 1460 | 1460 | static void check_apply_cts_event_workaround(struct uart_amba_port *uap) |
|---|
| 1461 | 1461 | { |
|---|
| 1462 | | - unsigned int dummy_read; |
|---|
| 1463 | | - |
|---|
| 1464 | 1462 | if (!uap->vendor->cts_event_workaround) |
|---|
| 1465 | 1463 | return; |
|---|
| 1466 | 1464 | |
|---|
| .. | .. |
|---|
| 1472 | 1470 | * single apb access will incur 2 pclk(133.12Mhz) delay, |
|---|
| 1473 | 1471 | * so add 2 dummy reads |
|---|
| 1474 | 1472 | */ |
|---|
| 1475 | | - dummy_read = pl011_read(uap, REG_ICR); |
|---|
| 1476 | | - dummy_read = pl011_read(uap, REG_ICR); |
|---|
| 1473 | + pl011_read(uap, REG_ICR); |
|---|
| 1474 | + pl011_read(uap, REG_ICR); |
|---|
| 1477 | 1475 | } |
|---|
| 1478 | 1476 | |
|---|
| 1479 | 1477 | static irqreturn_t pl011_int(int irq, void *dev_id) |
|---|
| .. | .. |
|---|
| 1718 | 1716 | { |
|---|
| 1719 | 1717 | pl011_write(uap->im, uap, REG_IMSC); |
|---|
| 1720 | 1718 | |
|---|
| 1721 | | - return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap); |
|---|
| 1719 | + return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011", uap); |
|---|
| 1722 | 1720 | } |
|---|
| 1723 | 1721 | |
|---|
| 1724 | 1722 | /* |
|---|
| .. | .. |
|---|
| 1728 | 1726 | */ |
|---|
| 1729 | 1727 | static void pl011_enable_interrupts(struct uart_amba_port *uap) |
|---|
| 1730 | 1728 | { |
|---|
| 1729 | + unsigned long flags; |
|---|
| 1731 | 1730 | unsigned int i; |
|---|
| 1732 | 1731 | |
|---|
| 1733 | | - spin_lock_irq(&uap->port.lock); |
|---|
| 1732 | + spin_lock_irqsave(&uap->port.lock, flags); |
|---|
| 1734 | 1733 | |
|---|
| 1735 | 1734 | /* Clear out any spuriously appearing RX interrupts */ |
|---|
| 1736 | 1735 | pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR); |
|---|
| .. | .. |
|---|
| 1752 | 1751 | if (!pl011_dma_rx_running(uap)) |
|---|
| 1753 | 1752 | uap->im |= UART011_RXIM; |
|---|
| 1754 | 1753 | pl011_write(uap->im, uap, REG_IMSC); |
|---|
| 1755 | | - spin_unlock_irq(&uap->port.lock); |
|---|
| 1754 | + spin_unlock_irqrestore(&uap->port.lock, flags); |
|---|
| 1755 | +} |
|---|
| 1756 | + |
|---|
| 1757 | +static void pl011_unthrottle_rx(struct uart_port *port) |
|---|
| 1758 | +{ |
|---|
| 1759 | + struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); |
|---|
| 1760 | + |
|---|
| 1761 | + pl011_enable_interrupts(uap); |
|---|
| 1756 | 1762 | } |
|---|
| 1757 | 1763 | |
|---|
| 1758 | 1764 | static int pl011_startup(struct uart_port *port) |
|---|
| .. | .. |
|---|
| 2127 | 2133 | .stop_tx = pl011_stop_tx, |
|---|
| 2128 | 2134 | .start_tx = pl011_start_tx, |
|---|
| 2129 | 2135 | .stop_rx = pl011_stop_rx, |
|---|
| 2136 | + .throttle = pl011_throttle_rx, |
|---|
| 2137 | + .unthrottle = pl011_unthrottle_rx, |
|---|
| 2130 | 2138 | .enable_ms = pl011_enable_ms, |
|---|
| 2131 | 2139 | .break_ctl = pl011_break_ctl, |
|---|
| 2132 | 2140 | .startup = pl011_startup, |
|---|
| .. | .. |
|---|
| 2432 | 2440 | uart_console_write(&dev->port, s, n, pl011_putc); |
|---|
| 2433 | 2441 | } |
|---|
| 2434 | 2442 | |
|---|
| 2443 | +#ifdef CONFIG_CONSOLE_POLL |
|---|
| 2444 | +static int pl011_getc(struct uart_port *port) |
|---|
| 2445 | +{ |
|---|
| 2446 | + if (readl(port->membase + UART01x_FR) & UART01x_FR_RXFE) |
|---|
| 2447 | + return NO_POLL_CHAR; |
|---|
| 2448 | + |
|---|
| 2449 | + if (port->iotype == UPIO_MEM32) |
|---|
| 2450 | + return readl(port->membase + UART01x_DR); |
|---|
| 2451 | + else |
|---|
| 2452 | + return readb(port->membase + UART01x_DR); |
|---|
| 2453 | +} |
|---|
| 2454 | + |
|---|
| 2455 | +static int pl011_early_read(struct console *con, char *s, unsigned int n) |
|---|
| 2456 | +{ |
|---|
| 2457 | + struct earlycon_device *dev = con->data; |
|---|
| 2458 | + int ch, num_read = 0; |
|---|
| 2459 | + |
|---|
| 2460 | + while (num_read < n) { |
|---|
| 2461 | + ch = pl011_getc(&dev->port); |
|---|
| 2462 | + if (ch == NO_POLL_CHAR) |
|---|
| 2463 | + break; |
|---|
| 2464 | + |
|---|
| 2465 | + s[num_read++] = ch; |
|---|
| 2466 | + } |
|---|
| 2467 | + |
|---|
| 2468 | + return num_read; |
|---|
| 2469 | +} |
|---|
| 2470 | +#else |
|---|
| 2471 | +#define pl011_early_read NULL |
|---|
| 2472 | +#endif |
|---|
| 2473 | + |
|---|
| 2435 | 2474 | /* |
|---|
| 2436 | 2475 | * On non-ACPI systems, earlycon is enabled by specifying |
|---|
| 2437 | 2476 | * "earlycon=pl011,<address>" on the kernel command line. |
|---|
| .. | .. |
|---|
| 2451 | 2490 | return -ENODEV; |
|---|
| 2452 | 2491 | |
|---|
| 2453 | 2492 | device->con->write = pl011_early_write; |
|---|
| 2493 | + device->con->read = pl011_early_read; |
|---|
| 2454 | 2494 | |
|---|
| 2455 | 2495 | return 0; |
|---|
| 2456 | 2496 | } |
|---|
| .. | .. |
|---|
| 2569 | 2609 | uap->port.mapbase = mmiobase->start; |
|---|
| 2570 | 2610 | uap->port.membase = base; |
|---|
| 2571 | 2611 | uap->port.fifosize = uap->fifosize; |
|---|
| 2612 | + uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE); |
|---|
| 2572 | 2613 | uap->port.flags = UPF_BOOT_AUTOCONF; |
|---|
| 2573 | 2614 | uap->port.line = index; |
|---|
| 2574 | | - spin_lock_init(&uap->port.lock); |
|---|
| 2575 | 2615 | |
|---|
| 2576 | 2616 | amba_ports[index] = uap; |
|---|
| 2577 | 2617 | |
|---|
| .. | .. |
|---|
| 2642 | 2682 | return pl011_register_port(uap); |
|---|
| 2643 | 2683 | } |
|---|
| 2644 | 2684 | |
|---|
| 2645 | | -static int pl011_remove(struct amba_device *dev) |
|---|
| 2685 | +static void pl011_remove(struct amba_device *dev) |
|---|
| 2646 | 2686 | { |
|---|
| 2647 | 2687 | struct uart_amba_port *uap = amba_get_drvdata(dev); |
|---|
| 2648 | 2688 | |
|---|
| 2649 | 2689 | uart_remove_one_port(&amba_reg, &uap->port); |
|---|
| 2650 | 2690 | pl011_unregister_port(uap); |
|---|
| 2651 | | - return 0; |
|---|
| 2652 | 2691 | } |
|---|
| 2653 | 2692 | |
|---|
| 2654 | 2693 | #ifdef CONFIG_PM_SLEEP |
|---|
| .. | .. |
|---|
| 2706 | 2745 | return -ENOMEM; |
|---|
| 2707 | 2746 | |
|---|
| 2708 | 2747 | ret = platform_get_irq(pdev, 0); |
|---|
| 2709 | | - if (ret < 0) { |
|---|
| 2710 | | - if (ret != -EPROBE_DEFER) |
|---|
| 2711 | | - dev_err(&pdev->dev, "cannot obtain irq\n"); |
|---|
| 2748 | + if (ret < 0) |
|---|
| 2712 | 2749 | return ret; |
|---|
| 2713 | | - } |
|---|
| 2714 | 2750 | uap->port.irq = ret; |
|---|
| 2715 | 2751 | |
|---|
| 2716 | 2752 | #ifdef CONFIG_ACPI_SPCR_TABLE |
|---|
| .. | .. |
|---|
| 2767 | 2803 | .remove = sbsa_uart_remove, |
|---|
| 2768 | 2804 | .driver = { |
|---|
| 2769 | 2805 | .name = "sbsa-uart", |
|---|
| 2806 | + .pm = &pl011_dev_pm_ops, |
|---|
| 2770 | 2807 | .of_match_table = of_match_ptr(sbsa_uart_of_match), |
|---|
| 2771 | 2808 | .acpi_match_table = ACPI_PTR(sbsa_uart_acpi_match), |
|---|
| 2772 | 2809 | .suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_AMBA_PL011), |
|---|