diff options
Diffstat (limited to 'drivers/serial/serial_mtk.c')
-rw-r--r-- | drivers/serial/serial_mtk.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/drivers/serial/serial_mtk.c b/drivers/serial/serial_mtk.c index 9d379f2e899..01cc415efdd 100644 --- a/drivers/serial/serial_mtk.c +++ b/drivers/serial/serial_mtk.c @@ -99,10 +99,18 @@ struct mtk_serial_priv { bool upstream_highspeed_logic; }; +static const unsigned short fraction_l_mapping[] = { + 0, 1, 0x5, 0x15, 0x55, 0x57, 0x57, 0x77, 0x7F, 0xFF, 0xFF +}; + +static const unsigned short fraction_m_mapping[] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3 +}; + static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud, uint clk_rate) { - u32 quot, realbaud, samplecount = 1; + u32 quot, realbaud, samplecount = 1, fraction, frac_l = 0, frac_m = 0; /* Special case for low baud clock */ if (baud <= 115200 && clk_rate == 12000000) { @@ -147,7 +155,13 @@ use_hs3: writel(3, &priv->regs->highspeed); quot = DIV_ROUND_UP(clk_rate, 256 * baud); - samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud); + samplecount = clk_rate / (quot * baud); + + fraction = ((clk_rate * 100) / quot / baud) % 100; + fraction = DIV_ROUND_CLOSEST(fraction, 10); + + frac_l = fraction_l_mapping[fraction]; + frac_m = fraction_m_mapping[fraction]; } set_baud: @@ -159,7 +173,11 @@ set_baud: /* set highspeed mode sample count & point */ writel(samplecount - 1, &priv->regs->sample_count); - writel((samplecount - 2) >> 1, &priv->regs->sample_point); + writel((samplecount >> 1) - 1, &priv->regs->sample_point); + + /* set baudrate fraction compensation */ + writel(frac_l, &priv->regs->fracdiv_l); + writel(frac_m, &priv->regs->fracdiv_m); } static int _mtk_serial_putc(struct mtk_serial_priv *priv, const char ch) |