Merge remote-tracking branch 'stable/linux-5.15.y' into rpi-5.15.y
authorDom Cobley <popcornmix@gmail.com>
Mon, 27 Jun 2022 12:28:53 +0000 (13:28 +0100)
committerDom Cobley <popcornmix@gmail.com>
Mon, 27 Jun 2022 12:28:53 +0000 (13:28 +0100)
1  2 
drivers/tty/serial/amba-pl011.c

@@@ -1360,32 -1360,6 +1360,32 @@@ static void pl011_start_tx(struct uart_
                pl011_start_tx_pio(uap);
  }
  
 +static void pl011_throttle(struct uart_port *port)
 +{
 +      struct uart_amba_port *uap =
 +          container_of(port, struct uart_amba_port, port);
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&uap->port.lock, flags);
 +      uap->im &= ~(UART011_RTIM | UART011_RXIM);
 +      pl011_write(uap->im, uap, REG_IMSC);
 +      spin_unlock_irqrestore(&uap->port.lock, flags);
 +}
 +
 +static void pl011_unthrottle(struct uart_port *port)
 +{
 +      struct uart_amba_port *uap =
 +          container_of(port, struct uart_amba_port, port);
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&uap->port.lock, flags);
 +      uap->im |= UART011_RTIM;
 +      if (!pl011_dma_rx_running(uap))
 +          uap->im |= UART011_RXIM;
 +      pl011_write(uap->im, uap, REG_IMSC);
 +      spin_unlock_irqrestore(&uap->port.lock, flags);
 +}
 +
  static void pl011_stop_rx(struct uart_port *port)
  {
        struct uart_amba_port *uap =
@@@ -1449,7 -1423,6 +1449,7 @@@ static bool pl011_tx_char(struct uart_a
                return false; /* unable to transmit character */
  
        pl011_write(c, uap, REG_DR);
 +      mb();
        uap->port.icount.tx++;
  
        return true;
@@@ -1510,10 -1483,6 +1510,10 @@@ static bool pl011_tx_chars(struct uart_
                if (likely(from_irq) && count-- == 0)
                        break;
  
 +              if (likely(from_irq) && count == 0 &&
 +                  pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
 +                      break;
 +
                if (!pl011_tx_char(uap, xmit->buf[xmit->tail], from_irq))
                        break;
  
@@@ -1651,13 -1620,6 +1651,6 @@@ static void pl011_set_mctrl(struct uart
            container_of(port, struct uart_amba_port, port);
        unsigned int cr;
  
-       if (port->rs485.flags & SER_RS485_ENABLED) {
-               if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
-                       mctrl &= ~TIOCM_RTS;
-               else
-                       mctrl |= TIOCM_RTS;
-       }
        cr = pl011_read(uap, REG_CR);
  
  #define       TIOCMBIT(tiocmbit, uartbit)             \
@@@ -1756,23 -1718,6 +1749,23 @@@ static void pl011_put_poll_char(struct 
  
  #endif /* CONFIG_CONSOLE_POLL */
  
 +unsigned long pl011_clk_round(unsigned long clk)
 +{
 +      unsigned long scaler;
 +
 +      /*
 +       * If increasing a clock by less than 0.1% changes it
 +       * from ..999.. to ..000.., round up.
 +       */
 +      scaler = 1;
 +      while (scaler * 100000 < clk)
 +              scaler *= 10;
 +      if ((clk + scaler - 1)/scaler % 1000 == 0)
 +              clk = (clk/scaler + 1) * scaler;
 +
 +      return clk;
 +}
 +
  static int pl011_hwinit(struct uart_port *port)
  {
        struct uart_amba_port *uap =
        if (retval)
                return retval;
  
 -      uap->port.uartclk = clk_get_rate(uap->clk);
 +      uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk));
  
        /* Clear pending error and receive interrupts */
        pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
@@@ -1898,14 -1843,8 +1891,8 @@@ static int pl011_startup(struct uart_po
        cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
        cr |= UART01x_CR_UARTEN | UART011_CR_RXE;
  
-       if (port->rs485.flags & SER_RS485_ENABLED) {
-               if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
-                       cr &= ~UART011_CR_RTS;
-               else
-                       cr |= UART011_CR_RTS;
-       } else {
+       if (!(port->rs485.flags & SER_RS485_ENABLED))
                cr |= UART011_CR_TXE;
-       }
  
        pl011_write(cr, uap, REG_CR);
  
@@@ -2306,8 -2245,6 +2293,8 @@@ static const struct uart_ops amba_pl011
        .stop_tx        = pl011_stop_tx,
        .start_tx       = pl011_start_tx,
        .stop_rx        = pl011_stop_rx,
 +      .throttle       = pl011_throttle,
 +      .unthrottle     = pl011_unthrottle,
        .enable_ms      = pl011_enable_ms,
        .break_ctl      = pl011_break_ctl,
        .startup        = pl011_startup,
@@@ -2484,7 -2421,7 +2471,7 @@@ static int pl011_console_setup(struct c
                        plat->init();
        }
  
 -      uap->port.uartclk = clk_get_rate(uap->clk);
 +      uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk));
  
        if (uap->vendor->fixed_options) {
                baud = uap->fixed_baud;
@@@ -2701,7 -2638,6 +2688,7 @@@ static struct uart_driver amba_reg = 
        .cons                   = AMBA_CONSOLE,
  };
  
 +#if 0
  static int pl011_probe_dt_alias(int index, struct device *dev)
  {
        struct device_node *np;
  
        return ret;
  }
 +#endif
  
  /* unregisters the driver also if no more ports are left */
  static void pl011_unregister_port(struct uart_amba_port *uap)
@@@ -2790,12 -2725,7 +2777,12 @@@ static int pl011_setup_port(struct devi
        if (IS_ERR(base))
                return PTR_ERR(base);
  
 +      /* Don't use DT serial<n> aliases - it causes the device to
 +         be renumbered to ttyAMA1 if it is the second serial port in the
 +         system, even though the other one is ttyS0. The 8250 driver
 +         doesn't use this logic, so always remains ttyS0.
        index = pl011_probe_dt_alias(index, dev);
 +      */
  
        uap->old_cr = 0;
        uap->port.dev = dev;
@@@ -2861,11 -2791,6 +2848,11 @@@ static int pl011_probe(struct amba_devi
        if (IS_ERR(uap->clk))
                return PTR_ERR(uap->clk);
  
 +      if (of_property_read_bool(dev->dev.of_node, "cts-event-workaround")) {
 +          vendor->cts_event_workaround = true;
 +          dev_info(&dev->dev, "cts_event_workaround enabled\n");
 +      }
 +
        uap->reg_offset = vendor->reg_offset;
        uap->vendor = vendor;
        uap->fifosize = vendor->get_fifosize(dev);