mirror of
https://abf.rosa.ru/djam/kernel-6.6.git
synced 2025-02-25 03:42:46 +00:00
72 lines
2.9 KiB
Diff
72 lines
2.9 KiB
Diff
From ba89e7e17e6bec3d1e2b49e9a632ff7fe28c4cc0 Mon Sep 17 00:00:00 2001
|
|
From: Alexey Sheplyakov <asheplyakov@basealt.ru>
|
|
Date: Tue, 11 Jan 2022 15:49:19 +0400
|
|
Subject: [PATCH 602/631] serial: 8250_dw: verify clock rate in
|
|
dw8250_set_termios
|
|
|
|
Refuse to change the clock rate if clk_round_rate() returns
|
|
a rate which is way too off (i.e. by more than 1/16 from the one
|
|
necessary for a given baud rate). In particular this happens if
|
|
the requested rate is below the minimum supported by the clock.
|
|
|
|
Fixes the UART console on Baikal-M SoC. Without this patch the
|
|
console gets garbled immediately after loading the driver.
|
|
dw8250_set_termios tries to configure the baud rate (115200),
|
|
and calls clk_round_rate to figure out the supported rate closest
|
|
to 1843200 Hz (which is 115200 * 16). However the (SoC-specific)
|
|
clock driver returns 4705882 Hz. This frequency is way too off,
|
|
hence after setting it the console gets garbled.
|
|
|
|
On Baikal-M Linux has no direct control over (most) clocks.
|
|
The registers of CMU (clock management unit) are accessible
|
|
only from the secure world, therefore clocks are managed by
|
|
the firmware (ARM-TF). Linux' driver, clk-baikal, is a shim which
|
|
calls into firmware. And that 4705882 Hz is exactly what
|
|
the firmware returns.
|
|
|
|
According to 8250_dw maintainer (Andy Shevchenko) the correct
|
|
way to fix the problem is to
|
|
1) use DLAB for the baud rate and fixed clock rate,
|
|
2) fix the firmware
|
|
|
|
Neither of these advices can be applied in practice. For one,
|
|
both methods require replacing the DTB, which is embedded into
|
|
the firmware. Updating firmware is possible only for some types
|
|
of (Baikal-M) based boards, and requires special hardware (JTAG
|
|
programmer) and skills.
|
|
Therfore the only practical way to address the issue is to adjust
|
|
the kernel (with this ugly patch).
|
|
|
|
Signed-off-by: Alexey Sheplyakov <asheplyakov@basealt.ru>
|
|
Co-developed-by: Vadim V. Vlasov <vadim.vlasov@elpitech.ru>
|
|
X-DONTUPSTREAM
|
|
X-feature-Baikal-M
|
|
---
|
|
drivers/tty/serial/8250/8250_dw.c | 5 +++--
|
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
|
|
index a1f2259cc9a9..d2c3fb10185e 100644
|
|
--- a/drivers/tty/serial/8250/8250_dw.c
|
|
+++ b/drivers/tty/serial/8250/8250_dw.c
|
|
@@ -352,14 +352,15 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
|
|
static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
|
|
const struct ktermios *old)
|
|
{
|
|
- unsigned long newrate = tty_termios_baud_rate(termios) * 16;
|
|
+ unsigned long baud = tty_termios_baud_rate(termios);
|
|
+ unsigned long newrate = baud * 16;
|
|
struct dw8250_data *d = to_dw8250_data(p->private_data);
|
|
long rate;
|
|
int ret;
|
|
|
|
clk_disable_unprepare(d->clk);
|
|
rate = clk_round_rate(d->clk, newrate);
|
|
- if (rate > 0) {
|
|
+ if (rate > 0 && rate >= baud * 15 && rate <= baud * 17) {
|
|
/*
|
|
* Note that any clock-notifer worker will block in
|
|
* serial8250_update_uartclk() until we are done.
|
|
--
|
|
2.40.1
|
|
|