From patchwork Fri Aug 7 10:47:04 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Juergen Borleis X-Patchwork-Id: 505096 Return-Path: X-Original-To: incoming-imx@patchwork.ozlabs.org Delivered-To: patchwork-incoming-imx@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2001:1868:205::9]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id D98AF140293 for ; Fri, 7 Aug 2015 20:50:40 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZNfBl-0005WC-4l; Fri, 07 Aug 2015 10:47:49 +0000 Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZNfBT-0005CW-OE for linux-arm-kernel@lists.infradead.org; Fri, 07 Aug 2015 10:47:33 +0000 Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.2:RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1ZNfB4-000793-Bn; Fri, 07 Aug 2015 12:47:06 +0200 Received: from jbe by dude.hi.pengutronix.de with local (Exim 4.86) (envelope-from ) id 1ZNfB2-0002Nb-IH; Fri, 07 Aug 2015 12:47:04 +0200 From: Juergen Borleis To: linux-kernel@vger.kernel.org Subject: [PATCH v4 2/2] serial: mxs-auart: keep the AUART unit in reset state when not in use Date: Fri, 7 Aug 2015 12:47:04 +0200 Message-Id: <1438944424-9053-2-git-send-email-jbe@pengutronix.de> X-Mailer: git-send-email 2.4.6 In-Reply-To: <1438944424-9053-1-git-send-email-jbe@pengutronix.de> References: <1438944424-9053-1-git-send-email-jbe@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: jbe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-arm-kernel@lists.infradead.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150807_034732_064819_90C381F5 X-CRM114-Status: GOOD ( 19.01 ) X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.1 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Stefan Wahren , linux-serial@vger.kernel.org, Greg Kroah-Hartman , kernel@pengutronix.de, Jiri Slaby , linux-arm-kernel@lists.infradead.org, Peter Hurley Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org List-Id: linux-imx-kernel.lists.patchwork.ozlabs.org Whenever the UART device driver gets closed from userland, the driver disables the UART unit and then stops the clocks to save power. The bit which disabled the UART unit is described as:  "UART Enable. If this bit is set to 1, the UART is enabled. Data transmission and reception occurs for the UART signals. When the UART is disabled in the middle of transmission or reception, it completes the current character before stopping." The important part is the "it completes the current character". Whenever a reception is ongoing when the UART gets disabled (including the clock off) the statemachine freezes and "remembers" this state on the next open() when re-enabling the unit's clock. In this case we end up receiving an additional bogus character immediately. The solution in this change is to switch the AUART unit into its reset state on close() and only release it from its reset state on the next open(). Note: when the unit is also used as system console it is always 'in use', so we cannot reset it on close(). Signed-off-by: Juergen Borleis Reviewed-by: Peter Hurley --- drivers/tty/serial/mxs-auart.c | 46 +++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 7dc87a9..8d1cd15 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -858,6 +858,30 @@ static void mxs_auart_reset_deassert(struct uart_port *u) writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); } +static void mxs_auart_reset_assert(struct uart_port *u) +{ + int i; + u32 reg; + + reg = readl(u->membase + AUART_CTRL0); + /* if already in reset state, keep it untouched */ + if (reg & AUART_CTRL0_SFTRST) + return; + + writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); + writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_SET); + + for (i = 0; i < 1000; i++) { + reg = readl(u->membase + AUART_CTRL0); + /* reset is finished when the clock is gated */ + if (reg & AUART_CTRL0_CLKGATE) + return; + udelay(10); + } + + dev_err(u->dev, "Failed to reset the unit."); +} + static int mxs_auart_startup(struct uart_port *u) { int ret; @@ -867,7 +891,13 @@ static int mxs_auart_startup(struct uart_port *u) if (ret) return ret; - writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); + if (uart_console(u)) { + writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); + } else { + /* reset the unit to a well known state */ + mxs_auart_reset_assert(u); + mxs_auart_reset_deassert(u); + } writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET); @@ -899,12 +929,14 @@ static void mxs_auart_shutdown(struct uart_port *u) if (auart_dma_enabled(s)) mxs_auart_dma_exit(s); - writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR); - - writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, - u->membase + AUART_INTR_CLR); - - writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET); + if (uart_console(u)) { + writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR); + writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, + u->membase + AUART_INTR_CLR); + writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET); + } else { + mxs_auart_reset_assert(u); + } clk_disable_unprepare(s->clk); }