From patchwork Tue Jul 14 14:41: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: 6787641 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A3BEBC05AC for ; Tue, 14 Jul 2015 14:43:33 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B7D2620663 for ; Tue, 14 Jul 2015 14:43:29 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D231120658 for ; Tue, 14 Jul 2015 14:43:28 +0000 (UTC) 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 1ZF1Oo-0005AN-Hd; Tue, 14 Jul 2015 14:41:34 +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 1ZF1Om-0004xC-22 for linux-arm-kernel@lists.infradead.org; Tue, 14 Jul 2015 14:41:32 +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 1ZEzWX-000097-KK; Tue, 14 Jul 2015 14:41:25 +0200 Received: from jbe by dude.hi.pengutronix.de with local (Exim 4.86_RC4) (envelope-from ) id 1ZF1OK-0001lz-Oh; Tue, 14 Jul 2015 16:41:04 +0200 From: Juergen Borleis To: linux-kernel@vger.kernel.org Subject: [PATCH] serial: mxs-auart: keep the AUART unit in reset state when not in use Date: Tue, 14 Jul 2015 16:41:04 +0200 Message-Id: <1436884864-6782-1-git-send-email-jbe@pengutronix.de> X-Mailer: git-send-email 2.1.4 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-20150714_074132_266872_F99F79F3 X-CRM114-Status: GOOD ( 18.52 ) X-Spam-Score: -3.3 (---) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kernel@pengutronix.de, Greg Kroah-Hartman , Jiri Slaby , linux-arm-kernel@lists.infradead.org, linux-serial@vger.kernel.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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() and re-enabling of the unit's clock. In this case we end up receiving an additional bogus character immediately. The solution in this change is to move the AUART unit into its reset state on close() and only release it from its reset state on the next open(). Signed-off-by: Juergen Borleis --- drivers/tty/serial/mxs-auart.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 13cf773..f42b6ad 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -858,6 +858,30 @@ static void mxs_auart_reset(struct uart_port *u) writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); } +static void mxs_auart_do_reset(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,10 @@ static int mxs_auart_startup(struct uart_port *u) if (ret) return ret; - writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); + /* reset the unit if not aready done */ + mxs_auart_do_reset(u); + /* bring it out of reset now */ + mxs_auart_reset(u); writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET); @@ -899,13 +926,8 @@ 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); - + /* reset the unit and keep it in reset state */ + mxs_auart_do_reset(u); clk_disable_unprepare(s->clk); }