[PATCH] serial: mtk: rewrite the setbrg function

Weijie Gao weijie.gao at mediatek.com
Fri Mar 5 03:35:39 CET 2021


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 at mediatek.com>
---
 drivers/serial/serial_mtk.c | 74 +++++++++++++++++--------------------
 1 file changed, 33 insertions(+), 41 deletions(-)

diff --git a/drivers/serial/serial_mtk.c b/drivers/serial/serial_mtk.c
index 6d416021de..c1c0eca24f 100644
--- a/drivers/serial/serial_mtk.c
+++ b/drivers/serial/serial_mtk.c
@@ -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;
 }
 
-- 
2.17.1


More information about the U-Boot mailing list