]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
serial: amba-pl011: Introduce set_uartclk_rate vendor flag
authorKartik Rajput <kkartik@nvidia.com>
Wed, 25 Feb 2026 06:59:12 +0000 (12:29 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Mar 2026 14:06:39 +0000 (15:06 +0100)
The NVIDIA Tegra264 UART relies on configuring the UART clock rate
directly to program the desired baud rate.

Introduce the set_uartclk_rate vendor flag. When set, the driver
uses clk_set_rate() to program the UART clock to the desired baud
rate and clk_round_rate() to determine the maximum supported baud
rate.

Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
Link: https://patch.msgid.link/20260225065915.341522-3-kkartik@nvidia.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/amba-pl011.c

index b6d881eb87ccfe462129d6d4355b31fd932ff643..e12facb2a16a4b745bdebace84e827da3d3d3ad6 100644 (file)
@@ -115,6 +115,7 @@ struct vendor_data {
        bool                    always_enabled;
        bool                    fixed_options;
        bool                    skip_ibrd_fbrd;
+       bool                    set_uartclk_rate;
 
        unsigned int (*get_fifosize)(struct amba_device *dev);
 };
@@ -2096,6 +2097,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
        unsigned int lcr_h, old_cr;
        unsigned long flags;
        unsigned int baud, quot, clkdiv;
+       unsigned int max_baud;
        unsigned int bits;
 
        if (uap->vendor->oversampling)
@@ -2103,11 +2105,34 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
        else
                clkdiv = 16;
 
+       max_baud = port->uartclk / clkdiv;
+
+       if (uap->vendor->set_uartclk_rate) {
+               long max_clkrate = clk_round_rate(uap->clk, UINT_MAX);
+
+               /*
+                * Clock is reprogrammable - determine max baud from the clock's
+                * maximum rate, not the current uartclk.
+                */
+               if (max_clkrate > 0)
+                       max_baud = max_clkrate / clkdiv;
+       }
+
        /*
         * Ask the core to calculate the divisor for us.
         */
-       baud = uart_get_baud_rate(port, termios, old, 0,
-                                 port->uartclk / clkdiv);
+       baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
+
+       if (uap->vendor->set_uartclk_rate) {
+               int err;
+
+               err = clk_set_rate(uap->clk, baud * clkdiv);
+               if (err) {
+                       dev_err(port->dev, "Failed to set clock rate: %d\n", err);
+                       return;
+               }
+       }
+
 #ifdef CONFIG_DMA_ENGINE
        /*
         * Adjust RX DMA polling rate with baud rate if not specified.