mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
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 <weijie.gao@mediatek.com>
This commit is contained in:
parent
e8b98f0270
commit
0b9f1ae586
1 changed files with 33 additions and 41 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue