2ce77333141ff9aeb148f10686567e32a0a32cd8
[openwrt/staging/wigyori.git] / package / boot / uboot-mediatek / patches / 000-mtk-11-serial-serial-mtk-rewrite-the-setbrg-function.patch
1 From d8bde59186dafdea5bbe8d29d3a6ae7cac98e9d0 Mon Sep 17 00:00:00 2001
2 From: Weijie Gao <weijie.gao@mediatek.com>
3 Date: Mon, 25 Jan 2021 11:19:08 +0800
4 Subject: [PATCH 11/21] serial: serial-mtk: rewrite the setbrg function
5
6 Currently the setbrg logic of serial-mtk is messy, and should be rewritten.
7 Also an option is added to make it possible to use highspeed=3 mode for all
8 bauds.
9
10 The new logic is:
11 1. If baud clock > 12MHz
12 a) If baud <= 115200, highspeed=0 mode will be used (ns16550 compatible)
13 b) If baud <= 576000, highspeed=2 mode will be used
14 c) any baud > 576000, highspeed=3 mode will be used
15 2. If baud clock <= 12MHz
16 Always uses highspeed=3 mode
17 a) If baud <= 115200, calculates the divisor using DIV_ROUND_CLOSEST
18 b) any baud > 115200, the same as 1. c)
19
20 Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
21 ---
22 drivers/serial/serial_mtk.c | 74 +++++++++++++++++--------------------
23 1 file changed, 33 insertions(+), 41 deletions(-)
24
25 --- a/drivers/serial/serial_mtk.c
26 +++ b/drivers/serial/serial_mtk.c
27 @@ -73,74 +73,64 @@ struct mtk_serial_regs {
28 struct mtk_serial_priv {
29 struct mtk_serial_regs __iomem *regs;
30 u32 clock;
31 + bool force_highspeed;
32 };
33
34 static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
35 {
36 - bool support_clk12m_baud115200;
37 - u32 quot, samplecount, realbaud;
38 + u32 quot, realbaud, samplecount = 1;
39
40 - if ((baud <= 115200) && (priv->clock == 12000000))
41 - support_clk12m_baud115200 = true;
42 - else
43 - support_clk12m_baud115200 = false;
44 + /* Special case for low baud clock */
45 + if ((baud <= 115200) && (priv->clock == 12000000)) {
46 + writel(3, &priv->regs->highspeed);
47 +
48 + quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
49 + if (quot == 0)
50 + quot = 1;
51 +
52 + samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
53 +
54 + realbaud = priv->clock / samplecount / quot;
55 + if ((realbaud > BAUD_ALLOW_MAX(baud)) ||
56 + (realbaud < BAUD_ALLOW_MIX(baud))) {
57 + pr_info("baud %d can't be handled\n", baud);
58 + }
59 +
60 + goto set_baud;
61 + }
62 +
63 + if (priv->force_highspeed)
64 + goto use_hs3;
65
66 if (baud <= 115200) {
67 writel(0, &priv->regs->highspeed);
68 quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud);
69 -
70 - if (support_clk12m_baud115200) {
71 - writel(3, &priv->regs->highspeed);
72 - quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
73 - if (quot == 0)
74 - quot = 1;
75 -
76 - samplecount = DIV_ROUND_CLOSEST(priv->clock,
77 - quot * baud);
78 - if (samplecount != 0) {
79 - realbaud = priv->clock / samplecount / quot;
80 - if ((realbaud > BAUD_ALLOW_MAX(baud)) ||
81 - (realbaud < BAUD_ALLOW_MIX(baud))) {
82 - pr_info("baud %d can't be handled\n",
83 - baud);
84 - }
85 - } else {
86 - pr_info("samplecount is 0\n");
87 - }
88 - }
89 } else if (baud <= 576000) {
90 writel(2, &priv->regs->highspeed);
91
92 /* Set to next lower baudrate supported */
93 if ((baud == 500000) || (baud == 576000))
94 baud = 460800;
95 +
96 quot = DIV_ROUND_UP(priv->clock, 4 * baud);
97 } else {
98 +use_hs3:
99 writel(3, &priv->regs->highspeed);
100 +
101 quot = DIV_ROUND_UP(priv->clock, 256 * baud);
102 + samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
103 }
104
105 +set_baud:
106 /* set divisor */
107 writel(UART_LCR_WLS_8 | UART_LCR_DLAB, &priv->regs->lcr);
108 writel(quot & 0xff, &priv->regs->dll);
109 writel((quot >> 8) & 0xff, &priv->regs->dlm);
110 writel(UART_LCR_WLS_8, &priv->regs->lcr);
111
112 - if (baud > 460800) {
113 - u32 tmp;
114 -
115 - tmp = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
116 - writel(tmp - 1, &priv->regs->sample_count);
117 - writel((tmp - 2) >> 1, &priv->regs->sample_point);
118 - } else {
119 - writel(0, &priv->regs->sample_count);
120 - writel(0xff, &priv->regs->sample_point);
121 - }
122 -
123 - if (support_clk12m_baud115200) {
124 - writel(samplecount - 1, &priv->regs->sample_count);
125 - writel((samplecount - 2) >> 1, &priv->regs->sample_point);
126 - }
127 + /* set highspeed mode sample count & point */
128 + writel(samplecount - 1, &priv->regs->sample_count);
129 + writel((samplecount - 2) >> 1, &priv->regs->sample_point);
130 }
131
132 static int _mtk_serial_putc(struct mtk_serial_priv *priv, const char ch)
133 @@ -248,6 +238,8 @@ static int mtk_serial_of_to_plat(struct
134 return -EINVAL;
135 }
136
137 + priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed");
138 +
139 return 0;
140 }
141