From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E461C433EF for ; Mon, 15 Nov 2021 12:48:55 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5E41061ABF for ; Mon, 15 Nov 2021 12:48:54 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 5E41061ABF Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id E24458360F; Mon, 15 Nov 2021 13:48:51 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="tjA2Y3lW"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 29805836C1; Mon, 15 Nov 2021 13:48:49 +0100 (CET) Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id C27F7836C3 for ; Mon, 15 Nov 2021 13:48:45 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=pali@kernel.org Received: by mail.kernel.org (Postfix) with ESMTPSA id BED8A61A6C; Mon, 15 Nov 2021 12:48:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1636980523; bh=p1qAJByjdyFcQ8PZw1efXk25YQUOSmnY8T8B1H2k5Pc=; h=From:To:Cc:Subject:Date:From; b=tjA2Y3lWJKhqVFHN8Em8/3g6LALG/rUY/ZacPkxVdpsDTft7dwBJ/UO/YF6Yzk5f4 9s065pa+eQRr7mNC6si5ld4UVTVY9aLO+v6VRd+Yh2VmqvCFzmG25lczA2G8t1x/+r Dl/15ZnXC/QLCXJ1spe1B2jshxMdgb5Cl1l9+vmGap55Smug9Ok1kRoR1D202lVf0n rv8KJ4ftRvWEGHEi1dutpFRGewAWRRa6/NGf5KVUoa3e78codPYHWT6B/7KEeMTC7r n8Ym22WjJr4l9BEyDqqnheeUYOYI6fN6Olt/BnoVeZaNxbtnwAUy3u0fS6i/NktyJv hfIqeW5xWJs8A== Received: by pali.im (Postfix) id 69215949; Mon, 15 Nov 2021 13:48:41 +0100 (CET) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Stefan Roese Cc: =?UTF-8?q?Marek=20Beh=C3=BAn?= , u-boot@lists.denx.de Subject: [PATCH] serial: a37xx: Reset whole UART when changing parent clock from TBG to XTAL Date: Mon, 15 Nov 2021 13:48:06 +0100 Message-Id: <20211115124806.16122-1-pali@kernel.org> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.35 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Sometimes UART stops transmitting characters after UART clock is changed back to XTAL. In this state UART fifo is always full. Kernel during early boot wants to print output on UART and is waiting for non-empty UART fifo. Which leads to CPU hangup without any (debug) output on UART. Marvell Armada 3700 Functional Specifications says that for programming fractional divisor registers it is required to disable UART, enable loopback mode, reset fifos, program registers, disable loopback mode, release reset of fifos and enable UART. But these steps do not fix above mentioned issue that UART hangup. Also gating UART clock does not help. And even resetting UART state machines do not help. Experiments showed that UART fifo is unblocked after board is being reset (during board reset UART HW transmit UART fifo even CPU is not executing kernel/bootloader anymore). And another experiments showed that same workaround can be achieved also by external reset of UART HW (without need to reset board). So do not implement any of "Marvell recommended" steps from Functional Specifications as they do not work. And rather prior changing parent clock back to XTAL, do external reset of UART HW. This operation also resets all UART registers, so basically it also sets UART clock to default, which is XTAL. It is unknown why UART hangups and enters such broken state. Signed-off-by: Pali Rohár --- drivers/serial/serial_mvebu_a3700.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/serial/serial_mvebu_a3700.c b/drivers/serial/serial_mvebu_a3700.c index 6bca8e4b7e2d..93e4d38d34c7 100644 --- a/drivers/serial/serial_mvebu_a3700.c +++ b/drivers/serial/serial_mvebu_a3700.c @@ -9,6 +9,7 @@ #include #include #include +#include struct mvebu_plat { void __iomem *base; @@ -213,6 +214,7 @@ static int mvebu_serial_remove(struct udevice *dev) u32 new_oversampling; u32 oversampling; u32 d1, d2; + u32 nb_rst; /* * Switch UART base clock back to XTAL because older Linux kernel @@ -260,12 +262,22 @@ static int mvebu_serial_remove(struct udevice *dev) return 0; } + /* wait until TX empty */ while (!(readl(base + UART_STATUS_REG) & UART_STATUS_TX_EMPTY)) ; + /* external reset of UART via North Bridge Peripheral */ + nb_rst = readl(MVEBU_REGISTER(0x12400)); + writel(nb_rst & ~BIT(3), MVEBU_REGISTER(0x12400)); + writel(nb_rst | BIT(3), MVEBU_REGISTER(0x12400)); + + /* set baudrate and oversampling */ writel(new_divider, base + UART_BAUD_REG); writel(new_oversampling, base + UART_POSSR_REG); + /* No Parity, 1 Stop */ + writel(0, base + UART_CTRL_REG); + return 0; } @@ -305,7 +317,6 @@ U_BOOT_DRIVER(serial_mvebu) = { #ifdef CONFIG_DEBUG_MVEBU_A3700_UART #include -#include static inline void _debug_uart_init(void) { -- 2.20.1