]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
serial: mtk: rewrite the setbrg function
authorWeijie Gao <weijie.gao@mediatek.com>
Fri, 5 Mar 2021 02:35:39 +0000 (10:35 +0800)
committerTom Rini <trini@konsulko.com>
Sat, 20 Mar 2021 20:24:27 +0000 (16:24 -0400)
Currently the setbrg logic of serial-mtk is messy, and should be rewritten.
Also an option is added to make it possible to use highspeed-3 mode for all
bauds.

The new logic is:
1. If baud clock > 12MHz
   a) If baud <= 115200, highspeed-0 mode will be used (ns16550 compatible)
   b) If baud <= 576000, highspeed-2 mode will be used
   c) any bauds > 576000, highspeed-3 mode will be used
2. If baud clock <= 12MHz
   Forced highspeed-3 mode
   a) If baud <= 115200, calculates the divisor using DIV_ROUND_CLOSEST
   b) any bauds > 115200, the same as 1. c)

Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
drivers/serial/serial_mtk.c

index 6d416021deef55aa55b24e7d045e27741a08974b..4145d9fdb3d3daa1ff225f9015a68a6f757b0d30 100644 (file)
@@ -73,74 +73,64 @@ struct mtk_serial_regs {
 struct mtk_serial_priv {
        struct mtk_serial_regs __iomem *regs;
        u32 clock;
+       bool force_highspeed;
 };
 
 static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
 {
-       bool support_clk12m_baud115200;
-       u32 quot, samplecount, realbaud;
+       u32 quot, realbaud, samplecount = 1;
 
-       if ((baud <= 115200) && (priv->clock == 12000000))
-               support_clk12m_baud115200 = true;
-       else
-               support_clk12m_baud115200 = false;
+       /* Special case for low baud clock */
+       if (baud <= 115200 && priv->clock <= 12000000) {
+               writel(3, &priv->regs->highspeed);
+
+               quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
+               if (quot == 0)
+                       quot = 1;
+
+               samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
+
+               realbaud = priv->clock / samplecount / quot;
+               if (realbaud > BAUD_ALLOW_MAX(baud) ||
+                   realbaud < BAUD_ALLOW_MIX(baud)) {
+                       pr_info("baud %d can't be handled\n", baud);
+               }
+
+               goto set_baud;
+       }
+
+       if (priv->force_highspeed)
+               goto use_hs3;
 
        if (baud <= 115200) {
                writel(0, &priv->regs->highspeed);
                quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud);
-
-               if (support_clk12m_baud115200) {
-                       writel(3, &priv->regs->highspeed);
-                       quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
-                       if (quot == 0)
-                               quot = 1;
-
-                       samplecount = DIV_ROUND_CLOSEST(priv->clock,
-                                                       quot * baud);
-                       if (samplecount != 0) {
-                               realbaud = priv->clock / samplecount / quot;
-                               if ((realbaud > BAUD_ALLOW_MAX(baud)) ||
-                                   (realbaud < BAUD_ALLOW_MIX(baud))) {
-                                       pr_info("baud %d can't be handled\n",
-                                               baud);
-                               }
-                       } else {
-                               pr_info("samplecount is 0\n");
-                       }
-               }
        } else if (baud <= 576000) {
                writel(2, &priv->regs->highspeed);
 
                /* Set to next lower baudrate supported */
                if ((baud == 500000) || (baud == 576000))
                        baud = 460800;
+
                quot = DIV_ROUND_UP(priv->clock, 4 * baud);
        } else {
+use_hs3:
                writel(3, &priv->regs->highspeed);
+
                quot = DIV_ROUND_UP(priv->clock, 256 * baud);
+               samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
        }
 
+set_baud:
        /* set divisor */
        writel(UART_LCR_WLS_8 | UART_LCR_DLAB, &priv->regs->lcr);
        writel(quot & 0xff, &priv->regs->dll);
        writel((quot >> 8) & 0xff, &priv->regs->dlm);
        writel(UART_LCR_WLS_8, &priv->regs->lcr);
 
-       if (baud > 460800) {
-               u32 tmp;
-
-               tmp = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
-               writel(tmp - 1, &priv->regs->sample_count);
-               writel((tmp - 2) >> 1, &priv->regs->sample_point);
-       } else {
-               writel(0, &priv->regs->sample_count);
-               writel(0xff, &priv->regs->sample_point);
-       }
-
-       if (support_clk12m_baud115200) {
-               writel(samplecount - 1, &priv->regs->sample_count);
-               writel((samplecount - 2) >> 1, &priv->regs->sample_point);
-       }
+       /* set highspeed mode sample count & point */
+       writel(samplecount - 1, &priv->regs->sample_count);
+       writel((samplecount - 2) >> 1, &priv->regs->sample_point);
 }
 
 static int _mtk_serial_putc(struct mtk_serial_priv *priv, const char ch)
@@ -248,6 +238,8 @@ static int mtk_serial_of_to_plat(struct udevice *dev)
                return -EINVAL;
        }
 
+       priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed");
+
        return 0;
 }