.. | .. |
---|
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, |
---|
.. | .. |
---|
2191 | 2211 | { |
---|
2192 | 2212 | struct uart_amba_port *uap = amba_ports[co->index]; |
---|
2193 | 2213 | unsigned int old_cr = 0, new_cr; |
---|
2194 | | - unsigned long flags = 0; |
---|
| 2214 | + unsigned long flags; |
---|
2195 | 2215 | int locked = 1; |
---|
2196 | 2216 | |
---|
2197 | 2217 | clk_enable(uap->clk); |
---|
2198 | 2218 | |
---|
2199 | | - /* |
---|
2200 | | - * local_irq_save(flags); |
---|
2201 | | - * |
---|
2202 | | - * This local_irq_save() is nonsense. If we come in via sysrq |
---|
2203 | | - * handling then interrupts are already disabled. Aside of |
---|
2204 | | - * that the port.sysrq check is racy on SMP regardless. |
---|
2205 | | - */ |
---|
| 2219 | + local_irq_save(flags); |
---|
2206 | 2220 | if (uap->port.sysrq) |
---|
2207 | 2221 | locked = 0; |
---|
2208 | 2222 | else if (oops_in_progress) |
---|
2209 | | - locked = spin_trylock_irqsave(&uap->port.lock, flags); |
---|
| 2223 | + locked = spin_trylock(&uap->port.lock); |
---|
2210 | 2224 | else |
---|
2211 | | - spin_lock_irqsave(&uap->port.lock, flags); |
---|
| 2225 | + spin_lock(&uap->port.lock); |
---|
2212 | 2226 | |
---|
2213 | 2227 | /* |
---|
2214 | 2228 | * First save the CR then disable the interrupts |
---|
.. | .. |
---|
2234 | 2248 | pl011_write(old_cr, uap, REG_CR); |
---|
2235 | 2249 | |
---|
2236 | 2250 | if (locked) |
---|
2237 | | - spin_unlock_irqrestore(&uap->port.lock, flags); |
---|
| 2251 | + spin_unlock(&uap->port.lock); |
---|
| 2252 | + local_irq_restore(flags); |
---|
2238 | 2253 | |
---|
2239 | 2254 | clk_disable(uap->clk); |
---|
2240 | 2255 | } |
---|
.. | .. |
---|
2432 | 2447 | uart_console_write(&dev->port, s, n, pl011_putc); |
---|
2433 | 2448 | } |
---|
2434 | 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 | + |
---|
2435 | 2481 | /* |
---|
2436 | 2482 | * On non-ACPI systems, earlycon is enabled by specifying |
---|
2437 | 2483 | * "earlycon=pl011,<address>" on the kernel command line. |
---|
.. | .. |
---|
2451 | 2497 | return -ENODEV; |
---|
2452 | 2498 | |
---|
2453 | 2499 | device->con->write = pl011_early_write; |
---|
| 2500 | + device->con->read = pl011_early_read; |
---|
2454 | 2501 | |
---|
2455 | 2502 | return 0; |
---|
2456 | 2503 | } |
---|
.. | .. |
---|
2569 | 2616 | uap->port.mapbase = mmiobase->start; |
---|
2570 | 2617 | uap->port.membase = base; |
---|
2571 | 2618 | uap->port.fifosize = uap->fifosize; |
---|
| 2619 | + uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE); |
---|
2572 | 2620 | uap->port.flags = UPF_BOOT_AUTOCONF; |
---|
2573 | 2621 | uap->port.line = index; |
---|
2574 | | - spin_lock_init(&uap->port.lock); |
---|
2575 | 2622 | |
---|
2576 | 2623 | amba_ports[index] = uap; |
---|
2577 | 2624 | |
---|
.. | .. |
---|
2642 | 2689 | return pl011_register_port(uap); |
---|
2643 | 2690 | } |
---|
2644 | 2691 | |
---|
2645 | | -static int pl011_remove(struct amba_device *dev) |
---|
| 2692 | +static void pl011_remove(struct amba_device *dev) |
---|
2646 | 2693 | { |
---|
2647 | 2694 | struct uart_amba_port *uap = amba_get_drvdata(dev); |
---|
2648 | 2695 | |
---|
2649 | 2696 | uart_remove_one_port(&amba_reg, &uap->port); |
---|
2650 | 2697 | pl011_unregister_port(uap); |
---|
2651 | | - return 0; |
---|
2652 | 2698 | } |
---|
2653 | 2699 | |
---|
2654 | 2700 | #ifdef CONFIG_PM_SLEEP |
---|
.. | .. |
---|
2706 | 2752 | return -ENOMEM; |
---|
2707 | 2753 | |
---|
2708 | 2754 | ret = platform_get_irq(pdev, 0); |
---|
2709 | | - if (ret < 0) { |
---|
2710 | | - if (ret != -EPROBE_DEFER) |
---|
2711 | | - dev_err(&pdev->dev, "cannot obtain irq\n"); |
---|
| 2755 | + if (ret < 0) |
---|
2712 | 2756 | return ret; |
---|
2713 | | - } |
---|
2714 | 2757 | uap->port.irq = ret; |
---|
2715 | 2758 | |
---|
2716 | 2759 | #ifdef CONFIG_ACPI_SPCR_TABLE |
---|
.. | .. |
---|
2767 | 2810 | .remove = sbsa_uart_remove, |
---|
2768 | 2811 | .driver = { |
---|
2769 | 2812 | .name = "sbsa-uart", |
---|
| 2813 | + .pm = &pl011_dev_pm_ops, |
---|
2770 | 2814 | .of_match_table = of_match_ptr(sbsa_uart_of_match), |
---|
2771 | 2815 | .acpi_match_table = ACPI_PTR(sbsa_uart_acpi_match), |
---|
2772 | 2816 | .suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_AMBA_PL011), |
---|