From 0b9f1ae5867df2e71bd4b98d675095a3417426d7 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Fri, 5 Mar 2021 10:35:39 +0800 Subject: [PATCH] serial: mtk: rewrite the setbrg function 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 --- 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..4145d9fdb3 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.39.5