1 From d19ad7515a7ef4ee58b5c6606ee9f74c94f28932 Mon Sep 17 00:00:00 2001
2 From: Weijie Gao <weijie.gao@mediatek.com>
3 Date: Wed, 31 Aug 2022 19:04:32 +0800
4 Subject: [PATCH 10/32] serial: mtk: add support for using dynamic baud clock
7 The baud clock on some platform may change due to assigned-clock-parent
8 set in DT. In current flow the baud clock is only retrieved during probe
9 stage. If the parent of the source clock changes after probe stage, the
10 setbrg will set wrong baudrate.
12 To get the right clock rate, this patch records the baud clk struct to the
13 driver's priv, and changes the driver's flow to get the clock rate before
14 calling _mtk_serial_setbrg().
16 Reviewed-by: Simon Glass <sjg@chromium.org>
17 Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
19 drivers/serial/serial_mtk.c | 80 ++++++++++++++++++++++---------------
20 1 file changed, 47 insertions(+), 33 deletions(-)
22 --- a/drivers/serial/serial_mtk.c
23 +++ b/drivers/serial/serial_mtk.c
28 +#include <dm/device_compat.h>
32 @@ -70,27 +71,37 @@ struct mtk_serial_regs {
33 #define BAUD_ALLOW_MAX(baud) ((baud) + (baud) * 3 / 100)
34 #define BAUD_ALLOW_MIX(baud) ((baud) - (baud) * 3 / 100)
36 +/* struct mtk_serial_priv - Structure holding all information used by the
38 + * @regs: Register base of the serial port
39 + * @clk: The baud clock device
40 + * @fixed_clk_rate: Fallback fixed baud clock rate if baud clock
41 + * device is not specified
42 + * @force_highspeed: Force using high-speed mode
44 struct mtk_serial_priv {
45 struct mtk_serial_regs __iomem *regs;
52 -static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
53 +static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud,
56 u32 quot, realbaud, samplecount = 1;
58 /* Special case for low baud clock */
59 - if (baud <= 115200 && priv->clock <= 12000000) {
60 + if (baud <= 115200 && clk_rate == 12000000) {
61 writel(3, &priv->regs->highspeed);
63 - quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
64 + quot = DIV_ROUND_CLOSEST(clk_rate, 256 * baud);
68 - samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
69 + samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud);
71 - realbaud = priv->clock / samplecount / quot;
72 + realbaud = clk_rate / samplecount / quot;
73 if (realbaud > BAUD_ALLOW_MAX(baud) ||
74 realbaud < BAUD_ALLOW_MIX(baud)) {
75 pr_info("baud %d can't be handled\n", baud);
76 @@ -104,7 +115,7 @@ static void _mtk_serial_setbrg(struct mt
79 writel(0, &priv->regs->highspeed);
80 - quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud);
81 + quot = DIV_ROUND_CLOSEST(clk_rate, 16 * baud);
82 } else if (baud <= 576000) {
83 writel(2, &priv->regs->highspeed);
85 @@ -112,13 +123,13 @@ static void _mtk_serial_setbrg(struct mt
86 if ((baud == 500000) || (baud == 576000))
89 - quot = DIV_ROUND_UP(priv->clock, 4 * baud);
90 + quot = DIV_ROUND_UP(clk_rate, 4 * baud);
93 writel(3, &priv->regs->highspeed);
95 - quot = DIV_ROUND_UP(priv->clock, 256 * baud);
96 - samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
97 + quot = DIV_ROUND_UP(clk_rate, 256 * baud);
98 + samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud);
102 @@ -167,8 +178,13 @@ static int _mtk_serial_pending(struct mt
103 static int mtk_serial_setbrg(struct udevice *dev, int baudrate)
105 struct mtk_serial_priv *priv = dev_get_priv(dev);
108 + clk_rate = clk_get_rate(&priv->clk);
109 + if (IS_ERR_VALUE(clk_rate) || clk_rate == 0)
110 + clk_rate = priv->fixed_clk_rate;
112 - _mtk_serial_setbrg(priv, baudrate);
113 + _mtk_serial_setbrg(priv, baudrate, clk_rate);
117 @@ -211,7 +227,6 @@ static int mtk_serial_of_to_plat(struct
119 struct mtk_serial_priv *priv = dev_get_priv(dev);
124 addr = dev_read_addr(dev);
125 @@ -220,22 +235,19 @@ static int mtk_serial_of_to_plat(struct
127 priv->regs = map_physmem(addr, 0, MAP_NOCACHE);
129 - err = clk_get_by_index(dev, 0, &clk);
131 - err = clk_get_rate(&clk);
132 - if (!IS_ERR_VALUE(err))
134 - } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
135 - debug("mtk_serial: failed to get clock\n");
140 - priv->clock = dev_read_u32_default(dev, "clock-frequency", 0);
142 - if (!priv->clock) {
143 - debug("mtk_serial: clock not defined\n");
145 + err = clk_get_by_index(dev, 0, &priv->clk);
147 + err = dev_read_u32(dev, "clock-frequency", &priv->fixed_clk_rate);
149 + dev_err(dev, "baud clock not defined\n");
153 + err = clk_get_rate(&priv->clk);
154 + if (IS_ERR_VALUE(err)) {
155 + dev_err(dev, "invalid baud clock\n");
160 priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed");
161 @@ -273,7 +285,7 @@ DECLARE_GLOBAL_DATA_PTR;
162 #define DECLARE_HSUART_PRIV(port) \
163 static struct mtk_serial_priv mtk_hsuart##port = { \
164 .regs = (struct mtk_serial_regs *)CONFIG_SYS_NS16550_COM##port, \
165 - .clock = CONFIG_SYS_NS16550_CLK \
166 + .fixed_clk_rate = CONFIG_SYS_NS16550_CLK \
169 #define DECLARE_HSUART_FUNCTIONS(port) \
170 @@ -282,12 +294,14 @@ DECLARE_GLOBAL_DATA_PTR;
171 writel(0, &mtk_hsuart##port.regs->ier); \
172 writel(UART_MCRVAL, &mtk_hsuart##port.regs->mcr); \
173 writel(UART_FCRVAL, &mtk_hsuart##port.regs->fcr); \
174 - _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
175 + _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \
176 + mtk_hsuart##port.fixed_clk_rate); \
179 static void mtk_serial##port##_setbrg(void) \
181 - _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
182 + _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \
183 + mtk_hsuart##port.fixed_clk_rate); \
185 static int mtk_serial##port##_getc(void) \
187 @@ -427,13 +441,13 @@ static inline void _debug_uart_init(void
188 struct mtk_serial_priv priv;
190 priv.regs = (void *) CONFIG_VAL(DEBUG_UART_BASE);
191 - priv.clock = CONFIG_DEBUG_UART_CLOCK;
192 + priv.fixed_clk_rate = CONFIG_DEBUG_UART_CLOCK;
194 writel(0, &priv.regs->ier);
195 writel(UART_MCRVAL, &priv.regs->mcr);
196 writel(UART_FCRVAL, &priv.regs->fcr);
198 - _mtk_serial_setbrg(&priv, CONFIG_BAUDRATE);
199 + _mtk_serial_setbrg(&priv, CONFIG_BAUDRATE, priv.fixed_clk_rate);
202 static inline void _debug_uart_putc(int ch)