From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on sa.local.altlinux.org X-Spam-Level: X-Spam-Status: No, score=-4.3 required=5.0 tests=ALL_TRUSTED,BAYES_00, RP_MATCHES_RCVD autolearn=unavailable autolearn_force=no version=3.4.1 From: Alexey Sheplyakov To: devel-kernel@lists.altlinux.org Date: Mon, 3 Oct 2022 18:01:59 +0400 Message-Id: <20221003140226.1064966-4-asheplyakov@basealt.ru> X-Mailer: git-send-email 2.33.3 In-Reply-To: <20221003140226.1064966-1-asheplyakov@basealt.ru> References: <20221003140226.1064966-1-asheplyakov@basealt.ru> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Cc: nir@basealt.ru, jqt4@basealt.ru, rst@basealt.ru, sin@basealt.ru Subject: [d-kernel] [PATCH 03/31] serial: 8250_dw: verify clock rate in dw8250_set_termios X-BeenThere: devel-kernel@lists.altlinux.org X-Mailman-Version: 2.1.12 Precedence: list Reply-To: ALT Linux kernel packages development List-Id: ALT Linux kernel packages development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 Oct 2022 14:03:33 -0000 Archived-At: List-Archive: List-Post: 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 Co-developed-by: Vadim V. Vlasov 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 a604b42e4458..db54f43c4e8c 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, 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.33.3